diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-26 09:11:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-26 09:11:09 -0400 |
commit | efb8d21b2c6db3497655cc6a033ae8a9883e4063 (patch) | |
tree | a14a0dbb9fec3a6db5e542ba7ed4a49681706420 | |
parent | 3cb603284b3d256ae9ae9e65887cee8416bfef15 (diff) | |
parent | d208a3bf77f902283894f546b6b5383202cf7882 (diff) |
Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (79 commits)
TTY: serial_core: Fix crash if DCD drop during suspend
tty/serial: atmel_serial: bootconsole removed from auto-enumerates
Revert "TTY: call tty_driver_lookup_tty unconditionally"
tty/serial: atmel_serial: add device tree support
tty/serial: atmel_serial: auto-enumerate ports
tty/serial: atmel_serial: whitespace and braces modifications
tty/serial: atmel_serial: change platform_data variable name
tty/serial: RS485 bindings for device tree
TTY: call tty_driver_lookup_tty unconditionally
TTY: pty, release tty in all ptmx_open fail paths
TTY: make tty_add_file non-failing
TTY: drop driver reference in tty_open fail path
8250_pci: Fix kernel panic when pch_uart is disabled
h8300: drivers/serial/Kconfig was moved
parport_pc: release IO region properly if unsupported ITE887x card is found
tty: Support compat_ioctl get/set termios_locked
hvc_console: display printk messages on console.
TTY: snyclinkmp: forever loop in tx_load_dma_buffer()
tty/n_gsm: avoid fifo overflow in gsm_dlci_data_output
tty/n_gsm: fix a bug in gsm_dlci_data_output (adaption = 2 case)
...
Fix up Conflicts in:
- drivers/tty/serial/8250_pci.c
Trivial conflict with removed duplicate device ID
- drivers/tty/serial/atmel_serial.c
Annoying silly conflict between "specify the port num via
platform_data" and other changes to atmel_console_init
110 files changed, 2101 insertions, 946 deletions
diff --git a/Documentation/devicetree/bindings/serial/rs485.txt b/Documentation/devicetree/bindings/serial/rs485.txt new file mode 100644 index 000000000000..1e753c69fc83 --- /dev/null +++ b/Documentation/devicetree/bindings/serial/rs485.txt | |||
@@ -0,0 +1,31 @@ | |||
1 | * RS485 serial communications | ||
2 | |||
3 | The RTS signal is capable of automatically controlling line direction for | ||
4 | the built-in half-duplex mode. | ||
5 | The properties described hereafter shall be given to a half-duplex capable | ||
6 | UART node. | ||
7 | |||
8 | Required properties: | ||
9 | - rs485-rts-delay: prop-encoded-array <a b> where: | ||
10 | * a is the delay beteween rts signal and beginning of data sent in milliseconds. | ||
11 | it corresponds to the delay before sending data. | ||
12 | * b is the delay between end of data sent and rts signal in milliseconds | ||
13 | it corresponds to the delay after sending data and actual release of the line. | ||
14 | |||
15 | Optional properties: | ||
16 | - linux,rs485-enabled-at-boot-time: empty property telling to enable the rs485 | ||
17 | feature at boot time. It can be disabled later with proper ioctl. | ||
18 | - rs485-rx-during-tx: empty property that enables the receiving of data even | ||
19 | whilst sending data. | ||
20 | |||
21 | RS485 example for Atmel USART: | ||
22 | usart0: serial@fff8c000 { | ||
23 | compatible = "atmel,at91sam9260-usart"; | ||
24 | reg = <0xfff8c000 0x4000>; | ||
25 | interrupts = <7>; | ||
26 | atmel,use-dma-rx; | ||
27 | atmel,use-dma-tx; | ||
28 | linux,rs485-enabled-at-boot-time; | ||
29 | rs485-rts-delay = <0 200>; // in milliseconds | ||
30 | }; | ||
31 | |||
diff --git a/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt new file mode 100644 index 000000000000..a49d9a1d4ccf --- /dev/null +++ b/Documentation/devicetree/bindings/tty/serial/atmel-usart.txt | |||
@@ -0,0 +1,27 @@ | |||
1 | * Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Should be "atmel,<chip>-usart" | ||
5 | The compatible <chip> indicated will be the first SoC to support an | ||
6 | additional mode or an USART new feature. | ||
7 | - reg: Should contain registers location and length | ||
8 | - interrupts: Should contain interrupt | ||
9 | |||
10 | Optional properties: | ||
11 | - atmel,use-dma-rx: use of PDC or DMA for receiving data | ||
12 | - atmel,use-dma-tx: use of PDC or DMA for transmitting data | ||
13 | |||
14 | <chip> compatible description: | ||
15 | - at91rm9200: legacy USART support | ||
16 | - at91sam9260: generic USART implementation for SAM9 SoCs | ||
17 | |||
18 | Example: | ||
19 | |||
20 | usart0: serial@fff8c000 { | ||
21 | compatible = "atmel,at91sam9260-usart"; | ||
22 | reg = <0xfff8c000 0x4000>; | ||
23 | interrupts = <7>; | ||
24 | atmel,use-dma-rx; | ||
25 | atmel,use-dma-tx; | ||
26 | }; | ||
27 | |||
diff --git a/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt b/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt new file mode 100644 index 000000000000..f13f1c5be91c --- /dev/null +++ b/Documentation/devicetree/bindings/tty/serial/snps-dw-apb-uart.txt | |||
@@ -0,0 +1,25 @@ | |||
1 | * Synopsys DesignWare ABP UART | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "snps,dw-apb-uart" | ||
5 | - reg : offset and length of the register set for the device. | ||
6 | - interrupts : should contain uart interrupt. | ||
7 | - clock-frequency : the input clock frequency for the UART. | ||
8 | |||
9 | Optional properties: | ||
10 | - reg-shift : quantity to shift the register offsets by. If this property is | ||
11 | not present then the register offsets are not shifted. | ||
12 | - reg-io-width : the size (in bytes) of the IO accesses that should be | ||
13 | performed on the device. If this property is not present then single byte | ||
14 | accesses are used. | ||
15 | |||
16 | Example: | ||
17 | |||
18 | uart@80230000 { | ||
19 | compatible = "snps,dw-apb-uart"; | ||
20 | reg = <0x80230000 0x100>; | ||
21 | clock-frequency = <3686400>; | ||
22 | interrupts = <10>; | ||
23 | reg-shift = <2>; | ||
24 | reg-io-width = <4>; | ||
25 | }; | ||
diff --git a/Documentation/serial/serial-rs485.txt b/Documentation/serial/serial-rs485.txt index a4932387bbfb..079cb3df62cf 100644 --- a/Documentation/serial/serial-rs485.txt +++ b/Documentation/serial/serial-rs485.txt | |||
@@ -28,6 +28,10 @@ | |||
28 | RS485 communications. This data structure is used to set and configure RS485 | 28 | RS485 communications. This data structure is used to set and configure RS485 |
29 | parameters in the platform data and in ioctls. | 29 | parameters in the platform data and in ioctls. |
30 | 30 | ||
31 | The device tree can also provide RS485 boot time parameters (see [2] | ||
32 | for bindings). The driver is in charge of filling this data structure from | ||
33 | the values given by the device tree. | ||
34 | |||
31 | Any driver for devices capable of working both as RS232 and RS485 should | 35 | Any driver for devices capable of working both as RS232 and RS485 should |
32 | provide at least the following ioctls: | 36 | provide at least the following ioctls: |
33 | 37 | ||
@@ -104,6 +108,9 @@ | |||
104 | rs485conf.flags |= SER_RS485_RTS_AFTER_SEND; | 108 | rs485conf.flags |= SER_RS485_RTS_AFTER_SEND; |
105 | rs485conf.delay_rts_after_send = ...; | 109 | rs485conf.delay_rts_after_send = ...; |
106 | 110 | ||
111 | /* Set this flag if you want to receive data even whilst sending data */ | ||
112 | rs485conf.flags |= SER_RS485_RX_DURING_TX; | ||
113 | |||
107 | if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) { | 114 | if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) { |
108 | /* Error handling. See errno. */ | 115 | /* Error handling. See errno. */ |
109 | } | 116 | } |
@@ -118,3 +125,4 @@ | |||
118 | 5. REFERENCES | 125 | 5. REFERENCES |
119 | 126 | ||
120 | [1] include/linux/serial.h | 127 | [1] include/linux/serial.h |
128 | [2] Documentation/devicetree/bindings/serial/rs485.txt | ||
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7536b9cbb072..795126ea4935 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -727,7 +727,6 @@ config ARCH_S3C64XX | |||
727 | select ARCH_REQUIRE_GPIOLIB | 727 | select ARCH_REQUIRE_GPIOLIB |
728 | select SAMSUNG_CLKSRC | 728 | select SAMSUNG_CLKSRC |
729 | select SAMSUNG_IRQ_VIC_TIMER | 729 | select SAMSUNG_IRQ_VIC_TIMER |
730 | select SAMSUNG_IRQ_UART | ||
731 | select S3C_GPIO_TRACK | 730 | select S3C_GPIO_TRACK |
732 | select S3C_GPIO_PULL_UPDOWN | 731 | select S3C_GPIO_PULL_UPDOWN |
733 | select S3C_GPIO_CFG_S3C24XX | 732 | select S3C_GPIO_CFG_S3C24XX |
diff --git a/arch/arm/mach-s3c64xx/dev-uart.c b/arch/arm/mach-s3c64xx/dev-uart.c index f797f748b999..c681b99eda08 100644 --- a/arch/arm/mach-s3c64xx/dev-uart.c +++ b/arch/arm/mach-s3c64xx/dev-uart.c | |||
@@ -37,21 +37,10 @@ static struct resource s3c64xx_uart0_resource[] = { | |||
37 | .flags = IORESOURCE_MEM, | 37 | .flags = IORESOURCE_MEM, |
38 | }, | 38 | }, |
39 | [1] = { | 39 | [1] = { |
40 | .start = IRQ_S3CUART_RX0, | 40 | .start = IRQ_UART0, |
41 | .end = IRQ_S3CUART_RX0, | 41 | .end = IRQ_UART0, |
42 | .flags = IORESOURCE_IRQ, | 42 | .flags = IORESOURCE_IRQ, |
43 | }, | 43 | }, |
44 | [2] = { | ||
45 | .start = IRQ_S3CUART_TX0, | ||
46 | .end = IRQ_S3CUART_TX0, | ||
47 | .flags = IORESOURCE_IRQ, | ||
48 | |||
49 | }, | ||
50 | [3] = { | ||
51 | .start = IRQ_S3CUART_ERR0, | ||
52 | .end = IRQ_S3CUART_ERR0, | ||
53 | .flags = IORESOURCE_IRQ, | ||
54 | } | ||
55 | }; | 44 | }; |
56 | 45 | ||
57 | static struct resource s3c64xx_uart1_resource[] = { | 46 | static struct resource s3c64xx_uart1_resource[] = { |
@@ -61,19 +50,8 @@ static struct resource s3c64xx_uart1_resource[] = { | |||
61 | .flags = IORESOURCE_MEM, | 50 | .flags = IORESOURCE_MEM, |
62 | }, | 51 | }, |
63 | [1] = { | 52 | [1] = { |
64 | .start = IRQ_S3CUART_RX1, | 53 | .start = IRQ_UART1, |
65 | .end = IRQ_S3CUART_RX1, | 54 | .end = IRQ_UART1, |
66 | .flags = IORESOURCE_IRQ, | ||
67 | }, | ||
68 | [2] = { | ||
69 | .start = IRQ_S3CUART_TX1, | ||
70 | .end = IRQ_S3CUART_TX1, | ||
71 | .flags = IORESOURCE_IRQ, | ||
72 | |||
73 | }, | ||
74 | [3] = { | ||
75 | .start = IRQ_S3CUART_ERR1, | ||
76 | .end = IRQ_S3CUART_ERR1, | ||
77 | .flags = IORESOURCE_IRQ, | 55 | .flags = IORESOURCE_IRQ, |
78 | }, | 56 | }, |
79 | }; | 57 | }; |
@@ -85,19 +63,8 @@ static struct resource s3c6xx_uart2_resource[] = { | |||
85 | .flags = IORESOURCE_MEM, | 63 | .flags = IORESOURCE_MEM, |
86 | }, | 64 | }, |
87 | [1] = { | 65 | [1] = { |
88 | .start = IRQ_S3CUART_RX2, | 66 | .start = IRQ_UART2, |
89 | .end = IRQ_S3CUART_RX2, | 67 | .end = IRQ_UART2, |
90 | .flags = IORESOURCE_IRQ, | ||
91 | }, | ||
92 | [2] = { | ||
93 | .start = IRQ_S3CUART_TX2, | ||
94 | .end = IRQ_S3CUART_TX2, | ||
95 | .flags = IORESOURCE_IRQ, | ||
96 | |||
97 | }, | ||
98 | [3] = { | ||
99 | .start = IRQ_S3CUART_ERR2, | ||
100 | .end = IRQ_S3CUART_ERR2, | ||
101 | .flags = IORESOURCE_IRQ, | 68 | .flags = IORESOURCE_IRQ, |
102 | }, | 69 | }, |
103 | }; | 70 | }; |
@@ -109,19 +76,8 @@ static struct resource s3c64xx_uart3_resource[] = { | |||
109 | .flags = IORESOURCE_MEM, | 76 | .flags = IORESOURCE_MEM, |
110 | }, | 77 | }, |
111 | [1] = { | 78 | [1] = { |
112 | .start = IRQ_S3CUART_RX3, | 79 | .start = IRQ_UART3, |
113 | .end = IRQ_S3CUART_RX3, | 80 | .end = IRQ_UART3, |
114 | .flags = IORESOURCE_IRQ, | ||
115 | }, | ||
116 | [2] = { | ||
117 | .start = IRQ_S3CUART_TX3, | ||
118 | .end = IRQ_S3CUART_TX3, | ||
119 | .flags = IORESOURCE_IRQ, | ||
120 | |||
121 | }, | ||
122 | [3] = { | ||
123 | .start = IRQ_S3CUART_ERR3, | ||
124 | .end = IRQ_S3CUART_ERR3, | ||
125 | .flags = IORESOURCE_IRQ, | 81 | .flags = IORESOURCE_IRQ, |
126 | }, | 82 | }, |
127 | }; | 83 | }; |
diff --git a/arch/arm/mach-s3c64xx/include/mach/irqs.h b/arch/arm/mach-s3c64xx/include/mach/irqs.h index c026f67a80de..443f85b3c203 100644 --- a/arch/arm/mach-s3c64xx/include/mach/irqs.h +++ b/arch/arm/mach-s3c64xx/include/mach/irqs.h | |||
@@ -27,36 +27,6 @@ | |||
27 | #define IRQ_VIC0_BASE S3C_IRQ(0) | 27 | #define IRQ_VIC0_BASE S3C_IRQ(0) |
28 | #define IRQ_VIC1_BASE S3C_IRQ(32) | 28 | #define IRQ_VIC1_BASE S3C_IRQ(32) |
29 | 29 | ||
30 | /* UART interrupts, each UART has 4 intterupts per channel so | ||
31 | * use the space between the ISA and S3C main interrupts. Note, these | ||
32 | * are not in the same order as the S3C24XX series! */ | ||
33 | |||
34 | #define IRQ_S3CUART_BASE0 (16) | ||
35 | #define IRQ_S3CUART_BASE1 (20) | ||
36 | #define IRQ_S3CUART_BASE2 (24) | ||
37 | #define IRQ_S3CUART_BASE3 (28) | ||
38 | |||
39 | #define UART_IRQ_RXD (0) | ||
40 | #define UART_IRQ_ERR (1) | ||
41 | #define UART_IRQ_TXD (2) | ||
42 | #define UART_IRQ_MODEM (3) | ||
43 | |||
44 | #define IRQ_S3CUART_RX0 (IRQ_S3CUART_BASE0 + UART_IRQ_RXD) | ||
45 | #define IRQ_S3CUART_TX0 (IRQ_S3CUART_BASE0 + UART_IRQ_TXD) | ||
46 | #define IRQ_S3CUART_ERR0 (IRQ_S3CUART_BASE0 + UART_IRQ_ERR) | ||
47 | |||
48 | #define IRQ_S3CUART_RX1 (IRQ_S3CUART_BASE1 + UART_IRQ_RXD) | ||
49 | #define IRQ_S3CUART_TX1 (IRQ_S3CUART_BASE1 + UART_IRQ_TXD) | ||
50 | #define IRQ_S3CUART_ERR1 (IRQ_S3CUART_BASE1 + UART_IRQ_ERR) | ||
51 | |||
52 | #define IRQ_S3CUART_RX2 (IRQ_S3CUART_BASE2 + UART_IRQ_RXD) | ||
53 | #define IRQ_S3CUART_TX2 (IRQ_S3CUART_BASE2 + UART_IRQ_TXD) | ||
54 | #define IRQ_S3CUART_ERR2 (IRQ_S3CUART_BASE2 + UART_IRQ_ERR) | ||
55 | |||
56 | #define IRQ_S3CUART_RX3 (IRQ_S3CUART_BASE3 + UART_IRQ_RXD) | ||
57 | #define IRQ_S3CUART_TX3 (IRQ_S3CUART_BASE3 + UART_IRQ_TXD) | ||
58 | #define IRQ_S3CUART_ERR3 (IRQ_S3CUART_BASE3 + UART_IRQ_ERR) | ||
59 | |||
60 | /* VIC based IRQs */ | 30 | /* VIC based IRQs */ |
61 | 31 | ||
62 | #define S3C64XX_IRQ_VIC0(x) (IRQ_VIC0_BASE + (x)) | 32 | #define S3C64XX_IRQ_VIC0(x) (IRQ_VIC0_BASE + (x)) |
diff --git a/arch/arm/mach-s3c64xx/irq.c b/arch/arm/mach-s3c64xx/irq.c index 75d9a0e49193..b07357e94958 100644 --- a/arch/arm/mach-s3c64xx/irq.c +++ b/arch/arm/mach-s3c64xx/irq.c | |||
@@ -25,29 +25,6 @@ | |||
25 | #include <plat/irq-uart.h> | 25 | #include <plat/irq-uart.h> |
26 | #include <plat/cpu.h> | 26 | #include <plat/cpu.h> |
27 | 27 | ||
28 | static struct s3c_uart_irq uart_irqs[] = { | ||
29 | [0] = { | ||
30 | .regs = S3C_VA_UART0, | ||
31 | .base_irq = IRQ_S3CUART_BASE0, | ||
32 | .parent_irq = IRQ_UART0, | ||
33 | }, | ||
34 | [1] = { | ||
35 | .regs = S3C_VA_UART1, | ||
36 | .base_irq = IRQ_S3CUART_BASE1, | ||
37 | .parent_irq = IRQ_UART1, | ||
38 | }, | ||
39 | [2] = { | ||
40 | .regs = S3C_VA_UART2, | ||
41 | .base_irq = IRQ_S3CUART_BASE2, | ||
42 | .parent_irq = IRQ_UART2, | ||
43 | }, | ||
44 | [3] = { | ||
45 | .regs = S3C_VA_UART3, | ||
46 | .base_irq = IRQ_S3CUART_BASE3, | ||
47 | .parent_irq = IRQ_UART3, | ||
48 | }, | ||
49 | }; | ||
50 | |||
51 | /* setup the sources the vic should advertise resume for, even though it | 28 | /* setup the sources the vic should advertise resume for, even though it |
52 | * is not doing the wake (set_irq_wake needs to be valid) */ | 29 | * is not doing the wake (set_irq_wake needs to be valid) */ |
53 | #define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE)) | 30 | #define IRQ_VIC0_RESUME (1 << (IRQ_RTC_TIC - IRQ_VIC0_BASE)) |
@@ -67,6 +44,4 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid) | |||
67 | 44 | ||
68 | /* add the timer sub-irqs */ | 45 | /* add the timer sub-irqs */ |
69 | s3c_init_vic_timer_irq(5, IRQ_TIMER0); | 46 | s3c_init_vic_timer_irq(5, IRQ_TIMER0); |
70 | |||
71 | s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs)); | ||
72 | } | 47 | } |
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index 9843c954c042..9a197e55f669 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig | |||
@@ -22,7 +22,6 @@ config PLAT_S5P | |||
22 | select PLAT_SAMSUNG | 22 | select PLAT_SAMSUNG |
23 | select SAMSUNG_CLKSRC | 23 | select SAMSUNG_CLKSRC |
24 | select SAMSUNG_IRQ_VIC_TIMER | 24 | select SAMSUNG_IRQ_VIC_TIMER |
25 | select SAMSUNG_IRQ_UART | ||
26 | help | 25 | help |
27 | Base platform code for Samsung's S5P series SoC. | 26 | Base platform code for Samsung's S5P series SoC. |
28 | 27 | ||
diff --git a/arch/arm/plat-s5p/dev-uart.c b/arch/arm/plat-s5p/dev-uart.c index afaf87fdb93e..c9308db36183 100644 --- a/arch/arm/plat-s5p/dev-uart.c +++ b/arch/arm/plat-s5p/dev-uart.c | |||
@@ -32,20 +32,10 @@ static struct resource s5p_uart0_resource[] = { | |||
32 | .flags = IORESOURCE_MEM, | 32 | .flags = IORESOURCE_MEM, |
33 | }, | 33 | }, |
34 | [1] = { | 34 | [1] = { |
35 | .start = IRQ_S5P_UART_RX0, | 35 | .start = IRQ_UART0, |
36 | .end = IRQ_S5P_UART_RX0, | 36 | .end = IRQ_UART0, |
37 | .flags = IORESOURCE_IRQ, | 37 | .flags = IORESOURCE_IRQ, |
38 | }, | 38 | }, |
39 | [2] = { | ||
40 | .start = IRQ_S5P_UART_TX0, | ||
41 | .end = IRQ_S5P_UART_TX0, | ||
42 | .flags = IORESOURCE_IRQ, | ||
43 | }, | ||
44 | [3] = { | ||
45 | .start = IRQ_S5P_UART_ERR0, | ||
46 | .end = IRQ_S5P_UART_ERR0, | ||
47 | .flags = IORESOURCE_IRQ, | ||
48 | } | ||
49 | }; | 39 | }; |
50 | 40 | ||
51 | static struct resource s5p_uart1_resource[] = { | 41 | static struct resource s5p_uart1_resource[] = { |
@@ -55,18 +45,8 @@ static struct resource s5p_uart1_resource[] = { | |||
55 | .flags = IORESOURCE_MEM, | 45 | .flags = IORESOURCE_MEM, |
56 | }, | 46 | }, |
57 | [1] = { | 47 | [1] = { |
58 | .start = IRQ_S5P_UART_RX1, | 48 | .start = IRQ_UART1, |
59 | .end = IRQ_S5P_UART_RX1, | 49 | .end = IRQ_UART1, |
60 | .flags = IORESOURCE_IRQ, | ||
61 | }, | ||
62 | [2] = { | ||
63 | .start = IRQ_S5P_UART_TX1, | ||
64 | .end = IRQ_S5P_UART_TX1, | ||
65 | .flags = IORESOURCE_IRQ, | ||
66 | }, | ||
67 | [3] = { | ||
68 | .start = IRQ_S5P_UART_ERR1, | ||
69 | .end = IRQ_S5P_UART_ERR1, | ||
70 | .flags = IORESOURCE_IRQ, | 50 | .flags = IORESOURCE_IRQ, |
71 | }, | 51 | }, |
72 | }; | 52 | }; |
@@ -78,18 +58,8 @@ static struct resource s5p_uart2_resource[] = { | |||
78 | .flags = IORESOURCE_MEM, | 58 | .flags = IORESOURCE_MEM, |
79 | }, | 59 | }, |
80 | [1] = { | 60 | [1] = { |
81 | .start = IRQ_S5P_UART_RX2, | 61 | .start = IRQ_UART2, |
82 | .end = IRQ_S5P_UART_RX2, | 62 | .end = IRQ_UART2, |
83 | .flags = IORESOURCE_IRQ, | ||
84 | }, | ||
85 | [2] = { | ||
86 | .start = IRQ_S5P_UART_TX2, | ||
87 | .end = IRQ_S5P_UART_TX2, | ||
88 | .flags = IORESOURCE_IRQ, | ||
89 | }, | ||
90 | [3] = { | ||
91 | .start = IRQ_S5P_UART_ERR2, | ||
92 | .end = IRQ_S5P_UART_ERR2, | ||
93 | .flags = IORESOURCE_IRQ, | 63 | .flags = IORESOURCE_IRQ, |
94 | }, | 64 | }, |
95 | }; | 65 | }; |
@@ -102,18 +72,8 @@ static struct resource s5p_uart3_resource[] = { | |||
102 | .flags = IORESOURCE_MEM, | 72 | .flags = IORESOURCE_MEM, |
103 | }, | 73 | }, |
104 | [1] = { | 74 | [1] = { |
105 | .start = IRQ_S5P_UART_RX3, | 75 | .start = IRQ_UART3, |
106 | .end = IRQ_S5P_UART_RX3, | 76 | .end = IRQ_UART3, |
107 | .flags = IORESOURCE_IRQ, | ||
108 | }, | ||
109 | [2] = { | ||
110 | .start = IRQ_S5P_UART_TX3, | ||
111 | .end = IRQ_S5P_UART_TX3, | ||
112 | .flags = IORESOURCE_IRQ, | ||
113 | }, | ||
114 | [3] = { | ||
115 | .start = IRQ_S5P_UART_ERR3, | ||
116 | .end = IRQ_S5P_UART_ERR3, | ||
117 | .flags = IORESOURCE_IRQ, | 77 | .flags = IORESOURCE_IRQ, |
118 | }, | 78 | }, |
119 | #endif | 79 | #endif |
@@ -127,18 +87,8 @@ static struct resource s5p_uart4_resource[] = { | |||
127 | .flags = IORESOURCE_MEM, | 87 | .flags = IORESOURCE_MEM, |
128 | }, | 88 | }, |
129 | [1] = { | 89 | [1] = { |
130 | .start = IRQ_S5P_UART_RX4, | 90 | .start = IRQ_UART4, |
131 | .end = IRQ_S5P_UART_RX4, | 91 | .end = IRQ_UART4, |
132 | .flags = IORESOURCE_IRQ, | ||
133 | }, | ||
134 | [2] = { | ||
135 | .start = IRQ_S5P_UART_TX4, | ||
136 | .end = IRQ_S5P_UART_TX4, | ||
137 | .flags = IORESOURCE_IRQ, | ||
138 | }, | ||
139 | [3] = { | ||
140 | .start = IRQ_S5P_UART_ERR4, | ||
141 | .end = IRQ_S5P_UART_ERR4, | ||
142 | .flags = IORESOURCE_IRQ, | 92 | .flags = IORESOURCE_IRQ, |
143 | }, | 93 | }, |
144 | #endif | 94 | #endif |
@@ -152,18 +102,8 @@ static struct resource s5p_uart5_resource[] = { | |||
152 | .flags = IORESOURCE_MEM, | 102 | .flags = IORESOURCE_MEM, |
153 | }, | 103 | }, |
154 | [1] = { | 104 | [1] = { |
155 | .start = IRQ_S5P_UART_RX5, | 105 | .start = IRQ_UART5, |
156 | .end = IRQ_S5P_UART_RX5, | 106 | .end = IRQ_UART5, |
157 | .flags = IORESOURCE_IRQ, | ||
158 | }, | ||
159 | [2] = { | ||
160 | .start = IRQ_S5P_UART_TX5, | ||
161 | .end = IRQ_S5P_UART_TX5, | ||
162 | .flags = IORESOURCE_IRQ, | ||
163 | }, | ||
164 | [3] = { | ||
165 | .start = IRQ_S5P_UART_ERR5, | ||
166 | .end = IRQ_S5P_UART_ERR5, | ||
167 | .flags = IORESOURCE_IRQ, | 107 | .flags = IORESOURCE_IRQ, |
168 | }, | 108 | }, |
169 | #endif | 109 | #endif |
diff --git a/arch/arm/plat-s5p/include/plat/irqs.h b/arch/arm/plat-s5p/include/plat/irqs.h index ba9121c60a2a..144dbfc6506d 100644 --- a/arch/arm/plat-s5p/include/plat/irqs.h +++ b/arch/arm/plat-s5p/include/plat/irqs.h | |||
@@ -37,41 +37,6 @@ | |||
37 | #define IRQ_VIC1_BASE S5P_VIC1_BASE | 37 | #define IRQ_VIC1_BASE S5P_VIC1_BASE |
38 | #define IRQ_VIC2_BASE S5P_VIC2_BASE | 38 | #define IRQ_VIC2_BASE S5P_VIC2_BASE |
39 | 39 | ||
40 | /* UART interrupts, each UART has 4 intterupts per channel so | ||
41 | * use the space between the ISA and S3C main interrupts. Note, these | ||
42 | * are not in the same order as the S3C24XX series! */ | ||
43 | |||
44 | #define IRQ_S5P_UART_BASE0 (16) | ||
45 | #define IRQ_S5P_UART_BASE1 (20) | ||
46 | #define IRQ_S5P_UART_BASE2 (24) | ||
47 | #define IRQ_S5P_UART_BASE3 (28) | ||
48 | |||
49 | #define UART_IRQ_RXD (0) | ||
50 | #define UART_IRQ_ERR (1) | ||
51 | #define UART_IRQ_TXD (2) | ||
52 | |||
53 | #define IRQ_S5P_UART_RX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_RXD) | ||
54 | #define IRQ_S5P_UART_TX0 (IRQ_S5P_UART_BASE0 + UART_IRQ_TXD) | ||
55 | #define IRQ_S5P_UART_ERR0 (IRQ_S5P_UART_BASE0 + UART_IRQ_ERR) | ||
56 | |||
57 | #define IRQ_S5P_UART_RX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_RXD) | ||
58 | #define IRQ_S5P_UART_TX1 (IRQ_S5P_UART_BASE1 + UART_IRQ_TXD) | ||
59 | #define IRQ_S5P_UART_ERR1 (IRQ_S5P_UART_BASE1 + UART_IRQ_ERR) | ||
60 | |||
61 | #define IRQ_S5P_UART_RX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_RXD) | ||
62 | #define IRQ_S5P_UART_TX2 (IRQ_S5P_UART_BASE2 + UART_IRQ_TXD) | ||
63 | #define IRQ_S5P_UART_ERR2 (IRQ_S5P_UART_BASE2 + UART_IRQ_ERR) | ||
64 | |||
65 | #define IRQ_S5P_UART_RX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_RXD) | ||
66 | #define IRQ_S5P_UART_TX3 (IRQ_S5P_UART_BASE3 + UART_IRQ_TXD) | ||
67 | #define IRQ_S5P_UART_ERR3 (IRQ_S5P_UART_BASE3 + UART_IRQ_ERR) | ||
68 | |||
69 | /* S3C compatibilty defines */ | ||
70 | #define IRQ_S3CUART_RX0 IRQ_S5P_UART_RX0 | ||
71 | #define IRQ_S3CUART_RX1 IRQ_S5P_UART_RX1 | ||
72 | #define IRQ_S3CUART_RX2 IRQ_S5P_UART_RX2 | ||
73 | #define IRQ_S3CUART_RX3 IRQ_S5P_UART_RX3 | ||
74 | |||
75 | /* VIC based IRQs */ | 40 | /* VIC based IRQs */ |
76 | 41 | ||
77 | #define S5P_IRQ_VIC0(x) (S5P_VIC0_BASE + (x)) | 42 | #define S5P_IRQ_VIC0(x) (S5P_VIC0_BASE + (x)) |
diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c index a97c08957f49..afdaa1082b9f 100644 --- a/arch/arm/plat-s5p/irq.c +++ b/arch/arm/plat-s5p/irq.c | |||
@@ -17,42 +17,10 @@ | |||
17 | 17 | ||
18 | #include <asm/hardware/vic.h> | 18 | #include <asm/hardware/vic.h> |
19 | 19 | ||
20 | #include <linux/serial_core.h> | ||
21 | #include <mach/map.h> | 20 | #include <mach/map.h> |
22 | #include <plat/regs-timer.h> | 21 | #include <plat/regs-timer.h> |
23 | #include <plat/regs-serial.h> | ||
24 | #include <plat/cpu.h> | 22 | #include <plat/cpu.h> |
25 | #include <plat/irq-vic-timer.h> | 23 | #include <plat/irq-vic-timer.h> |
26 | #include <plat/irq-uart.h> | ||
27 | |||
28 | /* | ||
29 | * Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] | ||
30 | * are consecutive when looking up the interrupt in the demux routines. | ||
31 | */ | ||
32 | static struct s3c_uart_irq uart_irqs[] = { | ||
33 | [0] = { | ||
34 | .regs = S5P_VA_UART0, | ||
35 | .base_irq = IRQ_S5P_UART_BASE0, | ||
36 | .parent_irq = IRQ_UART0, | ||
37 | }, | ||
38 | [1] = { | ||
39 | .regs = S5P_VA_UART1, | ||
40 | .base_irq = IRQ_S5P_UART_BASE1, | ||
41 | .parent_irq = IRQ_UART1, | ||
42 | }, | ||
43 | [2] = { | ||
44 | .regs = S5P_VA_UART2, | ||
45 | .base_irq = IRQ_S5P_UART_BASE2, | ||
46 | .parent_irq = IRQ_UART2, | ||
47 | }, | ||
48 | #if CONFIG_SERIAL_SAMSUNG_UARTS > 3 | ||
49 | [3] = { | ||
50 | .regs = S5P_VA_UART3, | ||
51 | .base_irq = IRQ_S5P_UART_BASE3, | ||
52 | .parent_irq = IRQ_UART3, | ||
53 | }, | ||
54 | #endif | ||
55 | }; | ||
56 | 24 | ||
57 | void __init s5p_init_irq(u32 *vic, u32 num_vic) | 25 | void __init s5p_init_irq(u32 *vic, u32 num_vic) |
58 | { | 26 | { |
@@ -65,6 +33,4 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic) | |||
65 | #endif | 33 | #endif |
66 | 34 | ||
67 | s3c_init_vic_timer_irq(5, IRQ_TIMER0); | 35 | s3c_init_vic_timer_irq(5, IRQ_TIMER0); |
68 | |||
69 | s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs)); | ||
70 | } | 36 | } |
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index b3e10659e4b8..dffa37bc4a0b 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig | |||
@@ -65,11 +65,6 @@ config SAMSUNG_IRQ_VIC_TIMER | |||
65 | help | 65 | help |
66 | Internal configuration to build the VIC timer interrupt code. | 66 | Internal configuration to build the VIC timer interrupt code. |
67 | 67 | ||
68 | config SAMSUNG_IRQ_UART | ||
69 | bool | ||
70 | help | ||
71 | Internal configuration to build the IRQ UART demux code. | ||
72 | |||
73 | # options for gpio configuration support | 68 | # options for gpio configuration support |
74 | 69 | ||
75 | config SAMSUNG_GPIOLIB_4BIT | 70 | config SAMSUNG_GPIOLIB_4BIT |
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 853764ba8cc5..1105922342fe 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile | |||
@@ -21,7 +21,6 @@ obj-y += dev-asocdma.o | |||
21 | 21 | ||
22 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o | 22 | obj-$(CONFIG_SAMSUNG_CLKSRC) += clock-clksrc.o |
23 | 23 | ||
24 | obj-$(CONFIG_SAMSUNG_IRQ_UART) += irq-uart.o | ||
25 | obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o | 24 | obj-$(CONFIG_SAMSUNG_IRQ_VIC_TIMER) += irq-vic-timer.o |
26 | 25 | ||
27 | # ADC | 26 | # ADC |
diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h index bac36fa3becb..720734847027 100644 --- a/arch/arm/plat-samsung/include/plat/regs-serial.h +++ b/arch/arm/plat-samsung/include/plat/regs-serial.h | |||
@@ -186,6 +186,11 @@ | |||
186 | #define S3C64XX_UINTSP 0x34 | 186 | #define S3C64XX_UINTSP 0x34 |
187 | #define S3C64XX_UINTM 0x38 | 187 | #define S3C64XX_UINTM 0x38 |
188 | 188 | ||
189 | #define S3C64XX_UINTM_RXD (0) | ||
190 | #define S3C64XX_UINTM_TXD (2) | ||
191 | #define S3C64XX_UINTM_RXD_MSK (1 << S3C64XX_UINTM_RXD) | ||
192 | #define S3C64XX_UINTM_TXD_MSK (1 << S3C64XX_UINTM_TXD) | ||
193 | |||
189 | /* Following are specific to S5PV210 */ | 194 | /* Following are specific to S5PV210 */ |
190 | #define S5PV210_UCON_CLKMASK (1<<10) | 195 | #define S5PV210_UCON_CLKMASK (1<<10) |
191 | #define S5PV210_UCON_PCLK (0<<10) | 196 | #define S5PV210_UCON_PCLK (0<<10) |
diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c deleted file mode 100644 index 3014c7226bd1..000000000000 --- a/arch/arm/plat-samsung/irq-uart.c +++ /dev/null | |||
@@ -1,96 +0,0 @@ | |||
1 | /* arch/arm/plat-samsung/irq-uart.c | ||
2 | * originally part of arch/arm/plat-s3c64xx/irq.c | ||
3 | * | ||
4 | * Copyright 2008 Openmoko, Inc. | ||
5 | * Copyright 2008 Simtec Electronics | ||
6 | * Ben Dooks <ben@simtec.co.uk> | ||
7 | * http://armlinux.simtec.co.uk/ | ||
8 | * | ||
9 | * Samsung- UART Interrupt handling | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/serial_core.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #include <asm/mach/irq.h> | ||
23 | |||
24 | #include <mach/map.h> | ||
25 | #include <plat/irq-uart.h> | ||
26 | #include <plat/regs-serial.h> | ||
27 | #include <plat/cpu.h> | ||
28 | |||
29 | /* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3] | ||
30 | * are consecutive when looking up the interrupt in the demux routines. | ||
31 | */ | ||
32 | static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc) | ||
33 | { | ||
34 | struct s3c_uart_irq *uirq = desc->irq_data.handler_data; | ||
35 | struct irq_chip *chip = irq_get_chip(irq); | ||
36 | u32 pend = __raw_readl(uirq->regs + S3C64XX_UINTP); | ||
37 | int base = uirq->base_irq; | ||
38 | |||
39 | chained_irq_enter(chip, desc); | ||
40 | |||
41 | if (pend & (1 << 0)) | ||
42 | generic_handle_irq(base); | ||
43 | if (pend & (1 << 1)) | ||
44 | generic_handle_irq(base + 1); | ||
45 | if (pend & (1 << 2)) | ||
46 | generic_handle_irq(base + 2); | ||
47 | if (pend & (1 << 3)) | ||
48 | generic_handle_irq(base + 3); | ||
49 | |||
50 | chained_irq_exit(chip, desc); | ||
51 | } | ||
52 | |||
53 | static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq) | ||
54 | { | ||
55 | void __iomem *reg_base = uirq->regs; | ||
56 | struct irq_chip_generic *gc; | ||
57 | struct irq_chip_type *ct; | ||
58 | |||
59 | /* mask all interrupts at the start. */ | ||
60 | __raw_writel(0xf, reg_base + S3C64XX_UINTM); | ||
61 | |||
62 | gc = irq_alloc_generic_chip("s3c-uart", 1, uirq->base_irq, reg_base, | ||
63 | handle_level_irq); | ||
64 | |||
65 | if (!gc) { | ||
66 | pr_err("%s: irq_alloc_generic_chip for IRQ %u failed\n", | ||
67 | __func__, uirq->base_irq); | ||
68 | return; | ||
69 | } | ||
70 | |||
71 | ct = gc->chip_types; | ||
72 | ct->chip.irq_ack = irq_gc_ack_set_bit; | ||
73 | ct->chip.irq_mask = irq_gc_mask_set_bit; | ||
74 | ct->chip.irq_unmask = irq_gc_mask_clr_bit; | ||
75 | ct->regs.ack = S3C64XX_UINTP; | ||
76 | ct->regs.mask = S3C64XX_UINTM; | ||
77 | irq_setup_generic_chip(gc, IRQ_MSK(4), IRQ_GC_INIT_MASK_CACHE, | ||
78 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | ||
79 | |||
80 | irq_set_handler_data(uirq->parent_irq, uirq); | ||
81 | irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart); | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * s3c_init_uart_irqs() - initialise UART IRQs and the necessary demuxing | ||
86 | * @irq: The interrupt data for registering | ||
87 | * @nr_irqs: The number of interrupt descriptions in @irq. | ||
88 | * | ||
89 | * Register the UART interrupts specified by @irq including the demuxing | ||
90 | * routines. This supports the S3C6400 and newer style of devices. | ||
91 | */ | ||
92 | void __init s3c_init_uart_irqs(struct s3c_uart_irq *irq, unsigned int nr_irqs) | ||
93 | { | ||
94 | for (; nr_irqs > 0; nr_irqs--, irq++) | ||
95 | s3c_init_uart_irq(irq); | ||
96 | } | ||
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index 7ed7714573c8..d1f377f5d3b6 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig | |||
@@ -195,7 +195,7 @@ config UNIX98_PTYS | |||
195 | 195 | ||
196 | source "drivers/char/pcmcia/Kconfig" | 196 | source "drivers/char/pcmcia/Kconfig" |
197 | 197 | ||
198 | source "drivers/serial/Kconfig" | 198 | source "drivers/tty/serial/Kconfig" |
199 | 199 | ||
200 | source "drivers/i2c/Kconfig" | 200 | source "drivers/i2c/Kconfig" |
201 | 201 | ||
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_serial.c b/arch/mips/pmc-sierra/msp71xx/msp_serial.c index f7261628d8a6..a1c7c7da2336 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_serial.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_serial.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/serial.h> | 27 | #include <linux/serial.h> |
28 | #include <linux/serial_core.h> | 28 | #include <linux/serial_core.h> |
29 | #include <linux/serial_reg.h> | 29 | #include <linux/serial_reg.h> |
30 | #include <linux/slab.h> | ||
30 | 31 | ||
31 | #include <asm/bootinfo.h> | 32 | #include <asm/bootinfo.h> |
32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
@@ -38,6 +39,55 @@ | |||
38 | #include <msp_int.h> | 39 | #include <msp_int.h> |
39 | #include <msp_regs.h> | 40 | #include <msp_regs.h> |
40 | 41 | ||
42 | struct msp_uart_data { | ||
43 | int last_lcr; | ||
44 | }; | ||
45 | |||
46 | static void msp_serial_out(struct uart_port *p, int offset, int value) | ||
47 | { | ||
48 | struct msp_uart_data *d = p->private_data; | ||
49 | |||
50 | if (offset == UART_LCR) | ||
51 | d->last_lcr = value; | ||
52 | |||
53 | offset <<= p->regshift; | ||
54 | writeb(value, p->membase + offset); | ||
55 | } | ||
56 | |||
57 | static unsigned int msp_serial_in(struct uart_port *p, int offset) | ||
58 | { | ||
59 | offset <<= p->regshift; | ||
60 | |||
61 | return readb(p->membase + offset); | ||
62 | } | ||
63 | |||
64 | static int msp_serial_handle_irq(struct uart_port *p) | ||
65 | { | ||
66 | struct msp_uart_data *d = p->private_data; | ||
67 | unsigned int iir = readb(p->membase + (UART_IIR << p->regshift)); | ||
68 | |||
69 | if (serial8250_handle_irq(p, iir)) { | ||
70 | return 1; | ||
71 | } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { | ||
72 | /* | ||
73 | * The DesignWare APB UART has an Busy Detect (0x07) interrupt | ||
74 | * meaning an LCR write attempt occurred while the UART was | ||
75 | * busy. The interrupt must be cleared by reading the UART | ||
76 | * status register (USR) and the LCR re-written. | ||
77 | * | ||
78 | * Note: MSP reserves 0x20 bytes of address space for the UART | ||
79 | * and the USR is mapped in a separate block at an offset of | ||
80 | * 0xc0 from the start of the UART. | ||
81 | */ | ||
82 | (void)readb(p->membase + 0xc0); | ||
83 | writeb(d->last_lcr, p->membase + (UART_LCR << p->regshift)); | ||
84 | |||
85 | return 1; | ||
86 | } | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
41 | void __init msp_serial_setup(void) | 91 | void __init msp_serial_setup(void) |
42 | { | 92 | { |
43 | char *s; | 93 | char *s; |
@@ -59,13 +109,22 @@ void __init msp_serial_setup(void) | |||
59 | up.irq = MSP_INT_UART0; | 109 | up.irq = MSP_INT_UART0; |
60 | up.uartclk = uartclk; | 110 | up.uartclk = uartclk; |
61 | up.regshift = 2; | 111 | up.regshift = 2; |
62 | up.iotype = UPIO_DWAPB; /* UPIO_MEM like */ | 112 | up.iotype = UPIO_MEM; |
63 | up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; | 113 | up.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; |
64 | up.type = PORT_16550A; | 114 | up.type = PORT_16550A; |
65 | up.line = 0; | 115 | up.line = 0; |
66 | up.private_data = (void*)UART0_STATUS_REG; | 116 | up.serial_out = msp_serial_out; |
67 | if (early_serial_setup(&up)) | 117 | up.serial_in = msp_serial_in; |
68 | printk(KERN_ERR "Early serial init of port 0 failed\n"); | 118 | up.handle_irq = msp_serial_handle_irq; |
119 | up.private_data = kzalloc(sizeof(struct msp_uart_data), GFP_KERNEL); | ||
120 | if (!up.private_data) { | ||
121 | pr_err("failed to allocate uart private data\n"); | ||
122 | return; | ||
123 | } | ||
124 | if (early_serial_setup(&up)) { | ||
125 | kfree(up.private_data); | ||
126 | pr_err("Early serial init of port 0 failed\n"); | ||
127 | } | ||
69 | 128 | ||
70 | /* Initialize the second serial port, if one exists */ | 129 | /* Initialize the second serial port, if one exists */ |
71 | switch (mips_machtype) { | 130 | switch (mips_machtype) { |
@@ -88,6 +147,8 @@ void __init msp_serial_setup(void) | |||
88 | up.irq = MSP_INT_UART1; | 147 | up.irq = MSP_INT_UART1; |
89 | up.line = 1; | 148 | up.line = 1; |
90 | up.private_data = (void*)UART1_STATUS_REG; | 149 | up.private_data = (void*)UART1_STATUS_REG; |
91 | if (early_serial_setup(&up)) | 150 | if (early_serial_setup(&up)) { |
92 | printk(KERN_ERR "Early serial init of port 1 failed\n"); | 151 | kfree(up.private_data); |
152 | pr_err("Early serial init of port 1 failed\n"); | ||
153 | } | ||
93 | } | 154 | } |
diff --git a/arch/powerpc/include/asm/udbg.h b/arch/powerpc/include/asm/udbg.h index 93e05d1b34b2..5354ae91bdde 100644 --- a/arch/powerpc/include/asm/udbg.h +++ b/arch/powerpc/include/asm/udbg.h | |||
@@ -54,6 +54,7 @@ extern void __init udbg_init_40x_realmode(void); | |||
54 | extern void __init udbg_init_cpm(void); | 54 | extern void __init udbg_init_cpm(void); |
55 | extern void __init udbg_init_usbgecko(void); | 55 | extern void __init udbg_init_usbgecko(void); |
56 | extern void __init udbg_init_wsp(void); | 56 | extern void __init udbg_init_wsp(void); |
57 | extern void __init udbg_init_ehv_bc(void); | ||
57 | 58 | ||
58 | #endif /* __KERNEL__ */ | 59 | #endif /* __KERNEL__ */ |
59 | #endif /* _ASM_POWERPC_UDBG_H */ | 60 | #endif /* _ASM_POWERPC_UDBG_H */ |
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index faa82c1f3f68..b4607a91d1f4 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c | |||
@@ -67,6 +67,8 @@ void __init udbg_early_init(void) | |||
67 | udbg_init_usbgecko(); | 67 | udbg_init_usbgecko(); |
68 | #elif defined(CONFIG_PPC_EARLY_DEBUG_WSP) | 68 | #elif defined(CONFIG_PPC_EARLY_DEBUG_WSP) |
69 | udbg_init_wsp(); | 69 | udbg_init_wsp(); |
70 | #elif defined(CONFIG_PPC_EARLY_DEBUG_EHV_BC) | ||
71 | udbg_init_ehv_bc(); | ||
70 | #endif | 72 | #endif |
71 | 73 | ||
72 | #ifdef CONFIG_PPC_EARLY_DEBUG | 74 | #ifdef CONFIG_PPC_EARLY_DEBUG |
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index fe73276e026b..e6379526675b 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/scatterlist.h> | ||
17 | #include <linux/sfi.h> | 19 | #include <linux/sfi.h> |
18 | #include <linux/intel_pmic_gpio.h> | 20 | #include <linux/intel_pmic_gpio.h> |
19 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
@@ -392,6 +394,7 @@ static void __init *max3111_platform_data(void *info) | |||
392 | struct spi_board_info *spi_info = info; | 394 | struct spi_board_info *spi_info = info; |
393 | int intr = get_gpio_by_name("max3111_int"); | 395 | int intr = get_gpio_by_name("max3111_int"); |
394 | 396 | ||
397 | spi_info->mode = SPI_MODE_0; | ||
395 | if (intr == -1) | 398 | if (intr == -1) |
396 | return NULL; | 399 | return NULL; |
397 | spi_info->irq = intr + MRST_IRQ_OFFSET; | 400 | spi_info->irq = intr + MRST_IRQ_OFFSET; |
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index d8504279e502..e5546cb3ac69 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c | |||
@@ -1693,7 +1693,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) | |||
1693 | * line status register. | 1693 | * line status register. |
1694 | */ | 1694 | */ |
1695 | if (info->flags & ISDN_ASYNC_INITIALIZED) { | 1695 | if (info->flags & ISDN_ASYNC_INITIALIZED) { |
1696 | tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ | 1696 | tty_wait_until_sent_from_close(tty, 3000); /* 30 seconds timeout */ |
1697 | /* | 1697 | /* |
1698 | * Before we drop DTR, make sure the UART transmitter | 1698 | * Before we drop DTR, make sure the UART transmitter |
1699 | * has completely drained; this is especially | 1699 | * has completely drained; this is especially |
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index d1cdb9449f84..d0b597b50398 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
@@ -2595,14 +2595,17 @@ static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, | |||
2595 | break; | 2595 | break; |
2596 | case 0x6: | 2596 | case 0x6: |
2597 | printk(KERN_INFO "parport_pc: ITE8873 found (1S)\n"); | 2597 | printk(KERN_INFO "parport_pc: ITE8873 found (1S)\n"); |
2598 | release_region(inta_addr[i], 32); | ||
2598 | return 0; | 2599 | return 0; |
2599 | case 0x8: | 2600 | case 0x8: |
2600 | printk(KERN_INFO "parport_pc: ITE8874 found (2S)\n"); | 2601 | printk(KERN_INFO "parport_pc: ITE8874 found (2S)\n"); |
2602 | release_region(inta_addr[i], 32); | ||
2601 | return 0; | 2603 | return 0; |
2602 | default: | 2604 | default: |
2603 | printk(KERN_INFO "parport_pc: unknown ITE887x\n"); | 2605 | printk(KERN_INFO "parport_pc: unknown ITE887x\n"); |
2604 | printk(KERN_INFO "parport_pc: please mail 'lspci -nvv' " | 2606 | printk(KERN_INFO "parport_pc: please mail 'lspci -nvv' " |
2605 | "output to Rich.Liu@ite.com.tw\n"); | 2607 | "output to Rich.Liu@ite.com.tw\n"); |
2608 | release_region(inta_addr[i], 32); | ||
2606 | return 0; | 2609 | return 0; |
2607 | } | 2610 | } |
2608 | 2611 | ||
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 2582e1890335..036d9de041b8 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -24,6 +24,8 @@ menuconfig STAGING | |||
24 | 24 | ||
25 | if STAGING | 25 | if STAGING |
26 | 26 | ||
27 | source "drivers/staging/serial/Kconfig" | ||
28 | |||
27 | source "drivers/staging/et131x/Kconfig" | 29 | source "drivers/staging/et131x/Kconfig" |
28 | 30 | ||
29 | source "drivers/staging/slicoss/Kconfig" | 31 | source "drivers/staging/slicoss/Kconfig" |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 50d112fe4ca1..0599509ff4f7 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -3,6 +3,7 @@ | |||
3 | # fix for build system bug... | 3 | # fix for build system bug... |
4 | obj-$(CONFIG_STAGING) += staging.o | 4 | obj-$(CONFIG_STAGING) += staging.o |
5 | 5 | ||
6 | obj-y += serial/ | ||
6 | obj-$(CONFIG_ET131X) += et131x/ | 7 | obj-$(CONFIG_ET131X) += et131x/ |
7 | obj-$(CONFIG_SLICOSS) += slicoss/ | 8 | obj-$(CONFIG_SLICOSS) += slicoss/ |
8 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ | 9 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ |
diff --git a/drivers/tty/serial/68360serial.c b/drivers/staging/serial/68360serial.c index 0a3e8787ed50..0a3e8787ed50 100644 --- a/drivers/tty/serial/68360serial.c +++ b/drivers/staging/serial/68360serial.c | |||
diff --git a/drivers/staging/serial/Kconfig b/drivers/staging/serial/Kconfig new file mode 100644 index 000000000000..9489688397e0 --- /dev/null +++ b/drivers/staging/serial/Kconfig | |||
@@ -0,0 +1,16 @@ | |||
1 | config SERIAL_68360_SMC | ||
2 | bool "68360 SMC uart support" | ||
3 | depends on M68360 | ||
4 | help | ||
5 | This driver supports the SMC serial ports of the Motorola 68360 CPU. | ||
6 | |||
7 | config SERIAL_68360_SCC | ||
8 | bool "68360 SCC uart support" | ||
9 | depends on M68360 | ||
10 | help | ||
11 | This driver supports the SCC serial ports of the Motorola 68360 CPU. | ||
12 | |||
13 | config SERIAL_68360 | ||
14 | bool | ||
15 | depends on SERIAL_68360_SMC || SERIAL_68360_SCC | ||
16 | default y | ||
diff --git a/drivers/staging/serial/Makefile b/drivers/staging/serial/Makefile new file mode 100644 index 000000000000..37a6a0b35fba --- /dev/null +++ b/drivers/staging/serial/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_SERIAL_68360) += 68360serial.o | |||
diff --git a/drivers/staging/serial/TODO b/drivers/staging/serial/TODO new file mode 100644 index 000000000000..a19cda81dab4 --- /dev/null +++ b/drivers/staging/serial/TODO | |||
@@ -0,0 +1,6 @@ | |||
1 | These are a few serial drivers that either do not build, or do not work if they | ||
2 | do build, or if they seem to work, are for obsolete hardware, or are full of | ||
3 | unfixable races and no one uses them anymore. | ||
4 | |||
5 | If no one steps up to adopt any of these drivers, they will be removed | ||
6 | in the 3.4 release. | ||
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index 33175504bb39..8816f53e004d 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig | |||
@@ -354,3 +354,37 @@ config TRACE_SINK | |||
354 | 354 | ||
355 | If you select this option, you need to select | 355 | If you select this option, you need to select |
356 | "Trace data router for MIPI P1149.7 cJTAG standard". | 356 | "Trace data router for MIPI P1149.7 cJTAG standard". |
357 | |||
358 | config PPC_EPAPR_HV_BYTECHAN | ||
359 | tristate "ePAPR hypervisor byte channel driver" | ||
360 | depends on PPC | ||
361 | help | ||
362 | This driver creates /dev entries for each ePAPR hypervisor byte | ||
363 | channel, thereby allowing applications to communicate with byte | ||
364 | channels as if they were serial ports. | ||
365 | |||
366 | config PPC_EARLY_DEBUG_EHV_BC | ||
367 | bool "Early console (udbg) support for ePAPR hypervisors" | ||
368 | depends on PPC_EPAPR_HV_BYTECHAN | ||
369 | help | ||
370 | Select this option to enable early console (a.k.a. "udbg") support | ||
371 | via an ePAPR byte channel. You also need to choose the byte channel | ||
372 | handle below. | ||
373 | |||
374 | config PPC_EARLY_DEBUG_EHV_BC_HANDLE | ||
375 | int "Byte channel handle for early console (udbg)" | ||
376 | depends on PPC_EARLY_DEBUG_EHV_BC | ||
377 | default 0 | ||
378 | help | ||
379 | If you want early console (udbg) output through a byte channel, | ||
380 | specify the handle of the byte channel to use. | ||
381 | |||
382 | For this to work, the byte channel driver must be compiled | ||
383 | in-kernel, not as a module. | ||
384 | |||
385 | Note that only one early console driver can be enabled, so don't | ||
386 | enable any others if you enable this one. | ||
387 | |||
388 | If the number you specify is not a valid byte channel handle, then | ||
389 | there simply will be no early console output. This is true also | ||
390 | if you don't boot under a hypervisor at all. | ||
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile index ea89b0bd15fe..2953059530e4 100644 --- a/drivers/tty/Makefile +++ b/drivers/tty/Makefile | |||
@@ -26,5 +26,6 @@ obj-$(CONFIG_ROCKETPORT) += rocket.o | |||
26 | obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o | 26 | obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o |
27 | obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o | 27 | obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o |
28 | obj-$(CONFIG_SYNCLINK) += synclink.o | 28 | obj-$(CONFIG_SYNCLINK) += synclink.o |
29 | obj-$(CONFIG_PPC_EPAPR_HV_BYTECHAN) += ehv_bytechan.o | ||
29 | 30 | ||
30 | obj-y += ipwireless/ | 31 | obj-y += ipwireless/ |
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c index 220579592c20..b84c83456dcc 100644 --- a/drivers/tty/amiserial.c +++ b/drivers/tty/amiserial.c | |||
@@ -1529,7 +1529,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1529 | { | 1529 | { |
1530 | struct async_struct * info = tty->driver_data; | 1530 | struct async_struct * info = tty->driver_data; |
1531 | unsigned long orig_jiffies, char_time; | 1531 | unsigned long orig_jiffies, char_time; |
1532 | int tty_was_locked = tty_locked(); | ||
1533 | int lsr; | 1532 | int lsr; |
1534 | 1533 | ||
1535 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) | 1534 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) |
@@ -1541,12 +1540,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1541 | orig_jiffies = jiffies; | 1540 | orig_jiffies = jiffies; |
1542 | 1541 | ||
1543 | /* | 1542 | /* |
1544 | * tty_wait_until_sent is called from lots of places, | ||
1545 | * with or without the BTM. | ||
1546 | */ | ||
1547 | if (!tty_was_locked) | ||
1548 | tty_lock(); | ||
1549 | /* | ||
1550 | * Set the check interval to be 1/5 of the estimated time to | 1543 | * Set the check interval to be 1/5 of the estimated time to |
1551 | * send a single character, and make it at least 1. The check | 1544 | * send a single character, and make it at least 1. The check |
1552 | * interval should also be less than the timeout. | 1545 | * interval should also be less than the timeout. |
@@ -1586,8 +1579,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1586 | break; | 1579 | break; |
1587 | } | 1580 | } |
1588 | __set_current_state(TASK_RUNNING); | 1581 | __set_current_state(TASK_RUNNING); |
1589 | if (!tty_was_locked) | 1582 | |
1590 | tty_unlock(); | ||
1591 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 1583 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
1592 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 1584 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); |
1593 | #endif | 1585 | #endif |
@@ -2025,7 +2017,7 @@ static int __init amiga_serial_probe(struct platform_device *pdev) | |||
2025 | if (error) | 2017 | if (error) |
2026 | goto fail_unregister; | 2018 | goto fail_unregister; |
2027 | 2019 | ||
2028 | error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED, | 2020 | error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, 0, |
2029 | "serial RX", state); | 2021 | "serial RX", state); |
2030 | if (error) | 2022 | if (error) |
2031 | goto fail_free_irq; | 2023 | goto fail_free_irq; |
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c index c0e8f2eeb886..c9bf779481d8 100644 --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #undef CY_DEBUG_IO | 45 | #undef CY_DEBUG_IO |
46 | #undef CY_DEBUG_COUNT | 46 | #undef CY_DEBUG_COUNT |
47 | #undef CY_DEBUG_DTR | 47 | #undef CY_DEBUG_DTR |
48 | #undef CY_DEBUG_WAIT_UNTIL_SENT | ||
49 | #undef CY_DEBUG_INTERRUPTS | 48 | #undef CY_DEBUG_INTERRUPTS |
50 | #undef CY_16Y_HACK | 49 | #undef CY_16Y_HACK |
51 | #undef CY_ENABLE_MONITORING | 50 | #undef CY_ENABLE_MONITORING |
@@ -1678,16 +1677,10 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1678 | */ | 1677 | */ |
1679 | if (!timeout || timeout > 2 * info->timeout) | 1678 | if (!timeout || timeout > 2 * info->timeout) |
1680 | timeout = 2 * info->timeout; | 1679 | timeout = 2 * info->timeout; |
1681 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT | 1680 | |
1682 | printk(KERN_DEBUG "In cy_wait_until_sent(%d) check=%d, jiff=%lu...", | ||
1683 | timeout, char_time, jiffies); | ||
1684 | #endif | ||
1685 | card = info->card; | 1681 | card = info->card; |
1686 | if (!cy_is_Z(card)) { | 1682 | if (!cy_is_Z(card)) { |
1687 | while (cyy_readb(info, CySRER) & CyTxRdy) { | 1683 | while (cyy_readb(info, CySRER) & CyTxRdy) { |
1688 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT | ||
1689 | printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies); | ||
1690 | #endif | ||
1691 | if (msleep_interruptible(jiffies_to_msecs(char_time))) | 1684 | if (msleep_interruptible(jiffies_to_msecs(char_time))) |
1692 | break; | 1685 | break; |
1693 | if (timeout && time_after(jiffies, orig_jiffies + | 1686 | if (timeout && time_after(jiffies, orig_jiffies + |
@@ -1697,9 +1690,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1697 | } | 1690 | } |
1698 | /* Run one more char cycle */ | 1691 | /* Run one more char cycle */ |
1699 | msleep_interruptible(jiffies_to_msecs(char_time * 5)); | 1692 | msleep_interruptible(jiffies_to_msecs(char_time * 5)); |
1700 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT | ||
1701 | printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); | ||
1702 | #endif | ||
1703 | } | 1693 | } |
1704 | 1694 | ||
1705 | static void cy_flush_buffer(struct tty_struct *tty) | 1695 | static void cy_flush_buffer(struct tty_struct *tty) |
@@ -3377,7 +3367,7 @@ static int __init cy_detect_isa(void) | |||
3377 | 3367 | ||
3378 | /* allocate IRQ */ | 3368 | /* allocate IRQ */ |
3379 | if (request_irq(cy_isa_irq, cyy_interrupt, | 3369 | if (request_irq(cy_isa_irq, cyy_interrupt, |
3380 | IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) { | 3370 | 0, "Cyclom-Y", &cy_card[j])) { |
3381 | printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but " | 3371 | printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but " |
3382 | "could not allocate IRQ#%d.\n", | 3372 | "could not allocate IRQ#%d.\n", |
3383 | (unsigned long)cy_isa_address, cy_isa_irq); | 3373 | (unsigned long)cy_isa_address, cy_isa_irq); |
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c new file mode 100644 index 000000000000..1595dba0072c --- /dev/null +++ b/drivers/tty/ehv_bytechan.c | |||
@@ -0,0 +1,881 @@ | |||
1 | /* ePAPR hypervisor byte channel device driver | ||
2 | * | ||
3 | * Copyright 2009-2011 Freescale Semiconductor, Inc. | ||
4 | * | ||
5 | * Author: Timur Tabi <timur@freescale.com> | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public License | ||
8 | * version 2. This program is licensed "as is" without any warranty of any | ||
9 | * kind, whether express or implied. | ||
10 | * | ||
11 | * This driver support three distinct interfaces, all of which are related to | ||
12 | * ePAPR hypervisor byte channels. | ||
13 | * | ||
14 | * 1) An early-console (udbg) driver. This provides early console output | ||
15 | * through a byte channel. The byte channel handle must be specified in a | ||
16 | * Kconfig option. | ||
17 | * | ||
18 | * 2) A normal console driver. Output is sent to the byte channel designated | ||
19 | * for stdout in the device tree. The console driver is for handling kernel | ||
20 | * printk calls. | ||
21 | * | ||
22 | * 3) A tty driver, which is used to handle user-space input and output. The | ||
23 | * byte channel used for the console is designated as the default tty. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/err.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <linux/fs.h> | ||
32 | #include <linux/poll.h> | ||
33 | #include <asm/epapr_hcalls.h> | ||
34 | #include <linux/of.h> | ||
35 | #include <linux/platform_device.h> | ||
36 | #include <linux/cdev.h> | ||
37 | #include <linux/console.h> | ||
38 | #include <linux/tty.h> | ||
39 | #include <linux/tty_flip.h> | ||
40 | #include <linux/circ_buf.h> | ||
41 | #include <asm/udbg.h> | ||
42 | |||
43 | /* The size of the transmit circular buffer. This must be a power of two. */ | ||
44 | #define BUF_SIZE 2048 | ||
45 | |||
46 | /* Per-byte channel private data */ | ||
47 | struct ehv_bc_data { | ||
48 | struct device *dev; | ||
49 | struct tty_port port; | ||
50 | uint32_t handle; | ||
51 | unsigned int rx_irq; | ||
52 | unsigned int tx_irq; | ||
53 | |||
54 | spinlock_t lock; /* lock for transmit buffer */ | ||
55 | unsigned char buf[BUF_SIZE]; /* transmit circular buffer */ | ||
56 | unsigned int head; /* circular buffer head */ | ||
57 | unsigned int tail; /* circular buffer tail */ | ||
58 | |||
59 | int tx_irq_enabled; /* true == TX interrupt is enabled */ | ||
60 | }; | ||
61 | |||
62 | /* Array of byte channel objects */ | ||
63 | static struct ehv_bc_data *bcs; | ||
64 | |||
65 | /* Byte channel handle for stdout (and stdin), taken from device tree */ | ||
66 | static unsigned int stdout_bc; | ||
67 | |||
68 | /* Virtual IRQ for the byte channel handle for stdin, taken from device tree */ | ||
69 | static unsigned int stdout_irq; | ||
70 | |||
71 | /**************************** SUPPORT FUNCTIONS ****************************/ | ||
72 | |||
73 | /* | ||
74 | * Enable the transmit interrupt | ||
75 | * | ||
76 | * Unlike a serial device, byte channels have no mechanism for disabling their | ||
77 | * own receive or transmit interrupts. To emulate that feature, we toggle | ||
78 | * the IRQ in the kernel. | ||
79 | * | ||
80 | * We cannot just blindly call enable_irq() or disable_irq(), because these | ||
81 | * calls are reference counted. This means that we cannot call enable_irq() | ||
82 | * if interrupts are already enabled. This can happen in two situations: | ||
83 | * | ||
84 | * 1. The tty layer makes two back-to-back calls to ehv_bc_tty_write() | ||
85 | * 2. A transmit interrupt occurs while executing ehv_bc_tx_dequeue() | ||
86 | * | ||
87 | * To work around this, we keep a flag to tell us if the IRQ is enabled or not. | ||
88 | */ | ||
89 | static void enable_tx_interrupt(struct ehv_bc_data *bc) | ||
90 | { | ||
91 | if (!bc->tx_irq_enabled) { | ||
92 | enable_irq(bc->tx_irq); | ||
93 | bc->tx_irq_enabled = 1; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static void disable_tx_interrupt(struct ehv_bc_data *bc) | ||
98 | { | ||
99 | if (bc->tx_irq_enabled) { | ||
100 | disable_irq_nosync(bc->tx_irq); | ||
101 | bc->tx_irq_enabled = 0; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * find the byte channel handle to use for the console | ||
107 | * | ||
108 | * The byte channel to be used for the console is specified via a "stdout" | ||
109 | * property in the /chosen node. | ||
110 | * | ||
111 | * For compatible with legacy device trees, we also look for a "stdout" alias. | ||
112 | */ | ||
113 | static int find_console_handle(void) | ||
114 | { | ||
115 | struct device_node *np, *np2; | ||
116 | const char *sprop = NULL; | ||
117 | const uint32_t *iprop; | ||
118 | |||
119 | np = of_find_node_by_path("/chosen"); | ||
120 | if (np) | ||
121 | sprop = of_get_property(np, "stdout-path", NULL); | ||
122 | |||
123 | if (!np || !sprop) { | ||
124 | of_node_put(np); | ||
125 | np = of_find_node_by_name(NULL, "aliases"); | ||
126 | if (np) | ||
127 | sprop = of_get_property(np, "stdout", NULL); | ||
128 | } | ||
129 | |||
130 | if (!sprop) { | ||
131 | of_node_put(np); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | /* We don't care what the aliased node is actually called. We only | ||
136 | * care if it's compatible with "epapr,hv-byte-channel", because that | ||
137 | * indicates that it's a byte channel node. We use a temporary | ||
138 | * variable, 'np2', because we can't release 'np' until we're done with | ||
139 | * 'sprop'. | ||
140 | */ | ||
141 | np2 = of_find_node_by_path(sprop); | ||
142 | of_node_put(np); | ||
143 | np = np2; | ||
144 | if (!np) { | ||
145 | pr_warning("ehv-bc: stdout node '%s' does not exist\n", sprop); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | /* Is it a byte channel? */ | ||
150 | if (!of_device_is_compatible(np, "epapr,hv-byte-channel")) { | ||
151 | of_node_put(np); | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | stdout_irq = irq_of_parse_and_map(np, 0); | ||
156 | if (stdout_irq == NO_IRQ) { | ||
157 | pr_err("ehv-bc: no 'interrupts' property in %s node\n", sprop); | ||
158 | of_node_put(np); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * The 'hv-handle' property contains the handle for this byte channel. | ||
164 | */ | ||
165 | iprop = of_get_property(np, "hv-handle", NULL); | ||
166 | if (!iprop) { | ||
167 | pr_err("ehv-bc: no 'hv-handle' property in %s node\n", | ||
168 | np->name); | ||
169 | of_node_put(np); | ||
170 | return 0; | ||
171 | } | ||
172 | stdout_bc = be32_to_cpu(*iprop); | ||
173 | |||
174 | of_node_put(np); | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | /*************************** EARLY CONSOLE DRIVER ***************************/ | ||
179 | |||
180 | #ifdef CONFIG_PPC_EARLY_DEBUG_EHV_BC | ||
181 | |||
182 | /* | ||
183 | * send a byte to a byte channel, wait if necessary | ||
184 | * | ||
185 | * This function sends a byte to a byte channel, and it waits and | ||
186 | * retries if the byte channel is full. It returns if the character | ||
187 | * has been sent, or if some error has occurred. | ||
188 | * | ||
189 | */ | ||
190 | static void byte_channel_spin_send(const char data) | ||
191 | { | ||
192 | int ret, count; | ||
193 | |||
194 | do { | ||
195 | count = 1; | ||
196 | ret = ev_byte_channel_send(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE, | ||
197 | &count, &data); | ||
198 | } while (ret == EV_EAGAIN); | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * The udbg subsystem calls this function to display a single character. | ||
203 | * We convert CR to a CR/LF. | ||
204 | */ | ||
205 | static void ehv_bc_udbg_putc(char c) | ||
206 | { | ||
207 | if (c == '\n') | ||
208 | byte_channel_spin_send('\r'); | ||
209 | |||
210 | byte_channel_spin_send(c); | ||
211 | } | ||
212 | |||
213 | /* | ||
214 | * early console initialization | ||
215 | * | ||
216 | * PowerPC kernels support an early printk console, also known as udbg. | ||
217 | * This function must be called via the ppc_md.init_early function pointer. | ||
218 | * At this point, the device tree has been unflattened, so we can obtain the | ||
219 | * byte channel handle for stdout. | ||
220 | * | ||
221 | * We only support displaying of characters (putc). We do not support | ||
222 | * keyboard input. | ||
223 | */ | ||
224 | void __init udbg_init_ehv_bc(void) | ||
225 | { | ||
226 | unsigned int rx_count, tx_count; | ||
227 | unsigned int ret; | ||
228 | |||
229 | /* Verify the byte channel handle */ | ||
230 | ret = ev_byte_channel_poll(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE, | ||
231 | &rx_count, &tx_count); | ||
232 | if (ret) | ||
233 | return; | ||
234 | |||
235 | udbg_putc = ehv_bc_udbg_putc; | ||
236 | register_early_udbg_console(); | ||
237 | |||
238 | udbg_printf("ehv-bc: early console using byte channel handle %u\n", | ||
239 | CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE); | ||
240 | } | ||
241 | |||
242 | #endif | ||
243 | |||
244 | /****************************** CONSOLE DRIVER ******************************/ | ||
245 | |||
246 | static struct tty_driver *ehv_bc_driver; | ||
247 | |||
248 | /* | ||
249 | * Byte channel console sending worker function. | ||
250 | * | ||
251 | * For consoles, if the output buffer is full, we should just spin until it | ||
252 | * clears. | ||
253 | */ | ||
254 | static int ehv_bc_console_byte_channel_send(unsigned int handle, const char *s, | ||
255 | unsigned int count) | ||
256 | { | ||
257 | unsigned int len; | ||
258 | int ret = 0; | ||
259 | |||
260 | while (count) { | ||
261 | len = min_t(unsigned int, count, EV_BYTE_CHANNEL_MAX_BYTES); | ||
262 | do { | ||
263 | ret = ev_byte_channel_send(handle, &len, s); | ||
264 | } while (ret == EV_EAGAIN); | ||
265 | count -= len; | ||
266 | s += len; | ||
267 | } | ||
268 | |||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * write a string to the console | ||
274 | * | ||
275 | * This function gets called to write a string from the kernel, typically from | ||
276 | * a printk(). This function spins until all data is written. | ||
277 | * | ||
278 | * We copy the data to a temporary buffer because we need to insert a \r in | ||
279 | * front of every \n. It's more efficient to copy the data to the buffer than | ||
280 | * it is to make multiple hcalls for each character or each newline. | ||
281 | */ | ||
282 | static void ehv_bc_console_write(struct console *co, const char *s, | ||
283 | unsigned int count) | ||
284 | { | ||
285 | char s2[EV_BYTE_CHANNEL_MAX_BYTES]; | ||
286 | unsigned int i, j = 0; | ||
287 | char c; | ||
288 | |||
289 | for (i = 0; i < count; i++) { | ||
290 | c = *s++; | ||
291 | |||
292 | if (c == '\n') | ||
293 | s2[j++] = '\r'; | ||
294 | |||
295 | s2[j++] = c; | ||
296 | if (j >= (EV_BYTE_CHANNEL_MAX_BYTES - 1)) { | ||
297 | if (ehv_bc_console_byte_channel_send(stdout_bc, s2, j)) | ||
298 | return; | ||
299 | j = 0; | ||
300 | } | ||
301 | } | ||
302 | |||
303 | if (j) | ||
304 | ehv_bc_console_byte_channel_send(stdout_bc, s2, j); | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * When /dev/console is opened, the kernel iterates the console list looking | ||
309 | * for one with ->device and then calls that method. On success, it expects | ||
310 | * the passed-in int* to contain the minor number to use. | ||
311 | */ | ||
312 | static struct tty_driver *ehv_bc_console_device(struct console *co, int *index) | ||
313 | { | ||
314 | *index = co->index; | ||
315 | |||
316 | return ehv_bc_driver; | ||
317 | } | ||
318 | |||
319 | static struct console ehv_bc_console = { | ||
320 | .name = "ttyEHV", | ||
321 | .write = ehv_bc_console_write, | ||
322 | .device = ehv_bc_console_device, | ||
323 | .flags = CON_PRINTBUFFER | CON_ENABLED, | ||
324 | }; | ||
325 | |||
326 | /* | ||
327 | * Console initialization | ||
328 | * | ||
329 | * This is the first function that is called after the device tree is | ||
330 | * available, so here is where we determine the byte channel handle and IRQ for | ||
331 | * stdout/stdin, even though that information is used by the tty and character | ||
332 | * drivers. | ||
333 | */ | ||
334 | static int __init ehv_bc_console_init(void) | ||
335 | { | ||
336 | if (!find_console_handle()) { | ||
337 | pr_debug("ehv-bc: stdout is not a byte channel\n"); | ||
338 | return -ENODEV; | ||
339 | } | ||
340 | |||
341 | #ifdef CONFIG_PPC_EARLY_DEBUG_EHV_BC | ||
342 | /* Print a friendly warning if the user chose the wrong byte channel | ||
343 | * handle for udbg. | ||
344 | */ | ||
345 | if (stdout_bc != CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE) | ||
346 | pr_warning("ehv-bc: udbg handle %u is not the stdout handle\n", | ||
347 | CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE); | ||
348 | #endif | ||
349 | |||
350 | /* add_preferred_console() must be called before register_console(), | ||
351 | otherwise it won't work. However, we don't want to enumerate all the | ||
352 | byte channels here, either, since we only care about one. */ | ||
353 | |||
354 | add_preferred_console(ehv_bc_console.name, ehv_bc_console.index, NULL); | ||
355 | register_console(&ehv_bc_console); | ||
356 | |||
357 | pr_info("ehv-bc: registered console driver for byte channel %u\n", | ||
358 | stdout_bc); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | console_initcall(ehv_bc_console_init); | ||
363 | |||
364 | /******************************** TTY DRIVER ********************************/ | ||
365 | |||
366 | /* | ||
367 | * byte channel receive interupt handler | ||
368 | * | ||
369 | * This ISR is called whenever data is available on a byte channel. | ||
370 | */ | ||
371 | static irqreturn_t ehv_bc_tty_rx_isr(int irq, void *data) | ||
372 | { | ||
373 | struct ehv_bc_data *bc = data; | ||
374 | struct tty_struct *ttys = tty_port_tty_get(&bc->port); | ||
375 | unsigned int rx_count, tx_count, len; | ||
376 | int count; | ||
377 | char buffer[EV_BYTE_CHANNEL_MAX_BYTES]; | ||
378 | int ret; | ||
379 | |||
380 | /* ttys could be NULL during a hangup */ | ||
381 | if (!ttys) | ||
382 | return IRQ_HANDLED; | ||
383 | |||
384 | /* Find out how much data needs to be read, and then ask the TTY layer | ||
385 | * if it can handle that much. We want to ensure that every byte we | ||
386 | * read from the byte channel will be accepted by the TTY layer. | ||
387 | */ | ||
388 | ev_byte_channel_poll(bc->handle, &rx_count, &tx_count); | ||
389 | count = tty_buffer_request_room(ttys, rx_count); | ||
390 | |||
391 | /* 'count' is the maximum amount of data the TTY layer can accept at | ||
392 | * this time. However, during testing, I was never able to get 'count' | ||
393 | * to be less than 'rx_count'. I'm not sure whether I'm calling it | ||
394 | * correctly. | ||
395 | */ | ||
396 | |||
397 | while (count > 0) { | ||
398 | len = min_t(unsigned int, count, sizeof(buffer)); | ||
399 | |||
400 | /* Read some data from the byte channel. This function will | ||
401 | * never return more than EV_BYTE_CHANNEL_MAX_BYTES bytes. | ||
402 | */ | ||
403 | ev_byte_channel_receive(bc->handle, &len, buffer); | ||
404 | |||
405 | /* 'len' is now the amount of data that's been received. 'len' | ||
406 | * can't be zero, and most likely it's equal to one. | ||
407 | */ | ||
408 | |||
409 | /* Pass the received data to the tty layer. */ | ||
410 | ret = tty_insert_flip_string(ttys, buffer, len); | ||
411 | |||
412 | /* 'ret' is the number of bytes that the TTY layer accepted. | ||
413 | * If it's not equal to 'len', then it means the buffer is | ||
414 | * full, which should never happen. If it does happen, we can | ||
415 | * exit gracefully, but we drop the last 'len - ret' characters | ||
416 | * that we read from the byte channel. | ||
417 | */ | ||
418 | if (ret != len) | ||
419 | break; | ||
420 | |||
421 | count -= len; | ||
422 | } | ||
423 | |||
424 | /* Tell the tty layer that we're done. */ | ||
425 | tty_flip_buffer_push(ttys); | ||
426 | |||
427 | tty_kref_put(ttys); | ||
428 | |||
429 | return IRQ_HANDLED; | ||
430 | } | ||
431 | |||
432 | /* | ||
433 | * dequeue the transmit buffer to the hypervisor | ||
434 | * | ||
435 | * This function, which can be called in interrupt context, dequeues as much | ||
436 | * data as possible from the transmit buffer to the byte channel. | ||
437 | */ | ||
438 | static void ehv_bc_tx_dequeue(struct ehv_bc_data *bc) | ||
439 | { | ||
440 | unsigned int count; | ||
441 | unsigned int len, ret; | ||
442 | unsigned long flags; | ||
443 | |||
444 | do { | ||
445 | spin_lock_irqsave(&bc->lock, flags); | ||
446 | len = min_t(unsigned int, | ||
447 | CIRC_CNT_TO_END(bc->head, bc->tail, BUF_SIZE), | ||
448 | EV_BYTE_CHANNEL_MAX_BYTES); | ||
449 | |||
450 | ret = ev_byte_channel_send(bc->handle, &len, bc->buf + bc->tail); | ||
451 | |||
452 | /* 'len' is valid only if the return code is 0 or EV_EAGAIN */ | ||
453 | if (!ret || (ret == EV_EAGAIN)) | ||
454 | bc->tail = (bc->tail + len) & (BUF_SIZE - 1); | ||
455 | |||
456 | count = CIRC_CNT(bc->head, bc->tail, BUF_SIZE); | ||
457 | spin_unlock_irqrestore(&bc->lock, flags); | ||
458 | } while (count && !ret); | ||
459 | |||
460 | spin_lock_irqsave(&bc->lock, flags); | ||
461 | if (CIRC_CNT(bc->head, bc->tail, BUF_SIZE)) | ||
462 | /* | ||
463 | * If we haven't emptied the buffer, then enable the TX IRQ. | ||
464 | * We'll get an interrupt when there's more room in the | ||
465 | * hypervisor's output buffer. | ||
466 | */ | ||
467 | enable_tx_interrupt(bc); | ||
468 | else | ||
469 | disable_tx_interrupt(bc); | ||
470 | spin_unlock_irqrestore(&bc->lock, flags); | ||
471 | } | ||
472 | |||
473 | /* | ||
474 | * byte channel transmit interupt handler | ||
475 | * | ||
476 | * This ISR is called whenever space becomes available for transmitting | ||
477 | * characters on a byte channel. | ||
478 | */ | ||
479 | static irqreturn_t ehv_bc_tty_tx_isr(int irq, void *data) | ||
480 | { | ||
481 | struct ehv_bc_data *bc = data; | ||
482 | struct tty_struct *ttys = tty_port_tty_get(&bc->port); | ||
483 | |||
484 | ehv_bc_tx_dequeue(bc); | ||
485 | if (ttys) { | ||
486 | tty_wakeup(ttys); | ||
487 | tty_kref_put(ttys); | ||
488 | } | ||
489 | |||
490 | return IRQ_HANDLED; | ||
491 | } | ||
492 | |||
493 | /* | ||
494 | * This function is called when the tty layer has data for us send. We store | ||
495 | * the data first in a circular buffer, and then dequeue as much of that data | ||
496 | * as possible. | ||
497 | * | ||
498 | * We don't need to worry about whether there is enough room in the buffer for | ||
499 | * all the data. The purpose of ehv_bc_tty_write_room() is to tell the tty | ||
500 | * layer how much data it can safely send to us. We guarantee that | ||
501 | * ehv_bc_tty_write_room() will never lie, so the tty layer will never send us | ||
502 | * too much data. | ||
503 | */ | ||
504 | static int ehv_bc_tty_write(struct tty_struct *ttys, const unsigned char *s, | ||
505 | int count) | ||
506 | { | ||
507 | struct ehv_bc_data *bc = ttys->driver_data; | ||
508 | unsigned long flags; | ||
509 | unsigned int len; | ||
510 | unsigned int written = 0; | ||
511 | |||
512 | while (1) { | ||
513 | spin_lock_irqsave(&bc->lock, flags); | ||
514 | len = CIRC_SPACE_TO_END(bc->head, bc->tail, BUF_SIZE); | ||
515 | if (count < len) | ||
516 | len = count; | ||
517 | if (len) { | ||
518 | memcpy(bc->buf + bc->head, s, len); | ||
519 | bc->head = (bc->head + len) & (BUF_SIZE - 1); | ||
520 | } | ||
521 | spin_unlock_irqrestore(&bc->lock, flags); | ||
522 | if (!len) | ||
523 | break; | ||
524 | |||
525 | s += len; | ||
526 | count -= len; | ||
527 | written += len; | ||
528 | } | ||
529 | |||
530 | ehv_bc_tx_dequeue(bc); | ||
531 | |||
532 | return written; | ||
533 | } | ||
534 | |||
535 | /* | ||
536 | * This function can be called multiple times for a given tty_struct, which is | ||
537 | * why we initialize bc->ttys in ehv_bc_tty_port_activate() instead. | ||
538 | * | ||
539 | * The tty layer will still call this function even if the device was not | ||
540 | * registered (i.e. tty_register_device() was not called). This happens | ||
541 | * because tty_register_device() is optional and some legacy drivers don't | ||
542 | * use it. So we need to check for that. | ||
543 | */ | ||
544 | static int ehv_bc_tty_open(struct tty_struct *ttys, struct file *filp) | ||
545 | { | ||
546 | struct ehv_bc_data *bc = &bcs[ttys->index]; | ||
547 | |||
548 | if (!bc->dev) | ||
549 | return -ENODEV; | ||
550 | |||
551 | return tty_port_open(&bc->port, ttys, filp); | ||
552 | } | ||
553 | |||
554 | /* | ||
555 | * Amazingly, if ehv_bc_tty_open() returns an error code, the tty layer will | ||
556 | * still call this function to close the tty device. So we can't assume that | ||
557 | * the tty port has been initialized. | ||
558 | */ | ||
559 | static void ehv_bc_tty_close(struct tty_struct *ttys, struct file *filp) | ||
560 | { | ||
561 | struct ehv_bc_data *bc = &bcs[ttys->index]; | ||
562 | |||
563 | if (bc->dev) | ||
564 | tty_port_close(&bc->port, ttys, filp); | ||
565 | } | ||
566 | |||
567 | /* | ||
568 | * Return the amount of space in the output buffer | ||
569 | * | ||
570 | * This is actually a contract between the driver and the tty layer outlining | ||
571 | * how much write room the driver can guarantee will be sent OR BUFFERED. This | ||
572 | * driver MUST honor the return value. | ||
573 | */ | ||
574 | static int ehv_bc_tty_write_room(struct tty_struct *ttys) | ||
575 | { | ||
576 | struct ehv_bc_data *bc = ttys->driver_data; | ||
577 | unsigned long flags; | ||
578 | int count; | ||
579 | |||
580 | spin_lock_irqsave(&bc->lock, flags); | ||
581 | count = CIRC_SPACE(bc->head, bc->tail, BUF_SIZE); | ||
582 | spin_unlock_irqrestore(&bc->lock, flags); | ||
583 | |||
584 | return count; | ||
585 | } | ||
586 | |||
587 | /* | ||
588 | * Stop sending data to the tty layer | ||
589 | * | ||
590 | * This function is called when the tty layer's input buffers are getting full, | ||
591 | * so the driver should stop sending it data. The easiest way to do this is to | ||
592 | * disable the RX IRQ, which will prevent ehv_bc_tty_rx_isr() from being | ||
593 | * called. | ||
594 | * | ||
595 | * The hypervisor will continue to queue up any incoming data. If there is any | ||
596 | * data in the queue when the RX interrupt is enabled, we'll immediately get an | ||
597 | * RX interrupt. | ||
598 | */ | ||
599 | static void ehv_bc_tty_throttle(struct tty_struct *ttys) | ||
600 | { | ||
601 | struct ehv_bc_data *bc = ttys->driver_data; | ||
602 | |||
603 | disable_irq(bc->rx_irq); | ||
604 | } | ||
605 | |||
606 | /* | ||
607 | * Resume sending data to the tty layer | ||
608 | * | ||
609 | * This function is called after previously calling ehv_bc_tty_throttle(). The | ||
610 | * tty layer's input buffers now have more room, so the driver can resume | ||
611 | * sending it data. | ||
612 | */ | ||
613 | static void ehv_bc_tty_unthrottle(struct tty_struct *ttys) | ||
614 | { | ||
615 | struct ehv_bc_data *bc = ttys->driver_data; | ||
616 | |||
617 | /* If there is any data in the queue when the RX interrupt is enabled, | ||
618 | * we'll immediately get an RX interrupt. | ||
619 | */ | ||
620 | enable_irq(bc->rx_irq); | ||
621 | } | ||
622 | |||
623 | static void ehv_bc_tty_hangup(struct tty_struct *ttys) | ||
624 | { | ||
625 | struct ehv_bc_data *bc = ttys->driver_data; | ||
626 | |||
627 | ehv_bc_tx_dequeue(bc); | ||
628 | tty_port_hangup(&bc->port); | ||
629 | } | ||
630 | |||
631 | /* | ||
632 | * TTY driver operations | ||
633 | * | ||
634 | * If we could ask the hypervisor how much data is still in the TX buffer, or | ||
635 | * at least how big the TX buffers are, then we could implement the | ||
636 | * .wait_until_sent and .chars_in_buffer functions. | ||
637 | */ | ||
638 | static const struct tty_operations ehv_bc_ops = { | ||
639 | .open = ehv_bc_tty_open, | ||
640 | .close = ehv_bc_tty_close, | ||
641 | .write = ehv_bc_tty_write, | ||
642 | .write_room = ehv_bc_tty_write_room, | ||
643 | .throttle = ehv_bc_tty_throttle, | ||
644 | .unthrottle = ehv_bc_tty_unthrottle, | ||
645 | .hangup = ehv_bc_tty_hangup, | ||
646 | }; | ||
647 | |||
648 | /* | ||
649 | * initialize the TTY port | ||
650 | * | ||
651 | * This function will only be called once, no matter how many times | ||
652 | * ehv_bc_tty_open() is called. That's why we register the ISR here, and also | ||
653 | * why we initialize tty_struct-related variables here. | ||
654 | */ | ||
655 | static int ehv_bc_tty_port_activate(struct tty_port *port, | ||
656 | struct tty_struct *ttys) | ||
657 | { | ||
658 | struct ehv_bc_data *bc = container_of(port, struct ehv_bc_data, port); | ||
659 | int ret; | ||
660 | |||
661 | ttys->driver_data = bc; | ||
662 | |||
663 | ret = request_irq(bc->rx_irq, ehv_bc_tty_rx_isr, 0, "ehv-bc", bc); | ||
664 | if (ret < 0) { | ||
665 | dev_err(bc->dev, "could not request rx irq %u (ret=%i)\n", | ||
666 | bc->rx_irq, ret); | ||
667 | return ret; | ||
668 | } | ||
669 | |||
670 | /* request_irq also enables the IRQ */ | ||
671 | bc->tx_irq_enabled = 1; | ||
672 | |||
673 | ret = request_irq(bc->tx_irq, ehv_bc_tty_tx_isr, 0, "ehv-bc", bc); | ||
674 | if (ret < 0) { | ||
675 | dev_err(bc->dev, "could not request tx irq %u (ret=%i)\n", | ||
676 | bc->tx_irq, ret); | ||
677 | free_irq(bc->rx_irq, bc); | ||
678 | return ret; | ||
679 | } | ||
680 | |||
681 | /* The TX IRQ is enabled only when we can't write all the data to the | ||
682 | * byte channel at once, so by default it's disabled. | ||
683 | */ | ||
684 | disable_tx_interrupt(bc); | ||
685 | |||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | static void ehv_bc_tty_port_shutdown(struct tty_port *port) | ||
690 | { | ||
691 | struct ehv_bc_data *bc = container_of(port, struct ehv_bc_data, port); | ||
692 | |||
693 | free_irq(bc->tx_irq, bc); | ||
694 | free_irq(bc->rx_irq, bc); | ||
695 | } | ||
696 | |||
697 | static const struct tty_port_operations ehv_bc_tty_port_ops = { | ||
698 | .activate = ehv_bc_tty_port_activate, | ||
699 | .shutdown = ehv_bc_tty_port_shutdown, | ||
700 | }; | ||
701 | |||
702 | static int __devinit ehv_bc_tty_probe(struct platform_device *pdev) | ||
703 | { | ||
704 | struct device_node *np = pdev->dev.of_node; | ||
705 | struct ehv_bc_data *bc; | ||
706 | const uint32_t *iprop; | ||
707 | unsigned int handle; | ||
708 | int ret; | ||
709 | static unsigned int index = 1; | ||
710 | unsigned int i; | ||
711 | |||
712 | iprop = of_get_property(np, "hv-handle", NULL); | ||
713 | if (!iprop) { | ||
714 | dev_err(&pdev->dev, "no 'hv-handle' property in %s node\n", | ||
715 | np->name); | ||
716 | return -ENODEV; | ||
717 | } | ||
718 | |||
719 | /* We already told the console layer that the index for the console | ||
720 | * device is zero, so we need to make sure that we use that index when | ||
721 | * we probe the console byte channel node. | ||
722 | */ | ||
723 | handle = be32_to_cpu(*iprop); | ||
724 | i = (handle == stdout_bc) ? 0 : index++; | ||
725 | bc = &bcs[i]; | ||
726 | |||
727 | bc->handle = handle; | ||
728 | bc->head = 0; | ||
729 | bc->tail = 0; | ||
730 | spin_lock_init(&bc->lock); | ||
731 | |||
732 | bc->rx_irq = irq_of_parse_and_map(np, 0); | ||
733 | bc->tx_irq = irq_of_parse_and_map(np, 1); | ||
734 | if ((bc->rx_irq == NO_IRQ) || (bc->tx_irq == NO_IRQ)) { | ||
735 | dev_err(&pdev->dev, "no 'interrupts' property in %s node\n", | ||
736 | np->name); | ||
737 | ret = -ENODEV; | ||
738 | goto error; | ||
739 | } | ||
740 | |||
741 | bc->dev = tty_register_device(ehv_bc_driver, i, &pdev->dev); | ||
742 | if (IS_ERR(bc->dev)) { | ||
743 | ret = PTR_ERR(bc->dev); | ||
744 | dev_err(&pdev->dev, "could not register tty (ret=%i)\n", ret); | ||
745 | goto error; | ||
746 | } | ||
747 | |||
748 | tty_port_init(&bc->port); | ||
749 | bc->port.ops = &ehv_bc_tty_port_ops; | ||
750 | |||
751 | dev_set_drvdata(&pdev->dev, bc); | ||
752 | |||
753 | dev_info(&pdev->dev, "registered /dev/%s%u for byte channel %u\n", | ||
754 | ehv_bc_driver->name, i, bc->handle); | ||
755 | |||
756 | return 0; | ||
757 | |||
758 | error: | ||
759 | irq_dispose_mapping(bc->tx_irq); | ||
760 | irq_dispose_mapping(bc->rx_irq); | ||
761 | |||
762 | memset(bc, 0, sizeof(struct ehv_bc_data)); | ||
763 | return ret; | ||
764 | } | ||
765 | |||
766 | static int ehv_bc_tty_remove(struct platform_device *pdev) | ||
767 | { | ||
768 | struct ehv_bc_data *bc = dev_get_drvdata(&pdev->dev); | ||
769 | |||
770 | tty_unregister_device(ehv_bc_driver, bc - bcs); | ||
771 | |||
772 | irq_dispose_mapping(bc->tx_irq); | ||
773 | irq_dispose_mapping(bc->rx_irq); | ||
774 | |||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | static const struct of_device_id ehv_bc_tty_of_ids[] = { | ||
779 | { .compatible = "epapr,hv-byte-channel" }, | ||
780 | {} | ||
781 | }; | ||
782 | |||
783 | static struct platform_driver ehv_bc_tty_driver = { | ||
784 | .driver = { | ||
785 | .owner = THIS_MODULE, | ||
786 | .name = "ehv-bc", | ||
787 | .of_match_table = ehv_bc_tty_of_ids, | ||
788 | }, | ||
789 | .probe = ehv_bc_tty_probe, | ||
790 | .remove = ehv_bc_tty_remove, | ||
791 | }; | ||
792 | |||
793 | /** | ||
794 | * ehv_bc_init - ePAPR hypervisor byte channel driver initialization | ||
795 | * | ||
796 | * This function is called when this module is loaded. | ||
797 | */ | ||
798 | static int __init ehv_bc_init(void) | ||
799 | { | ||
800 | struct device_node *np; | ||
801 | unsigned int count = 0; /* Number of elements in bcs[] */ | ||
802 | int ret; | ||
803 | |||
804 | pr_info("ePAPR hypervisor byte channel driver\n"); | ||
805 | |||
806 | /* Count the number of byte channels */ | ||
807 | for_each_compatible_node(np, NULL, "epapr,hv-byte-channel") | ||
808 | count++; | ||
809 | |||
810 | if (!count) | ||
811 | return -ENODEV; | ||
812 | |||
813 | /* The array index of an element in bcs[] is the same as the tty index | ||
814 | * for that element. If you know the address of an element in the | ||
815 | * array, then you can use pointer math (e.g. "bc - bcs") to get its | ||
816 | * tty index. | ||
817 | */ | ||
818 | bcs = kzalloc(count * sizeof(struct ehv_bc_data), GFP_KERNEL); | ||
819 | if (!bcs) | ||
820 | return -ENOMEM; | ||
821 | |||
822 | ehv_bc_driver = alloc_tty_driver(count); | ||
823 | if (!ehv_bc_driver) { | ||
824 | ret = -ENOMEM; | ||
825 | goto error; | ||
826 | } | ||
827 | |||
828 | ehv_bc_driver->owner = THIS_MODULE; | ||
829 | ehv_bc_driver->driver_name = "ehv-bc"; | ||
830 | ehv_bc_driver->name = ehv_bc_console.name; | ||
831 | ehv_bc_driver->type = TTY_DRIVER_TYPE_CONSOLE; | ||
832 | ehv_bc_driver->subtype = SYSTEM_TYPE_CONSOLE; | ||
833 | ehv_bc_driver->init_termios = tty_std_termios; | ||
834 | ehv_bc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | ||
835 | tty_set_operations(ehv_bc_driver, &ehv_bc_ops); | ||
836 | |||
837 | ret = tty_register_driver(ehv_bc_driver); | ||
838 | if (ret) { | ||
839 | pr_err("ehv-bc: could not register tty driver (ret=%i)\n", ret); | ||
840 | goto error; | ||
841 | } | ||
842 | |||
843 | ret = platform_driver_register(&ehv_bc_tty_driver); | ||
844 | if (ret) { | ||
845 | pr_err("ehv-bc: could not register platform driver (ret=%i)\n", | ||
846 | ret); | ||
847 | goto error; | ||
848 | } | ||
849 | |||
850 | return 0; | ||
851 | |||
852 | error: | ||
853 | if (ehv_bc_driver) { | ||
854 | tty_unregister_driver(ehv_bc_driver); | ||
855 | put_tty_driver(ehv_bc_driver); | ||
856 | } | ||
857 | |||
858 | kfree(bcs); | ||
859 | |||
860 | return ret; | ||
861 | } | ||
862 | |||
863 | |||
864 | /** | ||
865 | * ehv_bc_exit - ePAPR hypervisor byte channel driver termination | ||
866 | * | ||
867 | * This function is called when this driver is unloaded. | ||
868 | */ | ||
869 | static void __exit ehv_bc_exit(void) | ||
870 | { | ||
871 | tty_unregister_driver(ehv_bc_driver); | ||
872 | put_tty_driver(ehv_bc_driver); | ||
873 | kfree(bcs); | ||
874 | } | ||
875 | |||
876 | module_init(ehv_bc_init); | ||
877 | module_exit(ehv_bc_exit); | ||
878 | |||
879 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | ||
880 | MODULE_DESCRIPTION("ePAPR hypervisor byte channel driver"); | ||
881 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index e1aaf4f309b3..7430bc3c8d53 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c | |||
@@ -388,7 +388,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) | |||
388 | * there is no buffered data otherwise sleeps on a wait queue | 388 | * there is no buffered data otherwise sleeps on a wait queue |
389 | * waking periodically to check chars_in_buffer(). | 389 | * waking periodically to check chars_in_buffer(). |
390 | */ | 390 | */ |
391 | tty_wait_until_sent(tty, HVC_CLOSE_WAIT); | 391 | tty_wait_until_sent_from_close(tty, HVC_CLOSE_WAIT); |
392 | } else { | 392 | } else { |
393 | if (hp->count < 0) | 393 | if (hp->count < 0) |
394 | printk(KERN_ERR "hvc_close %X: oops, count is %d\n", | 394 | printk(KERN_ERR "hvc_close %X: oops, count is %d\n", |
@@ -852,7 +852,7 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, | |||
852 | * find index to use: | 852 | * find index to use: |
853 | * see if this vterm id matches one registered for console. | 853 | * see if this vterm id matches one registered for console. |
854 | */ | 854 | */ |
855 | for (i=0; i < MAX_NR_HVC_CONSOLES; i++) | 855 | for (i = 0; i < MAX_NR_HVC_CONSOLES; i++) |
856 | if (vtermnos[i] == hp->vtermno && | 856 | if (vtermnos[i] == hp->vtermno && |
857 | cons_ops[i] == hp->ops) | 857 | cons_ops[i] == hp->ops) |
858 | break; | 858 | break; |
@@ -862,9 +862,13 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, | |||
862 | i = ++last_hvc; | 862 | i = ++last_hvc; |
863 | 863 | ||
864 | hp->index = i; | 864 | hp->index = i; |
865 | hvc_console.index = i; | ||
866 | vtermnos[i] = vtermno; | ||
867 | cons_ops[i] = ops; | ||
865 | 868 | ||
866 | list_add_tail(&(hp->next), &hvc_structs); | 869 | list_add_tail(&(hp->next), &hvc_structs); |
867 | spin_unlock(&hvc_structs_lock); | 870 | spin_unlock(&hvc_structs_lock); |
871 | register_console(&hvc_console); | ||
868 | 872 | ||
869 | return hp; | 873 | return hp; |
870 | } | 874 | } |
@@ -875,6 +879,7 @@ int hvc_remove(struct hvc_struct *hp) | |||
875 | unsigned long flags; | 879 | unsigned long flags; |
876 | struct tty_struct *tty; | 880 | struct tty_struct *tty; |
877 | 881 | ||
882 | unregister_console(&hvc_console); | ||
878 | spin_lock_irqsave(&hp->lock, flags); | 883 | spin_lock_irqsave(&hp->lock, flags); |
879 | tty = tty_kref_get(hp->tty); | 884 | tty = tty_kref_get(hp->tty); |
880 | 885 | ||
diff --git a/drivers/tty/hvc/hvc_irq.c b/drivers/tty/hvc/hvc_irq.c index 2623e177e8d6..c9adb0559f61 100644 --- a/drivers/tty/hvc/hvc_irq.c +++ b/drivers/tty/hvc/hvc_irq.c | |||
@@ -28,7 +28,7 @@ int notifier_add_irq(struct hvc_struct *hp, int irq) | |||
28 | hp->irq_requested = 0; | 28 | hp->irq_requested = 0; |
29 | return 0; | 29 | return 0; |
30 | } | 30 | } |
31 | rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, | 31 | rc = request_irq(irq, hvc_handle_interrupt, 0, |
32 | "hvc_console", hp); | 32 | "hvc_console", hp); |
33 | if (!rc) | 33 | if (!rc) |
34 | hp->irq_requested = 1; | 34 | hp->irq_requested = 1; |
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index 4c8b66546930..55882b5930a6 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c | |||
@@ -1057,7 +1057,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, | |||
1057 | * the conn was registered and now. | 1057 | * the conn was registered and now. |
1058 | */ | 1058 | */ |
1059 | if (!(rc = request_irq(irq, &hvcs_handle_interrupt, | 1059 | if (!(rc = request_irq(irq, &hvcs_handle_interrupt, |
1060 | IRQF_DISABLED, "ibmhvcs", hvcsd))) { | 1060 | 0, "ibmhvcs", hvcsd))) { |
1061 | /* | 1061 | /* |
1062 | * It is possible the vty-server was removed after the irq was | 1062 | * It is possible the vty-server was removed after the irq was |
1063 | * requested but before we have time to enable interrupts. | 1063 | * requested but before we have time to enable interrupts. |
@@ -1237,7 +1237,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp) | |||
1237 | irq = hvcsd->vdev->irq; | 1237 | irq = hvcsd->vdev->irq; |
1238 | spin_unlock_irqrestore(&hvcsd->lock, flags); | 1238 | spin_unlock_irqrestore(&hvcsd->lock, flags); |
1239 | 1239 | ||
1240 | tty_wait_until_sent(tty, HVCS_CLOSE_WAIT); | 1240 | tty_wait_until_sent_from_close(tty, HVCS_CLOSE_WAIT); |
1241 | 1241 | ||
1242 | /* | 1242 | /* |
1243 | * This line is important because it tells hvcs_open that this | 1243 | * This line is important because it tells hvcs_open that this |
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c index c94e2f5853d8..cdfa3e02d627 100644 --- a/drivers/tty/hvc/hvsi.c +++ b/drivers/tty/hvc/hvsi.c | |||
@@ -1105,7 +1105,7 @@ static int __init hvsi_init(void) | |||
1105 | struct hvsi_struct *hp = &hvsi_ports[i]; | 1105 | struct hvsi_struct *hp = &hvsi_ports[i]; |
1106 | int ret = 1; | 1106 | int ret = 1; |
1107 | 1107 | ||
1108 | ret = request_irq(hp->virq, hvsi_interrupt, IRQF_DISABLED, "hvsi", hp); | 1108 | ret = request_irq(hp->virq, hvsi_interrupt, 0, "hvsi", hp); |
1109 | if (ret) | 1109 | if (ret) |
1110 | printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n", | 1110 | printk(KERN_ERR "HVSI: couldn't reserve irq 0x%x (error %i)\n", |
1111 | hp->virq, ret); | 1111 | hp->virq, ret); |
diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c index db1cf9c328d8..e5c295ab5dec 100644 --- a/drivers/tty/isicom.c +++ b/drivers/tty/isicom.c | |||
@@ -1598,7 +1598,7 @@ static int __devinit isicom_probe(struct pci_dev *pdev, | |||
1598 | } | 1598 | } |
1599 | 1599 | ||
1600 | retval = request_irq(board->irq, isicom_interrupt, | 1600 | retval = request_irq(board->irq, isicom_interrupt, |
1601 | IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board); | 1601 | IRQF_SHARED, ISICOM_NAME, board); |
1602 | if (retval < 0) { | 1602 | if (retval < 0) { |
1603 | dev_err(&pdev->dev, "Could not install handler at Irq %d. " | 1603 | dev_err(&pdev->dev, "Could not install handler at Irq %d. " |
1604 | "Card%d will be disabled.\n", board->irq, index + 1); | 1604 | "Card%d will be disabled.\n", board->irq, index + 1); |
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 7fc8c02fea6c..8998d527232a 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c | |||
@@ -2005,16 +2005,9 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
2005 | */ | 2005 | */ |
2006 | if (!timeout || timeout > 2 * info->timeout) | 2006 | if (!timeout || timeout > 2 * info->timeout) |
2007 | timeout = 2 * info->timeout; | 2007 | timeout = 2 * info->timeout; |
2008 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 2008 | |
2009 | printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", | ||
2010 | timeout, char_time); | ||
2011 | printk("jiff=%lu...", jiffies); | ||
2012 | #endif | ||
2013 | spin_lock_irqsave(&info->slock, flags); | 2009 | spin_lock_irqsave(&info->slock, flags); |
2014 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { | 2010 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { |
2015 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | ||
2016 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); | ||
2017 | #endif | ||
2018 | spin_unlock_irqrestore(&info->slock, flags); | 2011 | spin_unlock_irqrestore(&info->slock, flags); |
2019 | schedule_timeout_interruptible(char_time); | 2012 | schedule_timeout_interruptible(char_time); |
2020 | spin_lock_irqsave(&info->slock, flags); | 2013 | spin_lock_irqsave(&info->slock, flags); |
@@ -2025,10 +2018,6 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
2025 | } | 2018 | } |
2026 | spin_unlock_irqrestore(&info->slock, flags); | 2019 | spin_unlock_irqrestore(&info->slock, flags); |
2027 | set_current_state(TASK_RUNNING); | 2020 | set_current_state(TASK_RUNNING); |
2028 | |||
2029 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | ||
2030 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | ||
2031 | #endif | ||
2032 | } | 2021 | } |
2033 | 2022 | ||
2034 | /* | 2023 | /* |
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 8a50e4eebf18..4cb0d0a3e57b 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c | |||
@@ -21,7 +21,6 @@ | |||
21 | * Mostly done: ioctls for setting modes/timing | 21 | * Mostly done: ioctls for setting modes/timing |
22 | * Partly done: hooks so you can pull off frames to non tty devs | 22 | * Partly done: hooks so you can pull off frames to non tty devs |
23 | * Restart DLCI 0 when it closes ? | 23 | * Restart DLCI 0 when it closes ? |
24 | * Test basic encoding | ||
25 | * Improve the tx engine | 24 | * Improve the tx engine |
26 | * Resolve tx side locking by adding a queue_head and routing | 25 | * Resolve tx side locking by adding a queue_head and routing |
27 | * all control traffic via it | 26 | * all control traffic via it |
@@ -810,38 +809,41 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci) | |||
810 | { | 809 | { |
811 | struct gsm_msg *msg; | 810 | struct gsm_msg *msg; |
812 | u8 *dp; | 811 | u8 *dp; |
813 | int len, size; | 812 | int len, total_size, size; |
814 | int h = dlci->adaption - 1; | 813 | int h = dlci->adaption - 1; |
815 | 814 | ||
816 | len = kfifo_len(dlci->fifo); | 815 | total_size = 0; |
817 | if (len == 0) | 816 | while(1) { |
818 | return 0; | 817 | len = kfifo_len(dlci->fifo); |
819 | 818 | if (len == 0) | |
820 | /* MTU/MRU count only the data bits */ | 819 | return total_size; |
821 | if (len > gsm->mtu) | 820 | |
822 | len = gsm->mtu; | 821 | /* MTU/MRU count only the data bits */ |
823 | 822 | if (len > gsm->mtu) | |
824 | size = len + h; | 823 | len = gsm->mtu; |
825 | 824 | ||
826 | msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); | 825 | size = len + h; |
827 | /* FIXME: need a timer or something to kick this so it can't | 826 | |
828 | get stuck with no work outstanding and no buffer free */ | 827 | msg = gsm_data_alloc(gsm, dlci->addr, size, gsm->ftype); |
829 | if (msg == NULL) | 828 | /* FIXME: need a timer or something to kick this so it can't |
830 | return -ENOMEM; | 829 | get stuck with no work outstanding and no buffer free */ |
831 | dp = msg->data; | 830 | if (msg == NULL) |
832 | switch (dlci->adaption) { | 831 | return -ENOMEM; |
833 | case 1: /* Unstructured */ | 832 | dp = msg->data; |
834 | break; | 833 | switch (dlci->adaption) { |
835 | case 2: /* Unstructed with modem bits. Always one byte as we never | 834 | case 1: /* Unstructured */ |
836 | send inline break data */ | 835 | break; |
837 | *dp += gsm_encode_modem(dlci); | 836 | case 2: /* Unstructed with modem bits. Always one byte as we never |
838 | len--; | 837 | send inline break data */ |
839 | break; | 838 | *dp++ = gsm_encode_modem(dlci); |
839 | break; | ||
840 | } | ||
841 | WARN_ON(kfifo_out_locked(dlci->fifo, dp , len, &dlci->lock) != len); | ||
842 | __gsm_data_queue(dlci, msg); | ||
843 | total_size += size; | ||
840 | } | 844 | } |
841 | WARN_ON(kfifo_out_locked(dlci->fifo, dp , len, &dlci->lock) != len); | ||
842 | __gsm_data_queue(dlci, msg); | ||
843 | /* Bytes of data we used up */ | 845 | /* Bytes of data we used up */ |
844 | return size; | 846 | return total_size; |
845 | } | 847 | } |
846 | 848 | ||
847 | /** | 849 | /** |
@@ -2004,6 +2006,7 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) | |||
2004 | int i; | 2006 | int i; |
2005 | struct gsm_dlci *dlci = gsm->dlci[0]; | 2007 | struct gsm_dlci *dlci = gsm->dlci[0]; |
2006 | struct gsm_msg *txq; | 2008 | struct gsm_msg *txq; |
2009 | struct gsm_control *gc; | ||
2007 | 2010 | ||
2008 | gsm->dead = 1; | 2011 | gsm->dead = 1; |
2009 | 2012 | ||
@@ -2017,6 +2020,13 @@ void gsm_cleanup_mux(struct gsm_mux *gsm) | |||
2017 | spin_unlock(&gsm_mux_lock); | 2020 | spin_unlock(&gsm_mux_lock); |
2018 | WARN_ON(i == MAX_MUX); | 2021 | WARN_ON(i == MAX_MUX); |
2019 | 2022 | ||
2023 | /* In theory disconnecting DLCI 0 is sufficient but for some | ||
2024 | modems this is apparently not the case. */ | ||
2025 | if (dlci) { | ||
2026 | gc = gsm_control_send(gsm, CMD_CLD, NULL, 0); | ||
2027 | if (gc) | ||
2028 | gsm_control_wait(gsm, gc); | ||
2029 | } | ||
2020 | del_timer_sync(&gsm->t2_timer); | 2030 | del_timer_sync(&gsm->t2_timer); |
2021 | /* Now we are sure T2 has stopped */ | 2031 | /* Now we are sure T2 has stopped */ |
2022 | if (dlci) { | 2032 | if (dlci) { |
@@ -2982,7 +2992,7 @@ static int gsmtty_tiocmset(struct tty_struct *tty, | |||
2982 | struct gsm_dlci *dlci = tty->driver_data; | 2992 | struct gsm_dlci *dlci = tty->driver_data; |
2983 | unsigned int modem_tx = dlci->modem_tx; | 2993 | unsigned int modem_tx = dlci->modem_tx; |
2984 | 2994 | ||
2985 | modem_tx &= clear; | 2995 | modem_tx &= ~clear; |
2986 | modem_tx |= set; | 2996 | modem_tx |= set; |
2987 | 2997 | ||
2988 | if (modem_tx != dlci->modem_tx) { | 2998 | if (modem_tx != dlci->modem_tx) { |
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index e809e9d4683c..e18604b3fc7d 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
@@ -670,12 +670,18 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
670 | 670 | ||
671 | nonseekable_open(inode, filp); | 671 | nonseekable_open(inode, filp); |
672 | 672 | ||
673 | retval = tty_alloc_file(filp); | ||
674 | if (retval) | ||
675 | return retval; | ||
676 | |||
673 | /* find a device that is not in use. */ | 677 | /* find a device that is not in use. */ |
674 | tty_lock(); | 678 | tty_lock(); |
675 | index = devpts_new_index(inode); | 679 | index = devpts_new_index(inode); |
676 | tty_unlock(); | 680 | tty_unlock(); |
677 | if (index < 0) | 681 | if (index < 0) { |
678 | return index; | 682 | retval = index; |
683 | goto err_file; | ||
684 | } | ||
679 | 685 | ||
680 | mutex_lock(&tty_mutex); | 686 | mutex_lock(&tty_mutex); |
681 | tty_lock(); | 687 | tty_lock(); |
@@ -689,27 +695,27 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
689 | 695 | ||
690 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ | 696 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ |
691 | 697 | ||
692 | retval = tty_add_file(tty, filp); | 698 | tty_add_file(tty, filp); |
693 | if (retval) | ||
694 | goto out; | ||
695 | 699 | ||
696 | retval = devpts_pty_new(inode, tty->link); | 700 | retval = devpts_pty_new(inode, tty->link); |
697 | if (retval) | 701 | if (retval) |
698 | goto out1; | 702 | goto err_release; |
699 | 703 | ||
700 | retval = ptm_driver->ops->open(tty, filp); | 704 | retval = ptm_driver->ops->open(tty, filp); |
701 | if (retval) | 705 | if (retval) |
702 | goto out2; | 706 | goto err_release; |
703 | out1: | 707 | |
704 | tty_unlock(); | 708 | tty_unlock(); |
705 | return retval; | 709 | return 0; |
706 | out2: | 710 | err_release: |
707 | tty_unlock(); | 711 | tty_unlock(); |
708 | tty_release(inode, filp); | 712 | tty_release(inode, filp); |
709 | return retval; | 713 | return retval; |
710 | out: | 714 | out: |
711 | devpts_kill_index(inode, index); | 715 | devpts_kill_index(inode, index); |
712 | tty_unlock(); | 716 | tty_unlock(); |
717 | err_file: | ||
718 | tty_free_file(filp); | ||
713 | return retval; | 719 | return retval; |
714 | } | 720 | } |
715 | 721 | ||
diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c index e0a77540b8ca..a88ef9782a4f 100644 --- a/drivers/tty/serial/68328serial.c +++ b/drivers/tty/serial/68328serial.c | |||
@@ -235,22 +235,6 @@ static void batten_down_hatches(void) | |||
235 | 235 | ||
236 | static void status_handle(struct m68k_serial *info, unsigned short status) | 236 | static void status_handle(struct m68k_serial *info, unsigned short status) |
237 | { | 237 | { |
238 | #if 0 | ||
239 | if(status & DCD) { | ||
240 | if((info->port.tty->termios->c_cflag & CRTSCTS) && | ||
241 | ((info->curregs[3] & AUTO_ENAB)==0)) { | ||
242 | info->curregs[3] |= AUTO_ENAB; | ||
243 | info->pendregs[3] |= AUTO_ENAB; | ||
244 | write_zsreg(info->m68k_channel, 3, info->curregs[3]); | ||
245 | } | ||
246 | } else { | ||
247 | if((info->curregs[3] & AUTO_ENAB)) { | ||
248 | info->curregs[3] &= ~AUTO_ENAB; | ||
249 | info->pendregs[3] &= ~AUTO_ENAB; | ||
250 | write_zsreg(info->m68k_channel, 3, info->curregs[3]); | ||
251 | } | ||
252 | } | ||
253 | #endif | ||
254 | /* If this is console input and this is a | 238 | /* If this is console input and this is a |
255 | * 'break asserted' status change interrupt | 239 | * 'break asserted' status change interrupt |
256 | * see if we can drop into the debugger | 240 | * see if we can drop into the debugger |
@@ -340,9 +324,6 @@ static void transmit_chars(struct m68k_serial *info) | |||
340 | info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); | 324 | info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); |
341 | info->xmit_cnt--; | 325 | info->xmit_cnt--; |
342 | 326 | ||
343 | if (info->xmit_cnt < WAKEUP_CHARS) | ||
344 | schedule_work(&info->tqueue); | ||
345 | |||
346 | if(info->xmit_cnt <= 0) { | 327 | if(info->xmit_cnt <= 0) { |
347 | /* All done for now... TX ints off */ | 328 | /* All done for now... TX ints off */ |
348 | uart->ustcnt &= ~USTCNT_TX_INTR_MASK; | 329 | uart->ustcnt &= ~USTCNT_TX_INTR_MASK; |
@@ -378,21 +359,6 @@ irqreturn_t rs_interrupt(int irq, void *dev_id) | |||
378 | return IRQ_HANDLED; | 359 | return IRQ_HANDLED; |
379 | } | 360 | } |
380 | 361 | ||
381 | static void do_softint(struct work_struct *work) | ||
382 | { | ||
383 | struct m68k_serial *info = container_of(work, struct m68k_serial, tqueue); | ||
384 | struct tty_struct *tty; | ||
385 | |||
386 | tty = info->tty; | ||
387 | if (!tty) | ||
388 | return; | ||
389 | #if 0 | ||
390 | if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { | ||
391 | tty_wakeup(tty); | ||
392 | } | ||
393 | #endif | ||
394 | } | ||
395 | |||
396 | static int startup(struct m68k_serial * info) | 362 | static int startup(struct m68k_serial * info) |
397 | { | 363 | { |
398 | m68328_uart *uart = &uart_addr[info->line]; | 364 | m68328_uart *uart = &uart_addr[info->line]; |
@@ -1324,7 +1290,6 @@ rs68328_init(void) | |||
1324 | info->event = 0; | 1290 | info->event = 0; |
1325 | info->count = 0; | 1291 | info->count = 0; |
1326 | info->blocked_open = 0; | 1292 | info->blocked_open = 0; |
1327 | INIT_WORK(&info->tqueue, do_softint); | ||
1328 | init_waitqueue_head(&info->open_wait); | 1293 | init_waitqueue_head(&info->open_wait); |
1329 | init_waitqueue_head(&info->close_wait); | 1294 | init_waitqueue_head(&info->close_wait); |
1330 | info->line = i; | 1295 | info->line = i; |
@@ -1341,7 +1306,7 @@ rs68328_init(void) | |||
1341 | 1306 | ||
1342 | if (request_irq(uart_irqs[i], | 1307 | if (request_irq(uart_irqs[i], |
1343 | rs_interrupt, | 1308 | rs_interrupt, |
1344 | IRQF_DISABLED, | 1309 | 0, |
1345 | "M68328_UART", info)) | 1310 | "M68328_UART", info)) |
1346 | panic("Unable to attach 68328 serial interrupt\n"); | 1311 | panic("Unable to attach 68328 serial interrupt\n"); |
1347 | } | 1312 | } |
diff --git a/drivers/tty/serial/68328serial.h b/drivers/tty/serial/68328serial.h index 8c9c3c0745db..3d2faabd766f 100644 --- a/drivers/tty/serial/68328serial.h +++ b/drivers/tty/serial/68328serial.h | |||
@@ -158,7 +158,6 @@ struct m68k_serial { | |||
158 | int xmit_head; | 158 | int xmit_head; |
159 | int xmit_tail; | 159 | int xmit_tail; |
160 | int xmit_cnt; | 160 | int xmit_cnt; |
161 | struct work_struct tqueue; | ||
162 | wait_queue_head_t open_wait; | 161 | wait_queue_head_t open_wait; |
163 | wait_queue_head_t close_wait; | 162 | wait_queue_head_t close_wait; |
164 | }; | 163 | }; |
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index 7f50999eebc2..a87a56cb5417 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c | |||
@@ -309,6 +309,13 @@ static const struct serial8250_config uart_config[] = { | |||
309 | UART_FCR_T_TRIG_01, | 309 | UART_FCR_T_TRIG_01, |
310 | .flags = UART_CAP_FIFO | UART_CAP_RTOIE, | 310 | .flags = UART_CAP_FIFO | UART_CAP_RTOIE, |
311 | }, | 311 | }, |
312 | [PORT_XR17D15X] = { | ||
313 | .name = "XR17D15X", | ||
314 | .fifo_size = 64, | ||
315 | .tx_loadsz = 64, | ||
316 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | ||
317 | .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR, | ||
318 | }, | ||
312 | }; | 319 | }; |
313 | 320 | ||
314 | #if defined(CONFIG_MIPS_ALCHEMY) | 321 | #if defined(CONFIG_MIPS_ALCHEMY) |
@@ -461,42 +468,6 @@ static void tsi_serial_out(struct uart_port *p, int offset, int value) | |||
461 | writeb(value, p->membase + offset); | 468 | writeb(value, p->membase + offset); |
462 | } | 469 | } |
463 | 470 | ||
464 | /* Save the LCR value so it can be re-written when a Busy Detect IRQ occurs. */ | ||
465 | static inline void dwapb_save_out_value(struct uart_port *p, int offset, | ||
466 | int value) | ||
467 | { | ||
468 | struct uart_8250_port *up = | ||
469 | container_of(p, struct uart_8250_port, port); | ||
470 | |||
471 | if (offset == UART_LCR) | ||
472 | up->lcr = value; | ||
473 | } | ||
474 | |||
475 | /* Read the IER to ensure any interrupt is cleared before returning from ISR. */ | ||
476 | static inline void dwapb_check_clear_ier(struct uart_port *p, int offset) | ||
477 | { | ||
478 | if (offset == UART_TX || offset == UART_IER) | ||
479 | p->serial_in(p, UART_IER); | ||
480 | } | ||
481 | |||
482 | static void dwapb_serial_out(struct uart_port *p, int offset, int value) | ||
483 | { | ||
484 | int save_offset = offset; | ||
485 | offset = map_8250_out_reg(p, offset) << p->regshift; | ||
486 | dwapb_save_out_value(p, save_offset, value); | ||
487 | writeb(value, p->membase + offset); | ||
488 | dwapb_check_clear_ier(p, save_offset); | ||
489 | } | ||
490 | |||
491 | static void dwapb32_serial_out(struct uart_port *p, int offset, int value) | ||
492 | { | ||
493 | int save_offset = offset; | ||
494 | offset = map_8250_out_reg(p, offset) << p->regshift; | ||
495 | dwapb_save_out_value(p, save_offset, value); | ||
496 | writel(value, p->membase + offset); | ||
497 | dwapb_check_clear_ier(p, save_offset); | ||
498 | } | ||
499 | |||
500 | static unsigned int io_serial_in(struct uart_port *p, int offset) | 471 | static unsigned int io_serial_in(struct uart_port *p, int offset) |
501 | { | 472 | { |
502 | offset = map_8250_in_reg(p, offset) << p->regshift; | 473 | offset = map_8250_in_reg(p, offset) << p->regshift; |
@@ -509,6 +480,8 @@ static void io_serial_out(struct uart_port *p, int offset, int value) | |||
509 | outb(value, p->iobase + offset); | 480 | outb(value, p->iobase + offset); |
510 | } | 481 | } |
511 | 482 | ||
483 | static int serial8250_default_handle_irq(struct uart_port *port); | ||
484 | |||
512 | static void set_io_from_upio(struct uart_port *p) | 485 | static void set_io_from_upio(struct uart_port *p) |
513 | { | 486 | { |
514 | struct uart_8250_port *up = | 487 | struct uart_8250_port *up = |
@@ -540,16 +513,6 @@ static void set_io_from_upio(struct uart_port *p) | |||
540 | p->serial_out = tsi_serial_out; | 513 | p->serial_out = tsi_serial_out; |
541 | break; | 514 | break; |
542 | 515 | ||
543 | case UPIO_DWAPB: | ||
544 | p->serial_in = mem_serial_in; | ||
545 | p->serial_out = dwapb_serial_out; | ||
546 | break; | ||
547 | |||
548 | case UPIO_DWAPB32: | ||
549 | p->serial_in = mem32_serial_in; | ||
550 | p->serial_out = dwapb32_serial_out; | ||
551 | break; | ||
552 | |||
553 | default: | 516 | default: |
554 | p->serial_in = io_serial_in; | 517 | p->serial_in = io_serial_in; |
555 | p->serial_out = io_serial_out; | 518 | p->serial_out = io_serial_out; |
@@ -557,6 +520,7 @@ static void set_io_from_upio(struct uart_port *p) | |||
557 | } | 520 | } |
558 | /* Remember loaded iotype */ | 521 | /* Remember loaded iotype */ |
559 | up->cur_iotype = p->iotype; | 522 | up->cur_iotype = p->iotype; |
523 | p->handle_irq = serial8250_default_handle_irq; | ||
560 | } | 524 | } |
561 | 525 | ||
562 | static void | 526 | static void |
@@ -567,8 +531,6 @@ serial_out_sync(struct uart_8250_port *up, int offset, int value) | |||
567 | case UPIO_MEM: | 531 | case UPIO_MEM: |
568 | case UPIO_MEM32: | 532 | case UPIO_MEM32: |
569 | case UPIO_AU: | 533 | case UPIO_AU: |
570 | case UPIO_DWAPB: | ||
571 | case UPIO_DWAPB32: | ||
572 | p->serial_out(p, offset, value); | 534 | p->serial_out(p, offset, value); |
573 | p->serial_in(p, UART_LCR); /* safe, no side-effects */ | 535 | p->serial_in(p, UART_LCR); /* safe, no side-effects */ |
574 | break; | 536 | break; |
@@ -1120,6 +1082,14 @@ static void autoconfig_16550a(struct uart_8250_port *up) | |||
1120 | serial_outp(up, UART_IER, iersave); | 1082 | serial_outp(up, UART_IER, iersave); |
1121 | 1083 | ||
1122 | /* | 1084 | /* |
1085 | * Exar uarts have EFR in a weird location | ||
1086 | */ | ||
1087 | if (up->port.flags & UPF_EXAR_EFR) { | ||
1088 | up->port.type = PORT_XR17D15X; | ||
1089 | up->capabilities |= UART_CAP_AFE | UART_CAP_EFR; | ||
1090 | } | ||
1091 | |||
1092 | /* | ||
1123 | * We distinguish between 16550A and U6 16550A by counting | 1093 | * We distinguish between 16550A and U6 16550A by counting |
1124 | * how many bytes are in the FIFO. | 1094 | * how many bytes are in the FIFO. |
1125 | */ | 1095 | */ |
@@ -1621,6 +1591,29 @@ static void serial8250_handle_port(struct uart_8250_port *up) | |||
1621 | spin_unlock_irqrestore(&up->port.lock, flags); | 1591 | spin_unlock_irqrestore(&up->port.lock, flags); |
1622 | } | 1592 | } |
1623 | 1593 | ||
1594 | int serial8250_handle_irq(struct uart_port *port, unsigned int iir) | ||
1595 | { | ||
1596 | struct uart_8250_port *up = | ||
1597 | container_of(port, struct uart_8250_port, port); | ||
1598 | |||
1599 | if (!(iir & UART_IIR_NO_INT)) { | ||
1600 | serial8250_handle_port(up); | ||
1601 | return 1; | ||
1602 | } | ||
1603 | |||
1604 | return 0; | ||
1605 | } | ||
1606 | EXPORT_SYMBOL_GPL(serial8250_handle_irq); | ||
1607 | |||
1608 | static int serial8250_default_handle_irq(struct uart_port *port) | ||
1609 | { | ||
1610 | struct uart_8250_port *up = | ||
1611 | container_of(port, struct uart_8250_port, port); | ||
1612 | unsigned int iir = serial_in(up, UART_IIR); | ||
1613 | |||
1614 | return serial8250_handle_irq(port, iir); | ||
1615 | } | ||
1616 | |||
1624 | /* | 1617 | /* |
1625 | * This is the serial driver's interrupt routine. | 1618 | * This is the serial driver's interrupt routine. |
1626 | * | 1619 | * |
@@ -1648,30 +1641,13 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) | |||
1648 | l = i->head; | 1641 | l = i->head; |
1649 | do { | 1642 | do { |
1650 | struct uart_8250_port *up; | 1643 | struct uart_8250_port *up; |
1651 | unsigned int iir; | 1644 | struct uart_port *port; |
1652 | 1645 | ||
1653 | up = list_entry(l, struct uart_8250_port, list); | 1646 | up = list_entry(l, struct uart_8250_port, list); |
1647 | port = &up->port; | ||
1654 | 1648 | ||
1655 | iir = serial_in(up, UART_IIR); | 1649 | if (port->handle_irq(port)) { |
1656 | if (!(iir & UART_IIR_NO_INT)) { | ||
1657 | serial8250_handle_port(up); | ||
1658 | |||
1659 | handled = 1; | 1650 | handled = 1; |
1660 | |||
1661 | end = NULL; | ||
1662 | } else if ((up->port.iotype == UPIO_DWAPB || | ||
1663 | up->port.iotype == UPIO_DWAPB32) && | ||
1664 | (iir & UART_IIR_BUSY) == UART_IIR_BUSY) { | ||
1665 | /* The DesignWare APB UART has an Busy Detect (0x07) | ||
1666 | * interrupt meaning an LCR write attempt occurred while the | ||
1667 | * UART was busy. The interrupt must be cleared by reading | ||
1668 | * the UART status register (USR) and the LCR re-written. */ | ||
1669 | unsigned int status; | ||
1670 | status = *(volatile u32 *)up->port.private_data; | ||
1671 | serial_out(up, UART_LCR, up->lcr); | ||
1672 | |||
1673 | handled = 1; | ||
1674 | |||
1675 | end = NULL; | 1651 | end = NULL; |
1676 | } else if (end == NULL) | 1652 | } else if (end == NULL) |
1677 | end = l; | 1653 | end = l; |
@@ -2081,8 +2057,8 @@ static int serial8250_startup(struct uart_port *port) | |||
2081 | */ | 2057 | */ |
2082 | if (!(up->port.flags & UPF_BUGGY_UART) && | 2058 | if (!(up->port.flags & UPF_BUGGY_UART) && |
2083 | (serial_inp(up, UART_LSR) == 0xff)) { | 2059 | (serial_inp(up, UART_LSR) == 0xff)) { |
2084 | printk(KERN_INFO "ttyS%d: LSR safety check engaged!\n", | 2060 | printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n", |
2085 | serial_index(&up->port)); | 2061 | serial_index(&up->port)); |
2086 | return -ENODEV; | 2062 | return -ENODEV; |
2087 | } | 2063 | } |
2088 | 2064 | ||
@@ -2458,7 +2434,10 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, | |||
2458 | efr |= UART_EFR_CTS; | 2434 | efr |= UART_EFR_CTS; |
2459 | 2435 | ||
2460 | serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); | 2436 | serial_outp(up, UART_LCR, UART_LCR_CONF_MODE_B); |
2461 | serial_outp(up, UART_EFR, efr); | 2437 | if (up->port.flags & UPF_EXAR_EFR) |
2438 | serial_outp(up, UART_XR_EFR, efr); | ||
2439 | else | ||
2440 | serial_outp(up, UART_EFR, efr); | ||
2462 | } | 2441 | } |
2463 | 2442 | ||
2464 | #ifdef CONFIG_ARCH_OMAP | 2443 | #ifdef CONFIG_ARCH_OMAP |
@@ -2570,8 +2549,6 @@ static int serial8250_request_std_resource(struct uart_8250_port *up) | |||
2570 | case UPIO_TSI: | 2549 | case UPIO_TSI: |
2571 | case UPIO_MEM32: | 2550 | case UPIO_MEM32: |
2572 | case UPIO_MEM: | 2551 | case UPIO_MEM: |
2573 | case UPIO_DWAPB: | ||
2574 | case UPIO_DWAPB32: | ||
2575 | if (!up->port.mapbase) | 2552 | if (!up->port.mapbase) |
2576 | break; | 2553 | break; |
2577 | 2554 | ||
@@ -2608,8 +2585,6 @@ static void serial8250_release_std_resource(struct uart_8250_port *up) | |||
2608 | case UPIO_TSI: | 2585 | case UPIO_TSI: |
2609 | case UPIO_MEM32: | 2586 | case UPIO_MEM32: |
2610 | case UPIO_MEM: | 2587 | case UPIO_MEM: |
2611 | case UPIO_DWAPB: | ||
2612 | case UPIO_DWAPB32: | ||
2613 | if (!up->port.mapbase) | 2588 | if (!up->port.mapbase) |
2614 | break; | 2589 | break; |
2615 | 2590 | ||
@@ -3050,6 +3025,10 @@ int __init early_serial_setup(struct uart_port *port) | |||
3050 | p->serial_in = port->serial_in; | 3025 | p->serial_in = port->serial_in; |
3051 | if (port->serial_out) | 3026 | if (port->serial_out) |
3052 | p->serial_out = port->serial_out; | 3027 | p->serial_out = port->serial_out; |
3028 | if (port->handle_irq) | ||
3029 | p->handle_irq = port->handle_irq; | ||
3030 | else | ||
3031 | p->handle_irq = serial8250_default_handle_irq; | ||
3053 | 3032 | ||
3054 | return 0; | 3033 | return 0; |
3055 | } | 3034 | } |
@@ -3118,6 +3097,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
3118 | port.type = p->type; | 3097 | port.type = p->type; |
3119 | port.serial_in = p->serial_in; | 3098 | port.serial_in = p->serial_in; |
3120 | port.serial_out = p->serial_out; | 3099 | port.serial_out = p->serial_out; |
3100 | port.handle_irq = p->handle_irq; | ||
3121 | port.set_termios = p->set_termios; | 3101 | port.set_termios = p->set_termios; |
3122 | port.pm = p->pm; | 3102 | port.pm = p->pm; |
3123 | port.dev = &dev->dev; | 3103 | port.dev = &dev->dev; |
@@ -3283,6 +3263,8 @@ int serial8250_register_port(struct uart_port *port) | |||
3283 | uart->port.serial_in = port->serial_in; | 3263 | uart->port.serial_in = port->serial_in; |
3284 | if (port->serial_out) | 3264 | if (port->serial_out) |
3285 | uart->port.serial_out = port->serial_out; | 3265 | uart->port.serial_out = port->serial_out; |
3266 | if (port->handle_irq) | ||
3267 | uart->port.handle_irq = port->handle_irq; | ||
3286 | /* Possibly override set_termios call */ | 3268 | /* Possibly override set_termios call */ |
3287 | if (port->set_termios) | 3269 | if (port->set_termios) |
3288 | uart->port.set_termios = port->set_termios; | 3270 | uart->port.set_termios = port->set_termios; |
diff --git a/drivers/tty/serial/8250_dw.c b/drivers/tty/serial/8250_dw.c new file mode 100644 index 000000000000..bf1fba640c2d --- /dev/null +++ b/drivers/tty/serial/8250_dw.c | |||
@@ -0,0 +1,194 @@ | |||
1 | /* | ||
2 | * Synopsys DesignWare 8250 driver. | ||
3 | * | ||
4 | * Copyright 2011 Picochip, Jamie Iles. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * The Synopsys DesignWare 8250 has an extra feature whereby it detects if the | ||
12 | * LCR is written whilst busy. If it is, then a busy detect interrupt is | ||
13 | * raised, the LCR needs to be rewritten and the uart status register read. | ||
14 | */ | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/serial_8250.h> | ||
20 | #include <linux/serial_core.h> | ||
21 | #include <linux/serial_reg.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_irq.h> | ||
24 | #include <linux/of_platform.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/slab.h> | ||
27 | |||
28 | struct dw8250_data { | ||
29 | int last_lcr; | ||
30 | int line; | ||
31 | }; | ||
32 | |||
33 | static void dw8250_serial_out(struct uart_port *p, int offset, int value) | ||
34 | { | ||
35 | struct dw8250_data *d = p->private_data; | ||
36 | |||
37 | if (offset == UART_LCR) | ||
38 | d->last_lcr = value; | ||
39 | |||
40 | offset <<= p->regshift; | ||
41 | writeb(value, p->membase + offset); | ||
42 | } | ||
43 | |||
44 | static unsigned int dw8250_serial_in(struct uart_port *p, int offset) | ||
45 | { | ||
46 | offset <<= p->regshift; | ||
47 | |||
48 | return readb(p->membase + offset); | ||
49 | } | ||
50 | |||
51 | static void dw8250_serial_out32(struct uart_port *p, int offset, int value) | ||
52 | { | ||
53 | struct dw8250_data *d = p->private_data; | ||
54 | |||
55 | if (offset == UART_LCR) | ||
56 | d->last_lcr = value; | ||
57 | |||
58 | offset <<= p->regshift; | ||
59 | writel(value, p->membase + offset); | ||
60 | } | ||
61 | |||
62 | static unsigned int dw8250_serial_in32(struct uart_port *p, int offset) | ||
63 | { | ||
64 | offset <<= p->regshift; | ||
65 | |||
66 | return readl(p->membase + offset); | ||
67 | } | ||
68 | |||
69 | /* Offset for the DesignWare's UART Status Register. */ | ||
70 | #define UART_USR 0x1f | ||
71 | |||
72 | static int dw8250_handle_irq(struct uart_port *p) | ||
73 | { | ||
74 | struct dw8250_data *d = p->private_data; | ||
75 | unsigned int iir = p->serial_in(p, UART_IIR); | ||
76 | |||
77 | if (serial8250_handle_irq(p, iir)) { | ||
78 | return 1; | ||
79 | } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { | ||
80 | /* Clear the USR and write the LCR again. */ | ||
81 | (void)p->serial_in(p, UART_USR); | ||
82 | p->serial_out(p, d->last_lcr, UART_LCR); | ||
83 | |||
84 | return 1; | ||
85 | } | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int __devinit dw8250_probe(struct platform_device *pdev) | ||
91 | { | ||
92 | struct uart_port port = {}; | ||
93 | struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
94 | struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
95 | struct device_node *np = pdev->dev.of_node; | ||
96 | u32 val; | ||
97 | struct dw8250_data *data; | ||
98 | |||
99 | if (!regs || !irq) { | ||
100 | dev_err(&pdev->dev, "no registers/irq defined\n"); | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
105 | if (!data) | ||
106 | return -ENOMEM; | ||
107 | port.private_data = data; | ||
108 | |||
109 | spin_lock_init(&port.lock); | ||
110 | port.mapbase = regs->start; | ||
111 | port.irq = irq->start; | ||
112 | port.handle_irq = dw8250_handle_irq; | ||
113 | port.type = PORT_8250; | ||
114 | port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | | ||
115 | UPF_FIXED_PORT | UPF_FIXED_TYPE; | ||
116 | port.dev = &pdev->dev; | ||
117 | |||
118 | port.iotype = UPIO_MEM; | ||
119 | port.serial_in = dw8250_serial_in; | ||
120 | port.serial_out = dw8250_serial_out; | ||
121 | if (!of_property_read_u32(np, "reg-io-width", &val)) { | ||
122 | switch (val) { | ||
123 | case 1: | ||
124 | break; | ||
125 | case 4: | ||
126 | port.iotype = UPIO_MEM32; | ||
127 | port.serial_in = dw8250_serial_in32; | ||
128 | port.serial_out = dw8250_serial_out32; | ||
129 | break; | ||
130 | default: | ||
131 | dev_err(&pdev->dev, "unsupported reg-io-width (%u)\n", | ||
132 | val); | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | if (!of_property_read_u32(np, "reg-shift", &val)) | ||
138 | port.regshift = val; | ||
139 | |||
140 | if (of_property_read_u32(np, "clock-frequency", &val)) { | ||
141 | dev_err(&pdev->dev, "no clock-frequency property set\n"); | ||
142 | return -EINVAL; | ||
143 | } | ||
144 | port.uartclk = val; | ||
145 | |||
146 | data->line = serial8250_register_port(&port); | ||
147 | if (data->line < 0) | ||
148 | return data->line; | ||
149 | |||
150 | platform_set_drvdata(pdev, data); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int __devexit dw8250_remove(struct platform_device *pdev) | ||
156 | { | ||
157 | struct dw8250_data *data = platform_get_drvdata(pdev); | ||
158 | |||
159 | serial8250_unregister_port(data->line); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static const struct of_device_id dw8250_match[] = { | ||
165 | { .compatible = "snps,dw-apb-uart" }, | ||
166 | { /* Sentinel */ } | ||
167 | }; | ||
168 | MODULE_DEVICE_TABLE(of, dw8250_match); | ||
169 | |||
170 | static struct platform_driver dw8250_platform_driver = { | ||
171 | .driver = { | ||
172 | .name = "dw-apb-uart", | ||
173 | .owner = THIS_MODULE, | ||
174 | .of_match_table = dw8250_match, | ||
175 | }, | ||
176 | .probe = dw8250_probe, | ||
177 | .remove = __devexit_p(dw8250_remove), | ||
178 | }; | ||
179 | |||
180 | static int __init dw8250_init(void) | ||
181 | { | ||
182 | return platform_driver_register(&dw8250_platform_driver); | ||
183 | } | ||
184 | module_init(dw8250_init); | ||
185 | |||
186 | static void __exit dw8250_exit(void) | ||
187 | { | ||
188 | platform_driver_unregister(&dw8250_platform_driver); | ||
189 | } | ||
190 | module_exit(dw8250_exit); | ||
191 | |||
192 | MODULE_AUTHOR("Jamie Iles"); | ||
193 | MODULE_LICENSE("GPL"); | ||
194 | MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver"); | ||
diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c index 3abeca2a2a1b..825937a5f210 100644 --- a/drivers/tty/serial/8250_pci.c +++ b/drivers/tty/serial/8250_pci.c | |||
@@ -1101,6 +1101,15 @@ static int pci_eg20t_init(struct pci_dev *dev) | |||
1101 | #endif | 1101 | #endif |
1102 | } | 1102 | } |
1103 | 1103 | ||
1104 | static int | ||
1105 | pci_xr17c154_setup(struct serial_private *priv, | ||
1106 | const struct pciserial_board *board, | ||
1107 | struct uart_port *port, int idx) | ||
1108 | { | ||
1109 | port->flags |= UPF_EXAR_EFR; | ||
1110 | return pci_default_setup(priv, board, port, idx); | ||
1111 | } | ||
1112 | |||
1104 | /* This should be in linux/pci_ids.h */ | 1113 | /* This should be in linux/pci_ids.h */ |
1105 | #define PCI_VENDOR_ID_SBSMODULARIO 0x124B | 1114 | #define PCI_VENDOR_ID_SBSMODULARIO 0x124B |
1106 | #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B | 1115 | #define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B |
@@ -1506,6 +1515,30 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
1506 | .setup = pci_timedia_setup, | 1515 | .setup = pci_timedia_setup, |
1507 | }, | 1516 | }, |
1508 | /* | 1517 | /* |
1518 | * Exar cards | ||
1519 | */ | ||
1520 | { | ||
1521 | .vendor = PCI_VENDOR_ID_EXAR, | ||
1522 | .device = PCI_DEVICE_ID_EXAR_XR17C152, | ||
1523 | .subvendor = PCI_ANY_ID, | ||
1524 | .subdevice = PCI_ANY_ID, | ||
1525 | .setup = pci_xr17c154_setup, | ||
1526 | }, | ||
1527 | { | ||
1528 | .vendor = PCI_VENDOR_ID_EXAR, | ||
1529 | .device = PCI_DEVICE_ID_EXAR_XR17C154, | ||
1530 | .subvendor = PCI_ANY_ID, | ||
1531 | .subdevice = PCI_ANY_ID, | ||
1532 | .setup = pci_xr17c154_setup, | ||
1533 | }, | ||
1534 | { | ||
1535 | .vendor = PCI_VENDOR_ID_EXAR, | ||
1536 | .device = PCI_DEVICE_ID_EXAR_XR17C158, | ||
1537 | .subvendor = PCI_ANY_ID, | ||
1538 | .subdevice = PCI_ANY_ID, | ||
1539 | .setup = pci_xr17c154_setup, | ||
1540 | }, | ||
1541 | /* | ||
1509 | * Xircom cards | 1542 | * Xircom cards |
1510 | */ | 1543 | */ |
1511 | { | 1544 | { |
@@ -1558,46 +1591,55 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
1558 | .vendor = PCI_VENDOR_ID_INTEL, | 1591 | .vendor = PCI_VENDOR_ID_INTEL, |
1559 | .device = 0x8811, | 1592 | .device = 0x8811, |
1560 | .init = pci_eg20t_init, | 1593 | .init = pci_eg20t_init, |
1594 | .setup = pci_default_setup, | ||
1561 | }, | 1595 | }, |
1562 | { | 1596 | { |
1563 | .vendor = PCI_VENDOR_ID_INTEL, | 1597 | .vendor = PCI_VENDOR_ID_INTEL, |
1564 | .device = 0x8812, | 1598 | .device = 0x8812, |
1565 | .init = pci_eg20t_init, | 1599 | .init = pci_eg20t_init, |
1600 | .setup = pci_default_setup, | ||
1566 | }, | 1601 | }, |
1567 | { | 1602 | { |
1568 | .vendor = PCI_VENDOR_ID_INTEL, | 1603 | .vendor = PCI_VENDOR_ID_INTEL, |
1569 | .device = 0x8813, | 1604 | .device = 0x8813, |
1570 | .init = pci_eg20t_init, | 1605 | .init = pci_eg20t_init, |
1606 | .setup = pci_default_setup, | ||
1571 | }, | 1607 | }, |
1572 | { | 1608 | { |
1573 | .vendor = PCI_VENDOR_ID_INTEL, | 1609 | .vendor = PCI_VENDOR_ID_INTEL, |
1574 | .device = 0x8814, | 1610 | .device = 0x8814, |
1575 | .init = pci_eg20t_init, | 1611 | .init = pci_eg20t_init, |
1612 | .setup = pci_default_setup, | ||
1576 | }, | 1613 | }, |
1577 | { | 1614 | { |
1578 | .vendor = 0x10DB, | 1615 | .vendor = 0x10DB, |
1579 | .device = 0x8027, | 1616 | .device = 0x8027, |
1580 | .init = pci_eg20t_init, | 1617 | .init = pci_eg20t_init, |
1618 | .setup = pci_default_setup, | ||
1581 | }, | 1619 | }, |
1582 | { | 1620 | { |
1583 | .vendor = 0x10DB, | 1621 | .vendor = 0x10DB, |
1584 | .device = 0x8028, | 1622 | .device = 0x8028, |
1585 | .init = pci_eg20t_init, | 1623 | .init = pci_eg20t_init, |
1624 | .setup = pci_default_setup, | ||
1586 | }, | 1625 | }, |
1587 | { | 1626 | { |
1588 | .vendor = 0x10DB, | 1627 | .vendor = 0x10DB, |
1589 | .device = 0x8029, | 1628 | .device = 0x8029, |
1590 | .init = pci_eg20t_init, | 1629 | .init = pci_eg20t_init, |
1630 | .setup = pci_default_setup, | ||
1591 | }, | 1631 | }, |
1592 | { | 1632 | { |
1593 | .vendor = 0x10DB, | 1633 | .vendor = 0x10DB, |
1594 | .device = 0x800C, | 1634 | .device = 0x800C, |
1595 | .init = pci_eg20t_init, | 1635 | .init = pci_eg20t_init, |
1636 | .setup = pci_default_setup, | ||
1596 | }, | 1637 | }, |
1597 | { | 1638 | { |
1598 | .vendor = 0x10DB, | 1639 | .vendor = 0x10DB, |
1599 | .device = 0x800D, | 1640 | .device = 0x800D, |
1600 | .init = pci_eg20t_init, | 1641 | .init = pci_eg20t_init, |
1642 | .setup = pci_default_setup, | ||
1601 | }, | 1643 | }, |
1602 | /* | 1644 | /* |
1603 | * Cronyx Omega PCI (PLX-chip based) | 1645 | * Cronyx Omega PCI (PLX-chip based) |
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 4dcb37bbdf92..5f479dada6f2 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
@@ -267,6 +267,13 @@ config SERIAL_8250_RM9K | |||
267 | port hardware found on MIPS RM9122 and similar processors. | 267 | port hardware found on MIPS RM9122 and similar processors. |
268 | If unsure, say N. | 268 | If unsure, say N. |
269 | 269 | ||
270 | config SERIAL_8250_DW | ||
271 | tristate "Support for Synopsys DesignWare 8250 quirks" | ||
272 | depends on SERIAL_8250 && OF | ||
273 | help | ||
274 | Selecting this option will enable handling of the extra features | ||
275 | present in the Synopsys DesignWare APB UART. | ||
276 | |||
270 | comment "Non-8250 serial port support" | 277 | comment "Non-8250 serial port support" |
271 | 278 | ||
272 | config SERIAL_AMBA_PL010 | 279 | config SERIAL_AMBA_PL010 |
@@ -522,8 +529,8 @@ config SERIAL_S3C6400 | |||
522 | 529 | ||
523 | config SERIAL_S5PV210 | 530 | config SERIAL_S5PV210 |
524 | tristate "Samsung S5PV210 Serial port support" | 531 | tristate "Samsung S5PV210 Serial port support" |
525 | depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_EXYNOS4210) | 532 | depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_EXYNOS4210 || SOC_EXYNOS4212) |
526 | select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210) | 533 | select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210 || SOC_EXYNOS4212) |
527 | default y | 534 | default y |
528 | help | 535 | help |
529 | Serial port support for Samsung's S5P Family of SoC's | 536 | Serial port support for Samsung's S5P Family of SoC's |
@@ -722,7 +729,7 @@ config SERIAL_BFIN | |||
722 | Add support for the built-in UARTs on the Blackfin. | 729 | Add support for the built-in UARTs on the Blackfin. |
723 | 730 | ||
724 | To compile this driver as a module, choose M here: the | 731 | To compile this driver as a module, choose M here: the |
725 | module will be called bfin_5xx. | 732 | module is named bfin_uart.ko. |
726 | 733 | ||
727 | config SERIAL_BFIN_CONSOLE | 734 | config SERIAL_BFIN_CONSOLE |
728 | bool "Console on Blackfin serial port" | 735 | bool "Console on Blackfin serial port" |
@@ -1035,23 +1042,6 @@ config SERIAL_MCF_CONSOLE | |||
1035 | help | 1042 | help |
1036 | Enable a ColdFire internal serial port to be the system console. | 1043 | Enable a ColdFire internal serial port to be the system console. |
1037 | 1044 | ||
1038 | config SERIAL_68360_SMC | ||
1039 | bool "68360 SMC uart support" | ||
1040 | depends on M68360 | ||
1041 | help | ||
1042 | This driver supports the SMC serial ports of the Motorola 68360 CPU. | ||
1043 | |||
1044 | config SERIAL_68360_SCC | ||
1045 | bool "68360 SCC uart support" | ||
1046 | depends on M68360 | ||
1047 | help | ||
1048 | This driver supports the SCC serial ports of the Motorola 68360 CPU. | ||
1049 | |||
1050 | config SERIAL_68360 | ||
1051 | bool | ||
1052 | depends on SERIAL_68360_SMC || SERIAL_68360_SCC | ||
1053 | default y | ||
1054 | |||
1055 | config SERIAL_PMACZILOG | 1045 | config SERIAL_PMACZILOG |
1056 | tristate "Mac or PowerMac z85c30 ESCC support" | 1046 | tristate "Mac or PowerMac z85c30 ESCC support" |
1057 | depends on (M68K && MAC) || (PPC_OF && PPC_PMAC) | 1047 | depends on (M68K && MAC) || (PPC_OF && PPC_PMAC) |
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 83b4da6a1062..e10cf5b54b6d 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile | |||
@@ -28,6 +28,7 @@ obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o | |||
28 | obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o | 28 | obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o |
29 | obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o | 29 | obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o |
30 | obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o | 30 | obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o |
31 | obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o | ||
31 | obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o | 32 | obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o |
32 | obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o | 33 | obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o |
33 | obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o | 34 | obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o |
@@ -35,7 +36,7 @@ obj-$(CONFIG_SERIAL_PXA) += pxa.o | |||
35 | obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o | 36 | obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o |
36 | obj-$(CONFIG_SERIAL_SA1100) += sa1100.o | 37 | obj-$(CONFIG_SERIAL_SA1100) += sa1100.o |
37 | obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o | 38 | obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o |
38 | obj-$(CONFIG_SERIAL_BFIN) += bfin_5xx.o | 39 | obj-$(CONFIG_SERIAL_BFIN) += bfin_uart.o |
39 | obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o | 40 | obj-$(CONFIG_SERIAL_BFIN_SPORT) += bfin_sport_uart.o |
40 | obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o | 41 | obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o |
41 | obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o | 42 | obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o |
@@ -49,7 +50,6 @@ obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o | |||
49 | obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o | 50 | obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o |
50 | obj-$(CONFIG_SERIAL_MUX) += mux.o | 51 | obj-$(CONFIG_SERIAL_MUX) += mux.o |
51 | obj-$(CONFIG_SERIAL_68328) += 68328serial.o | 52 | obj-$(CONFIG_SERIAL_68328) += 68328serial.o |
52 | obj-$(CONFIG_SERIAL_68360) += 68360serial.o | ||
53 | obj-$(CONFIG_SERIAL_MCF) += mcf.o | 53 | obj-$(CONFIG_SERIAL_MCF) += mcf.o |
54 | obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o | 54 | obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o |
55 | obj-$(CONFIG_SERIAL_DZ) += dz.o | 55 | obj-$(CONFIG_SERIAL_DZ) += dz.o |
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c index 60e049b041a7..00a73ecb2dfb 100644 --- a/drivers/tty/serial/altera_jtaguart.c +++ b/drivers/tty/serial/altera_jtaguart.c | |||
@@ -218,7 +218,7 @@ static int altera_jtaguart_startup(struct uart_port *port) | |||
218 | unsigned long flags; | 218 | unsigned long flags; |
219 | int ret; | 219 | int ret; |
220 | 220 | ||
221 | ret = request_irq(port->irq, altera_jtaguart_interrupt, IRQF_DISABLED, | 221 | ret = request_irq(port->irq, altera_jtaguart_interrupt, 0, |
222 | DRV_NAME, port); | 222 | DRV_NAME, port); |
223 | if (ret) { | 223 | if (ret) { |
224 | pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d " | 224 | pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d " |
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c index 50bc5a5ac653..d902558ccfd2 100644 --- a/drivers/tty/serial/altera_uart.c +++ b/drivers/tty/serial/altera_uart.c | |||
@@ -315,7 +315,7 @@ static int altera_uart_startup(struct uart_port *port) | |||
315 | return 0; | 315 | return 0; |
316 | } | 316 | } |
317 | 317 | ||
318 | ret = request_irq(port->irq, altera_uart_interrupt, IRQF_DISABLED, | 318 | ret = request_irq(port->irq, altera_uart_interrupt, 0, |
319 | DRV_NAME, port); | 319 | DRV_NAME, port); |
320 | if (ret) { | 320 | if (ret) { |
321 | pr_err(DRV_NAME ": unable to attach Altera UART %d " | 321 | pr_err(DRV_NAME ": unable to attach Altera UART %d " |
diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c index 19a943693e4c..77554fd68d1f 100644 --- a/drivers/tty/serial/apbuart.c +++ b/drivers/tty/serial/apbuart.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/tty.h> | 18 | #include <linux/tty.h> |
19 | #include <linux/tty_flip.h> | ||
19 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include <linux/serial.h> | 22 | #include <linux/serial.h> |
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index b922f5d2e61e..9988c0c305c2 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/sysrq.h> | 33 | #include <linux/sysrq.h> |
34 | #include <linux/tty_flip.h> | 34 | #include <linux/tty_flip.h> |
35 | #include <linux/platform_device.h> | 35 | #include <linux/platform_device.h> |
36 | #include <linux/of.h> | ||
37 | #include <linux/of_device.h> | ||
36 | #include <linux/dma-mapping.h> | 38 | #include <linux/dma-mapping.h> |
37 | #include <linux/atmel_pdc.h> | 39 | #include <linux/atmel_pdc.h> |
38 | #include <linux/atmel_serial.h> | 40 | #include <linux/atmel_serial.h> |
@@ -157,11 +159,22 @@ struct atmel_uart_port { | |||
157 | }; | 159 | }; |
158 | 160 | ||
159 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; | 161 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; |
162 | static unsigned long atmel_ports_in_use; | ||
160 | 163 | ||
161 | #ifdef SUPPORT_SYSRQ | 164 | #ifdef SUPPORT_SYSRQ |
162 | static struct console atmel_console; | 165 | static struct console atmel_console; |
163 | #endif | 166 | #endif |
164 | 167 | ||
168 | #if defined(CONFIG_OF) | ||
169 | static const struct of_device_id atmel_serial_dt_ids[] = { | ||
170 | { .compatible = "atmel,at91rm9200-usart" }, | ||
171 | { .compatible = "atmel,at91sam9260-usart" }, | ||
172 | { /* sentinel */ } | ||
173 | }; | ||
174 | |||
175 | MODULE_DEVICE_TABLE(of, atmel_serial_dt_ids); | ||
176 | #endif | ||
177 | |||
165 | static inline struct atmel_uart_port * | 178 | static inline struct atmel_uart_port * |
166 | to_atmel_uart_port(struct uart_port *uart) | 179 | to_atmel_uart_port(struct uart_port *uart) |
167 | { | 180 | { |
@@ -339,7 +352,8 @@ static void atmel_stop_tx(struct uart_port *port) | |||
339 | /* Disable interrupts */ | 352 | /* Disable interrupts */ |
340 | UART_PUT_IDR(port, atmel_port->tx_done_mask); | 353 | UART_PUT_IDR(port, atmel_port->tx_done_mask); |
341 | 354 | ||
342 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) | 355 | if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && |
356 | !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) | ||
343 | atmel_start_rx(port); | 357 | atmel_start_rx(port); |
344 | } | 358 | } |
345 | 359 | ||
@@ -356,7 +370,8 @@ static void atmel_start_tx(struct uart_port *port) | |||
356 | really need this.*/ | 370 | really need this.*/ |
357 | return; | 371 | return; |
358 | 372 | ||
359 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) | 373 | if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && |
374 | !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) | ||
360 | atmel_stop_rx(port); | 375 | atmel_stop_rx(port); |
361 | 376 | ||
362 | /* re-enable PDC transmit */ | 377 | /* re-enable PDC transmit */ |
@@ -680,7 +695,8 @@ static void atmel_tx_dma(struct uart_port *port) | |||
680 | /* Enable interrupts */ | 695 | /* Enable interrupts */ |
681 | UART_PUT_IER(port, atmel_port->tx_done_mask); | 696 | UART_PUT_IER(port, atmel_port->tx_done_mask); |
682 | } else { | 697 | } else { |
683 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | 698 | if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && |
699 | !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) { | ||
684 | /* DMA done, stop TX, start RX for RS485 */ | 700 | /* DMA done, stop TX, start RX for RS485 */ |
685 | atmel_start_rx(port); | 701 | atmel_start_rx(port); |
686 | } | 702 | } |
@@ -1407,6 +1423,48 @@ static struct uart_ops atmel_pops = { | |||
1407 | #endif | 1423 | #endif |
1408 | }; | 1424 | }; |
1409 | 1425 | ||
1426 | static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port, | ||
1427 | struct device_node *np) | ||
1428 | { | ||
1429 | u32 rs485_delay[2]; | ||
1430 | |||
1431 | /* DMA/PDC usage specification */ | ||
1432 | if (of_get_property(np, "atmel,use-dma-rx", NULL)) | ||
1433 | atmel_port->use_dma_rx = 1; | ||
1434 | else | ||
1435 | atmel_port->use_dma_rx = 0; | ||
1436 | if (of_get_property(np, "atmel,use-dma-tx", NULL)) | ||
1437 | atmel_port->use_dma_tx = 1; | ||
1438 | else | ||
1439 | atmel_port->use_dma_tx = 0; | ||
1440 | |||
1441 | /* rs485 properties */ | ||
1442 | if (of_property_read_u32_array(np, "rs485-rts-delay", | ||
1443 | rs485_delay, 2) == 0) { | ||
1444 | struct serial_rs485 *rs485conf = &atmel_port->rs485; | ||
1445 | |||
1446 | rs485conf->delay_rts_before_send = rs485_delay[0]; | ||
1447 | rs485conf->delay_rts_after_send = rs485_delay[1]; | ||
1448 | rs485conf->flags = 0; | ||
1449 | |||
1450 | if (rs485conf->delay_rts_before_send == 0 && | ||
1451 | rs485conf->delay_rts_after_send == 0) { | ||
1452 | rs485conf->flags |= SER_RS485_RTS_ON_SEND; | ||
1453 | } else { | ||
1454 | if (rs485conf->delay_rts_before_send) | ||
1455 | rs485conf->flags |= SER_RS485_RTS_BEFORE_SEND; | ||
1456 | if (rs485conf->delay_rts_after_send) | ||
1457 | rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; | ||
1458 | } | ||
1459 | |||
1460 | if (of_get_property(np, "rs485-rx-during-tx", NULL)) | ||
1461 | rs485conf->flags |= SER_RS485_RX_DURING_TX; | ||
1462 | |||
1463 | if (of_get_property(np, "linux,rs485-enabled-at-boot-time", NULL)) | ||
1464 | rs485conf->flags |= SER_RS485_ENABLED; | ||
1465 | } | ||
1466 | } | ||
1467 | |||
1410 | /* | 1468 | /* |
1411 | * Configure the port from the platform device resource info. | 1469 | * Configure the port from the platform device resource info. |
1412 | */ | 1470 | */ |
@@ -1414,13 +1472,20 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
1414 | struct platform_device *pdev) | 1472 | struct platform_device *pdev) |
1415 | { | 1473 | { |
1416 | struct uart_port *port = &atmel_port->uart; | 1474 | struct uart_port *port = &atmel_port->uart; |
1417 | struct atmel_uart_data *data = pdev->dev.platform_data; | 1475 | struct atmel_uart_data *pdata = pdev->dev.platform_data; |
1476 | |||
1477 | if (pdev->dev.of_node) { | ||
1478 | atmel_of_init_port(atmel_port, pdev->dev.of_node); | ||
1479 | } else { | ||
1480 | atmel_port->use_dma_rx = pdata->use_dma_rx; | ||
1481 | atmel_port->use_dma_tx = pdata->use_dma_tx; | ||
1482 | atmel_port->rs485 = pdata->rs485; | ||
1483 | } | ||
1418 | 1484 | ||
1419 | port->iotype = UPIO_MEM; | 1485 | port->iotype = UPIO_MEM; |
1420 | port->flags = UPF_BOOT_AUTOCONF; | 1486 | port->flags = UPF_BOOT_AUTOCONF; |
1421 | port->ops = &atmel_pops; | 1487 | port->ops = &atmel_pops; |
1422 | port->fifosize = 1; | 1488 | port->fifosize = 1; |
1423 | port->line = data->num; | ||
1424 | port->dev = &pdev->dev; | 1489 | port->dev = &pdev->dev; |
1425 | port->mapbase = pdev->resource[0].start; | 1490 | port->mapbase = pdev->resource[0].start; |
1426 | port->irq = pdev->resource[1].start; | 1491 | port->irq = pdev->resource[1].start; |
@@ -1430,10 +1495,10 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
1430 | 1495 | ||
1431 | memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); | 1496 | memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); |
1432 | 1497 | ||
1433 | if (data->regs) | 1498 | if (pdata && pdata->regs) { |
1434 | /* Already mapped by setup code */ | 1499 | /* Already mapped by setup code */ |
1435 | port->membase = data->regs; | 1500 | port->membase = pdata->regs; |
1436 | else { | 1501 | } else { |
1437 | port->flags |= UPF_IOREMAP; | 1502 | port->flags |= UPF_IOREMAP; |
1438 | port->membase = NULL; | 1503 | port->membase = NULL; |
1439 | } | 1504 | } |
@@ -1447,9 +1512,6 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
1447 | /* only enable clock when USART is in use */ | 1512 | /* only enable clock when USART is in use */ |
1448 | } | 1513 | } |
1449 | 1514 | ||
1450 | atmel_port->use_dma_rx = data->use_dma_rx; | ||
1451 | atmel_port->use_dma_tx = data->use_dma_tx; | ||
1452 | atmel_port->rs485 = data->rs485; | ||
1453 | /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ | 1515 | /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ |
1454 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) | 1516 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) |
1455 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; | 1517 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; |
@@ -1611,10 +1673,14 @@ static int __init atmel_console_init(void) | |||
1611 | if (atmel_default_console_device) { | 1673 | if (atmel_default_console_device) { |
1612 | struct atmel_uart_data *pdata = | 1674 | struct atmel_uart_data *pdata = |
1613 | atmel_default_console_device->dev.platform_data; | 1675 | atmel_default_console_device->dev.platform_data; |
1676 | int id = pdata->num; | ||
1677 | struct atmel_uart_port *port = &atmel_ports[id]; | ||
1678 | |||
1679 | port->backup_imr = 0; | ||
1680 | port->uart.line = id; | ||
1614 | 1681 | ||
1615 | add_preferred_console(ATMEL_DEVICENAME, pdata->num, NULL); | 1682 | add_preferred_console(ATMEL_DEVICENAME, id, NULL); |
1616 | atmel_init_port(&atmel_ports[pdata->num], | 1683 | atmel_init_port(port, atmel_default_console_device); |
1617 | atmel_default_console_device); | ||
1618 | register_console(&atmel_console); | 1684 | register_console(&atmel_console); |
1619 | } | 1685 | } |
1620 | 1686 | ||
@@ -1711,14 +1777,39 @@ static int atmel_serial_resume(struct platform_device *pdev) | |||
1711 | static int __devinit atmel_serial_probe(struct platform_device *pdev) | 1777 | static int __devinit atmel_serial_probe(struct platform_device *pdev) |
1712 | { | 1778 | { |
1713 | struct atmel_uart_port *port; | 1779 | struct atmel_uart_port *port; |
1780 | struct device_node *np = pdev->dev.of_node; | ||
1714 | struct atmel_uart_data *pdata = pdev->dev.platform_data; | 1781 | struct atmel_uart_data *pdata = pdev->dev.platform_data; |
1715 | void *data; | 1782 | void *data; |
1716 | int ret; | 1783 | int ret = -ENODEV; |
1717 | 1784 | ||
1718 | BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); | 1785 | BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); |
1719 | 1786 | ||
1720 | port = &atmel_ports[pdata->num]; | 1787 | if (np) |
1788 | ret = of_alias_get_id(np, "serial"); | ||
1789 | else | ||
1790 | if (pdata) | ||
1791 | ret = pdata->num; | ||
1792 | |||
1793 | if (ret < 0) | ||
1794 | /* port id not found in platform data nor device-tree aliases: | ||
1795 | * auto-enumerate it */ | ||
1796 | ret = find_first_zero_bit(&atmel_ports_in_use, | ||
1797 | sizeof(atmel_ports_in_use)); | ||
1798 | |||
1799 | if (ret > ATMEL_MAX_UART) { | ||
1800 | ret = -ENODEV; | ||
1801 | goto err; | ||
1802 | } | ||
1803 | |||
1804 | if (test_and_set_bit(ret, &atmel_ports_in_use)) { | ||
1805 | /* port already in use */ | ||
1806 | ret = -EBUSY; | ||
1807 | goto err; | ||
1808 | } | ||
1809 | |||
1810 | port = &atmel_ports[ret]; | ||
1721 | port->backup_imr = 0; | 1811 | port->backup_imr = 0; |
1812 | port->uart.line = ret; | ||
1722 | 1813 | ||
1723 | atmel_init_port(port, pdev); | 1814 | atmel_init_port(port, pdev); |
1724 | 1815 | ||
@@ -1764,7 +1855,7 @@ err_alloc_ring: | |||
1764 | clk_put(port->clk); | 1855 | clk_put(port->clk); |
1765 | port->clk = NULL; | 1856 | port->clk = NULL; |
1766 | } | 1857 | } |
1767 | 1858 | err: | |
1768 | return ret; | 1859 | return ret; |
1769 | } | 1860 | } |
1770 | 1861 | ||
@@ -1784,6 +1875,8 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev) | |||
1784 | 1875 | ||
1785 | /* "port" is allocated statically, so we shouldn't free it */ | 1876 | /* "port" is allocated statically, so we shouldn't free it */ |
1786 | 1877 | ||
1878 | clear_bit(port->line, &atmel_ports_in_use); | ||
1879 | |||
1787 | clk_put(atmel_port->clk); | 1880 | clk_put(atmel_port->clk); |
1788 | 1881 | ||
1789 | return ret; | 1882 | return ret; |
@@ -1797,6 +1890,7 @@ static struct platform_driver atmel_serial_driver = { | |||
1797 | .driver = { | 1890 | .driver = { |
1798 | .name = "atmel_usart", | 1891 | .name = "atmel_usart", |
1799 | .owner = THIS_MODULE, | 1892 | .owner = THIS_MODULE, |
1893 | .of_match_table = of_match_ptr(atmel_serial_dt_ids), | ||
1800 | }, | 1894 | }, |
1801 | }; | 1895 | }; |
1802 | 1896 | ||
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c index 891d194ae754..ee101c0d358f 100644 --- a/drivers/tty/serial/bfin_sport_uart.c +++ b/drivers/tty/serial/bfin_sport_uart.c | |||
@@ -294,7 +294,7 @@ static int sport_startup(struct uart_port *port) | |||
294 | if (request_irq(gpio_to_irq(up->cts_pin), | 294 | if (request_irq(gpio_to_irq(up->cts_pin), |
295 | sport_mctrl_cts_int, | 295 | sport_mctrl_cts_int, |
296 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | | 296 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | |
297 | IRQF_DISABLED, "BFIN_SPORT_UART_CTS", up)) { | 297 | 0, "BFIN_SPORT_UART_CTS", up)) { |
298 | up->cts_pin = -1; | 298 | up->cts_pin = -1; |
299 | dev_info(port->dev, "Unable to attach BlackFin UART over SPORT CTS interrupt. So, disable it.\n"); | 299 | dev_info(port->dev, "Unable to attach BlackFin UART over SPORT CTS interrupt. So, disable it.\n"); |
300 | } | 300 | } |
diff --git a/drivers/tty/serial/bfin_5xx.c b/drivers/tty/serial/bfin_uart.c index ff6979181ac5..66afb98b77b5 100644 --- a/drivers/tty/serial/bfin_5xx.c +++ b/drivers/tty/serial/bfin_uart.c | |||
@@ -234,8 +234,8 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
234 | status = UART_GET_LSR(uart); | 234 | status = UART_GET_LSR(uart); |
235 | UART_CLEAR_LSR(uart); | 235 | UART_CLEAR_LSR(uart); |
236 | 236 | ||
237 | ch = UART_GET_CHAR(uart); | 237 | ch = UART_GET_CHAR(uart); |
238 | uart->port.icount.rx++; | 238 | uart->port.icount.rx++; |
239 | 239 | ||
240 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ | 240 | #if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \ |
241 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) | 241 | defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE) |
@@ -667,17 +667,17 @@ static int bfin_serial_startup(struct uart_port *port) | |||
667 | kgdboc_break_enabled = 0; | 667 | kgdboc_break_enabled = 0; |
668 | else { | 668 | else { |
669 | # endif | 669 | # endif |
670 | if (request_irq(uart->port.irq, bfin_serial_rx_int, IRQF_DISABLED, | 670 | if (request_irq(uart->rx_irq, bfin_serial_rx_int, 0, |
671 | "BFIN_UART_RX", uart)) { | 671 | "BFIN_UART_RX", uart)) { |
672 | printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); | 672 | printk(KERN_NOTICE "Unable to attach BlackFin UART RX interrupt\n"); |
673 | return -EBUSY; | 673 | return -EBUSY; |
674 | } | 674 | } |
675 | 675 | ||
676 | if (request_irq | 676 | if (request_irq |
677 | (uart->port.irq+1, bfin_serial_tx_int, IRQF_DISABLED, | 677 | (uart->tx_irq, bfin_serial_tx_int, 0, |
678 | "BFIN_UART_TX", uart)) { | 678 | "BFIN_UART_TX", uart)) { |
679 | printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n"); | 679 | printk(KERN_NOTICE "Unable to attach BlackFin UART TX interrupt\n"); |
680 | free_irq(uart->port.irq, uart); | 680 | free_irq(uart->rx_irq, uart); |
681 | return -EBUSY; | 681 | return -EBUSY; |
682 | } | 682 | } |
683 | 683 | ||
@@ -692,7 +692,7 @@ static int bfin_serial_startup(struct uart_port *port) | |||
692 | */ | 692 | */ |
693 | unsigned uart_dma_ch_rx, uart_dma_ch_tx; | 693 | unsigned uart_dma_ch_rx, uart_dma_ch_tx; |
694 | 694 | ||
695 | switch (uart->port.irq) { | 695 | switch (uart->rx_irq) { |
696 | case IRQ_UART3_RX: | 696 | case IRQ_UART3_RX: |
697 | uart_dma_ch_rx = CH_UART3_RX; | 697 | uart_dma_ch_rx = CH_UART3_RX; |
698 | uart_dma_ch_tx = CH_UART3_TX; | 698 | uart_dma_ch_tx = CH_UART3_TX; |
@@ -709,16 +709,16 @@ static int bfin_serial_startup(struct uart_port *port) | |||
709 | if (uart_dma_ch_rx && | 709 | if (uart_dma_ch_rx && |
710 | request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) { | 710 | request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) { |
711 | printk(KERN_NOTICE"Fail to attach UART interrupt\n"); | 711 | printk(KERN_NOTICE"Fail to attach UART interrupt\n"); |
712 | free_irq(uart->port.irq, uart); | 712 | free_irq(uart->rx_irq, uart); |
713 | free_irq(uart->port.irq + 1, uart); | 713 | free_irq(uart->tx_irq, uart); |
714 | return -EBUSY; | 714 | return -EBUSY; |
715 | } | 715 | } |
716 | if (uart_dma_ch_tx && | 716 | if (uart_dma_ch_tx && |
717 | request_dma(uart_dma_ch_tx, "BFIN_UART_TX") < 0) { | 717 | request_dma(uart_dma_ch_tx, "BFIN_UART_TX") < 0) { |
718 | printk(KERN_NOTICE "Fail to attach UART interrupt\n"); | 718 | printk(KERN_NOTICE "Fail to attach UART interrupt\n"); |
719 | free_dma(uart_dma_ch_rx); | 719 | free_dma(uart_dma_ch_rx); |
720 | free_irq(uart->port.irq, uart); | 720 | free_irq(uart->rx_irq, uart); |
721 | free_irq(uart->port.irq + 1, uart); | 721 | free_irq(uart->tx_irq, uart); |
722 | return -EBUSY; | 722 | return -EBUSY; |
723 | } | 723 | } |
724 | } | 724 | } |
@@ -734,19 +734,18 @@ static int bfin_serial_startup(struct uart_port *port) | |||
734 | if (request_irq(gpio_to_irq(uart->cts_pin), | 734 | if (request_irq(gpio_to_irq(uart->cts_pin), |
735 | bfin_serial_mctrl_cts_int, | 735 | bfin_serial_mctrl_cts_int, |
736 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | | 736 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | |
737 | IRQF_DISABLED, "BFIN_UART_CTS", uart)) { | 737 | 0, "BFIN_UART_CTS", uart)) { |
738 | uart->cts_pin = -1; | 738 | uart->cts_pin = -1; |
739 | pr_info("Unable to attach BlackFin UART CTS interrupt. So, disable it.\n"); | 739 | pr_info("Unable to attach BlackFin UART CTS interrupt. So, disable it.\n"); |
740 | } | 740 | } |
741 | } | 741 | } |
742 | if (uart->rts_pin >= 0) { | 742 | if (uart->rts_pin >= 0) |
743 | gpio_direction_output(uart->rts_pin, 0); | 743 | gpio_direction_output(uart->rts_pin, 0); |
744 | } | ||
745 | #endif | 744 | #endif |
746 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS | 745 | #ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS |
747 | if (uart->cts_pin >= 0 && request_irq(uart->status_irq, | 746 | if (uart->cts_pin >= 0 && request_irq(uart->status_irq, |
748 | bfin_serial_mctrl_cts_int, | 747 | bfin_serial_mctrl_cts_int, |
749 | IRQF_DISABLED, "BFIN_UART_MODEM_STATUS", uart)) { | 748 | 0, "BFIN_UART_MODEM_STATUS", uart)) { |
750 | uart->cts_pin = -1; | 749 | uart->cts_pin = -1; |
751 | pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n"); | 750 | pr_info("Unable to attach BlackFin UART Modem Status interrupt.\n"); |
752 | } | 751 | } |
@@ -786,8 +785,8 @@ static void bfin_serial_shutdown(struct uart_port *port) | |||
786 | break; | 785 | break; |
787 | }; | 786 | }; |
788 | #endif | 787 | #endif |
789 | free_irq(uart->port.irq, uart); | 788 | free_irq(uart->rx_irq, uart); |
790 | free_irq(uart->port.irq+1, uart); | 789 | free_irq(uart->tx_irq, uart); |
791 | #endif | 790 | #endif |
792 | 791 | ||
793 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | 792 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS |
@@ -1091,10 +1090,18 @@ bfin_serial_console_get_options(struct bfin_serial_port *uart, int *baud, | |||
1091 | *parity = 'o'; | 1090 | *parity = 'o'; |
1092 | } | 1091 | } |
1093 | switch (lcr & 0x03) { | 1092 | switch (lcr & 0x03) { |
1094 | case 0: *bits = 5; break; | 1093 | case 0: |
1095 | case 1: *bits = 6; break; | 1094 | *bits = 5; |
1096 | case 2: *bits = 7; break; | 1095 | break; |
1097 | case 3: *bits = 8; break; | 1096 | case 1: |
1097 | *bits = 6; | ||
1098 | break; | ||
1099 | case 2: | ||
1100 | *bits = 7; | ||
1101 | break; | ||
1102 | case 3: | ||
1103 | *bits = 8; | ||
1104 | break; | ||
1098 | } | 1105 | } |
1099 | /* Set DLAB in LCR to Access DLL and DLH */ | 1106 | /* Set DLAB in LCR to Access DLL and DLH */ |
1100 | UART_SET_DLAB(uart); | 1107 | UART_SET_DLAB(uart); |
@@ -1183,7 +1190,7 @@ static struct console bfin_serial_console = { | |||
1183 | .index = -1, | 1190 | .index = -1, |
1184 | .data = &bfin_serial_reg, | 1191 | .data = &bfin_serial_reg, |
1185 | }; | 1192 | }; |
1186 | #define BFIN_SERIAL_CONSOLE &bfin_serial_console | 1193 | #define BFIN_SERIAL_CONSOLE (&bfin_serial_console) |
1187 | #else | 1194 | #else |
1188 | #define BFIN_SERIAL_CONSOLE NULL | 1195 | #define BFIN_SERIAL_CONSOLE NULL |
1189 | #endif /* CONFIG_SERIAL_BFIN_CONSOLE */ | 1196 | #endif /* CONFIG_SERIAL_BFIN_CONSOLE */ |
@@ -1312,14 +1319,22 @@ static int bfin_serial_probe(struct platform_device *pdev) | |||
1312 | } | 1319 | } |
1313 | uart->port.mapbase = res->start; | 1320 | uart->port.mapbase = res->start; |
1314 | 1321 | ||
1315 | uart->port.irq = platform_get_irq(pdev, 0); | 1322 | uart->tx_irq = platform_get_irq(pdev, 0); |
1316 | if (uart->port.irq < 0) { | 1323 | if (uart->tx_irq < 0) { |
1317 | dev_err(&pdev->dev, "No uart RX/TX IRQ specified\n"); | 1324 | dev_err(&pdev->dev, "No uart TX IRQ specified\n"); |
1325 | ret = -ENOENT; | ||
1326 | goto out_error_unmap; | ||
1327 | } | ||
1328 | |||
1329 | uart->rx_irq = platform_get_irq(pdev, 1); | ||
1330 | if (uart->rx_irq < 0) { | ||
1331 | dev_err(&pdev->dev, "No uart RX IRQ specified\n"); | ||
1318 | ret = -ENOENT; | 1332 | ret = -ENOENT; |
1319 | goto out_error_unmap; | 1333 | goto out_error_unmap; |
1320 | } | 1334 | } |
1335 | uart->port.irq = uart->rx_irq; | ||
1321 | 1336 | ||
1322 | uart->status_irq = platform_get_irq(pdev, 1); | 1337 | uart->status_irq = platform_get_irq(pdev, 2); |
1323 | if (uart->status_irq < 0) { | 1338 | if (uart->status_irq < 0) { |
1324 | dev_err(&pdev->dev, "No uart status IRQ specified\n"); | 1339 | dev_err(&pdev->dev, "No uart status IRQ specified\n"); |
1325 | ret = -ENOENT; | 1340 | ret = -ENOENT; |
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index 9488da74d4f7..b418947b7107 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/tty.h> | 33 | #include <linux/tty.h> |
34 | #include <linux/tty_flip.h> | ||
34 | #include <linux/ioport.h> | 35 | #include <linux/ioport.h> |
35 | #include <linux/init.h> | 36 | #include <linux/init.h> |
36 | #include <linux/serial.h> | 37 | #include <linux/serial.h> |
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c index 58be715913cd..b7435043f2fe 100644 --- a/drivers/tty/serial/crisv10.c +++ b/drivers/tty/serial/crisv10.c | |||
@@ -258,7 +258,7 @@ static struct e100_serial rs_table[] = { | |||
258 | .dma_out_enabled = 1, | 258 | .dma_out_enabled = 1, |
259 | .dma_out_nbr = SER0_TX_DMA_NBR, | 259 | .dma_out_nbr = SER0_TX_DMA_NBR, |
260 | .dma_out_irq_nbr = SER0_DMA_TX_IRQ_NBR, | 260 | .dma_out_irq_nbr = SER0_DMA_TX_IRQ_NBR, |
261 | .dma_out_irq_flags = IRQF_DISABLED, | 261 | .dma_out_irq_flags = 0, |
262 | .dma_out_irq_description = "serial 0 dma tr", | 262 | .dma_out_irq_description = "serial 0 dma tr", |
263 | #else | 263 | #else |
264 | .dma_out_enabled = 0, | 264 | .dma_out_enabled = 0, |
@@ -271,7 +271,7 @@ static struct e100_serial rs_table[] = { | |||
271 | .dma_in_enabled = 1, | 271 | .dma_in_enabled = 1, |
272 | .dma_in_nbr = SER0_RX_DMA_NBR, | 272 | .dma_in_nbr = SER0_RX_DMA_NBR, |
273 | .dma_in_irq_nbr = SER0_DMA_RX_IRQ_NBR, | 273 | .dma_in_irq_nbr = SER0_DMA_RX_IRQ_NBR, |
274 | .dma_in_irq_flags = IRQF_DISABLED, | 274 | .dma_in_irq_flags = 0, |
275 | .dma_in_irq_description = "serial 0 dma rec", | 275 | .dma_in_irq_description = "serial 0 dma rec", |
276 | #else | 276 | #else |
277 | .dma_in_enabled = 0, | 277 | .dma_in_enabled = 0, |
@@ -313,7 +313,7 @@ static struct e100_serial rs_table[] = { | |||
313 | .dma_out_enabled = 1, | 313 | .dma_out_enabled = 1, |
314 | .dma_out_nbr = SER1_TX_DMA_NBR, | 314 | .dma_out_nbr = SER1_TX_DMA_NBR, |
315 | .dma_out_irq_nbr = SER1_DMA_TX_IRQ_NBR, | 315 | .dma_out_irq_nbr = SER1_DMA_TX_IRQ_NBR, |
316 | .dma_out_irq_flags = IRQF_DISABLED, | 316 | .dma_out_irq_flags = 0, |
317 | .dma_out_irq_description = "serial 1 dma tr", | 317 | .dma_out_irq_description = "serial 1 dma tr", |
318 | #else | 318 | #else |
319 | .dma_out_enabled = 0, | 319 | .dma_out_enabled = 0, |
@@ -326,7 +326,7 @@ static struct e100_serial rs_table[] = { | |||
326 | .dma_in_enabled = 1, | 326 | .dma_in_enabled = 1, |
327 | .dma_in_nbr = SER1_RX_DMA_NBR, | 327 | .dma_in_nbr = SER1_RX_DMA_NBR, |
328 | .dma_in_irq_nbr = SER1_DMA_RX_IRQ_NBR, | 328 | .dma_in_irq_nbr = SER1_DMA_RX_IRQ_NBR, |
329 | .dma_in_irq_flags = IRQF_DISABLED, | 329 | .dma_in_irq_flags = 0, |
330 | .dma_in_irq_description = "serial 1 dma rec", | 330 | .dma_in_irq_description = "serial 1 dma rec", |
331 | #else | 331 | #else |
332 | .dma_in_enabled = 0, | 332 | .dma_in_enabled = 0, |
@@ -369,7 +369,7 @@ static struct e100_serial rs_table[] = { | |||
369 | .dma_out_enabled = 1, | 369 | .dma_out_enabled = 1, |
370 | .dma_out_nbr = SER2_TX_DMA_NBR, | 370 | .dma_out_nbr = SER2_TX_DMA_NBR, |
371 | .dma_out_irq_nbr = SER2_DMA_TX_IRQ_NBR, | 371 | .dma_out_irq_nbr = SER2_DMA_TX_IRQ_NBR, |
372 | .dma_out_irq_flags = IRQF_DISABLED, | 372 | .dma_out_irq_flags = 0, |
373 | .dma_out_irq_description = "serial 2 dma tr", | 373 | .dma_out_irq_description = "serial 2 dma tr", |
374 | #else | 374 | #else |
375 | .dma_out_enabled = 0, | 375 | .dma_out_enabled = 0, |
@@ -382,7 +382,7 @@ static struct e100_serial rs_table[] = { | |||
382 | .dma_in_enabled = 1, | 382 | .dma_in_enabled = 1, |
383 | .dma_in_nbr = SER2_RX_DMA_NBR, | 383 | .dma_in_nbr = SER2_RX_DMA_NBR, |
384 | .dma_in_irq_nbr = SER2_DMA_RX_IRQ_NBR, | 384 | .dma_in_irq_nbr = SER2_DMA_RX_IRQ_NBR, |
385 | .dma_in_irq_flags = IRQF_DISABLED, | 385 | .dma_in_irq_flags = 0, |
386 | .dma_in_irq_description = "serial 2 dma rec", | 386 | .dma_in_irq_description = "serial 2 dma rec", |
387 | #else | 387 | #else |
388 | .dma_in_enabled = 0, | 388 | .dma_in_enabled = 0, |
@@ -423,7 +423,7 @@ static struct e100_serial rs_table[] = { | |||
423 | .dma_out_enabled = 1, | 423 | .dma_out_enabled = 1, |
424 | .dma_out_nbr = SER3_TX_DMA_NBR, | 424 | .dma_out_nbr = SER3_TX_DMA_NBR, |
425 | .dma_out_irq_nbr = SER3_DMA_TX_IRQ_NBR, | 425 | .dma_out_irq_nbr = SER3_DMA_TX_IRQ_NBR, |
426 | .dma_out_irq_flags = IRQF_DISABLED, | 426 | .dma_out_irq_flags = 0, |
427 | .dma_out_irq_description = "serial 3 dma tr", | 427 | .dma_out_irq_description = "serial 3 dma tr", |
428 | #else | 428 | #else |
429 | .dma_out_enabled = 0, | 429 | .dma_out_enabled = 0, |
@@ -436,7 +436,7 @@ static struct e100_serial rs_table[] = { | |||
436 | .dma_in_enabled = 1, | 436 | .dma_in_enabled = 1, |
437 | .dma_in_nbr = SER3_RX_DMA_NBR, | 437 | .dma_in_nbr = SER3_RX_DMA_NBR, |
438 | .dma_in_irq_nbr = SER3_DMA_RX_IRQ_NBR, | 438 | .dma_in_irq_nbr = SER3_DMA_RX_IRQ_NBR, |
439 | .dma_in_irq_flags = IRQF_DISABLED, | 439 | .dma_in_irq_flags = 0, |
440 | .dma_in_irq_description = "serial 3 dma rec", | 440 | .dma_in_irq_description = "serial 3 dma rec", |
441 | #else | 441 | #else |
442 | .dma_in_enabled = 0, | 442 | .dma_in_enabled = 0, |
@@ -1788,7 +1788,7 @@ static unsigned int handle_descr_data(struct e100_serial *info, | |||
1788 | struct etrax_recv_buffer *buffer = phys_to_virt(descr->buf) - sizeof *buffer; | 1788 | struct etrax_recv_buffer *buffer = phys_to_virt(descr->buf) - sizeof *buffer; |
1789 | 1789 | ||
1790 | if (info->recv_cnt + recvl > 65536) { | 1790 | if (info->recv_cnt + recvl > 65536) { |
1791 | printk(KERN_CRIT | 1791 | printk(KERN_WARNING |
1792 | "%s: Too much pending incoming serial data! Dropping %u bytes.\n", __func__, recvl); | 1792 | "%s: Too much pending incoming serial data! Dropping %u bytes.\n", __func__, recvl); |
1793 | return 0; | 1793 | return 0; |
1794 | } | 1794 | } |
@@ -3813,13 +3813,13 @@ rs_close(struct tty_struct *tty, struct file * filp) | |||
3813 | * one, we've got real problems, since it means the | 3813 | * one, we've got real problems, since it means the |
3814 | * serial port won't be shutdown. | 3814 | * serial port won't be shutdown. |
3815 | */ | 3815 | */ |
3816 | printk(KERN_CRIT | 3816 | printk(KERN_ERR |
3817 | "rs_close: bad serial port count; tty->count is 1, " | 3817 | "rs_close: bad serial port count; tty->count is 1, " |
3818 | "info->count is %d\n", info->count); | 3818 | "info->count is %d\n", info->count); |
3819 | info->count = 1; | 3819 | info->count = 1; |
3820 | } | 3820 | } |
3821 | if (--info->count < 0) { | 3821 | if (--info->count < 0) { |
3822 | printk(KERN_CRIT "rs_close: bad serial port count for ttyS%d: %d\n", | 3822 | printk(KERN_ERR "rs_close: bad serial port count for ttyS%d: %d\n", |
3823 | info->line, info->count); | 3823 | info->line, info->count); |
3824 | info->count = 0; | 3824 | info->count = 0; |
3825 | } | 3825 | } |
@@ -4452,7 +4452,7 @@ static int __init rs_init(void) | |||
4452 | #if defined(CONFIG_ETRAX_RS485_ON_PA) | 4452 | #if defined(CONFIG_ETRAX_RS485_ON_PA) |
4453 | if (cris_io_interface_allocate_pins(if_serial_0, 'a', rs485_pa_bit, | 4453 | if (cris_io_interface_allocate_pins(if_serial_0, 'a', rs485_pa_bit, |
4454 | rs485_pa_bit)) { | 4454 | rs485_pa_bit)) { |
4455 | printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " | 4455 | printk(KERN_ERR "ETRAX100LX serial: Could not allocate " |
4456 | "RS485 pin\n"); | 4456 | "RS485 pin\n"); |
4457 | put_tty_driver(driver); | 4457 | put_tty_driver(driver); |
4458 | return -EBUSY; | 4458 | return -EBUSY; |
@@ -4461,7 +4461,7 @@ static int __init rs_init(void) | |||
4461 | #if defined(CONFIG_ETRAX_RS485_ON_PORT_G) | 4461 | #if defined(CONFIG_ETRAX_RS485_ON_PORT_G) |
4462 | if (cris_io_interface_allocate_pins(if_serial_0, 'g', rs485_pa_bit, | 4462 | if (cris_io_interface_allocate_pins(if_serial_0, 'g', rs485_pa_bit, |
4463 | rs485_port_g_bit)) { | 4463 | rs485_port_g_bit)) { |
4464 | printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " | 4464 | printk(KERN_ERR "ETRAX100LX serial: Could not allocate " |
4465 | "RS485 pin\n"); | 4465 | "RS485 pin\n"); |
4466 | put_tty_driver(driver); | 4466 | put_tty_driver(driver); |
4467 | return -EBUSY; | 4467 | return -EBUSY; |
@@ -4494,7 +4494,7 @@ static int __init rs_init(void) | |||
4494 | if (info->enabled) { | 4494 | if (info->enabled) { |
4495 | if (cris_request_io_interface(info->io_if, | 4495 | if (cris_request_io_interface(info->io_if, |
4496 | info->io_if_description)) { | 4496 | info->io_if_description)) { |
4497 | printk(KERN_CRIT "ETRAX100LX async serial: " | 4497 | printk(KERN_ERR "ETRAX100LX async serial: " |
4498 | "Could not allocate IO pins for " | 4498 | "Could not allocate IO pins for " |
4499 | "%s, port %d\n", | 4499 | "%s, port %d\n", |
4500 | info->io_if_description, i); | 4500 | info->io_if_description, i); |
@@ -4558,7 +4558,7 @@ static int __init rs_init(void) | |||
4558 | /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */ | 4558 | /* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */ |
4559 | 4559 | ||
4560 | if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, | 4560 | if (request_irq(SERIAL_IRQ_NBR, ser_interrupt, |
4561 | IRQF_SHARED | IRQF_DISABLED, "serial ", driver)) | 4561 | IRQF_SHARED, "serial ", driver)) |
4562 | panic("%s: Failed to request irq8", __func__); | 4562 | panic("%s: Failed to request irq8", __func__); |
4563 | 4563 | ||
4564 | #endif | 4564 | #endif |
diff --git a/drivers/tty/serial/dz.c b/drivers/tty/serial/dz.c index ddc487a2d42f..e3699a84049f 100644 --- a/drivers/tty/serial/dz.c +++ b/drivers/tty/serial/dz.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/serial_core.h> | 47 | #include <linux/serial_core.h> |
48 | #include <linux/sysrq.h> | 48 | #include <linux/sysrq.h> |
49 | #include <linux/tty.h> | 49 | #include <linux/tty.h> |
50 | #include <linux/tty_flip.h> | ||
50 | 51 | ||
51 | #include <linux/atomic.h> | 52 | #include <linux/atomic.h> |
52 | #include <asm/bootinfo.h> | 53 | #include <asm/bootinfo.h> |
diff --git a/drivers/tty/serial/icom.c b/drivers/tty/serial/icom.c index 8a869e58f6d7..d55709a7a75a 100644 --- a/drivers/tty/serial/icom.c +++ b/drivers/tty/serial/icom.c | |||
@@ -1554,7 +1554,7 @@ static int __devinit icom_probe(struct pci_dev *dev, | |||
1554 | 1554 | ||
1555 | /* save off irq and request irq line */ | 1555 | /* save off irq and request irq line */ |
1556 | if ( (retval = request_irq(dev->irq, icom_interrupt, | 1556 | if ( (retval = request_irq(dev->irq, icom_interrupt, |
1557 | IRQF_DISABLED | IRQF_SHARED, ICOM_DRIVER_NAME, | 1557 | IRQF_SHARED, ICOM_DRIVER_NAME, |
1558 | (void *) icom_adapter))) { | 1558 | (void *) icom_adapter))) { |
1559 | goto probe_exit2; | 1559 | goto probe_exit2; |
1560 | } | 1560 | } |
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 7e91b3d368cd..54ffdc6243f9 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c | |||
@@ -508,8 +508,10 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) | |||
508 | if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx)) | 508 | if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx)) |
509 | continue; | 509 | continue; |
510 | 510 | ||
511 | if (rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) ) { | 511 | if (unlikely(rx & URXD_ERR)) { |
512 | if (rx & URXD_PRERR) | 512 | if (rx & URXD_BRK) |
513 | sport->port.icount.brk++; | ||
514 | else if (rx & URXD_PRERR) | ||
513 | sport->port.icount.parity++; | 515 | sport->port.icount.parity++; |
514 | else if (rx & URXD_FRMERR) | 516 | else if (rx & URXD_FRMERR) |
515 | sport->port.icount.frame++; | 517 | sport->port.icount.frame++; |
@@ -524,7 +526,9 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) | |||
524 | 526 | ||
525 | rx &= sport->port.read_status_mask; | 527 | rx &= sport->port.read_status_mask; |
526 | 528 | ||
527 | if (rx & URXD_PRERR) | 529 | if (rx & URXD_BRK) |
530 | flg = TTY_BREAK; | ||
531 | else if (rx & URXD_PRERR) | ||
528 | flg = TTY_PARITY; | 532 | flg = TTY_PARITY; |
529 | else if (rx & URXD_FRMERR) | 533 | else if (rx & URXD_FRMERR) |
530 | flg = TTY_FRAME; | 534 | flg = TTY_FRAME; |
diff --git a/drivers/tty/serial/ioc3_serial.c b/drivers/tty/serial/ioc3_serial.c index ee43efc7bdcc..758ff310f7f8 100644 --- a/drivers/tty/serial/ioc3_serial.c +++ b/drivers/tty/serial/ioc3_serial.c | |||
@@ -13,6 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/tty.h> | 15 | #include <linux/tty.h> |
16 | #include <linux/tty_flip.h> | ||
16 | #include <linux/serial.h> | 17 | #include <linux/serial.h> |
17 | #include <linux/circ_buf.h> | 18 | #include <linux/circ_buf.h> |
18 | #include <linux/serial_reg.h> | 19 | #include <linux/serial_reg.h> |
diff --git a/drivers/tty/serial/ioc4_serial.c b/drivers/tty/serial/ioc4_serial.c index fcfe82653ac8..6b36c1554d7e 100644 --- a/drivers/tty/serial/ioc4_serial.c +++ b/drivers/tty/serial/ioc4_serial.c | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
16 | #include <linux/tty.h> | 16 | #include <linux/tty.h> |
17 | #include <linux/tty_flip.h> | ||
17 | #include <linux/serial.h> | 18 | #include <linux/serial.h> |
18 | #include <linux/serialP.h> | 19 | #include <linux/serialP.h> |
19 | #include <linux/circ_buf.h> | 20 | #include <linux/circ_buf.h> |
diff --git a/drivers/tty/serial/jsm/jsm.h b/drivers/tty/serial/jsm/jsm.h index b704c8ce0d71..529bec6edaf8 100644 --- a/drivers/tty/serial/jsm/jsm.h +++ b/drivers/tty/serial/jsm/jsm.h | |||
@@ -88,7 +88,6 @@ enum { | |||
88 | 88 | ||
89 | /* 4 extra for alignment play space */ | 89 | /* 4 extra for alignment play space */ |
90 | #define WRITEBUFLEN ((4096) + 4) | 90 | #define WRITEBUFLEN ((4096) + 4) |
91 | #define MYFLIPLEN N_TTY_BUF_SIZE | ||
92 | 91 | ||
93 | #define JSM_VERSION "jsm: 1.2-1-INKERNEL" | 92 | #define JSM_VERSION "jsm: 1.2-1-INKERNEL" |
94 | #define JSM_PARTNUM "40002438_A-INKERNEL" | 93 | #define JSM_PARTNUM "40002438_A-INKERNEL" |
@@ -150,7 +149,6 @@ struct jsm_board | |||
150 | u32 bd_uart_offset; /* Space between each UART */ | 149 | u32 bd_uart_offset; /* Space between each UART */ |
151 | 150 | ||
152 | struct jsm_channel *channels[MAXPORTS]; /* array of pointers to our channels. */ | 151 | struct jsm_channel *channels[MAXPORTS]; /* array of pointers to our channels. */ |
153 | char *flipbuf; /* Our flip buffer, alloced if board is found */ | ||
154 | 152 | ||
155 | u32 bd_dividend; /* Board/UARTs specific dividend */ | 153 | u32 bd_dividend; /* Board/UARTs specific dividend */ |
156 | 154 | ||
@@ -177,16 +175,13 @@ struct jsm_board | |||
177 | #define CH_TX_FIFO_LWM 0x0800 /* TX Fifo is below Low Water */ | 175 | #define CH_TX_FIFO_LWM 0x0800 /* TX Fifo is below Low Water */ |
178 | #define CH_BREAK_SENDING 0x1000 /* Break is being sent */ | 176 | #define CH_BREAK_SENDING 0x1000 /* Break is being sent */ |
179 | #define CH_LOOPBACK 0x2000 /* Channel is in lookback mode */ | 177 | #define CH_LOOPBACK 0x2000 /* Channel is in lookback mode */ |
180 | #define CH_FLIPBUF_IN_USE 0x4000 /* Channel's flipbuf is in use */ | ||
181 | #define CH_BAUD0 0x08000 /* Used for checking B0 transitions */ | 178 | #define CH_BAUD0 0x08000 /* Used for checking B0 transitions */ |
182 | 179 | ||
183 | /* Our Read/Error/Write queue sizes */ | 180 | /* Our Read/Error/Write queue sizes */ |
184 | #define RQUEUEMASK 0x1FFF /* 8 K - 1 */ | 181 | #define RQUEUEMASK 0x1FFF /* 8 K - 1 */ |
185 | #define EQUEUEMASK 0x1FFF /* 8 K - 1 */ | 182 | #define EQUEUEMASK 0x1FFF /* 8 K - 1 */ |
186 | #define WQUEUEMASK 0x0FFF /* 4 K - 1 */ | ||
187 | #define RQUEUESIZE (RQUEUEMASK + 1) | 183 | #define RQUEUESIZE (RQUEUEMASK + 1) |
188 | #define EQUEUESIZE RQUEUESIZE | 184 | #define EQUEUESIZE RQUEUESIZE |
189 | #define WQUEUESIZE (WQUEUEMASK + 1) | ||
190 | 185 | ||
191 | 186 | ||
192 | /************************************************************************ | 187 | /************************************************************************ |
@@ -226,10 +221,6 @@ struct jsm_channel { | |||
226 | u16 ch_e_head; /* Head location of the error queue */ | 221 | u16 ch_e_head; /* Head location of the error queue */ |
227 | u16 ch_e_tail; /* Tail location of the error queue */ | 222 | u16 ch_e_tail; /* Tail location of the error queue */ |
228 | 223 | ||
229 | u8 *ch_wqueue; /* Our write queue buffer - malloc'ed */ | ||
230 | u16 ch_w_head; /* Head location of the write queue */ | ||
231 | u16 ch_w_tail; /* Tail location of the write queue */ | ||
232 | |||
233 | u64 ch_rxcount; /* total of data received so far */ | 224 | u64 ch_rxcount; /* total of data received so far */ |
234 | u64 ch_txcount; /* total of data transmitted so far */ | 225 | u64 ch_txcount; /* total of data transmitted so far */ |
235 | 226 | ||
@@ -378,7 +369,6 @@ extern int jsm_debug; | |||
378 | * Prototypes for non-static functions used in more than one module | 369 | * Prototypes for non-static functions used in more than one module |
379 | * | 370 | * |
380 | *************************************************************************/ | 371 | *************************************************************************/ |
381 | int jsm_tty_write(struct uart_port *port); | ||
382 | int jsm_tty_init(struct jsm_board *); | 372 | int jsm_tty_init(struct jsm_board *); |
383 | int jsm_uart_port_init(struct jsm_board *); | 373 | int jsm_uart_port_init(struct jsm_board *); |
384 | int jsm_remove_uart_port(struct jsm_board *); | 374 | int jsm_remove_uart_port(struct jsm_board *); |
diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c index 96da17868cf3..648b6a3efa32 100644 --- a/drivers/tty/serial/jsm/jsm_driver.c +++ b/drivers/tty/serial/jsm/jsm_driver.c | |||
@@ -160,27 +160,10 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device | |||
160 | dev_info(&pdev->dev, "board %d: Digi Neo (rev %d), irq %d\n", | 160 | dev_info(&pdev->dev, "board %d: Digi Neo (rev %d), irq %d\n", |
161 | adapter_count, brd->rev, brd->irq); | 161 | adapter_count, brd->rev, brd->irq); |
162 | 162 | ||
163 | /* | ||
164 | * allocate flip buffer for board. | ||
165 | * | ||
166 | * Okay to malloc with GFP_KERNEL, we are not at interrupt | ||
167 | * context, and there are no locks held. | ||
168 | */ | ||
169 | brd->flipbuf = kzalloc(MYFLIPLEN, GFP_KERNEL); | ||
170 | if (!brd->flipbuf) { | ||
171 | /* XXX: leaking all resources from jsm_tty_init and | ||
172 | jsm_uart_port_init here! */ | ||
173 | dev_err(&pdev->dev, "memory allocation for flipbuf failed\n"); | ||
174 | rc = -ENOMEM; | ||
175 | goto out_free_uart; | ||
176 | } | ||
177 | |||
178 | pci_set_drvdata(pdev, brd); | 163 | pci_set_drvdata(pdev, brd); |
179 | pci_save_state(pdev); | 164 | pci_save_state(pdev); |
180 | 165 | ||
181 | return 0; | 166 | return 0; |
182 | out_free_uart: | ||
183 | jsm_remove_uart_port(brd); | ||
184 | out_free_irq: | 167 | out_free_irq: |
185 | jsm_remove_uart_port(brd); | 168 | jsm_remove_uart_port(brd); |
186 | free_irq(brd->irq, brd); | 169 | free_irq(brd->irq, brd); |
@@ -211,14 +194,12 @@ static void __devexit jsm_remove_one(struct pci_dev *pdev) | |||
211 | if (brd->channels[i]) { | 194 | if (brd->channels[i]) { |
212 | kfree(brd->channels[i]->ch_rqueue); | 195 | kfree(brd->channels[i]->ch_rqueue); |
213 | kfree(brd->channels[i]->ch_equeue); | 196 | kfree(brd->channels[i]->ch_equeue); |
214 | kfree(brd->channels[i]->ch_wqueue); | ||
215 | kfree(brd->channels[i]); | 197 | kfree(brd->channels[i]); |
216 | } | 198 | } |
217 | } | 199 | } |
218 | 200 | ||
219 | pci_release_regions(pdev); | 201 | pci_release_regions(pdev); |
220 | pci_disable_device(pdev); | 202 | pci_disable_device(pdev); |
221 | kfree(brd->flipbuf); | ||
222 | kfree(brd); | 203 | kfree(brd); |
223 | } | 204 | } |
224 | 205 | ||
diff --git a/drivers/tty/serial/jsm/jsm_neo.c b/drivers/tty/serial/jsm/jsm_neo.c index 4538c3e3646e..81dfafa11b0b 100644 --- a/drivers/tty/serial/jsm/jsm_neo.c +++ b/drivers/tty/serial/jsm/jsm_neo.c | |||
@@ -496,12 +496,15 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch) | |||
496 | int s; | 496 | int s; |
497 | int qlen; | 497 | int qlen; |
498 | u32 len_written = 0; | 498 | u32 len_written = 0; |
499 | struct circ_buf *circ; | ||
499 | 500 | ||
500 | if (!ch) | 501 | if (!ch) |
501 | return; | 502 | return; |
502 | 503 | ||
504 | circ = &ch->uart_port.state->xmit; | ||
505 | |||
503 | /* No data to write to the UART */ | 506 | /* No data to write to the UART */ |
504 | if (ch->ch_w_tail == ch->ch_w_head) | 507 | if (uart_circ_empty(circ)) |
505 | return; | 508 | return; |
506 | 509 | ||
507 | /* If port is "stopped", don't send any data to the UART */ | 510 | /* If port is "stopped", don't send any data to the UART */ |
@@ -517,11 +520,10 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch) | |||
517 | if (ch->ch_cached_lsr & UART_LSR_THRE) { | 520 | if (ch->ch_cached_lsr & UART_LSR_THRE) { |
518 | ch->ch_cached_lsr &= ~(UART_LSR_THRE); | 521 | ch->ch_cached_lsr &= ~(UART_LSR_THRE); |
519 | 522 | ||
520 | writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx); | 523 | writeb(circ->buf[circ->tail], &ch->ch_neo_uart->txrx); |
521 | jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev, | 524 | jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev, |
522 | "Tx data: %x\n", ch->ch_wqueue[ch->ch_w_head]); | 525 | "Tx data: %x\n", circ->buf[circ->tail]); |
523 | ch->ch_w_tail++; | 526 | circ->tail = (circ->tail + 1) & (UART_XMIT_SIZE - 1); |
524 | ch->ch_w_tail &= WQUEUEMASK; | ||
525 | ch->ch_txcount++; | 527 | ch->ch_txcount++; |
526 | } | 528 | } |
527 | return; | 529 | return; |
@@ -536,36 +538,36 @@ static void neo_copy_data_from_queue_to_uart(struct jsm_channel *ch) | |||
536 | n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel; | 538 | n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel; |
537 | 539 | ||
538 | /* cache head and tail of queue */ | 540 | /* cache head and tail of queue */ |
539 | head = ch->ch_w_head & WQUEUEMASK; | 541 | head = circ->head & (UART_XMIT_SIZE - 1); |
540 | tail = ch->ch_w_tail & WQUEUEMASK; | 542 | tail = circ->tail & (UART_XMIT_SIZE - 1); |
541 | qlen = (head - tail) & WQUEUEMASK; | 543 | qlen = uart_circ_chars_pending(circ); |
542 | 544 | ||
543 | /* Find minimum of the FIFO space, versus queue length */ | 545 | /* Find minimum of the FIFO space, versus queue length */ |
544 | n = min(n, qlen); | 546 | n = min(n, qlen); |
545 | 547 | ||
546 | while (n > 0) { | 548 | while (n > 0) { |
547 | 549 | ||
548 | s = ((head >= tail) ? head : WQUEUESIZE) - tail; | 550 | s = ((head >= tail) ? head : UART_XMIT_SIZE) - tail; |
549 | s = min(s, n); | 551 | s = min(s, n); |
550 | 552 | ||
551 | if (s <= 0) | 553 | if (s <= 0) |
552 | break; | 554 | break; |
553 | 555 | ||
554 | memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s); | 556 | memcpy_toio(&ch->ch_neo_uart->txrxburst, circ->buf + tail, s); |
555 | /* Add and flip queue if needed */ | 557 | /* Add and flip queue if needed */ |
556 | tail = (tail + s) & WQUEUEMASK; | 558 | tail = (tail + s) & (UART_XMIT_SIZE - 1); |
557 | n -= s; | 559 | n -= s; |
558 | ch->ch_txcount += s; | 560 | ch->ch_txcount += s; |
559 | len_written += s; | 561 | len_written += s; |
560 | } | 562 | } |
561 | 563 | ||
562 | /* Update the final tail */ | 564 | /* Update the final tail */ |
563 | ch->ch_w_tail = tail & WQUEUEMASK; | 565 | circ->tail = tail & (UART_XMIT_SIZE - 1); |
564 | 566 | ||
565 | if (len_written >= ch->ch_t_tlevel) | 567 | if (len_written >= ch->ch_t_tlevel) |
566 | ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); | 568 | ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM); |
567 | 569 | ||
568 | if (!jsm_tty_write(&ch->uart_port)) | 570 | if (uart_circ_empty(circ)) |
569 | uart_write_wakeup(&ch->uart_port); | 571 | uart_write_wakeup(&ch->uart_port); |
570 | } | 572 | } |
571 | 573 | ||
@@ -946,7 +948,6 @@ static void neo_param(struct jsm_channel *ch) | |||
946 | if ((ch->ch_c_cflag & (CBAUD)) == 0) { | 948 | if ((ch->ch_c_cflag & (CBAUD)) == 0) { |
947 | ch->ch_r_head = ch->ch_r_tail = 0; | 949 | ch->ch_r_head = ch->ch_r_tail = 0; |
948 | ch->ch_e_head = ch->ch_e_tail = 0; | 950 | ch->ch_e_head = ch->ch_e_tail = 0; |
949 | ch->ch_w_head = ch->ch_w_tail = 0; | ||
950 | 951 | ||
951 | neo_flush_uart_write(ch); | 952 | neo_flush_uart_write(ch); |
952 | neo_flush_uart_read(ch); | 953 | neo_flush_uart_read(ch); |
diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 7a4a914ecff0..434bd881fcae 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c | |||
@@ -118,6 +118,19 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
118 | udelay(10); | 118 | udelay(10); |
119 | } | 119 | } |
120 | 120 | ||
121 | /* | ||
122 | * jsm_tty_write() | ||
123 | * | ||
124 | * Take data from the user or kernel and send it out to the FEP. | ||
125 | * In here exists all the Transparent Print magic as well. | ||
126 | */ | ||
127 | static void jsm_tty_write(struct uart_port *port) | ||
128 | { | ||
129 | struct jsm_channel *channel; | ||
130 | channel = container_of(port, struct jsm_channel, uart_port); | ||
131 | channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel); | ||
132 | } | ||
133 | |||
121 | static void jsm_tty_start_tx(struct uart_port *port) | 134 | static void jsm_tty_start_tx(struct uart_port *port) |
122 | { | 135 | { |
123 | struct jsm_channel *channel = (struct jsm_channel *)port; | 136 | struct jsm_channel *channel = (struct jsm_channel *)port; |
@@ -216,14 +229,6 @@ static int jsm_tty_open(struct uart_port *port) | |||
216 | return -ENOMEM; | 229 | return -ENOMEM; |
217 | } | 230 | } |
218 | } | 231 | } |
219 | if (!channel->ch_wqueue) { | ||
220 | channel->ch_wqueue = kzalloc(WQUEUESIZE, GFP_KERNEL); | ||
221 | if (!channel->ch_wqueue) { | ||
222 | jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev, | ||
223 | "unable to allocate write queue buf"); | ||
224 | return -ENOMEM; | ||
225 | } | ||
226 | } | ||
227 | 232 | ||
228 | channel->ch_flags &= ~(CH_OPENING); | 233 | channel->ch_flags &= ~(CH_OPENING); |
229 | /* | 234 | /* |
@@ -237,7 +242,6 @@ static int jsm_tty_open(struct uart_port *port) | |||
237 | */ | 242 | */ |
238 | channel->ch_r_head = channel->ch_r_tail = 0; | 243 | channel->ch_r_head = channel->ch_r_tail = 0; |
239 | channel->ch_e_head = channel->ch_e_tail = 0; | 244 | channel->ch_e_head = channel->ch_e_tail = 0; |
240 | channel->ch_w_head = channel->ch_w_tail = 0; | ||
241 | 245 | ||
242 | brd->bd_ops->flush_uart_write(channel); | 246 | brd->bd_ops->flush_uart_write(channel); |
243 | brd->bd_ops->flush_uart_read(channel); | 247 | brd->bd_ops->flush_uart_read(channel); |
@@ -836,75 +840,3 @@ void jsm_check_queue_flow_control(struct jsm_channel *ch) | |||
836 | } | 840 | } |
837 | } | 841 | } |
838 | } | 842 | } |
839 | |||
840 | /* | ||
841 | * jsm_tty_write() | ||
842 | * | ||
843 | * Take data from the user or kernel and send it out to the FEP. | ||
844 | * In here exists all the Transparent Print magic as well. | ||
845 | */ | ||
846 | int jsm_tty_write(struct uart_port *port) | ||
847 | { | ||
848 | int bufcount; | ||
849 | int data_count = 0,data_count1 =0; | ||
850 | u16 head; | ||
851 | u16 tail; | ||
852 | u16 tmask; | ||
853 | u32 remain; | ||
854 | int temp_tail = port->state->xmit.tail; | ||
855 | struct jsm_channel *channel = (struct jsm_channel *)port; | ||
856 | |||
857 | tmask = WQUEUEMASK; | ||
858 | head = (channel->ch_w_head) & tmask; | ||
859 | tail = (channel->ch_w_tail) & tmask; | ||
860 | |||
861 | if ((bufcount = tail - head - 1) < 0) | ||
862 | bufcount += WQUEUESIZE; | ||
863 | |||
864 | bufcount = min(bufcount, 56); | ||
865 | remain = WQUEUESIZE - head; | ||
866 | |||
867 | data_count = 0; | ||
868 | if (bufcount >= remain) { | ||
869 | bufcount -= remain; | ||
870 | while ((port->state->xmit.head != temp_tail) && | ||
871 | (data_count < remain)) { | ||
872 | channel->ch_wqueue[head++] = | ||
873 | port->state->xmit.buf[temp_tail]; | ||
874 | |||
875 | temp_tail++; | ||
876 | temp_tail &= (UART_XMIT_SIZE - 1); | ||
877 | data_count++; | ||
878 | } | ||
879 | if (data_count == remain) head = 0; | ||
880 | } | ||
881 | |||
882 | data_count1 = 0; | ||
883 | if (bufcount > 0) { | ||
884 | remain = bufcount; | ||
885 | while ((port->state->xmit.head != temp_tail) && | ||
886 | (data_count1 < remain)) { | ||
887 | channel->ch_wqueue[head++] = | ||
888 | port->state->xmit.buf[temp_tail]; | ||
889 | |||
890 | temp_tail++; | ||
891 | temp_tail &= (UART_XMIT_SIZE - 1); | ||
892 | data_count1++; | ||
893 | |||
894 | } | ||
895 | } | ||
896 | |||
897 | port->state->xmit.tail = temp_tail; | ||
898 | |||
899 | data_count += data_count1; | ||
900 | if (data_count) { | ||
901 | head &= tmask; | ||
902 | channel->ch_w_head = head; | ||
903 | } | ||
904 | |||
905 | if (data_count) { | ||
906 | channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel); | ||
907 | } | ||
908 | |||
909 | return data_count; | ||
910 | } | ||
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index bc95f52cad8b..96c1cacc7360 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c | |||
@@ -338,21 +338,21 @@ lqasc_startup(struct uart_port *port) | |||
338 | ASCCON_ROEN, port->membase + LTQ_ASC_CON); | 338 | ASCCON_ROEN, port->membase + LTQ_ASC_CON); |
339 | 339 | ||
340 | retval = request_irq(ltq_port->tx_irq, lqasc_tx_int, | 340 | retval = request_irq(ltq_port->tx_irq, lqasc_tx_int, |
341 | IRQF_DISABLED, "asc_tx", port); | 341 | 0, "asc_tx", port); |
342 | if (retval) { | 342 | if (retval) { |
343 | pr_err("failed to request lqasc_tx_int\n"); | 343 | pr_err("failed to request lqasc_tx_int\n"); |
344 | return retval; | 344 | return retval; |
345 | } | 345 | } |
346 | 346 | ||
347 | retval = request_irq(ltq_port->rx_irq, lqasc_rx_int, | 347 | retval = request_irq(ltq_port->rx_irq, lqasc_rx_int, |
348 | IRQF_DISABLED, "asc_rx", port); | 348 | 0, "asc_rx", port); |
349 | if (retval) { | 349 | if (retval) { |
350 | pr_err("failed to request lqasc_rx_int\n"); | 350 | pr_err("failed to request lqasc_rx_int\n"); |
351 | goto err1; | 351 | goto err1; |
352 | } | 352 | } |
353 | 353 | ||
354 | retval = request_irq(ltq_port->err_irq, lqasc_err_int, | 354 | retval = request_irq(ltq_port->err_irq, lqasc_err_int, |
355 | IRQF_DISABLED, "asc_err", port); | 355 | 0, "asc_err", port); |
356 | if (retval) { | 356 | if (retval) { |
357 | pr_err("failed to request lqasc_err_int\n"); | 357 | pr_err("failed to request lqasc_err_int\n"); |
358 | goto err2; | 358 | goto err2; |
diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/m32r_sio.c index 8e07517f8acd..08018934e013 100644 --- a/drivers/tty/serial/m32r_sio.c +++ b/drivers/tty/serial/m32r_sio.c | |||
@@ -32,6 +32,7 @@ | |||
32 | 32 | ||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/tty.h> | 34 | #include <linux/tty.h> |
35 | #include <linux/tty_flip.h> | ||
35 | #include <linux/ioport.h> | 36 | #include <linux/ioport.h> |
36 | #include <linux/init.h> | 37 | #include <linux/init.h> |
37 | #include <linux/console.h> | 38 | #include <linux/console.h> |
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index 7b951adac54b..2af5aa5f3a80 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #include <linux/serial.h> | 47 | #include <linux/serial.h> |
48 | #include <linux/spi/spi.h> | 48 | #include <linux/spi/spi.h> |
49 | #include <linux/freezer.h> | 49 | #include <linux/freezer.h> |
50 | #include <linux/tty.h> | ||
51 | #include <linux/tty_flip.h> | ||
50 | 52 | ||
51 | #include <linux/serial_max3100.h> | 53 | #include <linux/serial_max3100.h> |
52 | 54 | ||
diff --git a/drivers/tty/serial/max3107.c b/drivers/tty/serial/max3107.c index a8164601c0ea..db00b595cab0 100644 --- a/drivers/tty/serial/max3107.c +++ b/drivers/tty/serial/max3107.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/device.h> | 31 | #include <linux/device.h> |
32 | #include <linux/serial_core.h> | 32 | #include <linux/serial_core.h> |
33 | #include <linux/serial.h> | 33 | #include <linux/serial.h> |
34 | #include <linux/tty.h> | ||
35 | #include <linux/tty_flip.h> | ||
34 | #include <linux/gpio.h> | 36 | #include <linux/gpio.h> |
35 | #include <linux/spi/spi.h> | 37 | #include <linux/spi/spi.h> |
36 | #include <linux/freezer.h> | 38 | #include <linux/freezer.h> |
diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c index 3394b7cc1722..9afca093d6ec 100644 --- a/drivers/tty/serial/mcf.c +++ b/drivers/tty/serial/mcf.c | |||
@@ -380,7 +380,7 @@ static void mcf_config_port(struct uart_port *port, int flags) | |||
380 | /* Clear mask, so no surprise interrupts. */ | 380 | /* Clear mask, so no surprise interrupts. */ |
381 | writeb(0, port->membase + MCFUART_UIMR); | 381 | writeb(0, port->membase + MCFUART_UIMR); |
382 | 382 | ||
383 | if (request_irq(port->irq, mcf_interrupt, IRQF_DISABLED, "UART", port)) | 383 | if (request_irq(port->irq, mcf_interrupt, 0, "UART", port)) |
384 | printk(KERN_ERR "MCF: unable to attach ColdFire UART %d " | 384 | printk(KERN_ERR "MCF: unable to attach ColdFire UART %d " |
385 | "interrupt vector=%d\n", port->line, port->irq); | 385 | "interrupt vector=%d\n", port->line, port->irq); |
386 | } | 386 | } |
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c index cab52f4a88b0..286c386d9c46 100644 --- a/drivers/tty/serial/mfd.c +++ b/drivers/tty/serial/mfd.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
39 | #include <linux/io.h> | 39 | #include <linux/io.h> |
40 | #include <linux/debugfs.h> | 40 | #include <linux/debugfs.h> |
41 | #include <linux/pm_runtime.h> | ||
41 | 42 | ||
42 | #define HSU_DMA_BUF_SIZE 2048 | 43 | #define HSU_DMA_BUF_SIZE 2048 |
43 | 44 | ||
@@ -764,6 +765,8 @@ static int serial_hsu_startup(struct uart_port *port) | |||
764 | container_of(port, struct uart_hsu_port, port); | 765 | container_of(port, struct uart_hsu_port, port); |
765 | unsigned long flags; | 766 | unsigned long flags; |
766 | 767 | ||
768 | pm_runtime_get_sync(up->dev); | ||
769 | |||
767 | /* | 770 | /* |
768 | * Clear the FIFO buffers and disable them. | 771 | * Clear the FIFO buffers and disable them. |
769 | * (they will be reenabled in set_termios()) | 772 | * (they will be reenabled in set_termios()) |
@@ -871,6 +874,8 @@ static void serial_hsu_shutdown(struct uart_port *port) | |||
871 | UART_FCR_CLEAR_RCVR | | 874 | UART_FCR_CLEAR_RCVR | |
872 | UART_FCR_CLEAR_XMIT); | 875 | UART_FCR_CLEAR_XMIT); |
873 | serial_out(up, UART_FCR, 0); | 876 | serial_out(up, UART_FCR, 0); |
877 | |||
878 | pm_runtime_put(up->dev); | ||
874 | } | 879 | } |
875 | 880 | ||
876 | static void | 881 | static void |
@@ -1249,6 +1254,39 @@ static int serial_hsu_resume(struct pci_dev *pdev) | |||
1249 | #define serial_hsu_resume NULL | 1254 | #define serial_hsu_resume NULL |
1250 | #endif | 1255 | #endif |
1251 | 1256 | ||
1257 | #ifdef CONFIG_PM_RUNTIME | ||
1258 | static int serial_hsu_runtime_idle(struct device *dev) | ||
1259 | { | ||
1260 | int err; | ||
1261 | |||
1262 | err = pm_schedule_suspend(dev, 500); | ||
1263 | if (err) | ||
1264 | return -EBUSY; | ||
1265 | |||
1266 | return 0; | ||
1267 | } | ||
1268 | |||
1269 | static int serial_hsu_runtime_suspend(struct device *dev) | ||
1270 | { | ||
1271 | return 0; | ||
1272 | } | ||
1273 | |||
1274 | static int serial_hsu_runtime_resume(struct device *dev) | ||
1275 | { | ||
1276 | return 0; | ||
1277 | } | ||
1278 | #else | ||
1279 | #define serial_hsu_runtime_idle NULL | ||
1280 | #define serial_hsu_runtime_suspend NULL | ||
1281 | #define serial_hsu_runtime_resume NULL | ||
1282 | #endif | ||
1283 | |||
1284 | static const struct dev_pm_ops serial_hsu_pm_ops = { | ||
1285 | .runtime_suspend = serial_hsu_runtime_suspend, | ||
1286 | .runtime_resume = serial_hsu_runtime_resume, | ||
1287 | .runtime_idle = serial_hsu_runtime_idle, | ||
1288 | }; | ||
1289 | |||
1252 | /* temp global pointer before we settle down on using one or four PCI dev */ | 1290 | /* temp global pointer before we settle down on using one or four PCI dev */ |
1253 | static struct hsu_port *phsu; | 1291 | static struct hsu_port *phsu; |
1254 | 1292 | ||
@@ -1315,6 +1353,9 @@ static int serial_hsu_probe(struct pci_dev *pdev, | |||
1315 | pci_set_drvdata(pdev, uport); | 1353 | pci_set_drvdata(pdev, uport); |
1316 | } | 1354 | } |
1317 | 1355 | ||
1356 | pm_runtime_put_noidle(&pdev->dev); | ||
1357 | pm_runtime_allow(&pdev->dev); | ||
1358 | |||
1318 | return 0; | 1359 | return 0; |
1319 | 1360 | ||
1320 | err_disable: | 1361 | err_disable: |
@@ -1411,6 +1452,9 @@ static void serial_hsu_remove(struct pci_dev *pdev) | |||
1411 | if (!priv) | 1452 | if (!priv) |
1412 | return; | 1453 | return; |
1413 | 1454 | ||
1455 | pm_runtime_forbid(&pdev->dev); | ||
1456 | pm_runtime_get_noresume(&pdev->dev); | ||
1457 | |||
1414 | /* For port 0/1/2, priv is the address of uart_hsu_port */ | 1458 | /* For port 0/1/2, priv is the address of uart_hsu_port */ |
1415 | if (pdev->device != 0x081E) { | 1459 | if (pdev->device != 0x081E) { |
1416 | up = priv; | 1460 | up = priv; |
@@ -1423,7 +1467,7 @@ static void serial_hsu_remove(struct pci_dev *pdev) | |||
1423 | } | 1467 | } |
1424 | 1468 | ||
1425 | /* First 3 are UART ports, and the 4th is the DMA */ | 1469 | /* First 3 are UART ports, and the 4th is the DMA */ |
1426 | static const struct pci_device_id pci_ids[] __devinitdata = { | 1470 | static const struct pci_device_id pci_ids[] __devinitconst = { |
1427 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) }, | 1471 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) }, |
1428 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) }, | 1472 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) }, |
1429 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) }, | 1473 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) }, |
@@ -1438,6 +1482,9 @@ static struct pci_driver hsu_pci_driver = { | |||
1438 | .remove = __devexit_p(serial_hsu_remove), | 1482 | .remove = __devexit_p(serial_hsu_remove), |
1439 | .suspend = serial_hsu_suspend, | 1483 | .suspend = serial_hsu_suspend, |
1440 | .resume = serial_hsu_resume, | 1484 | .resume = serial_hsu_resume, |
1485 | .driver = { | ||
1486 | .pm = &serial_hsu_pm_ops, | ||
1487 | }, | ||
1441 | }; | 1488 | }; |
1442 | 1489 | ||
1443 | static int __init hsu_pci_init(void) | 1490 | static int __init hsu_pci_init(void) |
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index a0bcd8a3758d..1093a88a1fe3 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/device.h> | 34 | #include <linux/device.h> |
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/tty.h> | 36 | #include <linux/tty.h> |
37 | #include <linux/tty_flip.h> | ||
37 | #include <linux/serial.h> | 38 | #include <linux/serial.h> |
38 | #include <linux/sysrq.h> | 39 | #include <linux/sysrq.h> |
39 | #include <linux/console.h> | 40 | #include <linux/console.h> |
@@ -273,7 +274,7 @@ static unsigned int mpc5200b_psc_set_baudrate(struct uart_port *port, | |||
273 | 274 | ||
274 | static void mpc52xx_psc_get_irq(struct uart_port *port, struct device_node *np) | 275 | static void mpc52xx_psc_get_irq(struct uart_port *port, struct device_node *np) |
275 | { | 276 | { |
276 | port->irqflags = IRQF_DISABLED; | 277 | port->irqflags = 0; |
277 | port->irq = irq_of_parse_and_map(np, 0); | 278 | port->irq = irq_of_parse_and_map(np, 0); |
278 | } | 279 | } |
279 | 280 | ||
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c index 492c14d63e99..4c309e869903 100644 --- a/drivers/tty/serial/mrst_max3110.c +++ b/drivers/tty/serial/mrst_max3110.c | |||
@@ -27,6 +27,10 @@ | |||
27 | * interrupt for a low speed UART device | 27 | * interrupt for a low speed UART device |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #ifdef CONFIG_MAGIC_SYSRQ | ||
31 | #define SUPPORT_SYSRQ | ||
32 | #endif | ||
33 | |||
30 | #include <linux/module.h> | 34 | #include <linux/module.h> |
31 | #include <linux/ioport.h> | 35 | #include <linux/ioport.h> |
32 | #include <linux/irq.h> | 36 | #include <linux/irq.h> |
@@ -73,9 +77,9 @@ struct uart_max3110 { | |||
73 | /* global data structure, may need be removed */ | 77 | /* global data structure, may need be removed */ |
74 | static struct uart_max3110 *pmax; | 78 | static struct uart_max3110 *pmax; |
75 | 79 | ||
76 | static void receive_chars(struct uart_max3110 *max, | 80 | static int receive_chars(struct uart_max3110 *max, |
77 | unsigned char *str, int len); | 81 | unsigned short *str, int len); |
78 | static int max3110_read_multi(struct uart_max3110 *max, u8 *buf); | 82 | static int max3110_read_multi(struct uart_max3110 *max); |
79 | static void max3110_con_receive(struct uart_max3110 *max); | 83 | static void max3110_con_receive(struct uart_max3110 *max); |
80 | 84 | ||
81 | static int max3110_write_then_read(struct uart_max3110 *max, | 85 | static int max3110_write_then_read(struct uart_max3110 *max, |
@@ -108,7 +112,6 @@ static int max3110_out(struct uart_max3110 *max, const u16 out) | |||
108 | { | 112 | { |
109 | void *buf; | 113 | void *buf; |
110 | u16 *obuf, *ibuf; | 114 | u16 *obuf, *ibuf; |
111 | u8 ch; | ||
112 | int ret; | 115 | int ret; |
113 | 116 | ||
114 | buf = kzalloc(8, GFP_KERNEL | GFP_DMA); | 117 | buf = kzalloc(8, GFP_KERNEL | GFP_DMA); |
@@ -125,11 +128,7 @@ static int max3110_out(struct uart_max3110 *max, const u16 out) | |||
125 | goto exit; | 128 | goto exit; |
126 | } | 129 | } |
127 | 130 | ||
128 | /* If some valid data is read back */ | 131 | receive_chars(max, ibuf, 1); |
129 | if (*ibuf & MAX3110_READ_DATA_AVAILABLE) { | ||
130 | ch = *ibuf & 0xff; | ||
131 | receive_chars(max, &ch, 1); | ||
132 | } | ||
133 | 132 | ||
134 | exit: | 133 | exit: |
135 | kfree(buf); | 134 | kfree(buf); |
@@ -142,12 +141,11 @@ exit: | |||
142 | * | 141 | * |
143 | * Return how many valide bytes are read back | 142 | * Return how many valide bytes are read back |
144 | */ | 143 | */ |
145 | static int max3110_read_multi(struct uart_max3110 *max, u8 *rxbuf) | 144 | static int max3110_read_multi(struct uart_max3110 *max) |
146 | { | 145 | { |
147 | void *buf; | 146 | void *buf; |
148 | u16 *obuf, *ibuf; | 147 | u16 *obuf, *ibuf; |
149 | u8 *pbuf, valid_str[M3110_RX_FIFO_DEPTH]; | 148 | int ret, blen; |
150 | int i, j, blen; | ||
151 | 149 | ||
152 | blen = M3110_RX_FIFO_DEPTH * sizeof(u16); | 150 | blen = M3110_RX_FIFO_DEPTH * sizeof(u16); |
153 | buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA); | 151 | buf = kzalloc(blen * 2, GFP_KERNEL | GFP_DMA); |
@@ -165,19 +163,10 @@ static int max3110_read_multi(struct uart_max3110 *max, u8 *rxbuf) | |||
165 | return 0; | 163 | return 0; |
166 | } | 164 | } |
167 | 165 | ||
168 | /* If caller doesn't provide a buffer, then handle received char */ | 166 | ret = receive_chars(max, ibuf, M3110_RX_FIFO_DEPTH); |
169 | pbuf = rxbuf ? rxbuf : valid_str; | ||
170 | |||
171 | for (i = 0, j = 0; i < M3110_RX_FIFO_DEPTH; i++) { | ||
172 | if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE) | ||
173 | pbuf[j++] = ibuf[i] & 0xff; | ||
174 | } | ||
175 | |||
176 | if (j && (pbuf == valid_str)) | ||
177 | receive_chars(max, valid_str, j); | ||
178 | 167 | ||
179 | kfree(buf); | 168 | kfree(buf); |
180 | return j; | 169 | return ret; |
181 | } | 170 | } |
182 | 171 | ||
183 | static void serial_m3110_con_putchar(struct uart_port *port, int ch) | 172 | static void serial_m3110_con_putchar(struct uart_port *port, int ch) |
@@ -207,7 +196,7 @@ static void serial_m3110_con_write(struct console *co, | |||
207 | uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar); | 196 | uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar); |
208 | 197 | ||
209 | if (!test_and_set_bit(CON_TX_NEEDED, &pmax->uart_flags)) | 198 | if (!test_and_set_bit(CON_TX_NEEDED, &pmax->uart_flags)) |
210 | wake_up_process(pmax->main_thread); | 199 | wake_up(&pmax->wq); |
211 | } | 200 | } |
212 | 201 | ||
213 | static int __init | 202 | static int __init |
@@ -276,8 +265,7 @@ static void send_circ_buf(struct uart_max3110 *max, | |||
276 | { | 265 | { |
277 | void *buf; | 266 | void *buf; |
278 | u16 *obuf, *ibuf; | 267 | u16 *obuf, *ibuf; |
279 | u8 valid_str[WORDS_PER_XFER]; | 268 | int i, len, blen, dma_size, left, ret = 0; |
280 | int i, j, len, blen, dma_size, left, ret = 0; | ||
281 | 269 | ||
282 | 270 | ||
283 | dma_size = WORDS_PER_XFER * sizeof(u16) * 2; | 271 | dma_size = WORDS_PER_XFER * sizeof(u16) * 2; |
@@ -301,18 +289,13 @@ static void send_circ_buf(struct uart_max3110 *max, | |||
301 | } | 289 | } |
302 | 290 | ||
303 | /* Fail to send msg to console is not very critical */ | 291 | /* Fail to send msg to console is not very critical */ |
292 | |||
304 | ret = max3110_write_then_read(max, obuf, ibuf, blen, 0); | 293 | ret = max3110_write_then_read(max, obuf, ibuf, blen, 0); |
305 | if (ret) | 294 | if (ret) |
306 | pr_warning(PR_FMT "%s(): get err msg %d\n", | 295 | pr_warning(PR_FMT "%s(): get err msg %d\n", |
307 | __func__, ret); | 296 | __func__, ret); |
308 | 297 | ||
309 | for (i = 0, j = 0; i < len; i++) { | 298 | receive_chars(max, ibuf, len); |
310 | if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE) | ||
311 | valid_str[j++] = ibuf[i] & 0xff; | ||
312 | } | ||
313 | |||
314 | if (j) | ||
315 | receive_chars(max, valid_str, j); | ||
316 | 299 | ||
317 | max->port.icount.tx += len; | 300 | max->port.icount.tx += len; |
318 | left -= len; | 301 | left -= len; |
@@ -349,33 +332,54 @@ static void serial_m3110_start_tx(struct uart_port *port) | |||
349 | container_of(port, struct uart_max3110, port); | 332 | container_of(port, struct uart_max3110, port); |
350 | 333 | ||
351 | if (!test_and_set_bit(UART_TX_NEEDED, &max->uart_flags)) | 334 | if (!test_and_set_bit(UART_TX_NEEDED, &max->uart_flags)) |
352 | wake_up_process(max->main_thread); | 335 | wake_up(&max->wq); |
353 | } | 336 | } |
354 | 337 | ||
355 | static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) | 338 | static int |
339 | receive_chars(struct uart_max3110 *max, unsigned short *str, int len) | ||
356 | { | 340 | { |
357 | struct uart_port *port = &max->port; | 341 | struct uart_port *port = &max->port; |
358 | struct tty_struct *tty; | 342 | struct tty_struct *tty; |
359 | int usable; | 343 | char buf[M3110_RX_FIFO_DEPTH]; |
344 | int r, w, usable; | ||
360 | 345 | ||
361 | /* If uart is not opened, just return */ | 346 | /* If uart is not opened, just return */ |
362 | if (!port->state) | 347 | if (!port->state) |
363 | return; | 348 | return 0; |
364 | 349 | ||
365 | tty = port->state->port.tty; | 350 | tty = tty_port_tty_get(&port->state->port); |
366 | if (!tty) | 351 | if (!tty) |
367 | return; | 352 | return 0; |
353 | |||
354 | for (r = 0, w = 0; r < len; r++) { | ||
355 | if (str[r] & MAX3110_BREAK && | ||
356 | uart_handle_break(port)) | ||
357 | continue; | ||
358 | |||
359 | if (str[r] & MAX3110_READ_DATA_AVAILABLE) { | ||
360 | if (uart_handle_sysrq_char(port, str[r] & 0xff)) | ||
361 | continue; | ||
362 | |||
363 | buf[w++] = str[r] & 0xff; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | if (!w) { | ||
368 | tty_kref_put(tty); | ||
369 | return 0; | ||
370 | } | ||
368 | 371 | ||
369 | while (len) { | 372 | for (r = 0; w; r += usable, w -= usable) { |
370 | usable = tty_buffer_request_room(tty, len); | 373 | usable = tty_buffer_request_room(tty, w); |
371 | if (usable) { | 374 | if (usable) { |
372 | tty_insert_flip_string(tty, str, usable); | 375 | tty_insert_flip_string(tty, buf + r, usable); |
373 | str += usable; | ||
374 | port->icount.rx += usable; | 376 | port->icount.rx += usable; |
375 | } | 377 | } |
376 | len -= usable; | ||
377 | } | 378 | } |
378 | tty_flip_buffer_push(tty); | 379 | tty_flip_buffer_push(tty); |
380 | tty_kref_put(tty); | ||
381 | |||
382 | return r; | ||
379 | } | 383 | } |
380 | 384 | ||
381 | /* | 385 | /* |
@@ -390,28 +394,15 @@ static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) | |||
390 | */ | 394 | */ |
391 | static void max3110_con_receive(struct uart_max3110 *max) | 395 | static void max3110_con_receive(struct uart_max3110 *max) |
392 | { | 396 | { |
393 | int loop = 1, num, total = 0; | 397 | int loop = 1, num; |
394 | u8 recv_buf[512], *pbuf; | ||
395 | 398 | ||
396 | pbuf = recv_buf; | ||
397 | do { | 399 | do { |
398 | num = max3110_read_multi(max, pbuf); | 400 | num = max3110_read_multi(max); |
399 | 401 | ||
400 | if (num) { | 402 | if (num) { |
401 | loop = 5; | 403 | loop = 5; |
402 | pbuf += num; | ||
403 | total += num; | ||
404 | |||
405 | if (total >= 504) { | ||
406 | receive_chars(max, recv_buf, total); | ||
407 | pbuf = recv_buf; | ||
408 | total = 0; | ||
409 | } | ||
410 | } | 404 | } |
411 | } while (--loop); | 405 | } while (--loop); |
412 | |||
413 | if (total) | ||
414 | receive_chars(max, recv_buf, total); | ||
415 | } | 406 | } |
416 | 407 | ||
417 | static int max3110_main_thread(void *_max) | 408 | static int max3110_main_thread(void *_max) |
@@ -424,7 +415,8 @@ static int max3110_main_thread(void *_max) | |||
424 | pr_info(PR_FMT "start main thread\n"); | 415 | pr_info(PR_FMT "start main thread\n"); |
425 | 416 | ||
426 | do { | 417 | do { |
427 | wait_event_interruptible(*wq, max->uart_flags || kthread_should_stop()); | 418 | wait_event_interruptible(*wq, |
419 | max->uart_flags || kthread_should_stop()); | ||
428 | 420 | ||
429 | mutex_lock(&max->thread_mutex); | 421 | mutex_lock(&max->thread_mutex); |
430 | 422 | ||
@@ -452,8 +444,9 @@ static irqreturn_t serial_m3110_irq(int irq, void *dev_id) | |||
452 | 444 | ||
453 | /* max3110's irq is a falling edge, not level triggered, | 445 | /* max3110's irq is a falling edge, not level triggered, |
454 | * so no need to disable the irq */ | 446 | * so no need to disable the irq */ |
447 | |||
455 | if (!test_and_set_bit(BIT_IRQ_PENDING, &max->uart_flags)) | 448 | if (!test_and_set_bit(BIT_IRQ_PENDING, &max->uart_flags)) |
456 | wake_up_process(max->main_thread); | 449 | wake_up(&max->wq); |
457 | 450 | ||
458 | return IRQ_HANDLED; | 451 | return IRQ_HANDLED; |
459 | } | 452 | } |
diff --git a/drivers/tty/serial/mrst_max3110.h b/drivers/tty/serial/mrst_max3110.h index c37ea48c825a..35af0739513b 100644 --- a/drivers/tty/serial/mrst_max3110.h +++ b/drivers/tty/serial/mrst_max3110.h | |||
@@ -7,6 +7,7 @@ | |||
7 | /* status bits for all 4 MAX3110 operate modes */ | 7 | /* status bits for all 4 MAX3110 operate modes */ |
8 | #define MAX3110_READ_DATA_AVAILABLE (1 << 15) | 8 | #define MAX3110_READ_DATA_AVAILABLE (1 << 15) |
9 | #define MAX3110_WRITE_BUF_EMPTY (1 << 14) | 9 | #define MAX3110_WRITE_BUF_EMPTY (1 << 14) |
10 | #define MAX3110_BREAK (1 << 10) | ||
10 | 11 | ||
11 | #define WC_TAG (3 << 14) | 12 | #define WC_TAG (3 << 14) |
12 | #define RC_TAG (1 << 14) | 13 | #define RC_TAG (1 << 14) |
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index e6ba83876508..29cbfd8c4e7c 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c | |||
@@ -804,8 +804,6 @@ static int __init msm_console_setup(struct console *co, char *options) | |||
804 | if (unlikely(!port->membase)) | 804 | if (unlikely(!port->membase)) |
805 | return -ENXIO; | 805 | return -ENXIO; |
806 | 806 | ||
807 | port->cons = co; | ||
808 | |||
809 | msm_init_clock(port); | 807 | msm_init_clock(port); |
810 | 808 | ||
811 | if (options) | 809 | if (options) |
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index 624701f8138a..60c6eb850265 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c | |||
@@ -30,6 +30,8 @@ | |||
30 | 30 | ||
31 | #include <linux/serial.h> | 31 | #include <linux/serial.h> |
32 | #include <linux/serial_core.h> | 32 | #include <linux/serial_core.h> |
33 | #include <linux/tty.h> | ||
34 | #include <linux/tty_flip.h> | ||
33 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
34 | #include <linux/init.h> | 36 | #include <linux/init.h> |
35 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
diff --git a/drivers/tty/serial/mux.c b/drivers/tty/serial/mux.c index 9711e06a8374..06f6aefd5ba6 100644 --- a/drivers/tty/serial/mux.c +++ b/drivers/tty/serial/mux.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/ioport.h> | 21 | #include <linux/ioport.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/serial.h> | 23 | #include <linux/serial.h> |
24 | #include <linux/tty.h> | ||
25 | #include <linux/tty_flip.h> | ||
24 | #include <linux/console.h> | 26 | #include <linux/console.h> |
25 | #include <linux/delay.h> /* for udelay */ | 27 | #include <linux/delay.h> /* for udelay */ |
26 | #include <linux/device.h> | 28 | #include <linux/device.h> |
diff --git a/drivers/tty/serial/nwpserial.c b/drivers/tty/serial/nwpserial.c index de173671e3d0..9beaff1cec24 100644 --- a/drivers/tty/serial/nwpserial.c +++ b/drivers/tty/serial/nwpserial.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/serial_reg.h> | 15 | #include <linux/serial_reg.h> |
16 | #include <linux/serial_core.h> | 16 | #include <linux/serial_core.h> |
17 | #include <linux/tty.h> | 17 | #include <linux/tty.h> |
18 | #include <linux/tty_flip.h> | ||
18 | #include <linux/irqreturn.h> | 19 | #include <linux/irqreturn.h> |
19 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
20 | #include <linux/of_platform.h> | 21 | #include <linux/of_platform.h> |
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index b46218d679e2..21febef926aa 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
22 | #include <linux/serial_core.h> | 22 | #include <linux/serial_core.h> |
23 | #include <linux/tty.h> | ||
24 | #include <linux/tty_flip.h> | ||
23 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
24 | #include <linux/io.h> | 26 | #include <linux/io.h> |
25 | #include <linux/dmi.h> | 27 | #include <linux/dmi.h> |
diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index 531931c1b250..5c8e3bba6c84 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c | |||
@@ -100,6 +100,16 @@ static inline void receive_chars(struct uart_pxa_port *up, int *status) | |||
100 | int max_count = 256; | 100 | int max_count = 256; |
101 | 101 | ||
102 | do { | 102 | do { |
103 | /* work around Errata #20 according to | ||
104 | * Intel(R) PXA27x Processor Family | ||
105 | * Specification Update (May 2005) | ||
106 | * | ||
107 | * Step 2 | ||
108 | * Disable the Reciever Time Out Interrupt via IER[RTOEI] | ||
109 | */ | ||
110 | up->ier &= ~UART_IER_RTOIE; | ||
111 | serial_out(up, UART_IER, up->ier); | ||
112 | |||
103 | ch = serial_in(up, UART_RX); | 113 | ch = serial_in(up, UART_RX); |
104 | flag = TTY_NORMAL; | 114 | flag = TTY_NORMAL; |
105 | up->port.icount.rx++; | 115 | up->port.icount.rx++; |
@@ -156,6 +166,16 @@ static inline void receive_chars(struct uart_pxa_port *up, int *status) | |||
156 | *status = serial_in(up, UART_LSR); | 166 | *status = serial_in(up, UART_LSR); |
157 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); | 167 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); |
158 | tty_flip_buffer_push(tty); | 168 | tty_flip_buffer_push(tty); |
169 | |||
170 | /* work around Errata #20 according to | ||
171 | * Intel(R) PXA27x Processor Family | ||
172 | * Specification Update (May 2005) | ||
173 | * | ||
174 | * Step 6: | ||
175 | * No more data in FIFO: Re-enable RTO interrupt via IER[RTOIE] | ||
176 | */ | ||
177 | up->ier |= UART_IER_RTOIE; | ||
178 | serial_out(up, UART_IER, up->ier); | ||
159 | } | 179 | } |
160 | 180 | ||
161 | static void transmit_chars(struct uart_pxa_port *up) | 181 | static void transmit_chars(struct uart_pxa_port *up) |
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 6edafb5ace18..b31f1c3a2c4c 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c | |||
@@ -83,6 +83,16 @@ static int s3c24xx_serial_txempty_nofifo(struct uart_port *port) | |||
83 | return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE); | 83 | return (rd_regl(port, S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE); |
84 | } | 84 | } |
85 | 85 | ||
86 | /* | ||
87 | * s3c64xx and later SoC's include the interrupt mask and status registers in | ||
88 | * the controller itself, unlike the s3c24xx SoC's which have these registers | ||
89 | * in the interrupt controller. Check if the port type is s3c64xx or higher. | ||
90 | */ | ||
91 | static int s3c24xx_serial_has_interrupt_mask(struct uart_port *port) | ||
92 | { | ||
93 | return to_ourport(port)->info->type == PORT_S3C6400; | ||
94 | } | ||
95 | |||
86 | static void s3c24xx_serial_rx_enable(struct uart_port *port) | 96 | static void s3c24xx_serial_rx_enable(struct uart_port *port) |
87 | { | 97 | { |
88 | unsigned long flags; | 98 | unsigned long flags; |
@@ -126,7 +136,11 @@ static void s3c24xx_serial_stop_tx(struct uart_port *port) | |||
126 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 136 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
127 | 137 | ||
128 | if (tx_enabled(port)) { | 138 | if (tx_enabled(port)) { |
129 | disable_irq_nosync(ourport->tx_irq); | 139 | if (s3c24xx_serial_has_interrupt_mask(port)) |
140 | __set_bit(S3C64XX_UINTM_TXD, | ||
141 | portaddrl(port, S3C64XX_UINTM)); | ||
142 | else | ||
143 | disable_irq_nosync(ourport->tx_irq); | ||
130 | tx_enabled(port) = 0; | 144 | tx_enabled(port) = 0; |
131 | if (port->flags & UPF_CONS_FLOW) | 145 | if (port->flags & UPF_CONS_FLOW) |
132 | s3c24xx_serial_rx_enable(port); | 146 | s3c24xx_serial_rx_enable(port); |
@@ -141,19 +155,26 @@ static void s3c24xx_serial_start_tx(struct uart_port *port) | |||
141 | if (port->flags & UPF_CONS_FLOW) | 155 | if (port->flags & UPF_CONS_FLOW) |
142 | s3c24xx_serial_rx_disable(port); | 156 | s3c24xx_serial_rx_disable(port); |
143 | 157 | ||
144 | enable_irq(ourport->tx_irq); | 158 | if (s3c24xx_serial_has_interrupt_mask(port)) |
159 | __clear_bit(S3C64XX_UINTM_TXD, | ||
160 | portaddrl(port, S3C64XX_UINTM)); | ||
161 | else | ||
162 | enable_irq(ourport->tx_irq); | ||
145 | tx_enabled(port) = 1; | 163 | tx_enabled(port) = 1; |
146 | } | 164 | } |
147 | } | 165 | } |
148 | 166 | ||
149 | |||
150 | static void s3c24xx_serial_stop_rx(struct uart_port *port) | 167 | static void s3c24xx_serial_stop_rx(struct uart_port *port) |
151 | { | 168 | { |
152 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 169 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
153 | 170 | ||
154 | if (rx_enabled(port)) { | 171 | if (rx_enabled(port)) { |
155 | dbg("s3c24xx_serial_stop_rx: port=%p\n", port); | 172 | dbg("s3c24xx_serial_stop_rx: port=%p\n", port); |
156 | disable_irq_nosync(ourport->rx_irq); | 173 | if (s3c24xx_serial_has_interrupt_mask(port)) |
174 | __set_bit(S3C64XX_UINTM_RXD, | ||
175 | portaddrl(port, S3C64XX_UINTM)); | ||
176 | else | ||
177 | disable_irq_nosync(ourport->rx_irq); | ||
157 | rx_enabled(port) = 0; | 178 | rx_enabled(port) = 0; |
158 | } | 179 | } |
159 | } | 180 | } |
@@ -320,6 +341,28 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) | |||
320 | return IRQ_HANDLED; | 341 | return IRQ_HANDLED; |
321 | } | 342 | } |
322 | 343 | ||
344 | /* interrupt handler for s3c64xx and later SoC's.*/ | ||
345 | static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id) | ||
346 | { | ||
347 | struct s3c24xx_uart_port *ourport = id; | ||
348 | struct uart_port *port = &ourport->port; | ||
349 | unsigned int pend = rd_regl(port, S3C64XX_UINTP); | ||
350 | unsigned long flags; | ||
351 | irqreturn_t ret = IRQ_HANDLED; | ||
352 | |||
353 | spin_lock_irqsave(&port->lock, flags); | ||
354 | if (pend & S3C64XX_UINTM_RXD_MSK) { | ||
355 | ret = s3c24xx_serial_rx_chars(irq, id); | ||
356 | wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK); | ||
357 | } | ||
358 | if (pend & S3C64XX_UINTM_TXD_MSK) { | ||
359 | ret = s3c24xx_serial_tx_chars(irq, id); | ||
360 | wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK); | ||
361 | } | ||
362 | spin_unlock_irqrestore(&port->lock, flags); | ||
363 | return ret; | ||
364 | } | ||
365 | |||
323 | static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) | 366 | static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port) |
324 | { | 367 | { |
325 | struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); | 368 | struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); |
@@ -377,18 +420,25 @@ static void s3c24xx_serial_shutdown(struct uart_port *port) | |||
377 | struct s3c24xx_uart_port *ourport = to_ourport(port); | 420 | struct s3c24xx_uart_port *ourport = to_ourport(port); |
378 | 421 | ||
379 | if (ourport->tx_claimed) { | 422 | if (ourport->tx_claimed) { |
380 | free_irq(ourport->tx_irq, ourport); | 423 | if (!s3c24xx_serial_has_interrupt_mask(port)) |
424 | free_irq(ourport->tx_irq, ourport); | ||
381 | tx_enabled(port) = 0; | 425 | tx_enabled(port) = 0; |
382 | ourport->tx_claimed = 0; | 426 | ourport->tx_claimed = 0; |
383 | } | 427 | } |
384 | 428 | ||
385 | if (ourport->rx_claimed) { | 429 | if (ourport->rx_claimed) { |
386 | free_irq(ourport->rx_irq, ourport); | 430 | if (!s3c24xx_serial_has_interrupt_mask(port)) |
431 | free_irq(ourport->rx_irq, ourport); | ||
387 | ourport->rx_claimed = 0; | 432 | ourport->rx_claimed = 0; |
388 | rx_enabled(port) = 0; | 433 | rx_enabled(port) = 0; |
389 | } | 434 | } |
390 | } | ||
391 | 435 | ||
436 | /* Clear pending interrupts and mask all interrupts */ | ||
437 | if (s3c24xx_serial_has_interrupt_mask(port)) { | ||
438 | wr_regl(port, S3C64XX_UINTP, 0xf); | ||
439 | wr_regl(port, S3C64XX_UINTM, 0xf); | ||
440 | } | ||
441 | } | ||
392 | 442 | ||
393 | static int s3c24xx_serial_startup(struct uart_port *port) | 443 | static int s3c24xx_serial_startup(struct uart_port *port) |
394 | { | 444 | { |
@@ -436,6 +486,33 @@ static int s3c24xx_serial_startup(struct uart_port *port) | |||
436 | return ret; | 486 | return ret; |
437 | } | 487 | } |
438 | 488 | ||
489 | static int s3c64xx_serial_startup(struct uart_port *port) | ||
490 | { | ||
491 | struct s3c24xx_uart_port *ourport = to_ourport(port); | ||
492 | int ret; | ||
493 | |||
494 | dbg("s3c64xx_serial_startup: port=%p (%08lx,%p)\n", | ||
495 | port->mapbase, port->membase); | ||
496 | |||
497 | ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED, | ||
498 | s3c24xx_serial_portname(port), ourport); | ||
499 | if (ret) { | ||
500 | printk(KERN_ERR "cannot get irq %d\n", port->irq); | ||
501 | return ret; | ||
502 | } | ||
503 | |||
504 | /* For compatibility with s3c24xx Soc's */ | ||
505 | rx_enabled(port) = 1; | ||
506 | ourport->rx_claimed = 1; | ||
507 | tx_enabled(port) = 0; | ||
508 | ourport->tx_claimed = 1; | ||
509 | |||
510 | /* Enable Rx Interrupt */ | ||
511 | __clear_bit(S3C64XX_UINTM_RXD, portaddrl(port, S3C64XX_UINTM)); | ||
512 | dbg("s3c64xx_serial_startup ok\n"); | ||
513 | return ret; | ||
514 | } | ||
515 | |||
439 | /* power power management control */ | 516 | /* power power management control */ |
440 | 517 | ||
441 | static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, | 518 | static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level, |
@@ -879,7 +956,6 @@ static struct uart_ops s3c24xx_serial_ops = { | |||
879 | .verify_port = s3c24xx_serial_verify_port, | 956 | .verify_port = s3c24xx_serial_verify_port, |
880 | }; | 957 | }; |
881 | 958 | ||
882 | |||
883 | static struct uart_driver s3c24xx_uart_drv = { | 959 | static struct uart_driver s3c24xx_uart_drv = { |
884 | .owner = THIS_MODULE, | 960 | .owner = THIS_MODULE, |
885 | .driver_name = "s3c2410_serial", | 961 | .driver_name = "s3c2410_serial", |
@@ -895,7 +971,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS | |||
895 | .port = { | 971 | .port = { |
896 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock), | 972 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock), |
897 | .iotype = UPIO_MEM, | 973 | .iotype = UPIO_MEM, |
898 | .irq = IRQ_S3CUART_RX0, | ||
899 | .uartclk = 0, | 974 | .uartclk = 0, |
900 | .fifosize = 16, | 975 | .fifosize = 16, |
901 | .ops = &s3c24xx_serial_ops, | 976 | .ops = &s3c24xx_serial_ops, |
@@ -907,7 +982,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS | |||
907 | .port = { | 982 | .port = { |
908 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock), | 983 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[1].port.lock), |
909 | .iotype = UPIO_MEM, | 984 | .iotype = UPIO_MEM, |
910 | .irq = IRQ_S3CUART_RX1, | ||
911 | .uartclk = 0, | 985 | .uartclk = 0, |
912 | .fifosize = 16, | 986 | .fifosize = 16, |
913 | .ops = &s3c24xx_serial_ops, | 987 | .ops = &s3c24xx_serial_ops, |
@@ -921,7 +995,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS | |||
921 | .port = { | 995 | .port = { |
922 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock), | 996 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[2].port.lock), |
923 | .iotype = UPIO_MEM, | 997 | .iotype = UPIO_MEM, |
924 | .irq = IRQ_S3CUART_RX2, | ||
925 | .uartclk = 0, | 998 | .uartclk = 0, |
926 | .fifosize = 16, | 999 | .fifosize = 16, |
927 | .ops = &s3c24xx_serial_ops, | 1000 | .ops = &s3c24xx_serial_ops, |
@@ -935,7 +1008,6 @@ static struct s3c24xx_uart_port s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS | |||
935 | .port = { | 1008 | .port = { |
936 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock), | 1009 | .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[3].port.lock), |
937 | .iotype = UPIO_MEM, | 1010 | .iotype = UPIO_MEM, |
938 | .irq = IRQ_S3CUART_RX3, | ||
939 | .uartclk = 0, | 1011 | .uartclk = 0, |
940 | .fifosize = 16, | 1012 | .fifosize = 16, |
941 | .ops = &s3c24xx_serial_ops, | 1013 | .ops = &s3c24xx_serial_ops, |
@@ -1077,6 +1149,10 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, | |||
1077 | port->dev = &platdev->dev; | 1149 | port->dev = &platdev->dev; |
1078 | ourport->info = info; | 1150 | ourport->info = info; |
1079 | 1151 | ||
1152 | /* Startup sequence is different for s3c64xx and higher SoC's */ | ||
1153 | if (s3c24xx_serial_has_interrupt_mask(port)) | ||
1154 | s3c24xx_serial_ops.startup = s3c64xx_serial_startup; | ||
1155 | |||
1080 | /* copy the info in from provided structure */ | 1156 | /* copy the info in from provided structure */ |
1081 | ourport->port.fifosize = info->fifosize; | 1157 | ourport->port.fifosize = info->fifosize; |
1082 | 1158 | ||
@@ -1116,6 +1192,13 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, | |||
1116 | 1192 | ||
1117 | ourport->clk = clk_get(&platdev->dev, "uart"); | 1193 | ourport->clk = clk_get(&platdev->dev, "uart"); |
1118 | 1194 | ||
1195 | /* Keep all interrupts masked and cleared */ | ||
1196 | if (s3c24xx_serial_has_interrupt_mask(port)) { | ||
1197 | wr_regl(port, S3C64XX_UINTM, 0xf); | ||
1198 | wr_regl(port, S3C64XX_UINTP, 0xf); | ||
1199 | wr_regl(port, S3C64XX_UINTSP, 0xf); | ||
1200 | } | ||
1201 | |||
1119 | dbg("port: map=%08x, mem=%08x, irq=%d (%d,%d), clock=%ld\n", | 1202 | dbg("port: map=%08x, mem=%08x, irq=%d (%d,%d), clock=%ld\n", |
1120 | port->mapbase, port->membase, port->irq, | 1203 | port->mapbase, port->membase, port->irq, |
1121 | ourport->rx_irq, ourport->tx_irq, port->uartclk); | 1204 | ourport->rx_irq, ourport->tx_irq, port->uartclk); |
diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h index a69d9a54be94..8e87b788e5c6 100644 --- a/drivers/tty/serial/samsung.h +++ b/drivers/tty/serial/samsung.h | |||
@@ -61,6 +61,7 @@ struct s3c24xx_uart_port { | |||
61 | /* register access controls */ | 61 | /* register access controls */ |
62 | 62 | ||
63 | #define portaddr(port, reg) ((port)->membase + (reg)) | 63 | #define portaddr(port, reg) ((port)->membase + (reg)) |
64 | #define portaddrl(port, reg) ((unsigned long *)((port)->membase + (reg))) | ||
64 | 65 | ||
65 | #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg))) | 66 | #define rd_regb(port, reg) (__raw_readb(portaddr(port, reg))) |
66 | #define rd_regl(port, reg) (__raw_readl(portaddr(port, reg))) | 67 | #define rd_regl(port, reg) (__raw_readl(portaddr(port, reg))) |
diff --git a/drivers/tty/serial/sb1250-duart.c b/drivers/tty/serial/sb1250-duart.c index 6bc2e3f876f4..0be8a2f00d0b 100644 --- a/drivers/tty/serial/sb1250-duart.c +++ b/drivers/tty/serial/sb1250-duart.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
38 | #include <linux/sysrq.h> | 38 | #include <linux/sysrq.h> |
39 | #include <linux/tty.h> | 39 | #include <linux/tty.h> |
40 | #include <linux/tty_flip.h> | ||
40 | #include <linux/types.h> | 41 | #include <linux/types.h> |
41 | 42 | ||
42 | #include <linux/atomic.h> | 43 | #include <linux/atomic.h> |
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index a3efbea5dbba..0406d7ff505e 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -57,7 +57,7 @@ static struct lock_class_key port_lock_key; | |||
57 | 57 | ||
58 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, | 58 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, |
59 | struct ktermios *old_termios); | 59 | struct ktermios *old_termios); |
60 | static void __uart_wait_until_sent(struct uart_port *port, int timeout); | 60 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); |
61 | static void uart_change_pm(struct uart_state *state, int pm_state); | 61 | static void uart_change_pm(struct uart_state *state, int pm_state); |
62 | 62 | ||
63 | /* | 63 | /* |
@@ -72,7 +72,7 @@ void uart_write_wakeup(struct uart_port *port) | |||
72 | * closed. No cookie for you. | 72 | * closed. No cookie for you. |
73 | */ | 73 | */ |
74 | BUG_ON(!state); | 74 | BUG_ON(!state); |
75 | tasklet_schedule(&state->tlet); | 75 | tty_wakeup(state->port.tty); |
76 | } | 76 | } |
77 | 77 | ||
78 | static void uart_stop(struct tty_struct *tty) | 78 | static void uart_stop(struct tty_struct *tty) |
@@ -107,12 +107,6 @@ static void uart_start(struct tty_struct *tty) | |||
107 | spin_unlock_irqrestore(&port->lock, flags); | 107 | spin_unlock_irqrestore(&port->lock, flags); |
108 | } | 108 | } |
109 | 109 | ||
110 | static void uart_tasklet_action(unsigned long data) | ||
111 | { | ||
112 | struct uart_state *state = (struct uart_state *)data; | ||
113 | tty_wakeup(state->port.tty); | ||
114 | } | ||
115 | |||
116 | static inline void | 110 | static inline void |
117 | uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) | 111 | uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) |
118 | { | 112 | { |
@@ -255,9 +249,11 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) | |||
255 | } | 249 | } |
256 | 250 | ||
257 | /* | 251 | /* |
258 | * kill off our tasklet | 252 | * It's possible for shutdown to be called after suspend if we get |
253 | * a DCD drop (hangup) at just the right time. Clear suspended bit so | ||
254 | * we don't try to resume a port that has been shutdown. | ||
259 | */ | 255 | */ |
260 | tasklet_kill(&state->tlet); | 256 | clear_bit(ASYNCB_SUSPENDED, &port->flags); |
261 | 257 | ||
262 | /* | 258 | /* |
263 | * Free the transmit buffer page. | 259 | * Free the transmit buffer page. |
@@ -1261,8 +1257,6 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1261 | struct uart_port *uport; | 1257 | struct uart_port *uport; |
1262 | unsigned long flags; | 1258 | unsigned long flags; |
1263 | 1259 | ||
1264 | BUG_ON(!tty_locked()); | ||
1265 | |||
1266 | if (!state) | 1260 | if (!state) |
1267 | return; | 1261 | return; |
1268 | 1262 | ||
@@ -1271,12 +1265,11 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1271 | 1265 | ||
1272 | pr_debug("uart_close(%d) called\n", uport->line); | 1266 | pr_debug("uart_close(%d) called\n", uport->line); |
1273 | 1267 | ||
1274 | mutex_lock(&port->mutex); | ||
1275 | spin_lock_irqsave(&port->lock, flags); | 1268 | spin_lock_irqsave(&port->lock, flags); |
1276 | 1269 | ||
1277 | if (tty_hung_up_p(filp)) { | 1270 | if (tty_hung_up_p(filp)) { |
1278 | spin_unlock_irqrestore(&port->lock, flags); | 1271 | spin_unlock_irqrestore(&port->lock, flags); |
1279 | goto done; | 1272 | return; |
1280 | } | 1273 | } |
1281 | 1274 | ||
1282 | if ((tty->count == 1) && (port->count != 1)) { | 1275 | if ((tty->count == 1) && (port->count != 1)) { |
@@ -1298,7 +1291,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1298 | } | 1291 | } |
1299 | if (port->count) { | 1292 | if (port->count) { |
1300 | spin_unlock_irqrestore(&port->lock, flags); | 1293 | spin_unlock_irqrestore(&port->lock, flags); |
1301 | goto done; | 1294 | return; |
1302 | } | 1295 | } |
1303 | 1296 | ||
1304 | /* | 1297 | /* |
@@ -1306,19 +1299,13 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1306 | * the line discipline to only process XON/XOFF characters by | 1299 | * the line discipline to only process XON/XOFF characters by |
1307 | * setting tty->closing. | 1300 | * setting tty->closing. |
1308 | */ | 1301 | */ |
1302 | set_bit(ASYNCB_CLOSING, &port->flags); | ||
1309 | tty->closing = 1; | 1303 | tty->closing = 1; |
1310 | spin_unlock_irqrestore(&port->lock, flags); | 1304 | spin_unlock_irqrestore(&port->lock, flags); |
1311 | 1305 | ||
1312 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) { | 1306 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
1313 | /* | 1307 | tty_wait_until_sent_from_close(tty, |
1314 | * hack: open-coded tty_wait_until_sent to avoid | 1308 | msecs_to_jiffies(port->closing_wait)); |
1315 | * recursive tty_lock | ||
1316 | */ | ||
1317 | long timeout = msecs_to_jiffies(port->closing_wait); | ||
1318 | if (wait_event_interruptible_timeout(tty->write_wait, | ||
1319 | !tty_chars_in_buffer(tty), timeout) >= 0) | ||
1320 | __uart_wait_until_sent(uport, timeout); | ||
1321 | } | ||
1322 | 1309 | ||
1323 | /* | 1310 | /* |
1324 | * At this point, we stop accepting input. To do this, we | 1311 | * At this point, we stop accepting input. To do this, we |
@@ -1334,9 +1321,10 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1334 | * has completely drained; this is especially | 1321 | * has completely drained; this is especially |
1335 | * important if there is a transmit FIFO! | 1322 | * important if there is a transmit FIFO! |
1336 | */ | 1323 | */ |
1337 | __uart_wait_until_sent(uport, uport->timeout); | 1324 | uart_wait_until_sent(tty, uport->timeout); |
1338 | } | 1325 | } |
1339 | 1326 | ||
1327 | mutex_lock(&port->mutex); | ||
1340 | uart_shutdown(tty, state); | 1328 | uart_shutdown(tty, state); |
1341 | uart_flush_buffer(tty); | 1329 | uart_flush_buffer(tty); |
1342 | 1330 | ||
@@ -1361,15 +1349,18 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1361 | * Wake up anyone trying to open this port. | 1349 | * Wake up anyone trying to open this port. |
1362 | */ | 1350 | */ |
1363 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | 1351 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
1352 | clear_bit(ASYNCB_CLOSING, &port->flags); | ||
1364 | spin_unlock_irqrestore(&port->lock, flags); | 1353 | spin_unlock_irqrestore(&port->lock, flags); |
1365 | wake_up_interruptible(&port->open_wait); | 1354 | wake_up_interruptible(&port->open_wait); |
1355 | wake_up_interruptible(&port->close_wait); | ||
1366 | 1356 | ||
1367 | done: | ||
1368 | mutex_unlock(&port->mutex); | 1357 | mutex_unlock(&port->mutex); |
1369 | } | 1358 | } |
1370 | 1359 | ||
1371 | static void __uart_wait_until_sent(struct uart_port *port, int timeout) | 1360 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout) |
1372 | { | 1361 | { |
1362 | struct uart_state *state = tty->driver_data; | ||
1363 | struct uart_port *port = state->uart_port; | ||
1373 | unsigned long char_time, expire; | 1364 | unsigned long char_time, expire; |
1374 | 1365 | ||
1375 | if (port->type == PORT_UNKNOWN || port->fifosize == 0) | 1366 | if (port->type == PORT_UNKNOWN || port->fifosize == 0) |
@@ -1421,16 +1412,6 @@ static void __uart_wait_until_sent(struct uart_port *port, int timeout) | |||
1421 | } | 1412 | } |
1422 | } | 1413 | } |
1423 | 1414 | ||
1424 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | ||
1425 | { | ||
1426 | struct uart_state *state = tty->driver_data; | ||
1427 | struct uart_port *port = state->uart_port; | ||
1428 | |||
1429 | tty_lock(); | ||
1430 | __uart_wait_until_sent(port, timeout); | ||
1431 | tty_unlock(); | ||
1432 | } | ||
1433 | |||
1434 | /* | 1415 | /* |
1435 | * This is called with the BKL held in | 1416 | * This is called with the BKL held in |
1436 | * linux/drivers/char/tty_io.c:do_tty_hangup() | 1417 | * linux/drivers/char/tty_io.c:do_tty_hangup() |
@@ -1443,7 +1424,6 @@ static void uart_hangup(struct tty_struct *tty) | |||
1443 | struct tty_port *port = &state->port; | 1424 | struct tty_port *port = &state->port; |
1444 | unsigned long flags; | 1425 | unsigned long flags; |
1445 | 1426 | ||
1446 | BUG_ON(!tty_locked()); | ||
1447 | pr_debug("uart_hangup(%d)\n", state->uart_port->line); | 1427 | pr_debug("uart_hangup(%d)\n", state->uart_port->line); |
1448 | 1428 | ||
1449 | mutex_lock(&port->mutex); | 1429 | mutex_lock(&port->mutex); |
@@ -1530,7 +1510,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1530 | struct tty_port *port; | 1510 | struct tty_port *port; |
1531 | int retval, line = tty->index; | 1511 | int retval, line = tty->index; |
1532 | 1512 | ||
1533 | BUG_ON(!tty_locked()); | ||
1534 | pr_debug("uart_open(%d) called\n", line); | 1513 | pr_debug("uart_open(%d) called\n", line); |
1535 | 1514 | ||
1536 | /* | 1515 | /* |
@@ -2008,6 +1987,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) | |||
2008 | if (port->tty && port->tty->termios && termios.c_cflag == 0) | 1987 | if (port->tty && port->tty->termios && termios.c_cflag == 0) |
2009 | termios = *(port->tty->termios); | 1988 | termios = *(port->tty->termios); |
2010 | 1989 | ||
1990 | if (console_suspend_enabled) | ||
1991 | uart_change_pm(state, 0); | ||
2011 | uport->ops->set_termios(uport, &termios, NULL); | 1992 | uport->ops->set_termios(uport, &termios, NULL); |
2012 | if (console_suspend_enabled) | 1993 | if (console_suspend_enabled) |
2013 | console_start(uport->cons); | 1994 | console_start(uport->cons); |
@@ -2068,8 +2049,6 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) | |||
2068 | case UPIO_MEM32: | 2049 | case UPIO_MEM32: |
2069 | case UPIO_AU: | 2050 | case UPIO_AU: |
2070 | case UPIO_TSI: | 2051 | case UPIO_TSI: |
2071 | case UPIO_DWAPB: | ||
2072 | case UPIO_DWAPB32: | ||
2073 | snprintf(address, sizeof(address), | 2052 | snprintf(address, sizeof(address), |
2074 | "MMIO 0x%llx", (unsigned long long)port->mapbase); | 2053 | "MMIO 0x%llx", (unsigned long long)port->mapbase); |
2075 | break; | 2054 | break; |
@@ -2298,8 +2277,6 @@ int uart_register_driver(struct uart_driver *drv) | |||
2298 | port->ops = &uart_port_ops; | 2277 | port->ops = &uart_port_ops; |
2299 | port->close_delay = 500; /* .5 seconds */ | 2278 | port->close_delay = 500; /* .5 seconds */ |
2300 | port->closing_wait = 30000; /* 30 seconds */ | 2279 | port->closing_wait = 30000; /* 30 seconds */ |
2301 | tasklet_init(&state->tlet, uart_tasklet_action, | ||
2302 | (unsigned long)state); | ||
2303 | } | 2280 | } |
2304 | 2281 | ||
2305 | retval = tty_register_driver(normal); | 2282 | retval = tty_register_driver(normal); |
@@ -2460,11 +2437,6 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport) | |||
2460 | */ | 2437 | */ |
2461 | uport->type = PORT_UNKNOWN; | 2438 | uport->type = PORT_UNKNOWN; |
2462 | 2439 | ||
2463 | /* | ||
2464 | * Kill the tasklet, and free resources. | ||
2465 | */ | ||
2466 | tasklet_kill(&state->tlet); | ||
2467 | |||
2468 | state->uart_port = NULL; | 2440 | state->uart_port = NULL; |
2469 | mutex_unlock(&port_mutex); | 2441 | mutex_unlock(&port_mutex); |
2470 | 2442 | ||
@@ -2489,8 +2461,6 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2) | |||
2489 | case UPIO_MEM32: | 2461 | case UPIO_MEM32: |
2490 | case UPIO_AU: | 2462 | case UPIO_AU: |
2491 | case UPIO_TSI: | 2463 | case UPIO_TSI: |
2492 | case UPIO_DWAPB: | ||
2493 | case UPIO_DWAPB32: | ||
2494 | return (port1->mapbase == port2->mapbase); | 2464 | return (port1->mapbase == port2->mapbase); |
2495 | } | 2465 | } |
2496 | return 0; | 2466 | return 0; |
diff --git a/drivers/tty/serial/serial_ks8695.c b/drivers/tty/serial/serial_ks8695.c index 2430319f2f52..7c13639c597e 100644 --- a/drivers/tty/serial/serial_ks8695.c +++ b/drivers/tty/serial/serial_ks8695.c | |||
@@ -13,6 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/tty.h> | 15 | #include <linux/tty.h> |
16 | #include <linux/tty_flip.h> | ||
16 | #include <linux/ioport.h> | 17 | #include <linux/ioport.h> |
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/serial.h> | 19 | #include <linux/serial.h> |
@@ -336,19 +337,19 @@ static int ks8695uart_startup(struct uart_port *port) | |||
336 | /* | 337 | /* |
337 | * Allocate the IRQ | 338 | * Allocate the IRQ |
338 | */ | 339 | */ |
339 | retval = request_irq(KS8695_IRQ_UART_TX, ks8695uart_tx_chars, IRQF_DISABLED, "UART TX", port); | 340 | retval = request_irq(KS8695_IRQ_UART_TX, ks8695uart_tx_chars, 0, "UART TX", port); |
340 | if (retval) | 341 | if (retval) |
341 | goto err_tx; | 342 | goto err_tx; |
342 | 343 | ||
343 | retval = request_irq(KS8695_IRQ_UART_RX, ks8695uart_rx_chars, IRQF_DISABLED, "UART RX", port); | 344 | retval = request_irq(KS8695_IRQ_UART_RX, ks8695uart_rx_chars, 0, "UART RX", port); |
344 | if (retval) | 345 | if (retval) |
345 | goto err_rx; | 346 | goto err_rx; |
346 | 347 | ||
347 | retval = request_irq(KS8695_IRQ_UART_LINE_STATUS, ks8695uart_rx_chars, IRQF_DISABLED, "UART LineStatus", port); | 348 | retval = request_irq(KS8695_IRQ_UART_LINE_STATUS, ks8695uart_rx_chars, 0, "UART LineStatus", port); |
348 | if (retval) | 349 | if (retval) |
349 | goto err_ls; | 350 | goto err_ls; |
350 | 351 | ||
351 | retval = request_irq(KS8695_IRQ_UART_MODEM_STATUS, ks8695uart_modem_status, IRQF_DISABLED, "UART ModemStatus", port); | 352 | retval = request_irq(KS8695_IRQ_UART_MODEM_STATUS, ks8695uart_modem_status, 0, "UART ModemStatus", port); |
352 | if (retval) | 353 | if (retval) |
353 | goto err_ms; | 354 | goto err_ms; |
354 | 355 | ||
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c index 8e3fc1944e6d..34bd345da775 100644 --- a/drivers/tty/serial/serial_txx9.c +++ b/drivers/tty/serial/serial_txx9.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <linux/serial_core.h> | 29 | #include <linux/serial_core.h> |
30 | #include <linux/serial.h> | 30 | #include <linux/serial.h> |
31 | #include <linux/tty.h> | ||
32 | #include <linux/tty_flip.h> | ||
31 | 33 | ||
32 | #include <asm/io.h> | 34 | #include <asm/io.h> |
33 | 35 | ||
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 5ea6ec3442e6..9871c57b348e 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c | |||
@@ -1976,7 +1976,7 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1976 | * For the muxed case there's nothing more to do. | 1976 | * For the muxed case there's nothing more to do. |
1977 | */ | 1977 | */ |
1978 | port->irq = p->irqs[SCIx_RXI_IRQ]; | 1978 | port->irq = p->irqs[SCIx_RXI_IRQ]; |
1979 | port->irqflags = IRQF_DISABLED; | 1979 | port->irqflags = 0; |
1980 | 1980 | ||
1981 | port->serial_in = sci_serial_in; | 1981 | port->serial_in = sci_serial_in; |
1982 | port->serial_out = sci_serial_out; | 1982 | port->serial_out = sci_serial_out; |
diff --git a/drivers/tty/serial/sn_console.c b/drivers/tty/serial/sn_console.c index 377ae74e7154..238c7df73ef5 100644 --- a/drivers/tty/serial/sn_console.c +++ b/drivers/tty/serial/sn_console.c | |||
@@ -39,6 +39,7 @@ | |||
39 | 39 | ||
40 | #include <linux/interrupt.h> | 40 | #include <linux/interrupt.h> |
41 | #include <linux/tty.h> | 41 | #include <linux/tty.h> |
42 | #include <linux/tty_flip.h> | ||
42 | #include <linux/serial.h> | 43 | #include <linux/serial.h> |
43 | #include <linux/console.h> | 44 | #include <linux/console.h> |
44 | #include <linux/module.h> | 45 | #include <linux/module.h> |
@@ -737,7 +738,7 @@ static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port) | |||
737 | DPRINTF("sn_console: switching to interrupt driven console\n"); | 738 | DPRINTF("sn_console: switching to interrupt driven console\n"); |
738 | 739 | ||
739 | if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, | 740 | if (request_irq(SGI_UART_VECTOR, sn_sal_interrupt, |
740 | IRQF_DISABLED | IRQF_SHARED, | 741 | IRQF_SHARED, |
741 | "SAL console driver", port) >= 0) { | 742 | "SAL console driver", port) >= 0) { |
742 | spin_lock_irqsave(&port->sc_port.lock, flags); | 743 | spin_lock_irqsave(&port->sc_port.lock, flags); |
743 | port->sc_port.irq = SGI_UART_VECTOR; | 744 | port->sc_port.irq = SGI_UART_VECTOR; |
diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c index 1f36b7eb7351..a4b63bfeaa2f 100644 --- a/drivers/tty/serial/timbuart.c +++ b/drivers/tty/serial/timbuart.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/serial_core.h> | 25 | #include <linux/serial_core.h> |
26 | #include <linux/tty.h> | ||
27 | #include <linux/tty_flip.h> | ||
26 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
27 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
28 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index 8af1ed83a4c0..b908615ccaaf 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/serial.h> | 15 | #include <linux/serial.h> |
16 | #include <linux/serial_core.h> | 16 | #include <linux/serial_core.h> |
17 | #include <linux/tty.h> | 17 | #include <linux/tty.h> |
18 | #include <linux/tty_flip.h> | ||
18 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c index 9af9f0879a24..cea8918b8233 100644 --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c | |||
@@ -20,8 +20,10 @@ | |||
20 | 20 | ||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/serial.h> | 22 | #include <linux/serial.h> |
23 | #include <linux/slab.h> | ||
24 | #include <linux/serial_core.h> | 23 | #include <linux/serial_core.h> |
24 | #include <linux/slab.h> | ||
25 | #include <linux/tty.h> | ||
26 | #include <linux/tty_flip.h> | ||
25 | #include <linux/io.h> | 27 | #include <linux/io.h> |
26 | #include <linux/of_platform.h> | 28 | #include <linux/of_platform.h> |
27 | #include <linux/dma-mapping.h> | 29 | #include <linux/dma-mapping.h> |
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 19cc1e8149dd..8c03b127fd03 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c | |||
@@ -12,9 +12,11 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/serial.h> | ||
15 | #include <linux/serial_core.h> | 16 | #include <linux/serial_core.h> |
17 | #include <linux/tty.h> | ||
18 | #include <linux/tty_flip.h> | ||
16 | #include <linux/console.h> | 19 | #include <linux/console.h> |
17 | #include <linux/serial.h> | ||
18 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
19 | #include <linux/io.h> | 21 | #include <linux/io.h> |
20 | #include <linux/of.h> | 22 | #include <linux/of.h> |
diff --git a/drivers/tty/serial/zs.c b/drivers/tty/serial/zs.c index 0aebd7121b56..b7455b526080 100644 --- a/drivers/tty/serial/zs.c +++ b/drivers/tty/serial/zs.c | |||
@@ -63,6 +63,7 @@ | |||
63 | #include <linux/spinlock.h> | 63 | #include <linux/spinlock.h> |
64 | #include <linux/sysrq.h> | 64 | #include <linux/sysrq.h> |
65 | #include <linux/tty.h> | 65 | #include <linux/tty.h> |
66 | #include <linux/tty_flip.h> | ||
66 | #include <linux/types.h> | 67 | #include <linux/types.h> |
67 | 68 | ||
68 | #include <linux/atomic.h> | 69 | #include <linux/atomic.h> |
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c index 272e417a9b0d..e67fb20490d2 100644 --- a/drivers/tty/synclink.c +++ b/drivers/tty/synclink.c | |||
@@ -2124,7 +2124,6 @@ static int mgsl_write(struct tty_struct * tty, | |||
2124 | if ( info->params.mode == MGSL_MODE_HDLC || | 2124 | if ( info->params.mode == MGSL_MODE_HDLC || |
2125 | info->params.mode == MGSL_MODE_RAW ) { | 2125 | info->params.mode == MGSL_MODE_RAW ) { |
2126 | /* operating in synchronous (frame oriented) mode */ | 2126 | /* operating in synchronous (frame oriented) mode */ |
2127 | /* operating in synchronous (frame oriented) mode */ | ||
2128 | if (info->tx_active) { | 2127 | if (info->tx_active) { |
2129 | 2128 | ||
2130 | if ( info->params.mode == MGSL_MODE_HDLC ) { | 2129 | if ( info->params.mode == MGSL_MODE_HDLC ) { |
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c index c77831c7675a..0f6b796c95c5 100644 --- a/drivers/tty/synclinkmp.c +++ b/drivers/tty/synclinkmp.c | |||
@@ -4950,7 +4950,7 @@ CheckAgain: | |||
4950 | 4950 | ||
4951 | if ( debug_level >= DEBUG_LEVEL_DATA ) | 4951 | if ( debug_level >= DEBUG_LEVEL_DATA ) |
4952 | trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr, | 4952 | trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr, |
4953 | min_t(int, framesize,SCABUFSIZE),0); | 4953 | min_t(unsigned int, framesize, SCABUFSIZE), 0); |
4954 | 4954 | ||
4955 | if (framesize) { | 4955 | if (framesize) { |
4956 | if (framesize > info->max_frame_size) | 4956 | if (framesize > info->max_frame_size) |
@@ -5015,14 +5015,14 @@ static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int co | |||
5015 | SCADESC_EX *desc_ex; | 5015 | SCADESC_EX *desc_ex; |
5016 | 5016 | ||
5017 | if ( debug_level >= DEBUG_LEVEL_DATA ) | 5017 | if ( debug_level >= DEBUG_LEVEL_DATA ) |
5018 | trace_block(info,buf, min_t(int, count,SCABUFSIZE), 1); | 5018 | trace_block(info, buf, min_t(unsigned int, count, SCABUFSIZE), 1); |
5019 | 5019 | ||
5020 | /* Copy source buffer to one or more DMA buffers, starting with | 5020 | /* Copy source buffer to one or more DMA buffers, starting with |
5021 | * the first transmit dma buffer. | 5021 | * the first transmit dma buffer. |
5022 | */ | 5022 | */ |
5023 | for(i=0;;) | 5023 | for(i=0;;) |
5024 | { | 5024 | { |
5025 | copy_count = min_t(unsigned short,count,SCABUFSIZE); | 5025 | copy_count = min_t(unsigned int, count, SCABUFSIZE); |
5026 | 5026 | ||
5027 | desc = &info->tx_buf_list[i]; | 5027 | desc = &info->tx_buf_list[i]; |
5028 | desc_ex = &info->tx_buf_list_ex[i]; | 5028 | desc_ex = &info->tx_buf_list_ex[i]; |
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 4f1fc81112e6..05085beb83db 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -194,8 +194,7 @@ static inline struct tty_struct *file_tty(struct file *file) | |||
194 | return ((struct tty_file_private *)file->private_data)->tty; | 194 | return ((struct tty_file_private *)file->private_data)->tty; |
195 | } | 195 | } |
196 | 196 | ||
197 | /* Associate a new file with the tty structure */ | 197 | int tty_alloc_file(struct file *file) |
198 | int tty_add_file(struct tty_struct *tty, struct file *file) | ||
199 | { | 198 | { |
200 | struct tty_file_private *priv; | 199 | struct tty_file_private *priv; |
201 | 200 | ||
@@ -203,15 +202,36 @@ int tty_add_file(struct tty_struct *tty, struct file *file) | |||
203 | if (!priv) | 202 | if (!priv) |
204 | return -ENOMEM; | 203 | return -ENOMEM; |
205 | 204 | ||
205 | file->private_data = priv; | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | /* Associate a new file with the tty structure */ | ||
211 | void tty_add_file(struct tty_struct *tty, struct file *file) | ||
212 | { | ||
213 | struct tty_file_private *priv = file->private_data; | ||
214 | |||
206 | priv->tty = tty; | 215 | priv->tty = tty; |
207 | priv->file = file; | 216 | priv->file = file; |
208 | file->private_data = priv; | ||
209 | 217 | ||
210 | spin_lock(&tty_files_lock); | 218 | spin_lock(&tty_files_lock); |
211 | list_add(&priv->list, &tty->tty_files); | 219 | list_add(&priv->list, &tty->tty_files); |
212 | spin_unlock(&tty_files_lock); | 220 | spin_unlock(&tty_files_lock); |
221 | } | ||
213 | 222 | ||
214 | return 0; | 223 | /** |
224 | * tty_free_file - free file->private_data | ||
225 | * | ||
226 | * This shall be used only for fail path handling when tty_add_file was not | ||
227 | * called yet. | ||
228 | */ | ||
229 | void tty_free_file(struct file *file) | ||
230 | { | ||
231 | struct tty_file_private *priv = file->private_data; | ||
232 | |||
233 | file->private_data = NULL; | ||
234 | kfree(priv); | ||
215 | } | 235 | } |
216 | 236 | ||
217 | /* Delete file from its tty */ | 237 | /* Delete file from its tty */ |
@@ -222,8 +242,7 @@ void tty_del_file(struct file *file) | |||
222 | spin_lock(&tty_files_lock); | 242 | spin_lock(&tty_files_lock); |
223 | list_del(&priv->list); | 243 | list_del(&priv->list); |
224 | spin_unlock(&tty_files_lock); | 244 | spin_unlock(&tty_files_lock); |
225 | file->private_data = NULL; | 245 | tty_free_file(file); |
226 | kfree(priv); | ||
227 | } | 246 | } |
228 | 247 | ||
229 | 248 | ||
@@ -1811,6 +1830,10 @@ static int tty_open(struct inode *inode, struct file *filp) | |||
1811 | nonseekable_open(inode, filp); | 1830 | nonseekable_open(inode, filp); |
1812 | 1831 | ||
1813 | retry_open: | 1832 | retry_open: |
1833 | retval = tty_alloc_file(filp); | ||
1834 | if (retval) | ||
1835 | return -ENOMEM; | ||
1836 | |||
1814 | noctty = filp->f_flags & O_NOCTTY; | 1837 | noctty = filp->f_flags & O_NOCTTY; |
1815 | index = -1; | 1838 | index = -1; |
1816 | retval = 0; | 1839 | retval = 0; |
@@ -1823,6 +1846,7 @@ retry_open: | |||
1823 | if (!tty) { | 1846 | if (!tty) { |
1824 | tty_unlock(); | 1847 | tty_unlock(); |
1825 | mutex_unlock(&tty_mutex); | 1848 | mutex_unlock(&tty_mutex); |
1849 | tty_free_file(filp); | ||
1826 | return -ENXIO; | 1850 | return -ENXIO; |
1827 | } | 1851 | } |
1828 | driver = tty_driver_kref_get(tty->driver); | 1852 | driver = tty_driver_kref_get(tty->driver); |
@@ -1855,6 +1879,7 @@ retry_open: | |||
1855 | } | 1879 | } |
1856 | tty_unlock(); | 1880 | tty_unlock(); |
1857 | mutex_unlock(&tty_mutex); | 1881 | mutex_unlock(&tty_mutex); |
1882 | tty_free_file(filp); | ||
1858 | return -ENODEV; | 1883 | return -ENODEV; |
1859 | } | 1884 | } |
1860 | 1885 | ||
@@ -1862,6 +1887,7 @@ retry_open: | |||
1862 | if (!driver) { | 1887 | if (!driver) { |
1863 | tty_unlock(); | 1888 | tty_unlock(); |
1864 | mutex_unlock(&tty_mutex); | 1889 | mutex_unlock(&tty_mutex); |
1890 | tty_free_file(filp); | ||
1865 | return -ENODEV; | 1891 | return -ENODEV; |
1866 | } | 1892 | } |
1867 | got_driver: | 1893 | got_driver: |
@@ -1872,6 +1898,8 @@ got_driver: | |||
1872 | if (IS_ERR(tty)) { | 1898 | if (IS_ERR(tty)) { |
1873 | tty_unlock(); | 1899 | tty_unlock(); |
1874 | mutex_unlock(&tty_mutex); | 1900 | mutex_unlock(&tty_mutex); |
1901 | tty_driver_kref_put(driver); | ||
1902 | tty_free_file(filp); | ||
1875 | return PTR_ERR(tty); | 1903 | return PTR_ERR(tty); |
1876 | } | 1904 | } |
1877 | } | 1905 | } |
@@ -1887,15 +1915,11 @@ got_driver: | |||
1887 | tty_driver_kref_put(driver); | 1915 | tty_driver_kref_put(driver); |
1888 | if (IS_ERR(tty)) { | 1916 | if (IS_ERR(tty)) { |
1889 | tty_unlock(); | 1917 | tty_unlock(); |
1918 | tty_free_file(filp); | ||
1890 | return PTR_ERR(tty); | 1919 | return PTR_ERR(tty); |
1891 | } | 1920 | } |
1892 | 1921 | ||
1893 | retval = tty_add_file(tty, filp); | 1922 | tty_add_file(tty, filp); |
1894 | if (retval) { | ||
1895 | tty_unlock(); | ||
1896 | tty_release(inode, filp); | ||
1897 | return retval; | ||
1898 | } | ||
1899 | 1923 | ||
1900 | check_tty_count(tty, "tty_open"); | 1924 | check_tty_count(tty, "tty_open"); |
1901 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1925 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
@@ -2716,6 +2740,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, | |||
2716 | ld = tty_ldisc_ref_wait(tty); | 2740 | ld = tty_ldisc_ref_wait(tty); |
2717 | if (ld->ops->compat_ioctl) | 2741 | if (ld->ops->compat_ioctl) |
2718 | retval = ld->ops->compat_ioctl(tty, file, cmd, arg); | 2742 | retval = ld->ops->compat_ioctl(tty, file, cmd, arg); |
2743 | else | ||
2744 | retval = n_tty_compat_ioctl_helper(tty, file, cmd, arg); | ||
2719 | tty_ldisc_deref(ld); | 2745 | tty_ldisc_deref(ld); |
2720 | 2746 | ||
2721 | return retval; | 2747 | return retval; |
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 53f2442c6099..9314d93c1a20 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/bitops.h> | 20 | #include <linux/bitops.h> |
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/compat.h> | ||
22 | 23 | ||
23 | #include <asm/io.h> | 24 | #include <asm/io.h> |
24 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
@@ -1179,3 +1180,19 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, | |||
1179 | } | 1180 | } |
1180 | } | 1181 | } |
1181 | EXPORT_SYMBOL(n_tty_ioctl_helper); | 1182 | EXPORT_SYMBOL(n_tty_ioctl_helper); |
1183 | |||
1184 | #ifdef CONFIG_COMPAT | ||
1185 | long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file, | ||
1186 | unsigned int cmd, unsigned long arg) | ||
1187 | { | ||
1188 | switch (cmd) { | ||
1189 | case TIOCGLCKTRMIOS: | ||
1190 | case TIOCSLCKTRMIOS: | ||
1191 | return tty_mode_ioctl(tty, file, cmd, (unsigned long) compat_ptr(arg)); | ||
1192 | default: | ||
1193 | return -ENOIOCTLCMD; | ||
1194 | } | ||
1195 | } | ||
1196 | EXPORT_SYMBOL(n_tty_compat_ioctl_helper); | ||
1197 | #endif | ||
1198 | |||
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index ef925d581713..512c49f98e85 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c | |||
@@ -450,7 +450,6 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | |||
450 | if (ld->ops->open) { | 450 | if (ld->ops->open) { |
451 | int ret; | 451 | int ret; |
452 | /* BTM here locks versus a hangup event */ | 452 | /* BTM here locks versus a hangup event */ |
453 | WARN_ON(!tty_locked()); | ||
454 | ret = ld->ops->open(tty); | 453 | ret = ld->ops->open(tty); |
455 | if (ret) | 454 | if (ret) |
456 | clear_bit(TTY_LDISC_OPEN, &tty->flags); | 455 | clear_bit(TTY_LDISC_OPEN, &tty->flags); |
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c index 3b2bb7719442..9ff986c32a21 100644 --- a/drivers/tty/tty_mutex.c +++ b/drivers/tty/tty_mutex.c | |||
@@ -15,30 +15,18 @@ | |||
15 | * Don't use in new code. | 15 | * Don't use in new code. |
16 | */ | 16 | */ |
17 | static DEFINE_MUTEX(big_tty_mutex); | 17 | static DEFINE_MUTEX(big_tty_mutex); |
18 | struct task_struct *__big_tty_mutex_owner; | ||
19 | EXPORT_SYMBOL_GPL(__big_tty_mutex_owner); | ||
20 | 18 | ||
21 | /* | 19 | /* |
22 | * Getting the big tty mutex. | 20 | * Getting the big tty mutex. |
23 | */ | 21 | */ |
24 | void __lockfunc tty_lock(void) | 22 | void __lockfunc tty_lock(void) |
25 | { | 23 | { |
26 | struct task_struct *task = current; | ||
27 | |||
28 | WARN_ON(__big_tty_mutex_owner == task); | ||
29 | |||
30 | mutex_lock(&big_tty_mutex); | 24 | mutex_lock(&big_tty_mutex); |
31 | __big_tty_mutex_owner = task; | ||
32 | } | 25 | } |
33 | EXPORT_SYMBOL(tty_lock); | 26 | EXPORT_SYMBOL(tty_lock); |
34 | 27 | ||
35 | void __lockfunc tty_unlock(void) | 28 | void __lockfunc tty_unlock(void) |
36 | { | 29 | { |
37 | struct task_struct *task = current; | ||
38 | |||
39 | WARN_ON(__big_tty_mutex_owner != task); | ||
40 | __big_tty_mutex_owner = NULL; | ||
41 | |||
42 | mutex_unlock(&big_tty_mutex); | 30 | mutex_unlock(&big_tty_mutex); |
43 | } | 31 | } |
44 | EXPORT_SYMBOL(tty_unlock); | 32 | EXPORT_SYMBOL(tty_unlock); |
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c index 33d37d230f8f..ef9dd628ba0b 100644 --- a/drivers/tty/tty_port.c +++ b/drivers/tty/tty_port.c | |||
@@ -350,7 +350,7 @@ int tty_port_close_start(struct tty_port *port, | |||
350 | tty_driver_flush_buffer(tty); | 350 | tty_driver_flush_buffer(tty); |
351 | if (test_bit(ASYNCB_INITIALIZED, &port->flags) && | 351 | if (test_bit(ASYNCB_INITIALIZED, &port->flags) && |
352 | port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 352 | port->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
353 | tty_wait_until_sent(tty, port->closing_wait); | 353 | tty_wait_until_sent_from_close(tty, port->closing_wait); |
354 | if (port->drain_delay) { | 354 | if (port->drain_delay) { |
355 | unsigned int bps = tty_get_baud_rate(tty); | 355 | unsigned int bps = tty_get_baud_rate(tty); |
356 | long timeout; | 356 | long timeout; |
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 3761ccf0f340..a605549ee28f 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/string.h> | 33 | #include <linux/string.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/irq.h> | ||
37 | 36 | ||
38 | #include <linux/kbd_kern.h> | 37 | #include <linux/kbd_kern.h> |
39 | #include <linux/kbd_diacr.h> | 38 | #include <linux/kbd_diacr.h> |
@@ -43,6 +42,8 @@ | |||
43 | #include <linux/notifier.h> | 42 | #include <linux/notifier.h> |
44 | #include <linux/jiffies.h> | 43 | #include <linux/jiffies.h> |
45 | 44 | ||
45 | #include <asm/irq_regs.h> | ||
46 | |||
46 | extern void ctrl_alt_del(void); | 47 | extern void ctrl_alt_del(void); |
47 | 48 | ||
48 | /* | 49 | /* |
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index fb864e7fcd13..7a0a12ae5458 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c | |||
@@ -301,6 +301,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t | |||
301 | /* Insert the contents of the selection buffer into the | 301 | /* Insert the contents of the selection buffer into the |
302 | * queue of the tty associated with the current console. | 302 | * queue of the tty associated with the current console. |
303 | * Invoked by ioctl(). | 303 | * Invoked by ioctl(). |
304 | * | ||
305 | * Locking: always called with BTM from vt_ioctl | ||
304 | */ | 306 | */ |
305 | int paste_selection(struct tty_struct *tty) | 307 | int paste_selection(struct tty_struct *tty) |
306 | { | 308 | { |
@@ -310,8 +312,6 @@ int paste_selection(struct tty_struct *tty) | |||
310 | struct tty_ldisc *ld; | 312 | struct tty_ldisc *ld; |
311 | DECLARE_WAITQUEUE(wait, current); | 313 | DECLARE_WAITQUEUE(wait, current); |
312 | 314 | ||
313 | /* always called with BTM from vt_ioctl */ | ||
314 | WARN_ON(!tty_locked()); | ||
315 | 315 | ||
316 | console_lock(); | 316 | console_lock(); |
317 | poke_blanked_console(); | 317 | poke_blanked_console(); |
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index b3915b7ad3e2..e716839fab6e 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c | |||
@@ -259,7 +259,7 @@ EXPORT_SYMBOL_GPL(unregister_vt_notifier); | |||
259 | 259 | ||
260 | static void notify_write(struct vc_data *vc, unsigned int unicode) | 260 | static void notify_write(struct vc_data *vc, unsigned int unicode) |
261 | { | 261 | { |
262 | struct vt_notifier_param param = { .vc = vc, unicode = unicode }; | 262 | struct vt_notifier_param param = { .vc = vc, .c = unicode }; |
263 | atomic_notifier_call_chain(&vt_notifier_list, VT_WRITE, ¶m); | 263 | atomic_notifier_call_chain(&vt_notifier_list, VT_WRITE, ¶m); |
264 | } | 264 | } |
265 | 265 | ||
diff --git a/include/linux/serial.h b/include/linux/serial.h index ef914061511e..97ff8e27a6cc 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h | |||
@@ -211,6 +211,7 @@ struct serial_rs485 { | |||
211 | #define SER_RS485_RTS_ON_SEND (1 << 1) | 211 | #define SER_RS485_RTS_ON_SEND (1 << 1) |
212 | #define SER_RS485_RTS_AFTER_SEND (1 << 2) | 212 | #define SER_RS485_RTS_AFTER_SEND (1 << 2) |
213 | #define SER_RS485_RTS_BEFORE_SEND (1 << 3) | 213 | #define SER_RS485_RTS_BEFORE_SEND (1 << 3) |
214 | #define SER_RS485_RX_DURING_TX (1 << 4) | ||
214 | __u32 delay_rts_before_send; /* Milliseconds */ | 215 | __u32 delay_rts_before_send; /* Milliseconds */ |
215 | __u32 delay_rts_after_send; /* Milliseconds */ | 216 | __u32 delay_rts_after_send; /* Milliseconds */ |
216 | __u32 padding[5]; /* Memory is cheap, new structs | 217 | __u32 padding[5]; /* Memory is cheap, new structs |
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 97f5b45bbc07..1f05bbeac01e 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h | |||
@@ -35,6 +35,7 @@ struct plat_serial8250_port { | |||
35 | void (*set_termios)(struct uart_port *, | 35 | void (*set_termios)(struct uart_port *, |
36 | struct ktermios *new, | 36 | struct ktermios *new, |
37 | struct ktermios *old); | 37 | struct ktermios *old); |
38 | int (*handle_irq)(struct uart_port *); | ||
38 | void (*pm)(struct uart_port *, unsigned int state, | 39 | void (*pm)(struct uart_port *, unsigned int state, |
39 | unsigned old); | 40 | unsigned old); |
40 | }; | 41 | }; |
@@ -80,6 +81,7 @@ extern void serial8250_do_set_termios(struct uart_port *port, | |||
80 | struct ktermios *termios, struct ktermios *old); | 81 | struct ktermios *termios, struct ktermios *old); |
81 | extern void serial8250_do_pm(struct uart_port *port, unsigned int state, | 82 | extern void serial8250_do_pm(struct uart_port *port, unsigned int state, |
82 | unsigned int oldstate); | 83 | unsigned int oldstate); |
84 | int serial8250_handle_irq(struct uart_port *port, unsigned int iir); | ||
83 | 85 | ||
84 | extern void serial8250_set_isa_configurator(void (*v) | 86 | extern void serial8250_set_isa_configurator(void (*v) |
85 | (int port, struct uart_port *up, | 87 | (int port, struct uart_port *up, |
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index a5c31146a337..eadf33d0abba 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -46,7 +46,8 @@ | |||
46 | #define PORT_AR7 18 /* Texas Instruments AR7 internal UART */ | 46 | #define PORT_AR7 18 /* Texas Instruments AR7 internal UART */ |
47 | #define PORT_U6_16550A 19 /* ST-Ericsson U6xxx internal UART */ | 47 | #define PORT_U6_16550A 19 /* ST-Ericsson U6xxx internal UART */ |
48 | #define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */ | 48 | #define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */ |
49 | #define PORT_MAX_8250 20 /* max port ID */ | 49 | #define PORT_XR17D15X 21 /* Exar XR17D15x UART */ |
50 | #define PORT_MAX_8250 21 /* max port ID */ | ||
50 | 51 | ||
51 | /* | 52 | /* |
52 | * ARM specific type numbers. These are not currently guaranteed | 53 | * ARM specific type numbers. These are not currently guaranteed |
@@ -300,6 +301,7 @@ struct uart_port { | |||
300 | void (*set_termios)(struct uart_port *, | 301 | void (*set_termios)(struct uart_port *, |
301 | struct ktermios *new, | 302 | struct ktermios *new, |
302 | struct ktermios *old); | 303 | struct ktermios *old); |
304 | int (*handle_irq)(struct uart_port *); | ||
303 | void (*pm)(struct uart_port *, unsigned int state, | 305 | void (*pm)(struct uart_port *, unsigned int state, |
304 | unsigned int old); | 306 | unsigned int old); |
305 | unsigned int irq; /* irq number */ | 307 | unsigned int irq; /* irq number */ |
@@ -317,9 +319,7 @@ struct uart_port { | |||
317 | #define UPIO_MEM32 (3) | 319 | #define UPIO_MEM32 (3) |
318 | #define UPIO_AU (4) /* Au1x00 type IO */ | 320 | #define UPIO_AU (4) /* Au1x00 type IO */ |
319 | #define UPIO_TSI (5) /* Tsi108/109 type IO */ | 321 | #define UPIO_TSI (5) /* Tsi108/109 type IO */ |
320 | #define UPIO_DWAPB (6) /* DesignWare APB UART */ | 322 | #define UPIO_RM9000 (6) /* RM9000 type IO */ |
321 | #define UPIO_RM9000 (7) /* RM9000 type IO */ | ||
322 | #define UPIO_DWAPB32 (8) /* DesignWare APB UART (32 bit accesses) */ | ||
323 | 323 | ||
324 | unsigned int read_status_mask; /* driver specific */ | 324 | unsigned int read_status_mask; /* driver specific */ |
325 | unsigned int ignore_status_mask; /* driver specific */ | 325 | unsigned int ignore_status_mask; /* driver specific */ |
@@ -350,6 +350,7 @@ struct uart_port { | |||
350 | #define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16)) | 350 | #define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16)) |
351 | #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) | 351 | #define UPF_CONS_FLOW ((__force upf_t) (1 << 23)) |
352 | #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) | 352 | #define UPF_SHARE_IRQ ((__force upf_t) (1 << 24)) |
353 | #define UPF_EXAR_EFR ((__force upf_t) (1 << 25)) | ||
353 | /* The exact UART type is known and should not be probed. */ | 354 | /* The exact UART type is known and should not be probed. */ |
354 | #define UPF_FIXED_TYPE ((__force upf_t) (1 << 27)) | 355 | #define UPF_FIXED_TYPE ((__force upf_t) (1 << 27)) |
355 | #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28)) | 356 | #define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28)) |
@@ -384,7 +385,6 @@ struct uart_state { | |||
384 | int pm_state; | 385 | int pm_state; |
385 | struct circ_buf xmit; | 386 | struct circ_buf xmit; |
386 | 387 | ||
387 | struct tasklet_struct tlet; | ||
388 | struct uart_port *uart_port; | 388 | struct uart_port *uart_port; |
389 | }; | 389 | }; |
390 | 390 | ||
diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h index c75bda37c18e..8ce70d76f836 100644 --- a/include/linux/serial_reg.h +++ b/include/linux/serial_reg.h | |||
@@ -152,6 +152,7 @@ | |||
152 | * LCR=0xBF (or DLAB=1 for 16C660) | 152 | * LCR=0xBF (or DLAB=1 for 16C660) |
153 | */ | 153 | */ |
154 | #define UART_EFR 2 /* I/O: Extended Features Register */ | 154 | #define UART_EFR 2 /* I/O: Extended Features Register */ |
155 | #define UART_XR_EFR 9 /* I/O: Extended Features Register (XR17D15x) */ | ||
155 | #define UART_EFR_CTS 0x80 /* CTS flow control */ | 156 | #define UART_EFR_CTS 0x80 /* CTS flow control */ |
156 | #define UART_EFR_RTS 0x40 /* RTS flow control */ | 157 | #define UART_EFR_RTS 0x40 /* RTS flow control */ |
157 | #define UART_EFR_SCD 0x20 /* Special character detect */ | 158 | #define UART_EFR_SCD 0x20 /* Special character detect */ |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 5f2ede82b3d6..5dbb3cb05a82 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -473,7 +473,9 @@ extern void proc_clear_tty(struct task_struct *p); | |||
473 | extern struct tty_struct *get_current_tty(void); | 473 | extern struct tty_struct *get_current_tty(void); |
474 | extern void tty_default_fops(struct file_operations *fops); | 474 | extern void tty_default_fops(struct file_operations *fops); |
475 | extern struct tty_struct *alloc_tty_struct(void); | 475 | extern struct tty_struct *alloc_tty_struct(void); |
476 | extern int tty_add_file(struct tty_struct *tty, struct file *file); | 476 | extern int tty_alloc_file(struct file *file); |
477 | extern void tty_add_file(struct tty_struct *tty, struct file *file); | ||
478 | extern void tty_free_file(struct file *file); | ||
477 | extern void free_tty_struct(struct tty_struct *tty); | 479 | extern void free_tty_struct(struct tty_struct *tty); |
478 | extern void initialize_tty_struct(struct tty_struct *tty, | 480 | extern void initialize_tty_struct(struct tty_struct *tty, |
479 | struct tty_driver *driver, int idx); | 481 | struct tty_driver *driver, int idx); |
@@ -581,6 +583,8 @@ extern int __init tty_init(void); | |||
581 | /* tty_ioctl.c */ | 583 | /* tty_ioctl.c */ |
582 | extern int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, | 584 | extern int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, |
583 | unsigned int cmd, unsigned long arg); | 585 | unsigned int cmd, unsigned long arg); |
586 | extern long n_tty_compat_ioctl_helper(struct tty_struct *tty, struct file *file, | ||
587 | unsigned int cmd, unsigned long arg); | ||
584 | 588 | ||
585 | /* serial.c */ | 589 | /* serial.c */ |
586 | 590 | ||
@@ -602,8 +606,24 @@ extern long vt_compat_ioctl(struct tty_struct *tty, | |||
602 | /* functions for preparation of BKL removal */ | 606 | /* functions for preparation of BKL removal */ |
603 | extern void __lockfunc tty_lock(void) __acquires(tty_lock); | 607 | extern void __lockfunc tty_lock(void) __acquires(tty_lock); |
604 | extern void __lockfunc tty_unlock(void) __releases(tty_lock); | 608 | extern void __lockfunc tty_unlock(void) __releases(tty_lock); |
605 | extern struct task_struct *__big_tty_mutex_owner; | 609 | |
606 | #define tty_locked() (current == __big_tty_mutex_owner) | 610 | /* |
611 | * this shall be called only from where BTM is held (like close) | ||
612 | * | ||
613 | * We need this to ensure nobody waits for us to finish while we are waiting. | ||
614 | * Without this we were encountering system stalls. | ||
615 | * | ||
616 | * This should be indeed removed with BTM removal later. | ||
617 | * | ||
618 | * Locking: BTM required. Nobody is allowed to hold port->mutex. | ||
619 | */ | ||
620 | static inline void tty_wait_until_sent_from_close(struct tty_struct *tty, | ||
621 | long timeout) | ||
622 | { | ||
623 | tty_unlock(); /* tty->ops->close holds the BTM, drop it while waiting */ | ||
624 | tty_wait_until_sent(tty, timeout); | ||
625 | tty_lock(); | ||
626 | } | ||
607 | 627 | ||
608 | /* | 628 | /* |
609 | * wait_event_interruptible_tty -- wait for a condition with the tty lock held | 629 | * wait_event_interruptible_tty -- wait for a condition with the tty lock held |
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index b3cc8b3989a9..253695d43fd9 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c | |||
@@ -551,7 +551,7 @@ static void ircomm_tty_close(struct tty_struct *tty, struct file *filp) | |||
551 | */ | 551 | */ |
552 | tty->closing = 1; | 552 | tty->closing = 1; |
553 | if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 553 | if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
554 | tty_wait_until_sent(tty, self->closing_wait); | 554 | tty_wait_until_sent_from_close(tty, self->closing_wait); |
555 | 555 | ||
556 | ircomm_tty_shutdown(self); | 556 | ircomm_tty_shutdown(self); |
557 | 557 | ||