diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 18:03:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 18:03:42 -0400 |
commit | fc385c313275b114bc6ad36e60c5177d63250548 (patch) | |
tree | 3436184ec3af11e6506df5233889700a74427055 | |
parent | a92b166e6b8c3c0037493690b2800b0b0dd92063 (diff) | |
parent | 235dae5d094c415fcf0fc79fa637f1901bc8afe2 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (68 commits)
U6715 16550A serial driver support
Char: nozomi, set tty->driver_data appropriately
Char: nozomi, fix tty->count counting
serial: max3107: Fix gpiolib support
hsu: call PCI pm hooks in suspend/resume function
hsu: some code cleanup
hsu: add a periodic timer to check dma rx channel
hsu: driver for Medfield High Speed UART device
mxser: remove unnesesary NULL check
serial: add support for OX16PCI958 card
serial: 68328serial.c: remove dead (ALMA_ANS | DRAGONIXVZ | M68EZ328ADS)
timbuart: use __devinit and __devexit macros for probe and remove
serial: MMIO32 support for 8250_early.c
serial: mcf: don't take spinlocks in already protected functions
serial: general fixes in the serial_rs485 structure
serial: fix missing bit coverage of ASYNC_FLAGS
serial: "altera_uart: simplify altera_uart_console_putc()" checkpatch fixes
serial: crisv10: formatting of pointers in printk()
vt: Fix warning: statement with no effect due to vt_kern.h
tty_io: remove casts from void*
...
112 files changed, 5498 insertions, 647 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 44f6b19c50bb..d529b1363e95 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -681,8 +681,11 @@ and is between 256 and 4096 characters. It is defined in the file | |||
681 | earlycon= [KNL] Output early console device and options. | 681 | earlycon= [KNL] Output early console device and options. |
682 | uart[8250],io,<addr>[,options] | 682 | uart[8250],io,<addr>[,options] |
683 | uart[8250],mmio,<addr>[,options] | 683 | uart[8250],mmio,<addr>[,options] |
684 | uart[8250],mmio32,<addr>[,options] | ||
684 | Start an early, polled-mode console on the 8250/16550 | 685 | Start an early, polled-mode console on the 8250/16550 |
685 | UART at the specified I/O port or MMIO address. | 686 | UART at the specified I/O port or MMIO address. |
687 | MMIO inter-register address stride is either 8bit (mmio) | ||
688 | or 32bit (mmio32). | ||
686 | The options are the same as for ttyS, above. | 689 | The options are the same as for ttyS, above. |
687 | 690 | ||
688 | earlyprintk= [X86,SH,BLACKFIN] | 691 | earlyprintk= [X86,SH,BLACKFIN] |
diff --git a/arch/alpha/include/asm/ioctls.h b/arch/alpha/include/asm/ioctls.h index 67bb9f6fdbe4..59617c3c2be6 100644 --- a/arch/alpha/include/asm/ioctls.h +++ b/arch/alpha/include/asm/ioctls.h | |||
@@ -80,6 +80,7 @@ | |||
80 | # define TIOCPKT_START 8 | 80 | # define TIOCPKT_START 8 |
81 | # define TIOCPKT_NOSTOP 16 | 81 | # define TIOCPKT_NOSTOP 16 |
82 | # define TIOCPKT_DOSTOP 32 | 82 | # define TIOCPKT_DOSTOP 32 |
83 | # define TIOCPKT_IOCTL 64 | ||
83 | 84 | ||
84 | 85 | ||
85 | #define TIOCNOTTY 0x5422 | 86 | #define TIOCNOTTY 0x5422 |
@@ -91,6 +92,7 @@ | |||
91 | #define TIOCGSID 0x5429 /* Return the session ID of FD */ | 92 | #define TIOCGSID 0x5429 /* Return the session ID of FD */ |
92 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 93 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
93 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 94 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
95 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
94 | 96 | ||
95 | #define TIOCSERCONFIG 0x5453 | 97 | #define TIOCSERCONFIG 0x5453 |
96 | #define TIOCSERGWILD 0x5454 | 98 | #define TIOCSERGWILD 0x5454 |
@@ -106,7 +108,5 @@ | |||
106 | 108 | ||
107 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ | 109 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ |
108 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ | 110 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ |
109 | #define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ | ||
110 | #define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ | ||
111 | 111 | ||
112 | #endif /* _ASM_ALPHA_IOCTLS_H */ | 112 | #endif /* _ASM_ALPHA_IOCTLS_H */ |
diff --git a/arch/alpha/include/asm/termbits.h b/arch/alpha/include/asm/termbits.h index ad854a4a3af6..879dd3589921 100644 --- a/arch/alpha/include/asm/termbits.h +++ b/arch/alpha/include/asm/termbits.h | |||
@@ -180,6 +180,7 @@ struct ktermios { | |||
180 | #define FLUSHO 0x00800000 | 180 | #define FLUSHO 0x00800000 |
181 | #define PENDIN 0x20000000 | 181 | #define PENDIN 0x20000000 |
182 | #define IEXTEN 0x00000400 | 182 | #define IEXTEN 0x00000400 |
183 | #define EXTPROC 0x10000000 | ||
183 | 184 | ||
184 | /* Values for the ACTION argument to `tcflow'. */ | 185 | /* Values for the ACTION argument to `tcflow'. */ |
185 | #define TCOOFF 0 | 186 | #define TCOOFF 0 |
diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h index 7f0b6d13296a..0b30894b5482 100644 --- a/arch/arm/include/asm/ioctls.h +++ b/arch/arm/include/asm/ioctls.h | |||
@@ -52,6 +52,7 @@ | |||
52 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) | 52 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) |
53 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 53 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
54 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 54 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
55 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
55 | 56 | ||
56 | #define TIOCGRS485 0x542E | 57 | #define TIOCGRS485 0x542E |
57 | #define TIOCSRS485 0x542F | 58 | #define TIOCSRS485 0x542F |
@@ -81,6 +82,7 @@ | |||
81 | #define TIOCPKT_START 8 | 82 | #define TIOCPKT_START 8 |
82 | #define TIOCPKT_NOSTOP 16 | 83 | #define TIOCPKT_NOSTOP 16 |
83 | #define TIOCPKT_DOSTOP 32 | 84 | #define TIOCPKT_DOSTOP 32 |
85 | #define TIOCPKT_IOCTL 64 | ||
84 | 86 | ||
85 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 87 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
86 | 88 | ||
diff --git a/arch/arm/include/asm/termbits.h b/arch/arm/include/asm/termbits.h index f784d11f40b5..704135d28d1d 100644 --- a/arch/arm/include/asm/termbits.h +++ b/arch/arm/include/asm/termbits.h | |||
@@ -177,6 +177,7 @@ struct ktermios { | |||
177 | #define FLUSHO 0010000 | 177 | #define FLUSHO 0010000 |
178 | #define PENDIN 0040000 | 178 | #define PENDIN 0040000 |
179 | #define IEXTEN 0100000 | 179 | #define IEXTEN 0100000 |
180 | #define EXTPROC 0200000 | ||
180 | 181 | ||
181 | /* tcflow() and TCXONC use these */ | 182 | /* tcflow() and TCXONC use these */ |
182 | #define TCOOFF 0 | 183 | #define TCOOFF 0 |
diff --git a/arch/avr32/include/asm/ioctls.h b/arch/avr32/include/asm/ioctls.h index e6ac0b661076..b7dd324b46a9 100644 --- a/arch/avr32/include/asm/ioctls.h +++ b/arch/avr32/include/asm/ioctls.h | |||
@@ -53,6 +53,7 @@ | |||
53 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) | 53 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) |
54 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 54 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
55 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 55 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
56 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
56 | 57 | ||
57 | #define TIOCGRS485 0x542E | 58 | #define TIOCGRS485 0x542E |
58 | #define TIOCSRS485 0x542F | 59 | #define TIOCSRS485 0x542F |
@@ -72,8 +73,6 @@ | |||
72 | 73 | ||
73 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ | 74 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ |
74 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ | 75 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ |
75 | #define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ | ||
76 | #define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ | ||
77 | #define FIOQSIZE 0x5460 | 76 | #define FIOQSIZE 0x5460 |
78 | 77 | ||
79 | /* Used for packet mode */ | 78 | /* Used for packet mode */ |
@@ -84,6 +83,7 @@ | |||
84 | #define TIOCPKT_START 8 | 83 | #define TIOCPKT_START 8 |
85 | #define TIOCPKT_NOSTOP 16 | 84 | #define TIOCPKT_NOSTOP 16 |
86 | #define TIOCPKT_DOSTOP 32 | 85 | #define TIOCPKT_DOSTOP 32 |
86 | #define TIOCPKT_IOCTL 64 | ||
87 | 87 | ||
88 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 88 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
89 | 89 | ||
diff --git a/arch/avr32/include/asm/termbits.h b/arch/avr32/include/asm/termbits.h index db2daab31fdb..366adc5ebb10 100644 --- a/arch/avr32/include/asm/termbits.h +++ b/arch/avr32/include/asm/termbits.h | |||
@@ -175,6 +175,7 @@ struct ktermios { | |||
175 | #define FLUSHO 0010000 | 175 | #define FLUSHO 0010000 |
176 | #define PENDIN 0040000 | 176 | #define PENDIN 0040000 |
177 | #define IEXTEN 0100000 | 177 | #define IEXTEN 0100000 |
178 | #define EXTPROC 0200000 | ||
178 | 179 | ||
179 | /* tcflow() and TCXONC use these */ | 180 | /* tcflow() and TCXONC use these */ |
180 | #define TCOOFF 0 | 181 | #define TCOOFF 0 |
diff --git a/arch/cris/include/asm/ioctls.h b/arch/cris/include/asm/ioctls.h index 076c07824eb6..c9129ed37443 100644 --- a/arch/cris/include/asm/ioctls.h +++ b/arch/cris/include/asm/ioctls.h | |||
@@ -54,6 +54,7 @@ | |||
54 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) | 54 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) |
55 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 55 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
56 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 56 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
57 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
57 | 58 | ||
58 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ | 59 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ |
59 | #define FIOCLEX 0x5451 | 60 | #define FIOCLEX 0x5451 |
@@ -70,8 +71,6 @@ | |||
70 | 71 | ||
71 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ | 72 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ |
72 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ | 73 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ |
73 | #define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ | ||
74 | #define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ | ||
75 | #define FIOQSIZE 0x5460 | 74 | #define FIOQSIZE 0x5460 |
76 | 75 | ||
77 | #define TIOCSERSETRS485 0x5461 /* enable rs-485 (deprecated) */ | 76 | #define TIOCSERSETRS485 0x5461 /* enable rs-485 (deprecated) */ |
@@ -87,6 +86,7 @@ | |||
87 | #define TIOCPKT_START 8 | 86 | #define TIOCPKT_START 8 |
88 | #define TIOCPKT_NOSTOP 16 | 87 | #define TIOCPKT_NOSTOP 16 |
89 | #define TIOCPKT_DOSTOP 32 | 88 | #define TIOCPKT_DOSTOP 32 |
89 | #define TIOCPKT_IOCTL 64 | ||
90 | 90 | ||
91 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 91 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
92 | 92 | ||
diff --git a/arch/cris/include/asm/termbits.h b/arch/cris/include/asm/termbits.h index 66e1a7492a0c..1c43bc874ccf 100644 --- a/arch/cris/include/asm/termbits.h +++ b/arch/cris/include/asm/termbits.h | |||
@@ -214,6 +214,7 @@ struct ktermios { | |||
214 | #define FLUSHO 0010000 | 214 | #define FLUSHO 0010000 |
215 | #define PENDIN 0040000 | 215 | #define PENDIN 0040000 |
216 | #define IEXTEN 0100000 | 216 | #define IEXTEN 0100000 |
217 | #define EXTPROC 0200000 | ||
217 | 218 | ||
218 | /* tcflow() and TCXONC use these */ | 219 | /* tcflow() and TCXONC use these */ |
219 | #define TCOOFF 0 | 220 | #define TCOOFF 0 |
diff --git a/arch/frv/include/asm/ioctls.h b/arch/frv/include/asm/ioctls.h index d0c30e31fbda..a993e3759ccf 100644 --- a/arch/frv/include/asm/ioctls.h +++ b/arch/frv/include/asm/ioctls.h | |||
@@ -53,6 +53,7 @@ | |||
53 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) | 53 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) |
54 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 54 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
55 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 55 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
56 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
56 | 57 | ||
57 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ | 58 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ |
58 | #define FIOCLEX 0x5451 | 59 | #define FIOCLEX 0x5451 |
@@ -79,6 +80,7 @@ | |||
79 | #define TIOCPKT_START 8 | 80 | #define TIOCPKT_START 8 |
80 | #define TIOCPKT_NOSTOP 16 | 81 | #define TIOCPKT_NOSTOP 16 |
81 | #define TIOCPKT_DOSTOP 32 | 82 | #define TIOCPKT_DOSTOP 32 |
83 | #define TIOCPKT_IOCTL 64 | ||
82 | 84 | ||
83 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 85 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
84 | 86 | ||
diff --git a/arch/frv/include/asm/termbits.h b/arch/frv/include/asm/termbits.h index 5568492b5086..7722e19cc349 100644 --- a/arch/frv/include/asm/termbits.h +++ b/arch/frv/include/asm/termbits.h | |||
@@ -180,6 +180,7 @@ struct ktermios { | |||
180 | #define FLUSHO 0010000 | 180 | #define FLUSHO 0010000 |
181 | #define PENDIN 0040000 | 181 | #define PENDIN 0040000 |
182 | #define IEXTEN 0100000 | 182 | #define IEXTEN 0100000 |
183 | #define EXTPROC 0200000 | ||
183 | 184 | ||
184 | 185 | ||
185 | /* tcflow() and TCXONC use these */ | 186 | /* tcflow() and TCXONC use these */ |
diff --git a/arch/h8300/include/asm/ioctls.h b/arch/h8300/include/asm/ioctls.h index 98a53d067269..b6b249f9f308 100644 --- a/arch/h8300/include/asm/ioctls.h +++ b/arch/h8300/include/asm/ioctls.h | |||
@@ -53,6 +53,7 @@ | |||
53 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) | 53 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) |
54 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 54 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
55 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 55 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
56 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
56 | 57 | ||
57 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ | 58 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ |
58 | #define FIOCLEX 0x5451 | 59 | #define FIOCLEX 0x5451 |
@@ -79,6 +80,7 @@ | |||
79 | #define TIOCPKT_START 8 | 80 | #define TIOCPKT_START 8 |
80 | #define TIOCPKT_NOSTOP 16 | 81 | #define TIOCPKT_NOSTOP 16 |
81 | #define TIOCPKT_DOSTOP 32 | 82 | #define TIOCPKT_DOSTOP 32 |
83 | #define TIOCPKT_IOCTL 64 | ||
82 | 84 | ||
83 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 85 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
84 | 86 | ||
diff --git a/arch/h8300/include/asm/termbits.h b/arch/h8300/include/asm/termbits.h index 31eca81db3f7..3287a6244d74 100644 --- a/arch/h8300/include/asm/termbits.h +++ b/arch/h8300/include/asm/termbits.h | |||
@@ -179,6 +179,7 @@ struct ktermios { | |||
179 | #define FLUSHO 0010000 | 179 | #define FLUSHO 0010000 |
180 | #define PENDIN 0040000 | 180 | #define PENDIN 0040000 |
181 | #define IEXTEN 0100000 | 181 | #define IEXTEN 0100000 |
182 | #define EXTPROC 0200000 | ||
182 | 183 | ||
183 | 184 | ||
184 | /* tcflow() and TCXONC use these */ | 185 | /* tcflow() and TCXONC use these */ |
diff --git a/arch/ia64/include/asm/ioctls.h b/arch/ia64/include/asm/ioctls.h index f41b636a0bf6..b79c385114ef 100644 --- a/arch/ia64/include/asm/ioctls.h +++ b/arch/ia64/include/asm/ioctls.h | |||
@@ -59,6 +59,7 @@ | |||
59 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) | 59 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) |
60 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 60 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
61 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 61 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
62 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
62 | 63 | ||
63 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ | 64 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ |
64 | #define FIOCLEX 0x5451 | 65 | #define FIOCLEX 0x5451 |
@@ -75,8 +76,6 @@ | |||
75 | 76 | ||
76 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ | 77 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ |
77 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ | 78 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ |
78 | #define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ | ||
79 | #define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ | ||
80 | #define FIOQSIZE 0x5460 | 79 | #define FIOQSIZE 0x5460 |
81 | 80 | ||
82 | /* Used for packet mode */ | 81 | /* Used for packet mode */ |
@@ -87,6 +86,7 @@ | |||
87 | #define TIOCPKT_START 8 | 86 | #define TIOCPKT_START 8 |
88 | #define TIOCPKT_NOSTOP 16 | 87 | #define TIOCPKT_NOSTOP 16 |
89 | #define TIOCPKT_DOSTOP 32 | 88 | #define TIOCPKT_DOSTOP 32 |
89 | #define TIOCPKT_IOCTL 64 | ||
90 | 90 | ||
91 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 91 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
92 | 92 | ||
diff --git a/arch/ia64/include/asm/termbits.h b/arch/ia64/include/asm/termbits.h index 9f162e0089ad..c009b94e58d9 100644 --- a/arch/ia64/include/asm/termbits.h +++ b/arch/ia64/include/asm/termbits.h | |||
@@ -187,6 +187,7 @@ struct ktermios { | |||
187 | #define FLUSHO 0010000 | 187 | #define FLUSHO 0010000 |
188 | #define PENDIN 0040000 | 188 | #define PENDIN 0040000 |
189 | #define IEXTEN 0100000 | 189 | #define IEXTEN 0100000 |
190 | #define EXTPROC 0200000 | ||
190 | 191 | ||
191 | /* tcflow() and TCXONC use these */ | 192 | /* tcflow() and TCXONC use these */ |
192 | #define TCOOFF 0 | 193 | #define TCOOFF 0 |
diff --git a/arch/m32r/include/asm/ioctls.h b/arch/m32r/include/asm/ioctls.h index b9f54bb5d7cf..66288063a4c0 100644 --- a/arch/m32r/include/asm/ioctls.h +++ b/arch/m32r/include/asm/ioctls.h | |||
@@ -53,6 +53,7 @@ | |||
53 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) | 53 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) |
54 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 54 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
55 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 55 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
56 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
56 | 57 | ||
57 | #define FIONCLEX 0x5450 | 58 | #define FIONCLEX 0x5450 |
58 | #define FIOCLEX 0x5451 | 59 | #define FIOCLEX 0x5451 |
@@ -69,8 +70,6 @@ | |||
69 | 70 | ||
70 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ | 71 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ |
71 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ | 72 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ |
72 | #define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ | ||
73 | #define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ | ||
74 | #define FIOQSIZE 0x5460 | 73 | #define FIOQSIZE 0x5460 |
75 | 74 | ||
76 | /* Used for packet mode */ | 75 | /* Used for packet mode */ |
@@ -81,6 +80,7 @@ | |||
81 | #define TIOCPKT_START 8 | 80 | #define TIOCPKT_START 8 |
82 | #define TIOCPKT_NOSTOP 16 | 81 | #define TIOCPKT_NOSTOP 16 |
83 | #define TIOCPKT_DOSTOP 32 | 82 | #define TIOCPKT_DOSTOP 32 |
83 | #define TIOCPKT_IOCTL 64 | ||
84 | 84 | ||
85 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 85 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
86 | 86 | ||
diff --git a/arch/m32r/include/asm/termbits.h b/arch/m32r/include/asm/termbits.h index bc104008b55b..957a3c688549 100644 --- a/arch/m32r/include/asm/termbits.h +++ b/arch/m32r/include/asm/termbits.h | |||
@@ -179,6 +179,7 @@ struct ktermios { | |||
179 | #define FLUSHO 0010000 | 179 | #define FLUSHO 0010000 |
180 | #define PENDIN 0040000 | 180 | #define PENDIN 0040000 |
181 | #define IEXTEN 0100000 | 181 | #define IEXTEN 0100000 |
182 | #define EXTPROC 0200000 | ||
182 | 183 | ||
183 | /* tcflow() and TCXONC use these */ | 184 | /* tcflow() and TCXONC use these */ |
184 | #define TCOOFF 0 | 185 | #define TCOOFF 0 |
diff --git a/arch/m68k/include/asm/ioctls.h b/arch/m68k/include/asm/ioctls.h index b8d2f4be7fd7..91a57d665460 100644 --- a/arch/m68k/include/asm/ioctls.h +++ b/arch/m68k/include/asm/ioctls.h | |||
@@ -52,6 +52,7 @@ | |||
52 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) | 52 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) |
53 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 53 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
54 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 54 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
55 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
55 | 56 | ||
56 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ | 57 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ |
57 | #define FIOCLEX 0x5451 | 58 | #define FIOCLEX 0x5451 |
@@ -78,6 +79,7 @@ | |||
78 | #define TIOCPKT_START 8 | 79 | #define TIOCPKT_START 8 |
79 | #define TIOCPKT_NOSTOP 16 | 80 | #define TIOCPKT_NOSTOP 16 |
80 | #define TIOCPKT_DOSTOP 32 | 81 | #define TIOCPKT_DOSTOP 32 |
82 | #define TIOCPKT_IOCTL 64 | ||
81 | 83 | ||
82 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 84 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
83 | 85 | ||
diff --git a/arch/m68k/include/asm/termbits.h b/arch/m68k/include/asm/termbits.h index 8c14170996bb..aea1e37b765a 100644 --- a/arch/m68k/include/asm/termbits.h +++ b/arch/m68k/include/asm/termbits.h | |||
@@ -179,6 +179,7 @@ struct ktermios { | |||
179 | #define FLUSHO 0010000 | 179 | #define FLUSHO 0010000 |
180 | #define PENDIN 0040000 | 180 | #define PENDIN 0040000 |
181 | #define IEXTEN 0100000 | 181 | #define IEXTEN 0100000 |
182 | #define EXTPROC 0200000 | ||
182 | 183 | ||
183 | 184 | ||
184 | /* tcflow() and TCXONC use these */ | 185 | /* tcflow() and TCXONC use these */ |
diff --git a/arch/mips/include/asm/ioctls.h b/arch/mips/include/asm/ioctls.h index 3f04a995ec54..d87cb0465693 100644 --- a/arch/mips/include/asm/ioctls.h +++ b/arch/mips/include/asm/ioctls.h | |||
@@ -41,7 +41,7 @@ | |||
41 | #define TIOCPKT_START 0x08 /* start output */ | 41 | #define TIOCPKT_START 0x08 /* start output */ |
42 | #define TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */ | 42 | #define TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */ |
43 | #define TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */ | 43 | #define TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */ |
44 | /* #define TIOCPKT_IOCTL 0x40 state change of pty driver */ | 44 | #define TIOCPKT_IOCTL 0x40 /* state change of pty driver */ |
45 | #define TIOCSWINSZ _IOW('t', 103, struct winsize) /* set window size */ | 45 | #define TIOCSWINSZ _IOW('t', 103, struct winsize) /* set window size */ |
46 | #define TIOCGWINSZ _IOR('t', 104, struct winsize) /* get window size */ | 46 | #define TIOCGWINSZ _IOR('t', 104, struct winsize) /* get window size */ |
47 | #define TIOCNOTTY 0x5471 /* void tty association */ | 47 | #define TIOCNOTTY 0x5471 /* void tty association */ |
@@ -83,6 +83,7 @@ | |||
83 | #define TCSETSF2 _IOW('T', 0x2D, struct termios2) | 83 | #define TCSETSF2 _IOW('T', 0x2D, struct termios2) |
84 | #define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 84 | #define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
85 | #define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ | 85 | #define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ |
86 | #define TIOCSIG _IOW('T', 0x36, int) /* Generate signal on Pty slave */ | ||
86 | 87 | ||
87 | /* I hope the range from 0x5480 on is free ... */ | 88 | /* I hope the range from 0x5480 on is free ... */ |
88 | #define TIOCSCTTY 0x5480 /* become controlling tty */ | 89 | #define TIOCSCTTY 0x5480 /* become controlling tty */ |
@@ -103,7 +104,5 @@ | |||
103 | #define TIOCSERSETMULTI 0x5490 /* Set multiport config */ | 104 | #define TIOCSERSETMULTI 0x5490 /* Set multiport config */ |
104 | #define TIOCMIWAIT 0x5491 /* wait for a change on serial input line(s) */ | 105 | #define TIOCMIWAIT 0x5491 /* wait for a change on serial input line(s) */ |
105 | #define TIOCGICOUNT 0x5492 /* read serial port inline interrupt counts */ | 106 | #define TIOCGICOUNT 0x5492 /* read serial port inline interrupt counts */ |
106 | #define TIOCGHAYESESP 0x5493 /* Get Hayes ESP configuration */ | ||
107 | #define TIOCSHAYESESP 0x5494 /* Set Hayes ESP configuration */ | ||
108 | 107 | ||
109 | #endif /* __ASM_IOCTLS_H */ | 108 | #endif /* __ASM_IOCTLS_H */ |
diff --git a/arch/mips/include/asm/termbits.h b/arch/mips/include/asm/termbits.h index c83c68444e86..76630b396fac 100644 --- a/arch/mips/include/asm/termbits.h +++ b/arch/mips/include/asm/termbits.h | |||
@@ -203,6 +203,7 @@ struct ktermios { | |||
203 | #define PENDIN 0040000 /* Retype pending input (state). */ | 203 | #define PENDIN 0040000 /* Retype pending input (state). */ |
204 | #define TOSTOP 0100000 /* Send SIGTTOU for background output. */ | 204 | #define TOSTOP 0100000 /* Send SIGTTOU for background output. */ |
205 | #define ITOSTOP TOSTOP | 205 | #define ITOSTOP TOSTOP |
206 | #define EXTPROC 0200000 /* External processing on pty */ | ||
206 | 207 | ||
207 | /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ | 208 | /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ |
208 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 209 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
diff --git a/arch/mn10300/include/asm/ioctls.h b/arch/mn10300/include/asm/ioctls.h index dcbfb452974f..cb8cf1902234 100644 --- a/arch/mn10300/include/asm/ioctls.h +++ b/arch/mn10300/include/asm/ioctls.h | |||
@@ -54,6 +54,7 @@ | |||
54 | #define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number | 54 | #define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number |
55 | * (of pty-mux device) */ | 55 | * (of pty-mux device) */ |
56 | #define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ | 56 | #define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ |
57 | #define TIOCSIG _IOW('T', 0x36, int) /* Generate signal on Pty slave */ | ||
57 | 58 | ||
58 | #define FIONCLEX 0x5450 | 59 | #define FIONCLEX 0x5450 |
59 | #define FIOCLEX 0x5451 | 60 | #define FIOCLEX 0x5451 |
@@ -70,8 +71,6 @@ | |||
70 | 71 | ||
71 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ | 72 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ |
72 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ | 73 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ |
73 | #define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ | ||
74 | #define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ | ||
75 | #define FIOQSIZE 0x5460 | 74 | #define FIOQSIZE 0x5460 |
76 | 75 | ||
77 | /* Used for packet mode */ | 76 | /* Used for packet mode */ |
@@ -82,6 +81,7 @@ | |||
82 | #define TIOCPKT_START 8 | 81 | #define TIOCPKT_START 8 |
83 | #define TIOCPKT_NOSTOP 16 | 82 | #define TIOCPKT_NOSTOP 16 |
84 | #define TIOCPKT_DOSTOP 32 | 83 | #define TIOCPKT_DOSTOP 32 |
84 | #define TIOCPKT_IOCTL 64 | ||
85 | 85 | ||
86 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 86 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
87 | 87 | ||
diff --git a/arch/mn10300/include/asm/termbits.h b/arch/mn10300/include/asm/termbits.h index eb2b0dc1f696..130d42495972 100644 --- a/arch/mn10300/include/asm/termbits.h +++ b/arch/mn10300/include/asm/termbits.h | |||
@@ -180,6 +180,7 @@ struct ktermios { | |||
180 | #define FLUSHO 0010000 | 180 | #define FLUSHO 0010000 |
181 | #define PENDIN 0040000 | 181 | #define PENDIN 0040000 |
182 | #define IEXTEN 0100000 | 182 | #define IEXTEN 0100000 |
183 | #define EXTPROC 0200000 | ||
183 | 184 | ||
184 | /* tcflow() and TCXONC use these */ | 185 | /* tcflow() and TCXONC use these */ |
185 | #define TCOOFF 0 | 186 | #define TCOOFF 0 |
diff --git a/arch/parisc/include/asm/ioctls.h b/arch/parisc/include/asm/ioctls.h index 6747fad07a3e..4e0614456bea 100644 --- a/arch/parisc/include/asm/ioctls.h +++ b/arch/parisc/include/asm/ioctls.h | |||
@@ -52,6 +52,7 @@ | |||
52 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) | 52 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) |
53 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 53 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
54 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 54 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
55 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
55 | 56 | ||
56 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ | 57 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ |
57 | #define FIOCLEX 0x5451 | 58 | #define FIOCLEX 0x5451 |
@@ -68,8 +69,6 @@ | |||
68 | 69 | ||
69 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ | 70 | #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ |
70 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ | 71 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ |
71 | #define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ | ||
72 | #define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ | ||
73 | #define FIOQSIZE 0x5460 /* Get exact space used by quota */ | 72 | #define FIOQSIZE 0x5460 /* Get exact space used by quota */ |
74 | 73 | ||
75 | #define TIOCSTART 0x5461 | 74 | #define TIOCSTART 0x5461 |
@@ -84,6 +83,7 @@ | |||
84 | #define TIOCPKT_START 8 | 83 | #define TIOCPKT_START 8 |
85 | #define TIOCPKT_NOSTOP 16 | 84 | #define TIOCPKT_NOSTOP 16 |
86 | #define TIOCPKT_DOSTOP 32 | 85 | #define TIOCPKT_DOSTOP 32 |
86 | #define TIOCPKT_IOCTL 64 | ||
87 | 87 | ||
88 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 88 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
89 | 89 | ||
diff --git a/arch/parisc/include/asm/termbits.h b/arch/parisc/include/asm/termbits.h index d8bbc73b16b7..d1ab92177a5c 100644 --- a/arch/parisc/include/asm/termbits.h +++ b/arch/parisc/include/asm/termbits.h | |||
@@ -180,6 +180,7 @@ struct ktermios { | |||
180 | #define FLUSHO 0010000 | 180 | #define FLUSHO 0010000 |
181 | #define PENDIN 0040000 | 181 | #define PENDIN 0040000 |
182 | #define IEXTEN 0100000 | 182 | #define IEXTEN 0100000 |
183 | #define EXTPROC 0200000 | ||
183 | 184 | ||
184 | /* tcflow() and TCXONC use these */ | 185 | /* tcflow() and TCXONC use these */ |
185 | #define TCOOFF 0 | 186 | #define TCOOFF 0 |
diff --git a/arch/powerpc/include/asm/ioctls.h b/arch/powerpc/include/asm/ioctls.h index 1842186d872c..851920052e08 100644 --- a/arch/powerpc/include/asm/ioctls.h +++ b/arch/powerpc/include/asm/ioctls.h | |||
@@ -80,6 +80,7 @@ | |||
80 | # define TIOCPKT_START 8 | 80 | # define TIOCPKT_START 8 |
81 | # define TIOCPKT_NOSTOP 16 | 81 | # define TIOCPKT_NOSTOP 16 |
82 | # define TIOCPKT_DOSTOP 32 | 82 | # define TIOCPKT_DOSTOP 32 |
83 | # define TIOCPKT_IOCTL 64 | ||
83 | 84 | ||
84 | 85 | ||
85 | #define TIOCNOTTY 0x5422 | 86 | #define TIOCNOTTY 0x5422 |
@@ -93,6 +94,7 @@ | |||
93 | #define TIOCSRS485 0x542f | 94 | #define TIOCSRS485 0x542f |
94 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 95 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
95 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 96 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
97 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
96 | 98 | ||
97 | #define TIOCSERCONFIG 0x5453 | 99 | #define TIOCSERCONFIG 0x5453 |
98 | #define TIOCSERGWILD 0x5454 | 100 | #define TIOCSERGWILD 0x5454 |
diff --git a/arch/powerpc/include/asm/termbits.h b/arch/powerpc/include/asm/termbits.h index 6698188ca550..549d700e18f2 100644 --- a/arch/powerpc/include/asm/termbits.h +++ b/arch/powerpc/include/asm/termbits.h | |||
@@ -189,6 +189,7 @@ struct ktermios { | |||
189 | #define FLUSHO 0x00800000 | 189 | #define FLUSHO 0x00800000 |
190 | #define PENDIN 0x20000000 | 190 | #define PENDIN 0x20000000 |
191 | #define IEXTEN 0x00000400 | 191 | #define IEXTEN 0x00000400 |
192 | #define EXTPROC 0x10000000 | ||
192 | 193 | ||
193 | /* Values for the ACTION argument to `tcflow'. */ | 194 | /* Values for the ACTION argument to `tcflow'. */ |
194 | #define TCOOFF 0 | 195 | #define TCOOFF 0 |
diff --git a/arch/s390/include/asm/ioctls.h b/arch/s390/include/asm/ioctls.h index 40e481b1b461..2f3d8736361f 100644 --- a/arch/s390/include/asm/ioctls.h +++ b/arch/s390/include/asm/ioctls.h | |||
@@ -60,6 +60,7 @@ | |||
60 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) | 60 | #define TCSETSF2 _IOW('T',0x2D, struct termios2) |
61 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 61 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
62 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 62 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
63 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
63 | 64 | ||
64 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ | 65 | #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ |
65 | #define FIOCLEX 0x5451 | 66 | #define FIOCLEX 0x5451 |
@@ -86,6 +87,7 @@ | |||
86 | #define TIOCPKT_START 8 | 87 | #define TIOCPKT_START 8 |
87 | #define TIOCPKT_NOSTOP 16 | 88 | #define TIOCPKT_NOSTOP 16 |
88 | #define TIOCPKT_DOSTOP 32 | 89 | #define TIOCPKT_DOSTOP 32 |
90 | #define TIOCPKT_IOCTL 64 | ||
89 | 91 | ||
90 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 92 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
91 | 93 | ||
diff --git a/arch/sh/include/asm/ioctls.h b/arch/sh/include/asm/ioctls.h index c212c371a4a5..eb6c4c687972 100644 --- a/arch/sh/include/asm/ioctls.h +++ b/arch/sh/include/asm/ioctls.h | |||
@@ -69,6 +69,7 @@ | |||
69 | # define TIOCPKT_START 8 | 69 | # define TIOCPKT_START 8 |
70 | # define TIOCPKT_NOSTOP 16 | 70 | # define TIOCPKT_NOSTOP 16 |
71 | # define TIOCPKT_DOSTOP 32 | 71 | # define TIOCPKT_DOSTOP 32 |
72 | # define TIOCPKT_IOCTL 64 | ||
72 | 73 | ||
73 | 74 | ||
74 | #define TIOCNOTTY _IO('T', 34) /* 0x5422 */ | 75 | #define TIOCNOTTY _IO('T', 34) /* 0x5422 */ |
@@ -84,6 +85,7 @@ | |||
84 | #define TCSETSF2 _IOW('T', 45, struct termios2) | 85 | #define TCSETSF2 _IOW('T', 45, struct termios2) |
85 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 86 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
86 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 87 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
88 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
87 | 89 | ||
88 | #define TIOCSERCONFIG _IO('T', 83) /* 0x5453 */ | 90 | #define TIOCSERCONFIG _IO('T', 83) /* 0x5453 */ |
89 | #define TIOCSERGWILD _IOR('T', 84, int) /* 0x5454 */ | 91 | #define TIOCSERGWILD _IOR('T', 84, int) /* 0x5454 */ |
diff --git a/arch/sparc/include/asm/ioctls.h b/arch/sparc/include/asm/ioctls.h index 1fe6855c5c18..53f4ee009bdd 100644 --- a/arch/sparc/include/asm/ioctls.h +++ b/arch/sparc/include/asm/ioctls.h | |||
@@ -80,6 +80,7 @@ | |||
80 | /* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */ | 80 | /* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */ |
81 | #define TIOCGPTN _IOR('t', 134, unsigned int) /* Get Pty Number */ | 81 | #define TIOCGPTN _IOR('t', 134, unsigned int) /* Get Pty Number */ |
82 | #define TIOCSPTLCK _IOW('t', 135, int) /* Lock/unlock PTY */ | 82 | #define TIOCSPTLCK _IOW('t', 135, int) /* Lock/unlock PTY */ |
83 | #define TIOCSIG _IOW('t', 136, int) /* Generate signal on Pty slave */ | ||
83 | 84 | ||
84 | /* Little f */ | 85 | /* Little f */ |
85 | #define FIOCLEX _IO('f', 1) | 86 | #define FIOCLEX _IO('f', 1) |
@@ -132,5 +133,6 @@ | |||
132 | #define TIOCPKT_START 8 | 133 | #define TIOCPKT_START 8 |
133 | #define TIOCPKT_NOSTOP 16 | 134 | #define TIOCPKT_NOSTOP 16 |
134 | #define TIOCPKT_DOSTOP 32 | 135 | #define TIOCPKT_DOSTOP 32 |
136 | #define TIOCPKT_IOCTL 64 | ||
135 | 137 | ||
136 | #endif /* !(_ASM_SPARC_IOCTLS_H) */ | 138 | #endif /* !(_ASM_SPARC_IOCTLS_H) */ |
diff --git a/arch/sparc/include/asm/termbits.h b/arch/sparc/include/asm/termbits.h index d72dfed1f9d7..23b10ff08df2 100644 --- a/arch/sparc/include/asm/termbits.h +++ b/arch/sparc/include/asm/termbits.h | |||
@@ -225,6 +225,7 @@ struct ktermios { | |||
225 | #define FLUSHO 0x00002000 | 225 | #define FLUSHO 0x00002000 |
226 | #define PENDIN 0x00004000 | 226 | #define PENDIN 0x00004000 |
227 | #define IEXTEN 0x00008000 | 227 | #define IEXTEN 0x00008000 |
228 | #define EXTPROC 0x00010000 | ||
228 | 229 | ||
229 | /* modem lines */ | 230 | /* modem lines */ |
230 | #define TIOCM_LE 0x001 | 231 | #define TIOCM_LE 0x001 |
diff --git a/arch/xtensa/include/asm/ioctls.h b/arch/xtensa/include/asm/ioctls.h index 0ffa942954b9..ab1800012ed9 100644 --- a/arch/xtensa/include/asm/ioctls.h +++ b/arch/xtensa/include/asm/ioctls.h | |||
@@ -81,6 +81,7 @@ | |||
81 | # define TIOCPKT_START 8 | 81 | # define TIOCPKT_START 8 |
82 | # define TIOCPKT_NOSTOP 16 | 82 | # define TIOCPKT_NOSTOP 16 |
83 | # define TIOCPKT_DOSTOP 32 | 83 | # define TIOCPKT_DOSTOP 32 |
84 | # define TIOCPKT_IOCTL 64 | ||
84 | 85 | ||
85 | 86 | ||
86 | #define TIOCNOTTY _IO('T', 34) | 87 | #define TIOCNOTTY _IO('T', 34) |
@@ -97,6 +98,7 @@ | |||
97 | #define TCSETSF2 _IOW('T', 45, struct termios2) | 98 | #define TCSETSF2 _IOW('T', 45, struct termios2) |
98 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ | 99 | #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ |
99 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ | 100 | #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ |
101 | #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ | ||
100 | 102 | ||
101 | #define TIOCSERCONFIG _IO('T', 83) | 103 | #define TIOCSERCONFIG _IO('T', 83) |
102 | #define TIOCSERGWILD _IOR('T', 84, int) | 104 | #define TIOCSERGWILD _IOR('T', 84, int) |
diff --git a/arch/xtensa/include/asm/termbits.h b/arch/xtensa/include/asm/termbits.h index 85aa6a3c0b6e..0d6c8715b24f 100644 --- a/arch/xtensa/include/asm/termbits.h +++ b/arch/xtensa/include/asm/termbits.h | |||
@@ -196,6 +196,7 @@ struct ktermios { | |||
196 | #define FLUSHO 0010000 | 196 | #define FLUSHO 0010000 |
197 | #define PENDIN 0040000 | 197 | #define PENDIN 0040000 |
198 | #define IEXTEN 0100000 | 198 | #define IEXTEN 0100000 |
199 | #define EXTPROC 0200000 | ||
199 | 200 | ||
200 | /* tcflow() and TCXONC use these */ | 201 | /* tcflow() and TCXONC use these */ |
201 | 202 | ||
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 273cee1cc77b..dc9641660605 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -9,6 +9,7 @@ FONTMAPFILE = cp437.uni | |||
9 | 9 | ||
10 | obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o | 10 | obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o |
11 | 11 | ||
12 | obj-y += tty_mutex.o | ||
12 | obj-$(CONFIG_LEGACY_PTYS) += pty.o | 13 | obj-$(CONFIG_LEGACY_PTYS) += pty.o |
13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o | 14 | obj-$(CONFIG_UNIX98_PTYS) += pty.o |
14 | obj-y += misc.o | 15 | obj-y += misc.o |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 4f8d60c25a98..a11c8c9ca3d4 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -1072,7 +1072,7 @@ static int get_serial_info(struct async_struct * info, | |||
1072 | if (!retinfo) | 1072 | if (!retinfo) |
1073 | return -EFAULT; | 1073 | return -EFAULT; |
1074 | memset(&tmp, 0, sizeof(tmp)); | 1074 | memset(&tmp, 0, sizeof(tmp)); |
1075 | lock_kernel(); | 1075 | tty_lock(); |
1076 | tmp.type = state->type; | 1076 | tmp.type = state->type; |
1077 | tmp.line = state->line; | 1077 | tmp.line = state->line; |
1078 | tmp.port = state->port; | 1078 | tmp.port = state->port; |
@@ -1083,7 +1083,7 @@ static int get_serial_info(struct async_struct * info, | |||
1083 | tmp.close_delay = state->close_delay; | 1083 | tmp.close_delay = state->close_delay; |
1084 | tmp.closing_wait = state->closing_wait; | 1084 | tmp.closing_wait = state->closing_wait; |
1085 | tmp.custom_divisor = state->custom_divisor; | 1085 | tmp.custom_divisor = state->custom_divisor; |
1086 | unlock_kernel(); | 1086 | tty_unlock(); |
1087 | if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) | 1087 | if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) |
1088 | return -EFAULT; | 1088 | return -EFAULT; |
1089 | return 0; | 1089 | return 0; |
@@ -1100,14 +1100,14 @@ static int set_serial_info(struct async_struct * info, | |||
1100 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) | 1100 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) |
1101 | return -EFAULT; | 1101 | return -EFAULT; |
1102 | 1102 | ||
1103 | lock_kernel(); | 1103 | tty_lock(); |
1104 | state = info->state; | 1104 | state = info->state; |
1105 | old_state = *state; | 1105 | old_state = *state; |
1106 | 1106 | ||
1107 | change_irq = new_serial.irq != state->irq; | 1107 | change_irq = new_serial.irq != state->irq; |
1108 | change_port = (new_serial.port != state->port); | 1108 | change_port = (new_serial.port != state->port); |
1109 | if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { | 1109 | if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { |
1110 | unlock_kernel(); | 1110 | tty_unlock(); |
1111 | return -EINVAL; | 1111 | return -EINVAL; |
1112 | } | 1112 | } |
1113 | 1113 | ||
@@ -1127,7 +1127,7 @@ static int set_serial_info(struct async_struct * info, | |||
1127 | } | 1127 | } |
1128 | 1128 | ||
1129 | if (new_serial.baud_base < 9600) { | 1129 | if (new_serial.baud_base < 9600) { |
1130 | unlock_kernel(); | 1130 | tty_unlock(); |
1131 | return -EINVAL; | 1131 | return -EINVAL; |
1132 | } | 1132 | } |
1133 | 1133 | ||
@@ -1163,7 +1163,7 @@ check_and_exit: | |||
1163 | } | 1163 | } |
1164 | } else | 1164 | } else |
1165 | retval = startup(info); | 1165 | retval = startup(info); |
1166 | unlock_kernel(); | 1166 | tty_unlock(); |
1167 | return retval; | 1167 | return retval; |
1168 | } | 1168 | } |
1169 | 1169 | ||
@@ -1528,6 +1528,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1528 | { | 1528 | { |
1529 | struct async_struct * info = tty->driver_data; | 1529 | struct async_struct * info = tty->driver_data; |
1530 | unsigned long orig_jiffies, char_time; | 1530 | unsigned long orig_jiffies, char_time; |
1531 | int tty_was_locked = tty_locked(); | ||
1531 | int lsr; | 1532 | int lsr; |
1532 | 1533 | ||
1533 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) | 1534 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) |
@@ -1538,7 +1539,12 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1538 | 1539 | ||
1539 | orig_jiffies = jiffies; | 1540 | orig_jiffies = jiffies; |
1540 | 1541 | ||
1541 | lock_kernel(); | 1542 | /* |
1543 | * tty_wait_until_sent is called from lots of places, | ||
1544 | * with or without the BTM. | ||
1545 | */ | ||
1546 | if (!tty_was_locked) | ||
1547 | tty_lock(); | ||
1542 | /* | 1548 | /* |
1543 | * Set the check interval to be 1/5 of the estimated time to | 1549 | * Set the check interval to be 1/5 of the estimated time to |
1544 | * send a single character, and make it at least 1. The check | 1550 | * send a single character, and make it at least 1. The check |
@@ -1579,7 +1585,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1579 | break; | 1585 | break; |
1580 | } | 1586 | } |
1581 | __set_current_state(TASK_RUNNING); | 1587 | __set_current_state(TASK_RUNNING); |
1582 | unlock_kernel(); | 1588 | if (!tty_was_locked) |
1589 | tty_unlock(); | ||
1583 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 1590 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
1584 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 1591 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); |
1585 | #endif | 1592 | #endif |
@@ -1703,7 +1710,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1703 | printk("block_til_ready blocking: ttys%d, count = %d\n", | 1710 | printk("block_til_ready blocking: ttys%d, count = %d\n", |
1704 | info->line, state->count); | 1711 | info->line, state->count); |
1705 | #endif | 1712 | #endif |
1713 | tty_unlock(); | ||
1706 | schedule(); | 1714 | schedule(); |
1715 | tty_lock(); | ||
1707 | } | 1716 | } |
1708 | __set_current_state(TASK_RUNNING); | 1717 | __set_current_state(TASK_RUNNING); |
1709 | remove_wait_queue(&info->open_wait, &wait); | 1718 | remove_wait_queue(&info->open_wait, &wait); |
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index 555cd93c2ee5..d5fa113afe37 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c | |||
@@ -67,15 +67,15 @@ static void set_led(char state) | |||
67 | 67 | ||
68 | static int briq_panel_open(struct inode *ino, struct file *filep) | 68 | static int briq_panel_open(struct inode *ino, struct file *filep) |
69 | { | 69 | { |
70 | lock_kernel(); | 70 | tty_lock(); |
71 | /* enforce single access, vfd_is_open is protected by BKL */ | 71 | /* enforce single access, vfd_is_open is protected by BKL */ |
72 | if (vfd_is_open) { | 72 | if (vfd_is_open) { |
73 | unlock_kernel(); | 73 | tty_unlock(); |
74 | return -EBUSY; | 74 | return -EBUSY; |
75 | } | 75 | } |
76 | vfd_is_open = 1; | 76 | vfd_is_open = 1; |
77 | 77 | ||
78 | unlock_kernel(); | 78 | tty_unlock(); |
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 9824b4162904..27aad9422332 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -65,7 +65,6 @@ | |||
65 | #include <linux/tty.h> | 65 | #include <linux/tty.h> |
66 | #include <linux/tty_flip.h> | 66 | #include <linux/tty_flip.h> |
67 | #include <linux/serial.h> | 67 | #include <linux/serial.h> |
68 | #include <linux/smp_lock.h> | ||
69 | #include <linux/major.h> | 68 | #include <linux/major.h> |
70 | #include <linux/string.h> | 69 | #include <linux/string.h> |
71 | #include <linux/fcntl.h> | 70 | #include <linux/fcntl.h> |
@@ -1608,7 +1607,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
1608 | * If the port is the middle of closing, bail out now | 1607 | * If the port is the middle of closing, bail out now |
1609 | */ | 1608 | */ |
1610 | if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { | 1609 | if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) { |
1611 | wait_event_interruptible(info->port.close_wait, | 1610 | wait_event_interruptible_tty(info->port.close_wait, |
1612 | !(info->port.flags & ASYNC_CLOSING)); | 1611 | !(info->port.flags & ASYNC_CLOSING)); |
1613 | return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; | 1612 | return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; |
1614 | } | 1613 | } |
@@ -1655,7 +1654,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1655 | return; /* Just in case.... */ | 1654 | return; /* Just in case.... */ |
1656 | 1655 | ||
1657 | orig_jiffies = jiffies; | 1656 | orig_jiffies = jiffies; |
1658 | lock_kernel(); | ||
1659 | /* | 1657 | /* |
1660 | * Set the check interval to be 1/5 of the estimated time to | 1658 | * Set the check interval to be 1/5 of the estimated time to |
1661 | * send a single character, and make it at least 1. The check | 1659 | * send a single character, and make it at least 1. The check |
@@ -1702,7 +1700,6 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1702 | } | 1700 | } |
1703 | /* Run one more char cycle */ | 1701 | /* Run one more char cycle */ |
1704 | msleep_interruptible(jiffies_to_msecs(char_time * 5)); | 1702 | msleep_interruptible(jiffies_to_msecs(char_time * 5)); |
1705 | unlock_kernel(); | ||
1706 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT | 1703 | #ifdef CY_DEBUG_WAIT_UNTIL_SENT |
1707 | printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); | 1704 | printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); |
1708 | #endif | 1705 | #endif |
@@ -1959,7 +1956,6 @@ static int cy_chars_in_buffer(struct tty_struct *tty) | |||
1959 | int char_count; | 1956 | int char_count; |
1960 | __u32 tx_put, tx_get, tx_bufsize; | 1957 | __u32 tx_put, tx_get, tx_bufsize; |
1961 | 1958 | ||
1962 | lock_kernel(); | ||
1963 | tx_get = readl(&buf_ctrl->tx_get); | 1959 | tx_get = readl(&buf_ctrl->tx_get); |
1964 | tx_put = readl(&buf_ctrl->tx_put); | 1960 | tx_put = readl(&buf_ctrl->tx_put); |
1965 | tx_bufsize = readl(&buf_ctrl->tx_bufsize); | 1961 | tx_bufsize = readl(&buf_ctrl->tx_bufsize); |
@@ -1971,7 +1967,6 @@ static int cy_chars_in_buffer(struct tty_struct *tty) | |||
1971 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", | 1967 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", |
1972 | info->line, info->xmit_cnt + char_count); | 1968 | info->line, info->xmit_cnt + char_count); |
1973 | #endif | 1969 | #endif |
1974 | unlock_kernel(); | ||
1975 | return info->xmit_cnt + char_count; | 1970 | return info->xmit_cnt + char_count; |
1976 | } | 1971 | } |
1977 | #endif /* Z_EXT_CHARS_IN_BUFFER */ | 1972 | #endif /* Z_EXT_CHARS_IN_BUFFER */ |
@@ -2359,17 +2354,22 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, | |||
2359 | struct serial_struct __user *new_info) | 2354 | struct serial_struct __user *new_info) |
2360 | { | 2355 | { |
2361 | struct serial_struct new_serial; | 2356 | struct serial_struct new_serial; |
2357 | int ret; | ||
2362 | 2358 | ||
2363 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) | 2359 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) |
2364 | return -EFAULT; | 2360 | return -EFAULT; |
2365 | 2361 | ||
2362 | mutex_lock(&info->port.mutex); | ||
2366 | if (!capable(CAP_SYS_ADMIN)) { | 2363 | if (!capable(CAP_SYS_ADMIN)) { |
2367 | if (new_serial.close_delay != info->port.close_delay || | 2364 | if (new_serial.close_delay != info->port.close_delay || |
2368 | new_serial.baud_base != info->baud || | 2365 | new_serial.baud_base != info->baud || |
2369 | (new_serial.flags & ASYNC_FLAGS & | 2366 | (new_serial.flags & ASYNC_FLAGS & |
2370 | ~ASYNC_USR_MASK) != | 2367 | ~ASYNC_USR_MASK) != |
2371 | (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) | 2368 | (info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)) |
2369 | { | ||
2370 | mutex_unlock(&info->port.mutex); | ||
2372 | return -EPERM; | 2371 | return -EPERM; |
2372 | } | ||
2373 | info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) | | 2373 | info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) | |
2374 | (new_serial.flags & ASYNC_USR_MASK); | 2374 | (new_serial.flags & ASYNC_USR_MASK); |
2375 | info->baud = new_serial.baud_base; | 2375 | info->baud = new_serial.baud_base; |
@@ -2392,10 +2392,12 @@ cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty, | |||
2392 | check_and_exit: | 2392 | check_and_exit: |
2393 | if (info->port.flags & ASYNC_INITIALIZED) { | 2393 | if (info->port.flags & ASYNC_INITIALIZED) { |
2394 | cy_set_line_char(info, tty); | 2394 | cy_set_line_char(info, tty); |
2395 | return 0; | 2395 | ret = 0; |
2396 | } else { | 2396 | } else { |
2397 | return cy_startup(info, tty); | 2397 | ret = cy_startup(info, tty); |
2398 | } | 2398 | } |
2399 | mutex_unlock(&info->port.mutex); | ||
2400 | return ret; | ||
2399 | } /* set_serial_info */ | 2401 | } /* set_serial_info */ |
2400 | 2402 | ||
2401 | /* | 2403 | /* |
@@ -2438,7 +2440,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
2438 | 2440 | ||
2439 | card = info->card; | 2441 | card = info->card; |
2440 | 2442 | ||
2441 | lock_kernel(); | ||
2442 | if (!cy_is_Z(card)) { | 2443 | if (!cy_is_Z(card)) { |
2443 | unsigned long flags; | 2444 | unsigned long flags; |
2444 | int channel = info->line - card->first_line; | 2445 | int channel = info->line - card->first_line; |
@@ -2478,7 +2479,6 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
2478 | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); | 2479 | ((lstatus & C_RS_CTS) ? TIOCM_CTS : 0); |
2479 | } | 2480 | } |
2480 | end: | 2481 | end: |
2481 | unlock_kernel(); | ||
2482 | return result; | 2482 | return result; |
2483 | } /* cy_tiomget */ | 2483 | } /* cy_tiomget */ |
2484 | 2484 | ||
@@ -2696,7 +2696,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
2696 | printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", | 2696 | printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", |
2697 | info->line, cmd, arg); | 2697 | info->line, cmd, arg); |
2698 | #endif | 2698 | #endif |
2699 | lock_kernel(); | ||
2700 | 2699 | ||
2701 | switch (cmd) { | 2700 | switch (cmd) { |
2702 | case CYGETMON: | 2701 | case CYGETMON: |
@@ -2817,7 +2816,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
2817 | default: | 2816 | default: |
2818 | ret_val = -ENOIOCTLCMD; | 2817 | ret_val = -ENOIOCTLCMD; |
2819 | } | 2818 | } |
2820 | unlock_kernel(); | ||
2821 | 2819 | ||
2822 | #ifdef CY_DEBUG_OTHER | 2820 | #ifdef CY_DEBUG_OTHER |
2823 | printk(KERN_DEBUG "cyc:cy_ioctl done\n"); | 2821 | printk(KERN_DEBUG "cyc:cy_ioctl done\n"); |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 6f5ffe1320f7..d9df46aa0fba 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <linux/ctype.h> | 36 | #include <linux/ctype.h> |
37 | #include <linux/tty.h> | 37 | #include <linux/tty.h> |
38 | #include <linux/tty_flip.h> | 38 | #include <linux/tty_flip.h> |
39 | #include <linux/smp_lock.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/ioport.h> | 40 | #include <linux/ioport.h> |
41 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
42 | #include <linux/uaccess.h> | 42 | #include <linux/uaccess.h> |
@@ -2105,7 +2105,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
2105 | break; | 2105 | break; |
2106 | case DIGI_SETAW: | 2106 | case DIGI_SETAW: |
2107 | case DIGI_SETAF: | 2107 | case DIGI_SETAF: |
2108 | lock_kernel(); | ||
2109 | if (cmd == DIGI_SETAW) { | 2108 | if (cmd == DIGI_SETAW) { |
2110 | /* Setup an event to indicate when the transmit | 2109 | /* Setup an event to indicate when the transmit |
2111 | buffer empties */ | 2110 | buffer empties */ |
@@ -2118,7 +2117,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
2118 | if (tty->ldisc->ops->flush_buffer) | 2117 | if (tty->ldisc->ops->flush_buffer) |
2119 | tty->ldisc->ops->flush_buffer(tty); | 2118 | tty->ldisc->ops->flush_buffer(tty); |
2120 | } | 2119 | } |
2121 | unlock_kernel(); | ||
2122 | /* Fall Thru */ | 2120 | /* Fall Thru */ |
2123 | case DIGI_SETA: | 2121 | case DIGI_SETA: |
2124 | if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) | 2122 | if (copy_from_user(&ch->digiext, argp, sizeof(digi_t))) |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 911e1da6def2..07f3ea38b582 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -1486,7 +1486,9 @@ ip2_open( PTTY tty, struct file *pFile ) | |||
1486 | 1486 | ||
1487 | if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { | 1487 | if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) { |
1488 | if ( pCh->flags & ASYNC_CLOSING ) { | 1488 | if ( pCh->flags & ASYNC_CLOSING ) { |
1489 | tty_unlock(); | ||
1489 | schedule(); | 1490 | schedule(); |
1491 | tty_lock(); | ||
1490 | } | 1492 | } |
1491 | if ( tty_hung_up_p(pFile) ) { | 1493 | if ( tty_hung_up_p(pFile) ) { |
1492 | set_current_state( TASK_RUNNING ); | 1494 | set_current_state( TASK_RUNNING ); |
@@ -1548,7 +1550,9 @@ ip2_open( PTTY tty, struct file *pFile ) | |||
1548 | rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); | 1550 | rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS); |
1549 | break; | 1551 | break; |
1550 | } | 1552 | } |
1553 | tty_unlock(); | ||
1551 | schedule(); | 1554 | schedule(); |
1555 | tty_lock(); | ||
1552 | } | 1556 | } |
1553 | set_current_state( TASK_RUNNING ); | 1557 | set_current_state( TASK_RUNNING ); |
1554 | remove_wait_queue(&pCh->open_wait, &wait); | 1558 | remove_wait_queue(&pCh->open_wait, &wait); |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 98310e1aae30..c27e9d21fea9 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -124,7 +124,6 @@ | |||
124 | #include <linux/fs.h> | 124 | #include <linux/fs.h> |
125 | #include <linux/sched.h> | 125 | #include <linux/sched.h> |
126 | #include <linux/serial.h> | 126 | #include <linux/serial.h> |
127 | #include <linux/smp_lock.h> | ||
128 | #include <linux/mm.h> | 127 | #include <linux/mm.h> |
129 | #include <linux/interrupt.h> | 128 | #include <linux/interrupt.h> |
130 | #include <linux/timer.h> | 129 | #include <linux/timer.h> |
@@ -872,7 +871,6 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty) | |||
872 | static int isicom_open(struct tty_struct *tty, struct file *filp) | 871 | static int isicom_open(struct tty_struct *tty, struct file *filp) |
873 | { | 872 | { |
874 | struct isi_port *port; | 873 | struct isi_port *port; |
875 | struct isi_board *card; | ||
876 | struct tty_port *tport; | 874 | struct tty_port *tport; |
877 | 875 | ||
878 | tport = isicom_find_port(tty); | 876 | tport = isicom_find_port(tty); |
@@ -1118,8 +1116,7 @@ static int isicom_set_serial_info(struct tty_struct *tty, | |||
1118 | if (copy_from_user(&newinfo, info, sizeof(newinfo))) | 1116 | if (copy_from_user(&newinfo, info, sizeof(newinfo))) |
1119 | return -EFAULT; | 1117 | return -EFAULT; |
1120 | 1118 | ||
1121 | lock_kernel(); | 1119 | mutex_lock(&port->port.mutex); |
1122 | |||
1123 | reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) != | 1120 | reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) != |
1124 | (newinfo.flags & ASYNC_SPD_MASK)); | 1121 | (newinfo.flags & ASYNC_SPD_MASK)); |
1125 | 1122 | ||
@@ -1128,7 +1125,7 @@ static int isicom_set_serial_info(struct tty_struct *tty, | |||
1128 | (newinfo.closing_wait != port->port.closing_wait) || | 1125 | (newinfo.closing_wait != port->port.closing_wait) || |
1129 | ((newinfo.flags & ~ASYNC_USR_MASK) != | 1126 | ((newinfo.flags & ~ASYNC_USR_MASK) != |
1130 | (port->port.flags & ~ASYNC_USR_MASK))) { | 1127 | (port->port.flags & ~ASYNC_USR_MASK))) { |
1131 | unlock_kernel(); | 1128 | mutex_unlock(&port->port.mutex); |
1132 | return -EPERM; | 1129 | return -EPERM; |
1133 | } | 1130 | } |
1134 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | 1131 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | |
@@ -1145,7 +1142,7 @@ static int isicom_set_serial_info(struct tty_struct *tty, | |||
1145 | isicom_config_port(tty); | 1142 | isicom_config_port(tty); |
1146 | spin_unlock_irqrestore(&port->card->card_lock, flags); | 1143 | spin_unlock_irqrestore(&port->card->card_lock, flags); |
1147 | } | 1144 | } |
1148 | unlock_kernel(); | 1145 | mutex_unlock(&port->port.mutex); |
1149 | return 0; | 1146 | return 0; |
1150 | } | 1147 | } |
1151 | 1148 | ||
@@ -1154,7 +1151,7 @@ static int isicom_get_serial_info(struct isi_port *port, | |||
1154 | { | 1151 | { |
1155 | struct serial_struct out_info; | 1152 | struct serial_struct out_info; |
1156 | 1153 | ||
1157 | lock_kernel(); | 1154 | mutex_lock(&port->port.mutex); |
1158 | memset(&out_info, 0, sizeof(out_info)); | 1155 | memset(&out_info, 0, sizeof(out_info)); |
1159 | /* out_info.type = ? */ | 1156 | /* out_info.type = ? */ |
1160 | out_info.line = port - isi_ports; | 1157 | out_info.line = port - isi_ports; |
@@ -1164,7 +1161,7 @@ static int isicom_get_serial_info(struct isi_port *port, | |||
1164 | /* out_info.baud_base = ? */ | 1161 | /* out_info.baud_base = ? */ |
1165 | out_info.close_delay = port->port.close_delay; | 1162 | out_info.close_delay = port->port.close_delay; |
1166 | out_info.closing_wait = port->port.closing_wait; | 1163 | out_info.closing_wait = port->port.closing_wait; |
1167 | unlock_kernel(); | 1164 | mutex_unlock(&port->port.mutex); |
1168 | if (copy_to_user(info, &out_info, sizeof(out_info))) | 1165 | if (copy_to_user(info, &out_info, sizeof(out_info))) |
1169 | return -EFAULT; | 1166 | return -EFAULT; |
1170 | return 0; | 1167 | return 0; |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 4e395c956a09..be28391adb79 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -203,9 +203,9 @@ static int stli_shared; | |||
203 | * the board has been detected, and whether it is actually running a slave | 203 | * the board has been detected, and whether it is actually running a slave |
204 | * or not. | 204 | * or not. |
205 | */ | 205 | */ |
206 | #define BST_FOUND 0x1 | 206 | #define BST_FOUND 0 |
207 | #define BST_STARTED 0x2 | 207 | #define BST_STARTED 1 |
208 | #define BST_PROBED 0x4 | 208 | #define BST_PROBED 2 |
209 | 209 | ||
210 | /* | 210 | /* |
211 | * Define the set of port state flags. These are marked for internal | 211 | * Define the set of port state flags. These are marked for internal |
@@ -816,7 +816,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
816 | brdp = stli_brds[brdnr]; | 816 | brdp = stli_brds[brdnr]; |
817 | if (brdp == NULL) | 817 | if (brdp == NULL) |
818 | return -ENODEV; | 818 | return -ENODEV; |
819 | if ((brdp->state & BST_STARTED) == 0) | 819 | if (!test_bit(BST_STARTED, &brdp->state)) |
820 | return -ENODEV; | 820 | return -ENODEV; |
821 | portnr = MINOR2PORT(minordev); | 821 | portnr = MINOR2PORT(minordev); |
822 | if (portnr > brdp->nrports) | 822 | if (portnr > brdp->nrports) |
@@ -954,7 +954,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l | |||
954 | * order of opens and closes may not be preserved across shared | 954 | * order of opens and closes may not be preserved across shared |
955 | * memory, so we must wait until it is complete. | 955 | * memory, so we must wait until it is complete. |
956 | */ | 956 | */ |
957 | wait_event_interruptible(portp->raw_wait, | 957 | wait_event_interruptible_tty(portp->raw_wait, |
958 | !test_bit(ST_CLOSING, &portp->state)); | 958 | !test_bit(ST_CLOSING, &portp->state)); |
959 | if (signal_pending(current)) { | 959 | if (signal_pending(current)) { |
960 | return -ERESTARTSYS; | 960 | return -ERESTARTSYS; |
@@ -989,7 +989,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l | |||
989 | set_bit(ST_OPENING, &portp->state); | 989 | set_bit(ST_OPENING, &portp->state); |
990 | spin_unlock_irqrestore(&brd_lock, flags); | 990 | spin_unlock_irqrestore(&brd_lock, flags); |
991 | 991 | ||
992 | wait_event_interruptible(portp->raw_wait, | 992 | wait_event_interruptible_tty(portp->raw_wait, |
993 | !test_bit(ST_OPENING, &portp->state)); | 993 | !test_bit(ST_OPENING, &portp->state)); |
994 | if (signal_pending(current)) | 994 | if (signal_pending(current)) |
995 | rc = -ERESTARTSYS; | 995 | rc = -ERESTARTSYS; |
@@ -1020,7 +1020,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1020 | * occurs on this port. | 1020 | * occurs on this port. |
1021 | */ | 1021 | */ |
1022 | if (wait) { | 1022 | if (wait) { |
1023 | wait_event_interruptible(portp->raw_wait, | 1023 | wait_event_interruptible_tty(portp->raw_wait, |
1024 | !test_bit(ST_CLOSING, &portp->state)); | 1024 | !test_bit(ST_CLOSING, &portp->state)); |
1025 | if (signal_pending(current)) { | 1025 | if (signal_pending(current)) { |
1026 | return -ERESTARTSYS; | 1026 | return -ERESTARTSYS; |
@@ -1052,7 +1052,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1052 | * to come back. | 1052 | * to come back. |
1053 | */ | 1053 | */ |
1054 | rc = 0; | 1054 | rc = 0; |
1055 | wait_event_interruptible(portp->raw_wait, | 1055 | wait_event_interruptible_tty(portp->raw_wait, |
1056 | !test_bit(ST_CLOSING, &portp->state)); | 1056 | !test_bit(ST_CLOSING, &portp->state)); |
1057 | if (signal_pending(current)) | 1057 | if (signal_pending(current)) |
1058 | rc = -ERESTARTSYS; | 1058 | rc = -ERESTARTSYS; |
@@ -1073,6 +1073,10 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned | |||
1073 | 1073 | ||
1074 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) | 1074 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback) |
1075 | { | 1075 | { |
1076 | /* | ||
1077 | * no need for wait_event_tty because clearing ST_CMDING cannot block | ||
1078 | * on BTM | ||
1079 | */ | ||
1076 | wait_event_interruptible(portp->raw_wait, | 1080 | wait_event_interruptible(portp->raw_wait, |
1077 | !test_bit(ST_CMDING, &portp->state)); | 1081 | !test_bit(ST_CMDING, &portp->state)); |
1078 | if (signal_pending(current)) | 1082 | if (signal_pending(current)) |
@@ -1846,7 +1850,7 @@ static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stlip | |||
1846 | rc = stli_portcmdstats(NULL, portp); | 1850 | rc = stli_portcmdstats(NULL, portp); |
1847 | 1851 | ||
1848 | uart = "UNKNOWN"; | 1852 | uart = "UNKNOWN"; |
1849 | if (brdp->state & BST_STARTED) { | 1853 | if (test_bit(BST_STARTED, &brdp->state)) { |
1850 | switch (stli_comstats.hwid) { | 1854 | switch (stli_comstats.hwid) { |
1851 | case 0: uart = "2681"; break; | 1855 | case 0: uart = "2681"; break; |
1852 | case 1: uart = "SC26198"; break; | 1856 | case 1: uart = "SC26198"; break; |
@@ -1855,7 +1859,7 @@ static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stlip | |||
1855 | } | 1859 | } |
1856 | seq_printf(m, "%d: uart:%s ", portnr, uart); | 1860 | seq_printf(m, "%d: uart:%s ", portnr, uart); |
1857 | 1861 | ||
1858 | if ((brdp->state & BST_STARTED) && (rc >= 0)) { | 1862 | if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) { |
1859 | char sep; | 1863 | char sep; |
1860 | 1864 | ||
1861 | seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, | 1865 | seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, |
@@ -2355,7 +2359,7 @@ static void stli_poll(unsigned long arg) | |||
2355 | brdp = stli_brds[brdnr]; | 2359 | brdp = stli_brds[brdnr]; |
2356 | if (brdp == NULL) | 2360 | if (brdp == NULL) |
2357 | continue; | 2361 | continue; |
2358 | if ((brdp->state & BST_STARTED) == 0) | 2362 | if (!test_bit(BST_STARTED, &brdp->state)) |
2359 | continue; | 2363 | continue; |
2360 | 2364 | ||
2361 | spin_lock(&brd_lock); | 2365 | spin_lock(&brd_lock); |
@@ -3140,7 +3144,7 @@ static int stli_initecp(struct stlibrd *brdp) | |||
3140 | } | 3144 | } |
3141 | 3145 | ||
3142 | 3146 | ||
3143 | brdp->state |= BST_FOUND; | 3147 | set_bit(BST_FOUND, &brdp->state); |
3144 | return 0; | 3148 | return 0; |
3145 | err_unmap: | 3149 | err_unmap: |
3146 | iounmap(brdp->membase); | 3150 | iounmap(brdp->membase); |
@@ -3297,7 +3301,7 @@ static int stli_initonb(struct stlibrd *brdp) | |||
3297 | brdp->panels[0] = brdp->nrports; | 3301 | brdp->panels[0] = brdp->nrports; |
3298 | 3302 | ||
3299 | 3303 | ||
3300 | brdp->state |= BST_FOUND; | 3304 | set_bit(BST_FOUND, &brdp->state); |
3301 | return 0; | 3305 | return 0; |
3302 | err_unmap: | 3306 | err_unmap: |
3303 | iounmap(brdp->membase); | 3307 | iounmap(brdp->membase); |
@@ -3407,7 +3411,7 @@ stli_donestartup: | |||
3407 | spin_unlock_irqrestore(&brd_lock, flags); | 3411 | spin_unlock_irqrestore(&brd_lock, flags); |
3408 | 3412 | ||
3409 | if (rc == 0) | 3413 | if (rc == 0) |
3410 | brdp->state |= BST_STARTED; | 3414 | set_bit(BST_STARTED, &brdp->state); |
3411 | 3415 | ||
3412 | if (! stli_timeron) { | 3416 | if (! stli_timeron) { |
3413 | stli_timeron++; | 3417 | stli_timeron++; |
@@ -3710,7 +3714,7 @@ static int __devinit stli_pciprobe(struct pci_dev *pdev, | |||
3710 | if (retval) | 3714 | if (retval) |
3711 | goto err_null; | 3715 | goto err_null; |
3712 | 3716 | ||
3713 | brdp->state |= BST_PROBED; | 3717 | set_bit(BST_PROBED, &brdp->state); |
3714 | pci_set_drvdata(pdev, brdp); | 3718 | pci_set_drvdata(pdev, brdp); |
3715 | 3719 | ||
3716 | EBRDENABLE(brdp); | 3720 | EBRDENABLE(brdp); |
@@ -3841,7 +3845,7 @@ static int __init stli_initbrds(void) | |||
3841 | brdp = stli_brds[i]; | 3845 | brdp = stli_brds[i]; |
3842 | if (brdp == NULL) | 3846 | if (brdp == NULL) |
3843 | continue; | 3847 | continue; |
3844 | if (brdp->state & BST_FOUND) { | 3848 | if (test_bit(BST_FOUND, &brdp->state)) { |
3845 | EBRDENABLE(brdp); | 3849 | EBRDENABLE(brdp); |
3846 | brdp->enable = NULL; | 3850 | brdp->enable = NULL; |
3847 | brdp->disable = NULL; | 3851 | brdp->disable = NULL; |
@@ -4011,6 +4015,7 @@ static int stli_getbrdstats(combrd_t __user *bp) | |||
4011 | return -ENODEV; | 4015 | return -ENODEV; |
4012 | 4016 | ||
4013 | memset(&stli_brdstats, 0, sizeof(combrd_t)); | 4017 | memset(&stli_brdstats, 0, sizeof(combrd_t)); |
4018 | |||
4014 | stli_brdstats.brd = brdp->brdnr; | 4019 | stli_brdstats.brd = brdp->brdnr; |
4015 | stli_brdstats.type = brdp->brdtype; | 4020 | stli_brdstats.type = brdp->brdtype; |
4016 | stli_brdstats.hwid = 0; | 4021 | stli_brdstats.hwid = 0; |
@@ -4076,10 +4081,13 @@ static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp) | |||
4076 | if (brdp == NULL) | 4081 | if (brdp == NULL) |
4077 | return -ENODEV; | 4082 | return -ENODEV; |
4078 | 4083 | ||
4079 | if (brdp->state & BST_STARTED) { | 4084 | mutex_lock(&portp->port.mutex); |
4085 | if (test_bit(BST_STARTED, &brdp->state)) { | ||
4080 | if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, | 4086 | if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, |
4081 | &stli_cdkstats, sizeof(asystats_t), 1)) < 0) | 4087 | &stli_cdkstats, sizeof(asystats_t), 1)) < 0) { |
4088 | mutex_unlock(&portp->port.mutex); | ||
4082 | return rc; | 4089 | return rc; |
4090 | } | ||
4083 | } else { | 4091 | } else { |
4084 | memset(&stli_cdkstats, 0, sizeof(asystats_t)); | 4092 | memset(&stli_cdkstats, 0, sizeof(asystats_t)); |
4085 | } | 4093 | } |
@@ -4124,6 +4132,7 @@ static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp) | |||
4124 | stli_comstats.modem = stli_cdkstats.dcdcnt; | 4132 | stli_comstats.modem = stli_cdkstats.dcdcnt; |
4125 | stli_comstats.hwid = stli_cdkstats.hwid; | 4133 | stli_comstats.hwid = stli_cdkstats.hwid; |
4126 | stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals); | 4134 | stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals); |
4135 | mutex_unlock(&portp->port.mutex); | ||
4127 | 4136 | ||
4128 | return 0; | 4137 | return 0; |
4129 | } | 4138 | } |
@@ -4186,15 +4195,20 @@ static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp) | |||
4186 | if (!brdp) | 4195 | if (!brdp) |
4187 | return -ENODEV; | 4196 | return -ENODEV; |
4188 | 4197 | ||
4189 | if (brdp->state & BST_STARTED) { | 4198 | mutex_lock(&portp->port.mutex); |
4190 | if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) | 4199 | |
4200 | if (test_bit(BST_STARTED, &brdp->state)) { | ||
4201 | if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) { | ||
4202 | mutex_unlock(&portp->port.mutex); | ||
4191 | return rc; | 4203 | return rc; |
4204 | } | ||
4192 | } | 4205 | } |
4193 | 4206 | ||
4194 | memset(&stli_comstats, 0, sizeof(comstats_t)); | 4207 | memset(&stli_comstats, 0, sizeof(comstats_t)); |
4195 | stli_comstats.brd = portp->brdnr; | 4208 | stli_comstats.brd = portp->brdnr; |
4196 | stli_comstats.panel = portp->panelnr; | 4209 | stli_comstats.panel = portp->panelnr; |
4197 | stli_comstats.port = portp->portnr; | 4210 | stli_comstats.port = portp->portnr; |
4211 | mutex_unlock(&portp->port.mutex); | ||
4198 | 4212 | ||
4199 | if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t))) | 4213 | if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t))) |
4200 | return -EFAULT; | 4214 | return -EFAULT; |
@@ -4266,8 +4280,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4266 | done = 0; | 4280 | done = 0; |
4267 | rc = 0; | 4281 | rc = 0; |
4268 | 4282 | ||
4269 | lock_kernel(); | ||
4270 | |||
4271 | switch (cmd) { | 4283 | switch (cmd) { |
4272 | case COM_GETPORTSTATS: | 4284 | case COM_GETPORTSTATS: |
4273 | rc = stli_getportstats(NULL, NULL, argp); | 4285 | rc = stli_getportstats(NULL, NULL, argp); |
@@ -4290,8 +4302,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4290 | done++; | 4302 | done++; |
4291 | break; | 4303 | break; |
4292 | } | 4304 | } |
4293 | unlock_kernel(); | ||
4294 | |||
4295 | if (done) | 4305 | if (done) |
4296 | return rc; | 4306 | return rc; |
4297 | 4307 | ||
@@ -4308,8 +4318,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4308 | if (brdp->state == 0) | 4318 | if (brdp->state == 0) |
4309 | return -ENODEV; | 4319 | return -ENODEV; |
4310 | 4320 | ||
4311 | lock_kernel(); | ||
4312 | |||
4313 | switch (cmd) { | 4321 | switch (cmd) { |
4314 | case STL_BINTR: | 4322 | case STL_BINTR: |
4315 | EBRDINTR(brdp); | 4323 | EBRDINTR(brdp); |
@@ -4318,10 +4326,10 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4318 | rc = stli_startbrd(brdp); | 4326 | rc = stli_startbrd(brdp); |
4319 | break; | 4327 | break; |
4320 | case STL_BSTOP: | 4328 | case STL_BSTOP: |
4321 | brdp->state &= ~BST_STARTED; | 4329 | clear_bit(BST_STARTED, &brdp->state); |
4322 | break; | 4330 | break; |
4323 | case STL_BRESET: | 4331 | case STL_BRESET: |
4324 | brdp->state &= ~BST_STARTED; | 4332 | clear_bit(BST_STARTED, &brdp->state); |
4325 | EBRDRESET(brdp); | 4333 | EBRDRESET(brdp); |
4326 | if (stli_shared == 0) { | 4334 | if (stli_shared == 0) { |
4327 | if (brdp->reenable != NULL) | 4335 | if (brdp->reenable != NULL) |
@@ -4332,7 +4340,6 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
4332 | rc = -ENOIOCTLCMD; | 4340 | rc = -ENOIOCTLCMD; |
4333 | break; | 4341 | break; |
4334 | } | 4342 | } |
4335 | unlock_kernel(); | ||
4336 | return rc; | 4343 | return rc; |
4337 | } | 4344 | } |
4338 | 4345 | ||
@@ -4378,7 +4385,8 @@ static void istallion_cleanup_isa(void) | |||
4378 | unsigned int j; | 4385 | unsigned int j; |
4379 | 4386 | ||
4380 | for (j = 0; (j < stli_nrbrds); j++) { | 4387 | for (j = 0; (j < stli_nrbrds); j++) { |
4381 | if ((brdp = stli_brds[j]) == NULL || (brdp->state & BST_PROBED)) | 4388 | if ((brdp = stli_brds[j]) == NULL || |
4389 | test_bit(BST_PROBED, &brdp->state)) | ||
4382 | continue; | 4390 | continue; |
4383 | 4391 | ||
4384 | stli_cleanup_ports(brdp); | 4392 | stli_cleanup_ports(brdp); |
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 25be2102a60a..a7ca75212bfe 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -299,7 +299,7 @@ int kbd_rate(struct kbd_repeat *rep) | |||
299 | */ | 299 | */ |
300 | static void put_queue(struct vc_data *vc, int ch) | 300 | static void put_queue(struct vc_data *vc, int ch) |
301 | { | 301 | { |
302 | struct tty_struct *tty = vc->vc_tty; | 302 | struct tty_struct *tty = vc->port.tty; |
303 | 303 | ||
304 | if (tty) { | 304 | if (tty) { |
305 | tty_insert_flip_char(tty, ch, 0); | 305 | tty_insert_flip_char(tty, ch, 0); |
@@ -309,7 +309,7 @@ static void put_queue(struct vc_data *vc, int ch) | |||
309 | 309 | ||
310 | static void puts_queue(struct vc_data *vc, char *cp) | 310 | static void puts_queue(struct vc_data *vc, char *cp) |
311 | { | 311 | { |
312 | struct tty_struct *tty = vc->vc_tty; | 312 | struct tty_struct *tty = vc->port.tty; |
313 | 313 | ||
314 | if (!tty) | 314 | if (!tty) |
315 | return; | 315 | return; |
@@ -485,7 +485,7 @@ static void fn_show_ptregs(struct vc_data *vc) | |||
485 | 485 | ||
486 | static void fn_hold(struct vc_data *vc) | 486 | static void fn_hold(struct vc_data *vc) |
487 | { | 487 | { |
488 | struct tty_struct *tty = vc->vc_tty; | 488 | struct tty_struct *tty = vc->port.tty; |
489 | 489 | ||
490 | if (rep || !tty) | 490 | if (rep || !tty) |
491 | return; | 491 | return; |
@@ -563,7 +563,7 @@ static void fn_inc_console(struct vc_data *vc) | |||
563 | 563 | ||
564 | static void fn_send_intr(struct vc_data *vc) | 564 | static void fn_send_intr(struct vc_data *vc) |
565 | { | 565 | { |
566 | struct tty_struct *tty = vc->vc_tty; | 566 | struct tty_struct *tty = vc->port.tty; |
567 | 567 | ||
568 | if (!tty) | 568 | if (!tty) |
569 | return; | 569 | return; |
@@ -1162,7 +1162,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1162 | struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down }; | 1162 | struct keyboard_notifier_param param = { .vc = vc, .value = keycode, .down = down }; |
1163 | int rc; | 1163 | int rc; |
1164 | 1164 | ||
1165 | tty = vc->vc_tty; | 1165 | tty = vc->port.tty; |
1166 | 1166 | ||
1167 | if (tty && (!tty->driver_data)) { | 1167 | if (tty && (!tty->driver_data)) { |
1168 | /* No driver data? Strange. Okay we fix it then. */ | 1168 | /* No driver data? Strange. Okay we fix it then. */ |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index d2692d443f7b..3fc89da856ae 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -2193,7 +2193,7 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port | |||
2193 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); | 2193 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); |
2194 | port->icount.tx += (cnt - port->xmit_cnt); | 2194 | port->icount.tx += (cnt - port->xmit_cnt); |
2195 | 2195 | ||
2196 | if (port->xmit_cnt < WAKEUP_CHARS && tty) | 2196 | if (port->xmit_cnt < WAKEUP_CHARS) |
2197 | tty_wakeup(tty); | 2197 | tty_wakeup(tty); |
2198 | 2198 | ||
2199 | if (port->xmit_cnt <= 0) { | 2199 | if (port->xmit_cnt <= 0) { |
diff --git a/drivers/char/n_gsm.c b/drivers/char/n_gsm.c index e4089c432f15..099105e0894e 100644 --- a/drivers/char/n_gsm.c +++ b/drivers/char/n_gsm.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <linux/sched.h> | 43 | #include <linux/sched.h> |
44 | #include <linux/interrupt.h> | 44 | #include <linux/interrupt.h> |
45 | #include <linux/tty.h> | 45 | #include <linux/tty.h> |
46 | #include <linux/timer.h> | ||
47 | #include <linux/ctype.h> | 46 | #include <linux/ctype.h> |
48 | #include <linux/mm.h> | 47 | #include <linux/mm.h> |
49 | #include <linux/string.h> | 48 | #include <linux/string.h> |
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index c68118efad84..47d32281032c 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
@@ -598,18 +598,18 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
598 | return -EFAULT; | 598 | return -EFAULT; |
599 | } | 599 | } |
600 | 600 | ||
601 | lock_kernel(); | 601 | tty_lock(); |
602 | 602 | ||
603 | for (;;) { | 603 | for (;;) { |
604 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { | 604 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { |
605 | unlock_kernel(); | 605 | tty_unlock(); |
606 | return -EIO; | 606 | return -EIO; |
607 | } | 607 | } |
608 | 608 | ||
609 | n_hdlc = tty2n_hdlc (tty); | 609 | n_hdlc = tty2n_hdlc (tty); |
610 | if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || | 610 | if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || |
611 | tty != n_hdlc->tty) { | 611 | tty != n_hdlc->tty) { |
612 | unlock_kernel(); | 612 | tty_unlock(); |
613 | return 0; | 613 | return 0; |
614 | } | 614 | } |
615 | 615 | ||
@@ -619,13 +619,13 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
619 | 619 | ||
620 | /* no data */ | 620 | /* no data */ |
621 | if (file->f_flags & O_NONBLOCK) { | 621 | if (file->f_flags & O_NONBLOCK) { |
622 | unlock_kernel(); | 622 | tty_unlock(); |
623 | return -EAGAIN; | 623 | return -EAGAIN; |
624 | } | 624 | } |
625 | 625 | ||
626 | interruptible_sleep_on (&tty->read_wait); | 626 | interruptible_sleep_on (&tty->read_wait); |
627 | if (signal_pending(current)) { | 627 | if (signal_pending(current)) { |
628 | unlock_kernel(); | 628 | tty_unlock(); |
629 | return -EINTR; | 629 | return -EINTR; |
630 | } | 630 | } |
631 | } | 631 | } |
@@ -648,7 +648,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, | |||
648 | kfree(rbuf); | 648 | kfree(rbuf); |
649 | else | 649 | else |
650 | n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); | 650 | n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); |
651 | unlock_kernel(); | 651 | tty_unlock(); |
652 | return ret; | 652 | return ret; |
653 | 653 | ||
654 | } /* end of n_hdlc_tty_read() */ | 654 | } /* end of n_hdlc_tty_read() */ |
@@ -691,7 +691,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, | |||
691 | count = maxframe; | 691 | count = maxframe; |
692 | } | 692 | } |
693 | 693 | ||
694 | lock_kernel(); | 694 | tty_lock(); |
695 | 695 | ||
696 | add_wait_queue(&tty->write_wait, &wait); | 696 | add_wait_queue(&tty->write_wait, &wait); |
697 | set_current_state(TASK_INTERRUPTIBLE); | 697 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, | |||
731 | n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); | 731 | n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); |
732 | n_hdlc_send_frames(n_hdlc,tty); | 732 | n_hdlc_send_frames(n_hdlc,tty); |
733 | } | 733 | } |
734 | unlock_kernel(); | 734 | tty_unlock(); |
735 | return error; | 735 | return error; |
736 | 736 | ||
737 | } /* end of n_hdlc_tty_write() */ | 737 | } /* end of n_hdlc_tty_write() */ |
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index c1d8b54c816d..a98290d7a2c5 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -1067,7 +1067,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1067 | 1067 | ||
1068 | TRACE_L("read()"); | 1068 | TRACE_L("read()"); |
1069 | 1069 | ||
1070 | lock_kernel(); | 1070 | tty_lock(); |
1071 | 1071 | ||
1072 | pClient = findClient(pInfo, task_pid(current)); | 1072 | pClient = findClient(pInfo, task_pid(current)); |
1073 | if (pClient) { | 1073 | if (pClient) { |
@@ -1079,7 +1079,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1079 | goto unlock; | 1079 | goto unlock; |
1080 | } | 1080 | } |
1081 | /* block until there is a message: */ | 1081 | /* block until there is a message: */ |
1082 | wait_event_interruptible(pInfo->read_wait, | 1082 | wait_event_interruptible_tty(pInfo->read_wait, |
1083 | (pMsg = remove_msg(pInfo, pClient))); | 1083 | (pMsg = remove_msg(pInfo, pClient))); |
1084 | } | 1084 | } |
1085 | 1085 | ||
@@ -1109,7 +1109,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1109 | } | 1109 | } |
1110 | ret = -EPERM; | 1110 | ret = -EPERM; |
1111 | unlock: | 1111 | unlock: |
1112 | unlock_kernel(); | 1112 | tty_unlock(); |
1113 | return ret; | 1113 | return ret; |
1114 | } | 1114 | } |
1115 | 1115 | ||
@@ -1158,7 +1158,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | |||
1158 | pHeader->locks = 0; | 1158 | pHeader->locks = 0; |
1159 | pHeader->owner = NULL; | 1159 | pHeader->owner = NULL; |
1160 | 1160 | ||
1161 | lock_kernel(); | 1161 | tty_lock(); |
1162 | 1162 | ||
1163 | pClient = findClient(pInfo, task_pid(current)); | 1163 | pClient = findClient(pInfo, task_pid(current)); |
1164 | if (pClient) { | 1164 | if (pClient) { |
@@ -1177,7 +1177,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, | |||
1177 | add_tx_queue(pInfo, pHeader); | 1177 | add_tx_queue(pInfo, pHeader); |
1178 | trigger_transmit(pInfo); | 1178 | trigger_transmit(pInfo); |
1179 | 1179 | ||
1180 | unlock_kernel(); | 1180 | tty_unlock(); |
1181 | 1181 | ||
1182 | return 0; | 1182 | return 0; |
1183 | } | 1183 | } |
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index bdae8327143c..428f4fe0b5f7 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -1102,6 +1102,11 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
1102 | if (I_IUCLC(tty) && L_IEXTEN(tty)) | 1102 | if (I_IUCLC(tty) && L_IEXTEN(tty)) |
1103 | c = tolower(c); | 1103 | c = tolower(c); |
1104 | 1104 | ||
1105 | if (L_EXTPROC(tty)) { | ||
1106 | put_tty_queue(c, tty); | ||
1107 | return; | ||
1108 | } | ||
1109 | |||
1105 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && | 1110 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && |
1106 | I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && | 1111 | I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty) && |
1107 | c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) { | 1112 | c != INTR_CHAR(tty) && c != QUIT_CHAR(tty) && c != SUSP_CHAR(tty)) { |
@@ -1409,7 +1414,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1409 | 1414 | ||
1410 | n_tty_set_room(tty); | 1415 | n_tty_set_room(tty); |
1411 | 1416 | ||
1412 | if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) { | 1417 | if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) || |
1418 | L_EXTPROC(tty)) { | ||
1413 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); | 1419 | kill_fasync(&tty->fasync, SIGIO, POLL_IN); |
1414 | if (waitqueue_active(&tty->read_wait)) | 1420 | if (waitqueue_active(&tty->read_wait)) |
1415 | wake_up_interruptible(&tty->read_wait); | 1421 | wake_up_interruptible(&tty->read_wait); |
@@ -1585,7 +1591,7 @@ static int n_tty_open(struct tty_struct *tty) | |||
1585 | static inline int input_available_p(struct tty_struct *tty, int amt) | 1591 | static inline int input_available_p(struct tty_struct *tty, int amt) |
1586 | { | 1592 | { |
1587 | tty_flush_to_ldisc(tty); | 1593 | tty_flush_to_ldisc(tty); |
1588 | if (tty->icanon) { | 1594 | if (tty->icanon && !L_EXTPROC(tty)) { |
1589 | if (tty->canon_data) | 1595 | if (tty->canon_data) |
1590 | return 1; | 1596 | return 1; |
1591 | } else if (tty->read_cnt >= (amt ? amt : 1)) | 1597 | } else if (tty->read_cnt >= (amt ? amt : 1)) |
@@ -1632,6 +1638,11 @@ static int copy_from_read_buf(struct tty_struct *tty, | |||
1632 | spin_lock_irqsave(&tty->read_lock, flags); | 1638 | spin_lock_irqsave(&tty->read_lock, flags); |
1633 | tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); | 1639 | tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); |
1634 | tty->read_cnt -= n; | 1640 | tty->read_cnt -= n; |
1641 | /* Turn single EOF into zero-length read */ | ||
1642 | if (L_EXTPROC(tty) && tty->icanon && n == 1) { | ||
1643 | if (!tty->read_cnt && (*b)[n-1] == EOF_CHAR(tty)) | ||
1644 | n--; | ||
1645 | } | ||
1635 | spin_unlock_irqrestore(&tty->read_lock, flags); | 1646 | spin_unlock_irqrestore(&tty->read_lock, flags); |
1636 | *b += n; | 1647 | *b += n; |
1637 | *nr -= n; | 1648 | *nr -= n; |
@@ -1812,7 +1823,7 @@ do_it_again: | |||
1812 | nr--; | 1823 | nr--; |
1813 | } | 1824 | } |
1814 | 1825 | ||
1815 | if (tty->icanon) { | 1826 | if (tty->icanon && !L_EXTPROC(tty)) { |
1816 | /* N.B. avoid overrun if nr == 0 */ | 1827 | /* N.B. avoid overrun if nr == 0 */ |
1817 | while (nr && tty->read_cnt) { | 1828 | while (nr && tty->read_cnt) { |
1818 | int eol; | 1829 | int eol; |
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index a6638003f530..18af923093c3 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c | |||
@@ -1611,6 +1611,8 @@ static int ntty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
1611 | ret = tty_init_termios(tty); | 1611 | ret = tty_init_termios(tty); |
1612 | if (ret == 0) { | 1612 | if (ret == 0) { |
1613 | tty_driver_kref_get(driver); | 1613 | tty_driver_kref_get(driver); |
1614 | tty->count++; | ||
1615 | tty->driver_data = port; | ||
1614 | driver->ttys[tty->index] = tty; | 1616 | driver->ttys[tty->index] = tty; |
1615 | } | 1617 | } |
1616 | return ret; | 1618 | return ret; |
@@ -1639,7 +1641,7 @@ static int ntty_activate(struct tty_port *tport, struct tty_struct *tty) | |||
1639 | 1641 | ||
1640 | static int ntty_open(struct tty_struct *tty, struct file *filp) | 1642 | static int ntty_open(struct tty_struct *tty, struct file *filp) |
1641 | { | 1643 | { |
1642 | struct port *port = get_port_by_tty(tty); | 1644 | struct port *port = tty->driver_data; |
1643 | return tty_port_open(&port->port, tty, filp); | 1645 | return tty_port_open(&port->port, tty, filp); |
1644 | } | 1646 | } |
1645 | 1647 | ||
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index d83a43130df4..ad46eae1f9bb 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -62,7 +62,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
62 | if (tty->driver == ptm_driver) | 62 | if (tty->driver == ptm_driver) |
63 | devpts_pty_kill(tty->link); | 63 | devpts_pty_kill(tty->link); |
64 | #endif | 64 | #endif |
65 | tty_unlock(); | ||
65 | tty_vhangup(tty->link); | 66 | tty_vhangup(tty->link); |
67 | tty_lock(); | ||
66 | } | 68 | } |
67 | } | 69 | } |
68 | 70 | ||
@@ -171,6 +173,23 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg) | |||
171 | return 0; | 173 | return 0; |
172 | } | 174 | } |
173 | 175 | ||
176 | /* Send a signal to the slave */ | ||
177 | static int pty_signal(struct tty_struct *tty, int sig) | ||
178 | { | ||
179 | unsigned long flags; | ||
180 | struct pid *pgrp; | ||
181 | |||
182 | if (tty->link) { | ||
183 | spin_lock_irqsave(&tty->link->ctrl_lock, flags); | ||
184 | pgrp = get_pid(tty->link->pgrp); | ||
185 | spin_unlock_irqrestore(&tty->link->ctrl_lock, flags); | ||
186 | |||
187 | kill_pgrp(pgrp, sig, 1); | ||
188 | put_pid(pgrp); | ||
189 | } | ||
190 | return 0; | ||
191 | } | ||
192 | |||
174 | static void pty_flush_buffer(struct tty_struct *tty) | 193 | static void pty_flush_buffer(struct tty_struct *tty) |
175 | { | 194 | { |
176 | struct tty_struct *to = tty->link; | 195 | struct tty_struct *to = tty->link; |
@@ -321,6 +340,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, | |||
321 | switch (cmd) { | 340 | switch (cmd) { |
322 | case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ | 341 | case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ |
323 | return pty_set_lock(tty, (int __user *) arg); | 342 | return pty_set_lock(tty, (int __user *) arg); |
343 | case TIOCSIG: /* Send signal to other side of pty */ | ||
344 | return pty_signal(tty, (int) arg); | ||
324 | } | 345 | } |
325 | return -ENOIOCTLCMD; | 346 | return -ENOIOCTLCMD; |
326 | } | 347 | } |
@@ -476,6 +497,8 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, | |||
476 | return pty_set_lock(tty, (int __user *)arg); | 497 | return pty_set_lock(tty, (int __user *)arg); |
477 | case TIOCGPTN: /* Get PT Number */ | 498 | case TIOCGPTN: /* Get PT Number */ |
478 | return put_user(tty->index, (unsigned int __user *)arg); | 499 | return put_user(tty->index, (unsigned int __user *)arg); |
500 | case TIOCSIG: /* Send signal to other side of pty */ | ||
501 | return pty_signal(tty, (int) arg); | ||
479 | } | 502 | } |
480 | 503 | ||
481 | return -ENOIOCTLCMD; | 504 | return -ENOIOCTLCMD; |
@@ -626,7 +649,7 @@ static const struct tty_operations pty_unix98_ops = { | |||
626 | * allocated_ptys_lock handles the list of free pty numbers | 649 | * allocated_ptys_lock handles the list of free pty numbers |
627 | */ | 650 | */ |
628 | 651 | ||
629 | static int __ptmx_open(struct inode *inode, struct file *filp) | 652 | static int ptmx_open(struct inode *inode, struct file *filp) |
630 | { | 653 | { |
631 | struct tty_struct *tty; | 654 | struct tty_struct *tty; |
632 | int retval; | 655 | int retval; |
@@ -635,11 +658,14 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
635 | nonseekable_open(inode, filp); | 658 | nonseekable_open(inode, filp); |
636 | 659 | ||
637 | /* find a device that is not in use. */ | 660 | /* find a device that is not in use. */ |
661 | tty_lock(); | ||
638 | index = devpts_new_index(inode); | 662 | index = devpts_new_index(inode); |
663 | tty_unlock(); | ||
639 | if (index < 0) | 664 | if (index < 0) |
640 | return index; | 665 | return index; |
641 | 666 | ||
642 | mutex_lock(&tty_mutex); | 667 | mutex_lock(&tty_mutex); |
668 | tty_lock(); | ||
643 | tty = tty_init_dev(ptm_driver, index, 1); | 669 | tty = tty_init_dev(ptm_driver, index, 1); |
644 | mutex_unlock(&tty_mutex); | 670 | mutex_unlock(&tty_mutex); |
645 | 671 | ||
@@ -657,26 +683,21 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
657 | goto out1; | 683 | goto out1; |
658 | 684 | ||
659 | retval = ptm_driver->ops->open(tty, filp); | 685 | retval = ptm_driver->ops->open(tty, filp); |
660 | if (!retval) | 686 | if (retval) |
661 | return 0; | 687 | goto out2; |
662 | out1: | 688 | out1: |
689 | tty_unlock(); | ||
690 | return retval; | ||
691 | out2: | ||
692 | tty_unlock(); | ||
663 | tty_release(inode, filp); | 693 | tty_release(inode, filp); |
664 | return retval; | 694 | return retval; |
665 | out: | 695 | out: |
666 | devpts_kill_index(inode, index); | 696 | devpts_kill_index(inode, index); |
697 | tty_unlock(); | ||
667 | return retval; | 698 | return retval; |
668 | } | 699 | } |
669 | 700 | ||
670 | static int ptmx_open(struct inode *inode, struct file *filp) | ||
671 | { | ||
672 | int ret; | ||
673 | |||
674 | lock_kernel(); | ||
675 | ret = __ptmx_open(inode, filp); | ||
676 | unlock_kernel(); | ||
677 | return ret; | ||
678 | } | ||
679 | |||
680 | static struct file_operations ptmx_fops; | 701 | static struct file_operations ptmx_fops; |
681 | 702 | ||
682 | static void __init unix98_pty_init(void) | 703 | static void __init unix98_pty_init(void) |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index b02332a5412f..af4de1fe8445 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include <linux/init.h> | 47 | #include <linux/init.h> |
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/tty_flip.h> | 49 | #include <linux/tty_flip.h> |
50 | #include <linux/smp_lock.h> | ||
51 | #include <linux/spinlock.h> | 50 | #include <linux/spinlock.h> |
52 | #include <linux/device.h> | 51 | #include <linux/device.h> |
53 | 52 | ||
@@ -1184,6 +1183,7 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, | |||
1184 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) | 1183 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) |
1185 | return -EFAULT; | 1184 | return -EFAULT; |
1186 | 1185 | ||
1186 | mutex_lock(&port->port.mutex); | ||
1187 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != | 1187 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != |
1188 | (tmp.flags & ASYNC_SPD_MASK)); | 1188 | (tmp.flags & ASYNC_SPD_MASK)); |
1189 | 1189 | ||
@@ -1191,8 +1191,10 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, | |||
1191 | if ((tmp.close_delay != port->port.close_delay) || | 1191 | if ((tmp.close_delay != port->port.close_delay) || |
1192 | (tmp.closing_wait != port->port.closing_wait) || | 1192 | (tmp.closing_wait != port->port.closing_wait) || |
1193 | ((tmp.flags & ~ASYNC_USR_MASK) != | 1193 | ((tmp.flags & ~ASYNC_USR_MASK) != |
1194 | (port->port.flags & ~ASYNC_USR_MASK))) | 1194 | (port->port.flags & ~ASYNC_USR_MASK))) { |
1195 | mutex_unlock(&port->port.mutex); | ||
1195 | return -EPERM; | 1196 | return -EPERM; |
1197 | } | ||
1196 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | 1198 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | |
1197 | (tmp.flags & ASYNC_USR_MASK)); | 1199 | (tmp.flags & ASYNC_USR_MASK)); |
1198 | } else { | 1200 | } else { |
@@ -1208,6 +1210,7 @@ static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port, | |||
1208 | rc_change_speed(tty, bp, port); | 1210 | rc_change_speed(tty, bp, port); |
1209 | spin_unlock_irqrestore(&riscom_lock, flags); | 1211 | spin_unlock_irqrestore(&riscom_lock, flags); |
1210 | } | 1212 | } |
1213 | mutex_unlock(&port->port.mutex); | ||
1211 | return 0; | 1214 | return 0; |
1212 | } | 1215 | } |
1213 | 1216 | ||
@@ -1220,12 +1223,15 @@ static int rc_get_serial_info(struct riscom_port *port, | |||
1220 | memset(&tmp, 0, sizeof(tmp)); | 1223 | memset(&tmp, 0, sizeof(tmp)); |
1221 | tmp.type = PORT_CIRRUS; | 1224 | tmp.type = PORT_CIRRUS; |
1222 | tmp.line = port - rc_port; | 1225 | tmp.line = port - rc_port; |
1226 | |||
1227 | mutex_lock(&port->port.mutex); | ||
1223 | tmp.port = bp->base; | 1228 | tmp.port = bp->base; |
1224 | tmp.irq = bp->irq; | 1229 | tmp.irq = bp->irq; |
1225 | tmp.flags = port->port.flags; | 1230 | tmp.flags = port->port.flags; |
1226 | tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC; | 1231 | tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC; |
1227 | tmp.close_delay = port->port.close_delay * HZ/100; | 1232 | tmp.close_delay = port->port.close_delay * HZ/100; |
1228 | tmp.closing_wait = port->port.closing_wait * HZ/100; | 1233 | tmp.closing_wait = port->port.closing_wait * HZ/100; |
1234 | mutex_unlock(&port->port.mutex); | ||
1229 | tmp.xmit_fifo_size = CD180_NFIFO; | 1235 | tmp.xmit_fifo_size = CD180_NFIFO; |
1230 | return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0; | 1236 | return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0; |
1231 | } | 1237 | } |
@@ -1242,14 +1248,10 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp, | |||
1242 | 1248 | ||
1243 | switch (cmd) { | 1249 | switch (cmd) { |
1244 | case TIOCGSERIAL: | 1250 | case TIOCGSERIAL: |
1245 | lock_kernel(); | ||
1246 | retval = rc_get_serial_info(port, argp); | 1251 | retval = rc_get_serial_info(port, argp); |
1247 | unlock_kernel(); | ||
1248 | break; | 1252 | break; |
1249 | case TIOCSSERIAL: | 1253 | case TIOCSSERIAL: |
1250 | lock_kernel(); | ||
1251 | retval = rc_set_serial_info(tty, port, argp); | 1254 | retval = rc_set_serial_info(tty, port, argp); |
1252 | unlock_kernel(); | ||
1253 | break; | 1255 | break; |
1254 | default: | 1256 | default: |
1255 | retval = -ENOIOCTLCMD; | 1257 | retval = -ENOIOCTLCMD; |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 0e29a23ec4c5..79c3bc69165a 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -73,7 +73,6 @@ | |||
73 | #include <linux/tty_driver.h> | 73 | #include <linux/tty_driver.h> |
74 | #include <linux/tty_flip.h> | 74 | #include <linux/tty_flip.h> |
75 | #include <linux/serial.h> | 75 | #include <linux/serial.h> |
76 | #include <linux/smp_lock.h> | ||
77 | #include <linux/string.h> | 76 | #include <linux/string.h> |
78 | #include <linux/fcntl.h> | 77 | #include <linux/fcntl.h> |
79 | #include <linux/ptrace.h> | 78 | #include <linux/ptrace.h> |
@@ -1017,6 +1016,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1017 | if (tty_port_close_start(port, tty, filp) == 0) | 1016 | if (tty_port_close_start(port, tty, filp) == 0) |
1018 | return; | 1017 | return; |
1019 | 1018 | ||
1019 | mutex_lock(&port->mutex); | ||
1020 | cp = &info->channel; | 1020 | cp = &info->channel; |
1021 | /* | 1021 | /* |
1022 | * Before we drop DTR, make sure the UART transmitter | 1022 | * Before we drop DTR, make sure the UART transmitter |
@@ -1060,9 +1060,13 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1060 | info->xmit_buf = NULL; | 1060 | info->xmit_buf = NULL; |
1061 | } | 1061 | } |
1062 | } | 1062 | } |
1063 | spin_lock_irq(&port->lock); | ||
1063 | info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); | 1064 | info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE); |
1064 | tty->closing = 0; | 1065 | tty->closing = 0; |
1066 | spin_unlock_irq(&port->lock); | ||
1067 | mutex_unlock(&port->mutex); | ||
1065 | tty_port_tty_set(port, NULL); | 1068 | tty_port_tty_set(port, NULL); |
1069 | |||
1066 | wake_up_interruptible(&port->close_wait); | 1070 | wake_up_interruptible(&port->close_wait); |
1067 | complete_all(&info->close_wait); | 1071 | complete_all(&info->close_wait); |
1068 | atomic_dec(&rp_num_ports_open); | 1072 | atomic_dec(&rp_num_ports_open); |
@@ -1210,11 +1214,13 @@ static int get_config(struct r_port *info, struct rocket_config __user *retinfo) | |||
1210 | if (!retinfo) | 1214 | if (!retinfo) |
1211 | return -EFAULT; | 1215 | return -EFAULT; |
1212 | memset(&tmp, 0, sizeof (tmp)); | 1216 | memset(&tmp, 0, sizeof (tmp)); |
1217 | mutex_lock(&info->port.mutex); | ||
1213 | tmp.line = info->line; | 1218 | tmp.line = info->line; |
1214 | tmp.flags = info->flags; | 1219 | tmp.flags = info->flags; |
1215 | tmp.close_delay = info->port.close_delay; | 1220 | tmp.close_delay = info->port.close_delay; |
1216 | tmp.closing_wait = info->port.closing_wait; | 1221 | tmp.closing_wait = info->port.closing_wait; |
1217 | tmp.port = rcktpt_io_addr[(info->line >> 5) & 3]; | 1222 | tmp.port = rcktpt_io_addr[(info->line >> 5) & 3]; |
1223 | mutex_unlock(&info->port.mutex); | ||
1218 | 1224 | ||
1219 | if (copy_to_user(retinfo, &tmp, sizeof (*retinfo))) | 1225 | if (copy_to_user(retinfo, &tmp, sizeof (*retinfo))) |
1220 | return -EFAULT; | 1226 | return -EFAULT; |
@@ -1229,10 +1235,13 @@ static int set_config(struct tty_struct *tty, struct r_port *info, | |||
1229 | if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) | 1235 | if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) |
1230 | return -EFAULT; | 1236 | return -EFAULT; |
1231 | 1237 | ||
1238 | mutex_lock(&info->port.mutex); | ||
1232 | if (!capable(CAP_SYS_ADMIN)) | 1239 | if (!capable(CAP_SYS_ADMIN)) |
1233 | { | 1240 | { |
1234 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) | 1241 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) { |
1242 | mutex_unlock(&info->port.mutex); | ||
1235 | return -EPERM; | 1243 | return -EPERM; |
1244 | } | ||
1236 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); | 1245 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); |
1237 | configure_r_port(tty, info, NULL); | 1246 | configure_r_port(tty, info, NULL); |
1238 | return 0; | 1247 | return 0; |
@@ -1250,6 +1259,7 @@ static int set_config(struct tty_struct *tty, struct r_port *info, | |||
1250 | tty->alt_speed = 230400; | 1259 | tty->alt_speed = 230400; |
1251 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) | 1260 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) |
1252 | tty->alt_speed = 460800; | 1261 | tty->alt_speed = 460800; |
1262 | mutex_unlock(&info->port.mutex); | ||
1253 | 1263 | ||
1254 | configure_r_port(tty, info, NULL); | 1264 | configure_r_port(tty, info, NULL); |
1255 | return 0; | 1265 | return 0; |
@@ -1325,8 +1335,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, | |||
1325 | if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl")) | 1335 | if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl")) |
1326 | return -ENXIO; | 1336 | return -ENXIO; |
1327 | 1337 | ||
1328 | lock_kernel(); | ||
1329 | |||
1330 | switch (cmd) { | 1338 | switch (cmd) { |
1331 | case RCKP_GET_STRUCT: | 1339 | case RCKP_GET_STRUCT: |
1332 | if (copy_to_user(argp, info, sizeof (struct r_port))) | 1340 | if (copy_to_user(argp, info, sizeof (struct r_port))) |
@@ -1350,7 +1358,6 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, | |||
1350 | default: | 1358 | default: |
1351 | ret = -ENOIOCTLCMD; | 1359 | ret = -ENOIOCTLCMD; |
1352 | } | 1360 | } |
1353 | unlock_kernel(); | ||
1354 | return ret; | 1361 | return ret; |
1355 | } | 1362 | } |
1356 | 1363 | ||
@@ -1471,7 +1478,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1471 | jiffies); | 1478 | jiffies); |
1472 | printk(KERN_INFO "cps=%d...\n", info->cps); | 1479 | printk(KERN_INFO "cps=%d...\n", info->cps); |
1473 | #endif | 1480 | #endif |
1474 | lock_kernel(); | ||
1475 | while (1) { | 1481 | while (1) { |
1476 | txcnt = sGetTxCnt(cp); | 1482 | txcnt = sGetTxCnt(cp); |
1477 | if (!txcnt) { | 1483 | if (!txcnt) { |
@@ -1499,7 +1505,6 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1499 | break; | 1505 | break; |
1500 | } | 1506 | } |
1501 | __set_current_state(TASK_RUNNING); | 1507 | __set_current_state(TASK_RUNNING); |
1502 | unlock_kernel(); | ||
1503 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT | 1508 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT |
1504 | printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); | 1509 | printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); |
1505 | #endif | 1510 | #endif |
@@ -1512,6 +1517,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1512 | { | 1517 | { |
1513 | CHANNEL_t *cp; | 1518 | CHANNEL_t *cp; |
1514 | struct r_port *info = tty->driver_data; | 1519 | struct r_port *info = tty->driver_data; |
1520 | unsigned long flags; | ||
1515 | 1521 | ||
1516 | if (rocket_paranoia_check(info, "rp_hangup")) | 1522 | if (rocket_paranoia_check(info, "rp_hangup")) |
1517 | return; | 1523 | return; |
@@ -1520,11 +1526,15 @@ static void rp_hangup(struct tty_struct *tty) | |||
1520 | printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); | 1526 | printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); |
1521 | #endif | 1527 | #endif |
1522 | rp_flush_buffer(tty); | 1528 | rp_flush_buffer(tty); |
1523 | if (info->port.flags & ASYNC_CLOSING) | 1529 | spin_lock_irqsave(&info->port.lock, flags); |
1530 | if (info->port.flags & ASYNC_CLOSING) { | ||
1531 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
1524 | return; | 1532 | return; |
1533 | } | ||
1525 | if (info->port.count) | 1534 | if (info->port.count) |
1526 | atomic_dec(&rp_num_ports_open); | 1535 | atomic_dec(&rp_num_ports_open); |
1527 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); | 1536 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); |
1537 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
1528 | 1538 | ||
1529 | tty_port_hangup(&info->port); | 1539 | tty_port_hangup(&info->port); |
1530 | 1540 | ||
@@ -1535,7 +1545,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1535 | sDisCTSFlowCtl(cp); | 1545 | sDisCTSFlowCtl(cp); |
1536 | sDisTxSoftFlowCtl(cp); | 1546 | sDisTxSoftFlowCtl(cp); |
1537 | sClrTxXOFF(cp); | 1547 | sClrTxXOFF(cp); |
1538 | info->port.flags &= ~ASYNC_INITIALIZED; | 1548 | clear_bit(ASYNCB_INITIALIZED, &info->port.flags); |
1539 | 1549 | ||
1540 | wake_up_interruptible(&info->port.open_wait); | 1550 | wake_up_interruptible(&info->port.open_wait); |
1541 | } | 1551 | } |
diff --git a/drivers/char/selection.c b/drivers/char/selection.c index f97b9e848064..ebae344ce910 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/selection.h> | 26 | #include <linux/selection.h> |
27 | #include <linux/tiocl.h> | 27 | #include <linux/tiocl.h> |
28 | #include <linux/console.h> | 28 | #include <linux/console.h> |
29 | #include <linux/smp_lock.h> | ||
29 | 30 | ||
30 | /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */ | 31 | /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */ |
31 | #define isspace(c) ((c) == ' ') | 32 | #define isspace(c) ((c) == ' ') |
@@ -312,12 +313,20 @@ int paste_selection(struct tty_struct *tty) | |||
312 | struct tty_ldisc *ld; | 313 | struct tty_ldisc *ld; |
313 | DECLARE_WAITQUEUE(wait, current); | 314 | DECLARE_WAITQUEUE(wait, current); |
314 | 315 | ||
316 | /* always called with BTM from vt_ioctl */ | ||
317 | WARN_ON(!tty_locked()); | ||
318 | |||
315 | acquire_console_sem(); | 319 | acquire_console_sem(); |
316 | poke_blanked_console(); | 320 | poke_blanked_console(); |
317 | release_console_sem(); | 321 | release_console_sem(); |
318 | 322 | ||
319 | ld = tty_ldisc_ref_wait(tty); | 323 | ld = tty_ldisc_ref(tty); |
320 | 324 | if (!ld) { | |
325 | tty_unlock(); | ||
326 | ld = tty_ldisc_ref_wait(tty); | ||
327 | tty_lock(); | ||
328 | } | ||
329 | |||
321 | add_wait_queue(&vc->paste_wait, &wait); | 330 | add_wait_queue(&vc->paste_wait, &wait); |
322 | while (sel_buffer && sel_buffer_lth > pasted) { | 331 | while (sel_buffer && sel_buffer_lth > pasted) { |
323 | set_current_state(TASK_INTERRUPTIBLE); | 332 | set_current_state(TASK_INTERRUPTIBLE); |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index ecbe479c7d68..f646725bd567 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
@@ -1505,7 +1505,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
1505 | printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ | 1505 | printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ |
1506 | #endif | 1506 | #endif |
1507 | 1507 | ||
1508 | lock_kernel(); | 1508 | tty_lock(); |
1509 | 1509 | ||
1510 | switch (cmd) { | 1510 | switch (cmd) { |
1511 | case CYGETMON: | 1511 | case CYGETMON: |
@@ -1561,7 +1561,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, | |||
1561 | default: | 1561 | default: |
1562 | ret_val = -ENOIOCTLCMD; | 1562 | ret_val = -ENOIOCTLCMD; |
1563 | } | 1563 | } |
1564 | unlock_kernel(); | 1564 | tty_unlock(); |
1565 | 1565 | ||
1566 | #ifdef SERIAL_DEBUG_OTHER | 1566 | #ifdef SERIAL_DEBUG_OTHER |
1567 | printk("cy_ioctl done\n"); | 1567 | printk("cy_ioctl done\n"); |
@@ -1786,7 +1786,9 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
1786 | tty->name, info->count); | 1786 | tty->name, info->count); |
1787 | /**/ | 1787 | /**/ |
1788 | #endif | 1788 | #endif |
1789 | schedule(); | 1789 | tty_unlock(); |
1790 | schedule(); | ||
1791 | tty_lock(); | ||
1790 | } | 1792 | } |
1791 | __set_current_state(TASK_RUNNING); | 1793 | __set_current_state(TASK_RUNNING); |
1792 | remove_wait_queue(&info->open_wait, &wait); | 1794 | remove_wait_queue(&info->open_wait, &wait); |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 2c24fcdc722a..9f8495b4fc8f 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -1365,7 +1365,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
1365 | retval = -ERESTARTSYS; | 1365 | retval = -ERESTARTSYS; |
1366 | break; | 1366 | break; |
1367 | } | 1367 | } |
1368 | tty_unlock(); | ||
1368 | schedule(); | 1369 | schedule(); |
1370 | tty_lock(); | ||
1369 | } | 1371 | } |
1370 | 1372 | ||
1371 | set_current_state(TASK_RUNNING); | 1373 | set_current_state(TASK_RUNNING); |
@@ -1863,8 +1865,7 @@ static int sx_set_serial_info(struct specialix_port *port, | |||
1863 | return -EFAULT; | 1865 | return -EFAULT; |
1864 | } | 1866 | } |
1865 | 1867 | ||
1866 | lock_kernel(); | 1868 | mutex_lock(&port->port.mutex); |
1867 | |||
1868 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != | 1869 | change_speed = ((port->port.flags & ASYNC_SPD_MASK) != |
1869 | (tmp.flags & ASYNC_SPD_MASK)); | 1870 | (tmp.flags & ASYNC_SPD_MASK)); |
1870 | change_speed |= (tmp.custom_divisor != port->custom_divisor); | 1871 | change_speed |= (tmp.custom_divisor != port->custom_divisor); |
@@ -1875,7 +1876,7 @@ static int sx_set_serial_info(struct specialix_port *port, | |||
1875 | ((tmp.flags & ~ASYNC_USR_MASK) != | 1876 | ((tmp.flags & ~ASYNC_USR_MASK) != |
1876 | (port->port.flags & ~ASYNC_USR_MASK))) { | 1877 | (port->port.flags & ~ASYNC_USR_MASK))) { |
1877 | func_exit(); | 1878 | func_exit(); |
1878 | unlock_kernel(); | 1879 | mutex_unlock(&port->port.mutex); |
1879 | return -EPERM; | 1880 | return -EPERM; |
1880 | } | 1881 | } |
1881 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | | 1882 | port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | |
@@ -1892,7 +1893,7 @@ static int sx_set_serial_info(struct specialix_port *port, | |||
1892 | sx_change_speed(bp, port); | 1893 | sx_change_speed(bp, port); |
1893 | 1894 | ||
1894 | func_exit(); | 1895 | func_exit(); |
1895 | unlock_kernel(); | 1896 | mutex_unlock(&port->port.mutex); |
1896 | return 0; | 1897 | return 0; |
1897 | } | 1898 | } |
1898 | 1899 | ||
@@ -1906,7 +1907,7 @@ static int sx_get_serial_info(struct specialix_port *port, | |||
1906 | func_enter(); | 1907 | func_enter(); |
1907 | 1908 | ||
1908 | memset(&tmp, 0, sizeof(tmp)); | 1909 | memset(&tmp, 0, sizeof(tmp)); |
1909 | lock_kernel(); | 1910 | mutex_lock(&port->port.mutex); |
1910 | tmp.type = PORT_CIRRUS; | 1911 | tmp.type = PORT_CIRRUS; |
1911 | tmp.line = port - sx_port; | 1912 | tmp.line = port - sx_port; |
1912 | tmp.port = bp->base; | 1913 | tmp.port = bp->base; |
@@ -1917,7 +1918,7 @@ static int sx_get_serial_info(struct specialix_port *port, | |||
1917 | tmp.closing_wait = port->port.closing_wait * HZ/100; | 1918 | tmp.closing_wait = port->port.closing_wait * HZ/100; |
1918 | tmp.custom_divisor = port->custom_divisor; | 1919 | tmp.custom_divisor = port->custom_divisor; |
1919 | tmp.xmit_fifo_size = CD186x_NFIFO; | 1920 | tmp.xmit_fifo_size = CD186x_NFIFO; |
1920 | unlock_kernel(); | 1921 | mutex_unlock(&port->port.mutex); |
1921 | if (copy_to_user(retinfo, &tmp, sizeof(tmp))) { | 1922 | if (copy_to_user(retinfo, &tmp, sizeof(tmp))) { |
1922 | func_exit(); | 1923 | func_exit(); |
1923 | return -EFAULT; | 1924 | return -EFAULT; |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 6049fd731924..f2167f8e5aab 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -807,7 +807,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
807 | timeout = HZ; | 807 | timeout = HZ; |
808 | tend = jiffies + timeout; | 808 | tend = jiffies + timeout; |
809 | 809 | ||
810 | lock_kernel(); | ||
811 | while (stl_datastate(portp)) { | 810 | while (stl_datastate(portp)) { |
812 | if (signal_pending(current)) | 811 | if (signal_pending(current)) |
813 | break; | 812 | break; |
@@ -815,7 +814,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
815 | if (time_after_eq(jiffies, tend)) | 814 | if (time_after_eq(jiffies, tend)) |
816 | break; | 815 | break; |
817 | } | 816 | } |
818 | unlock_kernel(); | ||
819 | } | 817 | } |
820 | 818 | ||
821 | /*****************************************************************************/ | 819 | /*****************************************************************************/ |
@@ -1029,6 +1027,8 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) | |||
1029 | pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp); | 1027 | pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp); |
1030 | 1028 | ||
1031 | memset(&sio, 0, sizeof(struct serial_struct)); | 1029 | memset(&sio, 0, sizeof(struct serial_struct)); |
1030 | |||
1031 | mutex_lock(&portp->port.mutex); | ||
1032 | sio.line = portp->portnr; | 1032 | sio.line = portp->portnr; |
1033 | sio.port = portp->ioaddr; | 1033 | sio.port = portp->ioaddr; |
1034 | sio.flags = portp->port.flags; | 1034 | sio.flags = portp->port.flags; |
@@ -1048,6 +1048,7 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) | |||
1048 | brdp = stl_brds[portp->brdnr]; | 1048 | brdp = stl_brds[portp->brdnr]; |
1049 | if (brdp != NULL) | 1049 | if (brdp != NULL) |
1050 | sio.irq = brdp->irq; | 1050 | sio.irq = brdp->irq; |
1051 | mutex_unlock(&portp->port.mutex); | ||
1051 | 1052 | ||
1052 | return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0; | 1053 | return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0; |
1053 | } | 1054 | } |
@@ -1069,12 +1070,15 @@ static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp | |||
1069 | 1070 | ||
1070 | if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) | 1071 | if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) |
1071 | return -EFAULT; | 1072 | return -EFAULT; |
1073 | mutex_lock(&portp->port.mutex); | ||
1072 | if (!capable(CAP_SYS_ADMIN)) { | 1074 | if (!capable(CAP_SYS_ADMIN)) { |
1073 | if ((sio.baud_base != portp->baud_base) || | 1075 | if ((sio.baud_base != portp->baud_base) || |
1074 | (sio.close_delay != portp->close_delay) || | 1076 | (sio.close_delay != portp->close_delay) || |
1075 | ((sio.flags & ~ASYNC_USR_MASK) != | 1077 | ((sio.flags & ~ASYNC_USR_MASK) != |
1076 | (portp->port.flags & ~ASYNC_USR_MASK))) | 1078 | (portp->port.flags & ~ASYNC_USR_MASK))) { |
1079 | mutex_unlock(&portp->port.mutex); | ||
1077 | return -EPERM; | 1080 | return -EPERM; |
1081 | } | ||
1078 | } | 1082 | } |
1079 | 1083 | ||
1080 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | | 1084 | portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) | |
@@ -1083,6 +1087,7 @@ static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp | |||
1083 | portp->close_delay = sio.close_delay; | 1087 | portp->close_delay = sio.close_delay; |
1084 | portp->closing_wait = sio.closing_wait; | 1088 | portp->closing_wait = sio.closing_wait; |
1085 | portp->custom_divisor = sio.custom_divisor; | 1089 | portp->custom_divisor = sio.custom_divisor; |
1090 | mutex_unlock(&portp->port.mutex); | ||
1086 | stl_setport(portp, tty->termios); | 1091 | stl_setport(portp, tty->termios); |
1087 | return 0; | 1092 | return 0; |
1088 | } | 1093 | } |
@@ -1147,8 +1152,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd | |||
1147 | 1152 | ||
1148 | rc = 0; | 1153 | rc = 0; |
1149 | 1154 | ||
1150 | lock_kernel(); | ||
1151 | |||
1152 | switch (cmd) { | 1155 | switch (cmd) { |
1153 | case TIOCGSERIAL: | 1156 | case TIOCGSERIAL: |
1154 | rc = stl_getserial(portp, argp); | 1157 | rc = stl_getserial(portp, argp); |
@@ -1173,7 +1176,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd | |||
1173 | rc = -ENOIOCTLCMD; | 1176 | rc = -ENOIOCTLCMD; |
1174 | break; | 1177 | break; |
1175 | } | 1178 | } |
1176 | unlock_kernel(); | ||
1177 | return rc; | 1179 | return rc; |
1178 | } | 1180 | } |
1179 | 1181 | ||
@@ -2327,6 +2329,7 @@ static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comst | |||
2327 | return -ENODEV; | 2329 | return -ENODEV; |
2328 | } | 2330 | } |
2329 | 2331 | ||
2332 | mutex_lock(&portp->port.mutex); | ||
2330 | portp->stats.state = portp->istate; | 2333 | portp->stats.state = portp->istate; |
2331 | portp->stats.flags = portp->port.flags; | 2334 | portp->stats.flags = portp->port.flags; |
2332 | portp->stats.hwid = portp->hwid; | 2335 | portp->stats.hwid = portp->hwid; |
@@ -2358,6 +2361,7 @@ static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comst | |||
2358 | (STL_TXBUFSIZE - (tail - head)); | 2361 | (STL_TXBUFSIZE - (tail - head)); |
2359 | 2362 | ||
2360 | portp->stats.signals = (unsigned long) stl_getsignals(portp); | 2363 | portp->stats.signals = (unsigned long) stl_getsignals(portp); |
2364 | mutex_unlock(&portp->port.mutex); | ||
2361 | 2365 | ||
2362 | return copy_to_user(cp, &portp->stats, | 2366 | return copy_to_user(cp, &portp->stats, |
2363 | sizeof(comstats_t)) ? -EFAULT : 0; | 2367 | sizeof(comstats_t)) ? -EFAULT : 0; |
@@ -2382,10 +2386,12 @@ static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp) | |||
2382 | return -ENODEV; | 2386 | return -ENODEV; |
2383 | } | 2387 | } |
2384 | 2388 | ||
2389 | mutex_lock(&portp->port.mutex); | ||
2385 | memset(&portp->stats, 0, sizeof(comstats_t)); | 2390 | memset(&portp->stats, 0, sizeof(comstats_t)); |
2386 | portp->stats.brd = portp->brdnr; | 2391 | portp->stats.brd = portp->brdnr; |
2387 | portp->stats.panel = portp->panelnr; | 2392 | portp->stats.panel = portp->panelnr; |
2388 | portp->stats.port = portp->portnr; | 2393 | portp->stats.port = portp->portnr; |
2394 | mutex_unlock(&portp->port.mutex); | ||
2389 | return copy_to_user(cp, &portp->stats, | 2395 | return copy_to_user(cp, &portp->stats, |
2390 | sizeof(comstats_t)) ? -EFAULT : 0; | 2396 | sizeof(comstats_t)) ? -EFAULT : 0; |
2391 | } | 2397 | } |
@@ -2451,7 +2457,6 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
2451 | return -ENODEV; | 2457 | return -ENODEV; |
2452 | rc = 0; | 2458 | rc = 0; |
2453 | 2459 | ||
2454 | lock_kernel(); | ||
2455 | switch (cmd) { | 2460 | switch (cmd) { |
2456 | case COM_GETPORTSTATS: | 2461 | case COM_GETPORTSTATS: |
2457 | rc = stl_getportstats(NULL, NULL, argp); | 2462 | rc = stl_getportstats(NULL, NULL, argp); |
@@ -2472,7 +2477,6 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) | |||
2472 | rc = -ENOIOCTLCMD; | 2477 | rc = -ENOIOCTLCMD; |
2473 | break; | 2478 | break; |
2474 | } | 2479 | } |
2475 | unlock_kernel(); | ||
2476 | return rc; | 2480 | return rc; |
2477 | } | 2481 | } |
2478 | 2482 | ||
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index a81ec4fcf6ff..5b24db4ff7f1 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -1699,7 +1699,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, | |||
1699 | if (!capable(CAP_SYS_RAWIO)) | 1699 | if (!capable(CAP_SYS_RAWIO)) |
1700 | return -EPERM; | 1700 | return -EPERM; |
1701 | 1701 | ||
1702 | lock_kernel(); | 1702 | tty_lock(); |
1703 | 1703 | ||
1704 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); | 1704 | sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); |
1705 | 1705 | ||
@@ -1848,7 +1848,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, | |||
1848 | break; | 1848 | break; |
1849 | } | 1849 | } |
1850 | out: | 1850 | out: |
1851 | unlock_kernel(); | 1851 | tty_unlock(); |
1852 | func_exit(); | 1852 | func_exit(); |
1853 | return rc; | 1853 | return rc; |
1854 | } | 1854 | } |
@@ -1859,7 +1859,7 @@ static int sx_break(struct tty_struct *tty, int flag) | |||
1859 | int rv; | 1859 | int rv; |
1860 | 1860 | ||
1861 | func_enter(); | 1861 | func_enter(); |
1862 | lock_kernel(); | 1862 | tty_lock(); |
1863 | 1863 | ||
1864 | if (flag) | 1864 | if (flag) |
1865 | rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); | 1865 | rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); |
@@ -1868,7 +1868,7 @@ static int sx_break(struct tty_struct *tty, int flag) | |||
1868 | if (rv != 1) | 1868 | if (rv != 1) |
1869 | printk(KERN_ERR "sx: couldn't send break (%x).\n", | 1869 | printk(KERN_ERR "sx: couldn't send break (%x).\n", |
1870 | read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); | 1870 | read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); |
1871 | unlock_kernel(); | 1871 | tty_unlock(); |
1872 | func_exit(); | 1872 | func_exit(); |
1873 | return 0; | 1873 | return 0; |
1874 | } | 1874 | } |
@@ -1909,7 +1909,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, | |||
1909 | /* func_enter2(); */ | 1909 | /* func_enter2(); */ |
1910 | 1910 | ||
1911 | rc = 0; | 1911 | rc = 0; |
1912 | lock_kernel(); | 1912 | tty_lock(); |
1913 | switch (cmd) { | 1913 | switch (cmd) { |
1914 | case TIOCGSERIAL: | 1914 | case TIOCGSERIAL: |
1915 | rc = gs_getserial(&port->gs, argp); | 1915 | rc = gs_getserial(&port->gs, argp); |
@@ -1921,7 +1921,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, | |||
1921 | rc = -ENOIOCTLCMD; | 1921 | rc = -ENOIOCTLCMD; |
1922 | break; | 1922 | break; |
1923 | } | 1923 | } |
1924 | unlock_kernel(); | 1924 | tty_unlock(); |
1925 | 1925 | ||
1926 | /* func_exit(); */ | 1926 | /* func_exit(); */ |
1927 | return rc; | 1927 | return rc; |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 0658fc548222..a2a58004e188 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -81,7 +81,6 @@ | |||
81 | #include <linux/mm.h> | 81 | #include <linux/mm.h> |
82 | #include <linux/seq_file.h> | 82 | #include <linux/seq_file.h> |
83 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
84 | #include <linux/smp_lock.h> | ||
85 | #include <linux/delay.h> | 84 | #include <linux/delay.h> |
86 | #include <linux/netdevice.h> | 85 | #include <linux/netdevice.h> |
87 | #include <linux/vmalloc.h> | 86 | #include <linux/vmalloc.h> |
@@ -2436,7 +2435,9 @@ static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user * | |||
2436 | if (!user_icount) { | 2435 | if (!user_icount) { |
2437 | memset(&info->icount, 0, sizeof(info->icount)); | 2436 | memset(&info->icount, 0, sizeof(info->icount)); |
2438 | } else { | 2437 | } else { |
2438 | mutex_lock(&info->port.mutex); | ||
2439 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); | 2439 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); |
2440 | mutex_unlock(&info->port.mutex); | ||
2440 | if (err) | 2441 | if (err) |
2441 | return -EFAULT; | 2442 | return -EFAULT; |
2442 | } | 2443 | } |
@@ -2461,7 +2462,9 @@ static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_p | |||
2461 | printk("%s(%d):mgsl_get_params(%s)\n", | 2462 | printk("%s(%d):mgsl_get_params(%s)\n", |
2462 | __FILE__,__LINE__, info->device_name); | 2463 | __FILE__,__LINE__, info->device_name); |
2463 | 2464 | ||
2465 | mutex_lock(&info->port.mutex); | ||
2464 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); | 2466 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); |
2467 | mutex_unlock(&info->port.mutex); | ||
2465 | if (err) { | 2468 | if (err) { |
2466 | if ( debug_level >= DEBUG_LEVEL_INFO ) | 2469 | if ( debug_level >= DEBUG_LEVEL_INFO ) |
2467 | printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n", | 2470 | printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n", |
@@ -2501,11 +2504,13 @@ static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_pa | |||
2501 | return -EFAULT; | 2504 | return -EFAULT; |
2502 | } | 2505 | } |
2503 | 2506 | ||
2507 | mutex_lock(&info->port.mutex); | ||
2504 | spin_lock_irqsave(&info->irq_spinlock,flags); | 2508 | spin_lock_irqsave(&info->irq_spinlock,flags); |
2505 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); | 2509 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); |
2506 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | 2510 | spin_unlock_irqrestore(&info->irq_spinlock,flags); |
2507 | 2511 | ||
2508 | mgsl_change_params(info); | 2512 | mgsl_change_params(info); |
2513 | mutex_unlock(&info->port.mutex); | ||
2509 | 2514 | ||
2510 | return 0; | 2515 | return 0; |
2511 | 2516 | ||
@@ -2935,7 +2940,6 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file, | |||
2935 | unsigned int cmd, unsigned long arg) | 2940 | unsigned int cmd, unsigned long arg) |
2936 | { | 2941 | { |
2937 | struct mgsl_struct * info = tty->driver_data; | 2942 | struct mgsl_struct * info = tty->driver_data; |
2938 | int ret; | ||
2939 | 2943 | ||
2940 | if (debug_level >= DEBUG_LEVEL_INFO) | 2944 | if (debug_level >= DEBUG_LEVEL_INFO) |
2941 | printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__, | 2945 | printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__, |
@@ -2950,10 +2954,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file, | |||
2950 | return -EIO; | 2954 | return -EIO; |
2951 | } | 2955 | } |
2952 | 2956 | ||
2953 | lock_kernel(); | 2957 | return mgsl_ioctl_common(info, cmd, arg); |
2954 | ret = mgsl_ioctl_common(info, cmd, arg); | ||
2955 | unlock_kernel(); | ||
2956 | return ret; | ||
2957 | } | 2958 | } |
2958 | 2959 | ||
2959 | static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) | 2960 | static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) |
@@ -3109,12 +3110,14 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp) | |||
3109 | 3110 | ||
3110 | if (tty_port_close_start(&info->port, tty, filp) == 0) | 3111 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
3111 | goto cleanup; | 3112 | goto cleanup; |
3112 | 3113 | ||
3114 | mutex_lock(&info->port.mutex); | ||
3113 | if (info->port.flags & ASYNC_INITIALIZED) | 3115 | if (info->port.flags & ASYNC_INITIALIZED) |
3114 | mgsl_wait_until_sent(tty, info->timeout); | 3116 | mgsl_wait_until_sent(tty, info->timeout); |
3115 | mgsl_flush_buffer(tty); | 3117 | mgsl_flush_buffer(tty); |
3116 | tty_ldisc_flush(tty); | 3118 | tty_ldisc_flush(tty); |
3117 | shutdown(info); | 3119 | shutdown(info); |
3120 | mutex_unlock(&info->port.mutex); | ||
3118 | 3121 | ||
3119 | tty_port_close_end(&info->port, tty); | 3122 | tty_port_close_end(&info->port, tty); |
3120 | info->port.tty = NULL; | 3123 | info->port.tty = NULL; |
@@ -3162,7 +3165,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) | |||
3162 | * Note: use tight timings here to satisfy the NIST-PCTS. | 3165 | * Note: use tight timings here to satisfy the NIST-PCTS. |
3163 | */ | 3166 | */ |
3164 | 3167 | ||
3165 | lock_kernel(); | ||
3166 | if ( info->params.data_rate ) { | 3168 | if ( info->params.data_rate ) { |
3167 | char_time = info->timeout/(32 * 5); | 3169 | char_time = info->timeout/(32 * 5); |
3168 | if (!char_time) | 3170 | if (!char_time) |
@@ -3192,7 +3194,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) | |||
3192 | break; | 3194 | break; |
3193 | } | 3195 | } |
3194 | } | 3196 | } |
3195 | unlock_kernel(); | ||
3196 | 3197 | ||
3197 | exit: | 3198 | exit: |
3198 | if (debug_level >= DEBUG_LEVEL_INFO) | 3199 | if (debug_level >= DEBUG_LEVEL_INFO) |
@@ -3348,7 +3349,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3348 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", | 3349 | printk("%s(%d):block_til_ready blocking on %s count=%d\n", |
3349 | __FILE__,__LINE__, tty->driver->name, port->count ); | 3350 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3350 | 3351 | ||
3352 | tty_unlock(); | ||
3351 | schedule(); | 3353 | schedule(); |
3354 | tty_lock(); | ||
3352 | } | 3355 | } |
3353 | 3356 | ||
3354 | set_current_state(TASK_RUNNING); | 3357 | set_current_state(TASK_RUNNING); |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 334cf5c8c8b6..fef80cfcab5c 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -40,8 +40,8 @@ | |||
40 | #define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt | 40 | #define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt |
41 | #define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt | 41 | #define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt |
42 | #define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) | 42 | #define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) |
43 | //#define DBGTBUF(info) dump_tbufs(info) | 43 | /*#define DBGTBUF(info) dump_tbufs(info)*/ |
44 | //#define DBGRBUF(info) dump_rbufs(info) | 44 | /*#define DBGRBUF(info) dump_rbufs(info)*/ |
45 | 45 | ||
46 | 46 | ||
47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
@@ -62,7 +62,6 @@ | |||
62 | #include <linux/mm.h> | 62 | #include <linux/mm.h> |
63 | #include <linux/seq_file.h> | 63 | #include <linux/seq_file.h> |
64 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
65 | #include <linux/smp_lock.h> | ||
66 | #include <linux/netdevice.h> | 65 | #include <linux/netdevice.h> |
67 | #include <linux/vmalloc.h> | 66 | #include <linux/vmalloc.h> |
68 | #include <linux/init.h> | 67 | #include <linux/init.h> |
@@ -676,12 +675,14 @@ static int open(struct tty_struct *tty, struct file *filp) | |||
676 | goto cleanup; | 675 | goto cleanup; |
677 | } | 676 | } |
678 | 677 | ||
678 | mutex_lock(&info->port.mutex); | ||
679 | info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 679 | info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
680 | 680 | ||
681 | spin_lock_irqsave(&info->netlock, flags); | 681 | spin_lock_irqsave(&info->netlock, flags); |
682 | if (info->netcount) { | 682 | if (info->netcount) { |
683 | retval = -EBUSY; | 683 | retval = -EBUSY; |
684 | spin_unlock_irqrestore(&info->netlock, flags); | 684 | spin_unlock_irqrestore(&info->netlock, flags); |
685 | mutex_unlock(&info->port.mutex); | ||
685 | goto cleanup; | 686 | goto cleanup; |
686 | } | 687 | } |
687 | info->port.count++; | 688 | info->port.count++; |
@@ -693,7 +694,7 @@ static int open(struct tty_struct *tty, struct file *filp) | |||
693 | if (retval < 0) | 694 | if (retval < 0) |
694 | goto cleanup; | 695 | goto cleanup; |
695 | } | 696 | } |
696 | 697 | mutex_unlock(&info->port.mutex); | |
697 | retval = block_til_ready(tty, filp, info); | 698 | retval = block_til_ready(tty, filp, info); |
698 | if (retval) { | 699 | if (retval) { |
699 | DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); | 700 | DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); |
@@ -725,12 +726,14 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
725 | if (tty_port_close_start(&info->port, tty, filp) == 0) | 726 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
726 | goto cleanup; | 727 | goto cleanup; |
727 | 728 | ||
729 | mutex_lock(&info->port.mutex); | ||
728 | if (info->port.flags & ASYNC_INITIALIZED) | 730 | if (info->port.flags & ASYNC_INITIALIZED) |
729 | wait_until_sent(tty, info->timeout); | 731 | wait_until_sent(tty, info->timeout); |
730 | flush_buffer(tty); | 732 | flush_buffer(tty); |
731 | tty_ldisc_flush(tty); | 733 | tty_ldisc_flush(tty); |
732 | 734 | ||
733 | shutdown(info); | 735 | shutdown(info); |
736 | mutex_unlock(&info->port.mutex); | ||
734 | 737 | ||
735 | tty_port_close_end(&info->port, tty); | 738 | tty_port_close_end(&info->port, tty); |
736 | info->port.tty = NULL; | 739 | info->port.tty = NULL; |
@@ -741,17 +744,23 @@ cleanup: | |||
741 | static void hangup(struct tty_struct *tty) | 744 | static void hangup(struct tty_struct *tty) |
742 | { | 745 | { |
743 | struct slgt_info *info = tty->driver_data; | 746 | struct slgt_info *info = tty->driver_data; |
747 | unsigned long flags; | ||
744 | 748 | ||
745 | if (sanity_check(info, tty->name, "hangup")) | 749 | if (sanity_check(info, tty->name, "hangup")) |
746 | return; | 750 | return; |
747 | DBGINFO(("%s hangup\n", info->device_name)); | 751 | DBGINFO(("%s hangup\n", info->device_name)); |
748 | 752 | ||
749 | flush_buffer(tty); | 753 | flush_buffer(tty); |
754 | |||
755 | mutex_lock(&info->port.mutex); | ||
750 | shutdown(info); | 756 | shutdown(info); |
751 | 757 | ||
758 | spin_lock_irqsave(&info->port.lock, flags); | ||
752 | info->port.count = 0; | 759 | info->port.count = 0; |
753 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 760 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
754 | info->port.tty = NULL; | 761 | info->port.tty = NULL; |
762 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
763 | mutex_unlock(&info->port.mutex); | ||
755 | 764 | ||
756 | wake_up_interruptible(&info->port.open_wait); | 765 | wake_up_interruptible(&info->port.open_wait); |
757 | } | 766 | } |
@@ -901,8 +910,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
901 | * Note: use tight timings here to satisfy the NIST-PCTS. | 910 | * Note: use tight timings here to satisfy the NIST-PCTS. |
902 | */ | 911 | */ |
903 | 912 | ||
904 | lock_kernel(); | ||
905 | |||
906 | if (info->params.data_rate) { | 913 | if (info->params.data_rate) { |
907 | char_time = info->timeout/(32 * 5); | 914 | char_time = info->timeout/(32 * 5); |
908 | if (!char_time) | 915 | if (!char_time) |
@@ -920,8 +927,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
920 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | 927 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) |
921 | break; | 928 | break; |
922 | } | 929 | } |
923 | unlock_kernel(); | ||
924 | |||
925 | exit: | 930 | exit: |
926 | DBGINFO(("%s wait_until_sent exit\n", info->device_name)); | 931 | DBGINFO(("%s wait_until_sent exit\n", info->device_name)); |
927 | } | 932 | } |
@@ -1041,8 +1046,37 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1041 | return -EIO; | 1046 | return -EIO; |
1042 | } | 1047 | } |
1043 | 1048 | ||
1044 | lock_kernel(); | 1049 | switch (cmd) { |
1045 | 1050 | case MGSL_IOCWAITEVENT: | |
1051 | return wait_mgsl_event(info, argp); | ||
1052 | case TIOCMIWAIT: | ||
1053 | return modem_input_wait(info,(int)arg); | ||
1054 | case TIOCGICOUNT: | ||
1055 | spin_lock_irqsave(&info->lock,flags); | ||
1056 | cnow = info->icount; | ||
1057 | spin_unlock_irqrestore(&info->lock,flags); | ||
1058 | p_cuser = argp; | ||
1059 | if (put_user(cnow.cts, &p_cuser->cts) || | ||
1060 | put_user(cnow.dsr, &p_cuser->dsr) || | ||
1061 | put_user(cnow.rng, &p_cuser->rng) || | ||
1062 | put_user(cnow.dcd, &p_cuser->dcd) || | ||
1063 | put_user(cnow.rx, &p_cuser->rx) || | ||
1064 | put_user(cnow.tx, &p_cuser->tx) || | ||
1065 | put_user(cnow.frame, &p_cuser->frame) || | ||
1066 | put_user(cnow.overrun, &p_cuser->overrun) || | ||
1067 | put_user(cnow.parity, &p_cuser->parity) || | ||
1068 | put_user(cnow.brk, &p_cuser->brk) || | ||
1069 | put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | ||
1070 | return -EFAULT; | ||
1071 | return 0; | ||
1072 | case MGSL_IOCSGPIO: | ||
1073 | return set_gpio(info, argp); | ||
1074 | case MGSL_IOCGGPIO: | ||
1075 | return get_gpio(info, argp); | ||
1076 | case MGSL_IOCWAITGPIO: | ||
1077 | return wait_gpio(info, argp); | ||
1078 | } | ||
1079 | mutex_lock(&info->port.mutex); | ||
1046 | switch (cmd) { | 1080 | switch (cmd) { |
1047 | case MGSL_IOCGPARAMS: | 1081 | case MGSL_IOCGPARAMS: |
1048 | ret = get_params(info, argp); | 1082 | ret = get_params(info, argp); |
@@ -1068,50 +1102,16 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1068 | case MGSL_IOCGSTATS: | 1102 | case MGSL_IOCGSTATS: |
1069 | ret = get_stats(info, argp); | 1103 | ret = get_stats(info, argp); |
1070 | break; | 1104 | break; |
1071 | case MGSL_IOCWAITEVENT: | ||
1072 | ret = wait_mgsl_event(info, argp); | ||
1073 | break; | ||
1074 | case TIOCMIWAIT: | ||
1075 | ret = modem_input_wait(info,(int)arg); | ||
1076 | break; | ||
1077 | case MGSL_IOCGIF: | 1105 | case MGSL_IOCGIF: |
1078 | ret = get_interface(info, argp); | 1106 | ret = get_interface(info, argp); |
1079 | break; | 1107 | break; |
1080 | case MGSL_IOCSIF: | 1108 | case MGSL_IOCSIF: |
1081 | ret = set_interface(info,(int)arg); | 1109 | ret = set_interface(info,(int)arg); |
1082 | break; | 1110 | break; |
1083 | case MGSL_IOCSGPIO: | ||
1084 | ret = set_gpio(info, argp); | ||
1085 | break; | ||
1086 | case MGSL_IOCGGPIO: | ||
1087 | ret = get_gpio(info, argp); | ||
1088 | break; | ||
1089 | case MGSL_IOCWAITGPIO: | ||
1090 | ret = wait_gpio(info, argp); | ||
1091 | break; | ||
1092 | case TIOCGICOUNT: | ||
1093 | spin_lock_irqsave(&info->lock,flags); | ||
1094 | cnow = info->icount; | ||
1095 | spin_unlock_irqrestore(&info->lock,flags); | ||
1096 | p_cuser = argp; | ||
1097 | if (put_user(cnow.cts, &p_cuser->cts) || | ||
1098 | put_user(cnow.dsr, &p_cuser->dsr) || | ||
1099 | put_user(cnow.rng, &p_cuser->rng) || | ||
1100 | put_user(cnow.dcd, &p_cuser->dcd) || | ||
1101 | put_user(cnow.rx, &p_cuser->rx) || | ||
1102 | put_user(cnow.tx, &p_cuser->tx) || | ||
1103 | put_user(cnow.frame, &p_cuser->frame) || | ||
1104 | put_user(cnow.overrun, &p_cuser->overrun) || | ||
1105 | put_user(cnow.parity, &p_cuser->parity) || | ||
1106 | put_user(cnow.brk, &p_cuser->brk) || | ||
1107 | put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | ||
1108 | ret = -EFAULT; | ||
1109 | ret = 0; | ||
1110 | break; | ||
1111 | default: | 1111 | default: |
1112 | ret = -ENOIOCTLCMD; | 1112 | ret = -ENOIOCTLCMD; |
1113 | } | 1113 | } |
1114 | unlock_kernel(); | 1114 | mutex_unlock(&info->port.mutex); |
1115 | return ret; | 1115 | return ret; |
1116 | } | 1116 | } |
1117 | 1117 | ||
@@ -3244,7 +3244,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3244 | } | 3244 | } |
3245 | 3245 | ||
3246 | DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); | 3246 | DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); |
3247 | tty_unlock(); | ||
3247 | schedule(); | 3248 | schedule(); |
3249 | tty_lock(); | ||
3248 | } | 3250 | } |
3249 | 3251 | ||
3250 | set_current_state(TASK_RUNNING); | 3252 | set_current_state(TASK_RUNNING); |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 2b18adc4ee19..e56caf7d82aa 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
53 | #include <linux/seq_file.h> | 53 | #include <linux/seq_file.h> |
54 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
55 | #include <linux/smp_lock.h> | ||
56 | #include <linux/netdevice.h> | 55 | #include <linux/netdevice.h> |
57 | #include <linux/vmalloc.h> | 56 | #include <linux/vmalloc.h> |
58 | #include <linux/init.h> | 57 | #include <linux/init.h> |
@@ -813,13 +812,15 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
813 | 812 | ||
814 | if (tty_port_close_start(&info->port, tty, filp) == 0) | 813 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
815 | goto cleanup; | 814 | goto cleanup; |
816 | 815 | ||
816 | mutex_lock(&info->port.mutex); | ||
817 | if (info->port.flags & ASYNC_INITIALIZED) | 817 | if (info->port.flags & ASYNC_INITIALIZED) |
818 | wait_until_sent(tty, info->timeout); | 818 | wait_until_sent(tty, info->timeout); |
819 | 819 | ||
820 | flush_buffer(tty); | 820 | flush_buffer(tty); |
821 | tty_ldisc_flush(tty); | 821 | tty_ldisc_flush(tty); |
822 | shutdown(info); | 822 | shutdown(info); |
823 | mutex_unlock(&info->port.mutex); | ||
823 | 824 | ||
824 | tty_port_close_end(&info->port, tty); | 825 | tty_port_close_end(&info->port, tty); |
825 | info->port.tty = NULL; | 826 | info->port.tty = NULL; |
@@ -835,6 +836,7 @@ cleanup: | |||
835 | static void hangup(struct tty_struct *tty) | 836 | static void hangup(struct tty_struct *tty) |
836 | { | 837 | { |
837 | SLMP_INFO *info = tty->driver_data; | 838 | SLMP_INFO *info = tty->driver_data; |
839 | unsigned long flags; | ||
838 | 840 | ||
839 | if (debug_level >= DEBUG_LEVEL_INFO) | 841 | if (debug_level >= DEBUG_LEVEL_INFO) |
840 | printk("%s(%d):%s hangup()\n", | 842 | printk("%s(%d):%s hangup()\n", |
@@ -843,12 +845,16 @@ static void hangup(struct tty_struct *tty) | |||
843 | if (sanity_check(info, tty->name, "hangup")) | 845 | if (sanity_check(info, tty->name, "hangup")) |
844 | return; | 846 | return; |
845 | 847 | ||
848 | mutex_lock(&info->port.mutex); | ||
846 | flush_buffer(tty); | 849 | flush_buffer(tty); |
847 | shutdown(info); | 850 | shutdown(info); |
848 | 851 | ||
852 | spin_lock_irqsave(&info->port.lock, flags); | ||
849 | info->port.count = 0; | 853 | info->port.count = 0; |
850 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 854 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
851 | info->port.tty = NULL; | 855 | info->port.tty = NULL; |
856 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
857 | mutex_unlock(&info->port.mutex); | ||
852 | 858 | ||
853 | wake_up_interruptible(&info->port.open_wait); | 859 | wake_up_interruptible(&info->port.open_wait); |
854 | } | 860 | } |
@@ -1062,9 +1068,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
1062 | if (sanity_check(info, tty->name, "wait_until_sent")) | 1068 | if (sanity_check(info, tty->name, "wait_until_sent")) |
1063 | return; | 1069 | return; |
1064 | 1070 | ||
1065 | lock_kernel(); | 1071 | if (!test_bit(ASYNCB_INITIALIZED, &info->port.flags)) |
1066 | |||
1067 | if (!(info->port.flags & ASYNC_INITIALIZED)) | ||
1068 | goto exit; | 1072 | goto exit; |
1069 | 1073 | ||
1070 | orig_jiffies = jiffies; | 1074 | orig_jiffies = jiffies; |
@@ -1094,8 +1098,10 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
1094 | break; | 1098 | break; |
1095 | } | 1099 | } |
1096 | } else { | 1100 | } else { |
1097 | //TODO: determine if there is something similar to USC16C32 | 1101 | /* |
1098 | // TXSTATUS_ALL_SENT status | 1102 | * TODO: determine if there is something similar to USC16C32 |
1103 | * TXSTATUS_ALL_SENT status | ||
1104 | */ | ||
1099 | while ( info->tx_active && info->tx_enabled) { | 1105 | while ( info->tx_active && info->tx_enabled) { |
1100 | msleep_interruptible(jiffies_to_msecs(char_time)); | 1106 | msleep_interruptible(jiffies_to_msecs(char_time)); |
1101 | if (signal_pending(current)) | 1107 | if (signal_pending(current)) |
@@ -1106,7 +1112,6 @@ static void wait_until_sent(struct tty_struct *tty, int timeout) | |||
1106 | } | 1112 | } |
1107 | 1113 | ||
1108 | exit: | 1114 | exit: |
1109 | unlock_kernel(); | ||
1110 | if (debug_level >= DEBUG_LEVEL_INFO) | 1115 | if (debug_level >= DEBUG_LEVEL_INFO) |
1111 | printk("%s(%d):%s wait_until_sent() exit\n", | 1116 | printk("%s(%d):%s wait_until_sent() exit\n", |
1112 | __FILE__,__LINE__, info->device_name ); | 1117 | __FILE__,__LINE__, info->device_name ); |
@@ -1122,7 +1127,6 @@ static int write_room(struct tty_struct *tty) | |||
1122 | if (sanity_check(info, tty->name, "write_room")) | 1127 | if (sanity_check(info, tty->name, "write_room")) |
1123 | return 0; | 1128 | return 0; |
1124 | 1129 | ||
1125 | lock_kernel(); | ||
1126 | if (info->params.mode == MGSL_MODE_HDLC) { | 1130 | if (info->params.mode == MGSL_MODE_HDLC) { |
1127 | ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; | 1131 | ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; |
1128 | } else { | 1132 | } else { |
@@ -1130,7 +1134,6 @@ static int write_room(struct tty_struct *tty) | |||
1130 | if (ret < 0) | 1134 | if (ret < 0) |
1131 | ret = 0; | 1135 | ret = 0; |
1132 | } | 1136 | } |
1133 | unlock_kernel(); | ||
1134 | 1137 | ||
1135 | if (debug_level >= DEBUG_LEVEL_INFO) | 1138 | if (debug_level >= DEBUG_LEVEL_INFO) |
1136 | printk("%s(%d):%s write_room()=%d\n", | 1139 | printk("%s(%d):%s write_room()=%d\n", |
@@ -1251,7 +1254,7 @@ static void tx_release(struct tty_struct *tty) | |||
1251 | * | 1254 | * |
1252 | * Return Value: 0 if success, otherwise error code | 1255 | * Return Value: 0 if success, otherwise error code |
1253 | */ | 1256 | */ |
1254 | static int do_ioctl(struct tty_struct *tty, struct file *file, | 1257 | static int ioctl(struct tty_struct *tty, struct file *file, |
1255 | unsigned int cmd, unsigned long arg) | 1258 | unsigned int cmd, unsigned long arg) |
1256 | { | 1259 | { |
1257 | SLMP_INFO *info = tty->driver_data; | 1260 | SLMP_INFO *info = tty->driver_data; |
@@ -1341,16 +1344,6 @@ static int do_ioctl(struct tty_struct *tty, struct file *file, | |||
1341 | return 0; | 1344 | return 0; |
1342 | } | 1345 | } |
1343 | 1346 | ||
1344 | static int ioctl(struct tty_struct *tty, struct file *file, | ||
1345 | unsigned int cmd, unsigned long arg) | ||
1346 | { | ||
1347 | int ret; | ||
1348 | lock_kernel(); | ||
1349 | ret = do_ioctl(tty, file, cmd, arg); | ||
1350 | unlock_kernel(); | ||
1351 | return ret; | ||
1352 | } | ||
1353 | |||
1354 | /* | 1347 | /* |
1355 | * /proc fs routines.... | 1348 | * /proc fs routines.... |
1356 | */ | 1349 | */ |
@@ -2883,7 +2876,9 @@ static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount) | |||
2883 | if (!user_icount) { | 2876 | if (!user_icount) { |
2884 | memset(&info->icount, 0, sizeof(info->icount)); | 2877 | memset(&info->icount, 0, sizeof(info->icount)); |
2885 | } else { | 2878 | } else { |
2879 | mutex_lock(&info->port.mutex); | ||
2886 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); | 2880 | COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount)); |
2881 | mutex_unlock(&info->port.mutex); | ||
2887 | if (err) | 2882 | if (err) |
2888 | return -EFAULT; | 2883 | return -EFAULT; |
2889 | } | 2884 | } |
@@ -2898,7 +2893,9 @@ static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params) | |||
2898 | printk("%s(%d):%s get_params()\n", | 2893 | printk("%s(%d):%s get_params()\n", |
2899 | __FILE__,__LINE__, info->device_name); | 2894 | __FILE__,__LINE__, info->device_name); |
2900 | 2895 | ||
2896 | mutex_lock(&info->port.mutex); | ||
2901 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); | 2897 | COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS)); |
2898 | mutex_unlock(&info->port.mutex); | ||
2902 | if (err) { | 2899 | if (err) { |
2903 | if ( debug_level >= DEBUG_LEVEL_INFO ) | 2900 | if ( debug_level >= DEBUG_LEVEL_INFO ) |
2904 | printk( "%s(%d):%s get_params() user buffer copy failed\n", | 2901 | printk( "%s(%d):%s get_params() user buffer copy failed\n", |
@@ -2926,11 +2923,13 @@ static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params) | |||
2926 | return -EFAULT; | 2923 | return -EFAULT; |
2927 | } | 2924 | } |
2928 | 2925 | ||
2926 | mutex_lock(&info->port.mutex); | ||
2929 | spin_lock_irqsave(&info->lock,flags); | 2927 | spin_lock_irqsave(&info->lock,flags); |
2930 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); | 2928 | memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS)); |
2931 | spin_unlock_irqrestore(&info->lock,flags); | 2929 | spin_unlock_irqrestore(&info->lock,flags); |
2932 | 2930 | ||
2933 | change_params(info); | 2931 | change_params(info); |
2932 | mutex_unlock(&info->port.mutex); | ||
2934 | 2933 | ||
2935 | return 0; | 2934 | return 0; |
2936 | } | 2935 | } |
@@ -3366,7 +3365,9 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3366 | printk("%s(%d):%s block_til_ready() count=%d\n", | 3365 | printk("%s(%d):%s block_til_ready() count=%d\n", |
3367 | __FILE__,__LINE__, tty->driver->name, port->count ); | 3366 | __FILE__,__LINE__, tty->driver->name, port->count ); |
3368 | 3367 | ||
3368 | tty_unlock(); | ||
3369 | schedule(); | 3369 | schedule(); |
3370 | tty_lock(); | ||
3370 | } | 3371 | } |
3371 | 3372 | ||
3372 | set_current_state(TASK_RUNNING); | 3373 | set_current_state(TASK_RUNNING); |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 507441ac6edb..0350c42375a2 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -149,6 +149,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, | |||
149 | #else | 149 | #else |
150 | #define tty_compat_ioctl NULL | 150 | #define tty_compat_ioctl NULL |
151 | #endif | 151 | #endif |
152 | static int __tty_fasync(int fd, struct file *filp, int on); | ||
152 | static int tty_fasync(int fd, struct file *filp, int on); | 153 | static int tty_fasync(int fd, struct file *filp, int on); |
153 | static void release_tty(struct tty_struct *tty, int idx); | 154 | static void release_tty(struct tty_struct *tty, int idx); |
154 | static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); | 155 | static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); |
@@ -470,7 +471,7 @@ void tty_wakeup(struct tty_struct *tty) | |||
470 | EXPORT_SYMBOL_GPL(tty_wakeup); | 471 | EXPORT_SYMBOL_GPL(tty_wakeup); |
471 | 472 | ||
472 | /** | 473 | /** |
473 | * do_tty_hangup - actual handler for hangup events | 474 | * __tty_hangup - actual handler for hangup events |
474 | * @work: tty device | 475 | * @work: tty device |
475 | * | 476 | * |
476 | * This can be called by the "eventd" kernel thread. That is process | 477 | * This can be called by the "eventd" kernel thread. That is process |
@@ -483,7 +484,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup); | |||
483 | * remains intact. | 484 | * remains intact. |
484 | * | 485 | * |
485 | * Locking: | 486 | * Locking: |
486 | * BKL | 487 | * BTM |
487 | * redirect lock for undoing redirection | 488 | * redirect lock for undoing redirection |
488 | * file list lock for manipulating list of ttys | 489 | * file list lock for manipulating list of ttys |
489 | * tty_ldisc_lock from called functions | 490 | * tty_ldisc_lock from called functions |
@@ -491,10 +492,8 @@ EXPORT_SYMBOL_GPL(tty_wakeup); | |||
491 | * tasklist_lock to walk task list for hangup event | 492 | * tasklist_lock to walk task list for hangup event |
492 | * ->siglock to protect ->signal/->sighand | 493 | * ->siglock to protect ->signal/->sighand |
493 | */ | 494 | */ |
494 | static void do_tty_hangup(struct work_struct *work) | 495 | void __tty_hangup(struct tty_struct *tty) |
495 | { | 496 | { |
496 | struct tty_struct *tty = | ||
497 | container_of(work, struct tty_struct, hangup_work); | ||
498 | struct file *cons_filp = NULL; | 497 | struct file *cons_filp = NULL; |
499 | struct file *filp, *f = NULL; | 498 | struct file *filp, *f = NULL; |
500 | struct task_struct *p; | 499 | struct task_struct *p; |
@@ -513,9 +512,12 @@ static void do_tty_hangup(struct work_struct *work) | |||
513 | } | 512 | } |
514 | spin_unlock(&redirect_lock); | 513 | spin_unlock(&redirect_lock); |
515 | 514 | ||
516 | /* inuse_filps is protected by the single kernel lock */ | 515 | tty_lock(); |
517 | lock_kernel(); | 516 | |
518 | check_tty_count(tty, "do_tty_hangup"); | 517 | /* inuse_filps is protected by the single tty lock, |
518 | this really needs to change if we want to flush the | ||
519 | workqueue with the lock held */ | ||
520 | check_tty_count(tty, "tty_hangup"); | ||
519 | 521 | ||
520 | file_list_lock(); | 522 | file_list_lock(); |
521 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ | 523 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ |
@@ -525,7 +527,7 @@ static void do_tty_hangup(struct work_struct *work) | |||
525 | if (filp->f_op->write != tty_write) | 527 | if (filp->f_op->write != tty_write) |
526 | continue; | 528 | continue; |
527 | closecount++; | 529 | closecount++; |
528 | tty_fasync(-1, filp, 0); /* can't block */ | 530 | __tty_fasync(-1, filp, 0); /* can't block */ |
529 | filp->f_op = &hung_up_tty_fops; | 531 | filp->f_op = &hung_up_tty_fops; |
530 | } | 532 | } |
531 | file_list_unlock(); | 533 | file_list_unlock(); |
@@ -594,11 +596,21 @@ static void do_tty_hangup(struct work_struct *work) | |||
594 | */ | 596 | */ |
595 | set_bit(TTY_HUPPED, &tty->flags); | 597 | set_bit(TTY_HUPPED, &tty->flags); |
596 | tty_ldisc_enable(tty); | 598 | tty_ldisc_enable(tty); |
597 | unlock_kernel(); | 599 | |
600 | tty_unlock(); | ||
601 | |||
598 | if (f) | 602 | if (f) |
599 | fput(f); | 603 | fput(f); |
600 | } | 604 | } |
601 | 605 | ||
606 | static void do_tty_hangup(struct work_struct *work) | ||
607 | { | ||
608 | struct tty_struct *tty = | ||
609 | container_of(work, struct tty_struct, hangup_work); | ||
610 | |||
611 | __tty_hangup(tty); | ||
612 | } | ||
613 | |||
602 | /** | 614 | /** |
603 | * tty_hangup - trigger a hangup event | 615 | * tty_hangup - trigger a hangup event |
604 | * @tty: tty to hangup | 616 | * @tty: tty to hangup |
@@ -634,11 +646,12 @@ void tty_vhangup(struct tty_struct *tty) | |||
634 | 646 | ||
635 | printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); | 647 | printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); |
636 | #endif | 648 | #endif |
637 | do_tty_hangup(&tty->hangup_work); | 649 | __tty_hangup(tty); |
638 | } | 650 | } |
639 | 651 | ||
640 | EXPORT_SYMBOL(tty_vhangup); | 652 | EXPORT_SYMBOL(tty_vhangup); |
641 | 653 | ||
654 | |||
642 | /** | 655 | /** |
643 | * tty_vhangup_self - process vhangup for own ctty | 656 | * tty_vhangup_self - process vhangup for own ctty |
644 | * | 657 | * |
@@ -696,7 +709,8 @@ static void session_clear_tty(struct pid *session) | |||
696 | * exiting; it is 0 if called by the ioctl TIOCNOTTY. | 709 | * exiting; it is 0 if called by the ioctl TIOCNOTTY. |
697 | * | 710 | * |
698 | * Locking: | 711 | * Locking: |
699 | * BKL is taken for hysterical raisins | 712 | * BTM is taken for hysterical raisins, and held when |
713 | * called from no_tty(). | ||
700 | * tty_mutex is taken to protect tty | 714 | * tty_mutex is taken to protect tty |
701 | * ->siglock is taken to protect ->signal/->sighand | 715 | * ->siglock is taken to protect ->signal/->sighand |
702 | * tasklist_lock is taken to walk process list for sessions | 716 | * tasklist_lock is taken to walk process list for sessions |
@@ -714,10 +728,10 @@ void disassociate_ctty(int on_exit) | |||
714 | tty = get_current_tty(); | 728 | tty = get_current_tty(); |
715 | if (tty) { | 729 | if (tty) { |
716 | tty_pgrp = get_pid(tty->pgrp); | 730 | tty_pgrp = get_pid(tty->pgrp); |
717 | lock_kernel(); | 731 | if (on_exit) { |
718 | if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) | 732 | if (tty->driver->type != TTY_DRIVER_TYPE_PTY) |
719 | tty_vhangup(tty); | 733 | tty_vhangup(tty); |
720 | unlock_kernel(); | 734 | } |
721 | tty_kref_put(tty); | 735 | tty_kref_put(tty); |
722 | } else if (on_exit) { | 736 | } else if (on_exit) { |
723 | struct pid *old_pgrp; | 737 | struct pid *old_pgrp; |
@@ -774,9 +788,9 @@ void disassociate_ctty(int on_exit) | |||
774 | void no_tty(void) | 788 | void no_tty(void) |
775 | { | 789 | { |
776 | struct task_struct *tsk = current; | 790 | struct task_struct *tsk = current; |
777 | lock_kernel(); | 791 | tty_lock(); |
778 | disassociate_ctty(0); | 792 | disassociate_ctty(0); |
779 | unlock_kernel(); | 793 | tty_unlock(); |
780 | proc_clear_tty(tsk); | 794 | proc_clear_tty(tsk); |
781 | } | 795 | } |
782 | 796 | ||
@@ -879,7 +893,7 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, | |||
879 | struct inode *inode; | 893 | struct inode *inode; |
880 | struct tty_ldisc *ld; | 894 | struct tty_ldisc *ld; |
881 | 895 | ||
882 | tty = (struct tty_struct *)file->private_data; | 896 | tty = file->private_data; |
883 | inode = file->f_path.dentry->d_inode; | 897 | inode = file->f_path.dentry->d_inode; |
884 | if (tty_paranoia_check(tty, inode, "tty_read")) | 898 | if (tty_paranoia_check(tty, inode, "tty_read")) |
885 | return -EIO; | 899 | return -EIO; |
@@ -1013,19 +1027,19 @@ out: | |||
1013 | * We don't put it into the syslog queue right now maybe in the future if | 1027 | * We don't put it into the syslog queue right now maybe in the future if |
1014 | * really needed. | 1028 | * really needed. |
1015 | * | 1029 | * |
1016 | * We must still hold the BKL and test the CLOSING flag for the moment. | 1030 | * We must still hold the BTM and test the CLOSING flag for the moment. |
1017 | */ | 1031 | */ |
1018 | 1032 | ||
1019 | void tty_write_message(struct tty_struct *tty, char *msg) | 1033 | void tty_write_message(struct tty_struct *tty, char *msg) |
1020 | { | 1034 | { |
1021 | if (tty) { | 1035 | if (tty) { |
1022 | mutex_lock(&tty->atomic_write_lock); | 1036 | mutex_lock(&tty->atomic_write_lock); |
1023 | lock_kernel(); | 1037 | tty_lock(); |
1024 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { | 1038 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { |
1025 | unlock_kernel(); | 1039 | tty_unlock(); |
1026 | tty->ops->write(tty, msg, strlen(msg)); | 1040 | tty->ops->write(tty, msg, strlen(msg)); |
1027 | } else | 1041 | } else |
1028 | unlock_kernel(); | 1042 | tty_unlock(); |
1029 | tty_write_unlock(tty); | 1043 | tty_write_unlock(tty); |
1030 | } | 1044 | } |
1031 | return; | 1045 | return; |
@@ -1056,7 +1070,7 @@ static ssize_t tty_write(struct file *file, const char __user *buf, | |||
1056 | ssize_t ret; | 1070 | ssize_t ret; |
1057 | struct tty_ldisc *ld; | 1071 | struct tty_ldisc *ld; |
1058 | 1072 | ||
1059 | tty = (struct tty_struct *)file->private_data; | 1073 | tty = file->private_data; |
1060 | if (tty_paranoia_check(tty, inode, "tty_write")) | 1074 | if (tty_paranoia_check(tty, inode, "tty_write")) |
1061 | return -EIO; | 1075 | return -EIO; |
1062 | if (!tty || !tty->ops->write || | 1076 | if (!tty || !tty->ops->write || |
@@ -1208,18 +1222,14 @@ static int tty_driver_install_tty(struct tty_driver *driver, | |||
1208 | int ret; | 1222 | int ret; |
1209 | 1223 | ||
1210 | if (driver->ops->install) { | 1224 | if (driver->ops->install) { |
1211 | lock_kernel(); | ||
1212 | ret = driver->ops->install(driver, tty); | 1225 | ret = driver->ops->install(driver, tty); |
1213 | unlock_kernel(); | ||
1214 | return ret; | 1226 | return ret; |
1215 | } | 1227 | } |
1216 | 1228 | ||
1217 | if (tty_init_termios(tty) == 0) { | 1229 | if (tty_init_termios(tty) == 0) { |
1218 | lock_kernel(); | ||
1219 | tty_driver_kref_get(driver); | 1230 | tty_driver_kref_get(driver); |
1220 | tty->count++; | 1231 | tty->count++; |
1221 | driver->ttys[idx] = tty; | 1232 | driver->ttys[idx] = tty; |
1222 | unlock_kernel(); | ||
1223 | return 0; | 1233 | return 0; |
1224 | } | 1234 | } |
1225 | return -ENOMEM; | 1235 | return -ENOMEM; |
@@ -1312,14 +1322,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
1312 | struct tty_struct *tty; | 1322 | struct tty_struct *tty; |
1313 | int retval; | 1323 | int retval; |
1314 | 1324 | ||
1315 | lock_kernel(); | ||
1316 | /* Check if pty master is being opened multiple times */ | 1325 | /* Check if pty master is being opened multiple times */ |
1317 | if (driver->subtype == PTY_TYPE_MASTER && | 1326 | if (driver->subtype == PTY_TYPE_MASTER && |
1318 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { | 1327 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { |
1319 | unlock_kernel(); | ||
1320 | return ERR_PTR(-EIO); | 1328 | return ERR_PTR(-EIO); |
1321 | } | 1329 | } |
1322 | unlock_kernel(); | ||
1323 | 1330 | ||
1324 | /* | 1331 | /* |
1325 | * First time open is complex, especially for PTY devices. | 1332 | * First time open is complex, especially for PTY devices. |
@@ -1363,9 +1370,7 @@ release_mem_out: | |||
1363 | if (printk_ratelimit()) | 1370 | if (printk_ratelimit()) |
1364 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " | 1371 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " |
1365 | "clearing slot %d\n", idx); | 1372 | "clearing slot %d\n", idx); |
1366 | lock_kernel(); | ||
1367 | release_tty(tty, idx); | 1373 | release_tty(tty, idx); |
1368 | unlock_kernel(); | ||
1369 | return ERR_PTR(retval); | 1374 | return ERR_PTR(retval); |
1370 | } | 1375 | } |
1371 | 1376 | ||
@@ -1508,14 +1513,14 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1508 | int idx; | 1513 | int idx; |
1509 | char buf[64]; | 1514 | char buf[64]; |
1510 | 1515 | ||
1511 | tty = (struct tty_struct *)filp->private_data; | 1516 | tty = filp->private_data; |
1512 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) | 1517 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) |
1513 | return 0; | 1518 | return 0; |
1514 | 1519 | ||
1515 | lock_kernel(); | 1520 | tty_lock(); |
1516 | check_tty_count(tty, "tty_release_dev"); | 1521 | check_tty_count(tty, "tty_release_dev"); |
1517 | 1522 | ||
1518 | tty_fasync(-1, filp, 0); | 1523 | __tty_fasync(-1, filp, 0); |
1519 | 1524 | ||
1520 | idx = tty->index; | 1525 | idx = tty->index; |
1521 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1526 | pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
@@ -1527,18 +1532,18 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1527 | if (idx < 0 || idx >= tty->driver->num) { | 1532 | if (idx < 0 || idx >= tty->driver->num) { |
1528 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " | 1533 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " |
1529 | "free (%s)\n", tty->name); | 1534 | "free (%s)\n", tty->name); |
1530 | unlock_kernel(); | 1535 | tty_unlock(); |
1531 | return 0; | 1536 | return 0; |
1532 | } | 1537 | } |
1533 | if (!devpts) { | 1538 | if (!devpts) { |
1534 | if (tty != tty->driver->ttys[idx]) { | 1539 | if (tty != tty->driver->ttys[idx]) { |
1535 | unlock_kernel(); | 1540 | tty_unlock(); |
1536 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " | 1541 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " |
1537 | "for (%s)\n", idx, tty->name); | 1542 | "for (%s)\n", idx, tty->name); |
1538 | return 0; | 1543 | return 0; |
1539 | } | 1544 | } |
1540 | if (tty->termios != tty->driver->termios[idx]) { | 1545 | if (tty->termios != tty->driver->termios[idx]) { |
1541 | unlock_kernel(); | 1546 | tty_unlock(); |
1542 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " | 1547 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " |
1543 | "for (%s)\n", | 1548 | "for (%s)\n", |
1544 | idx, tty->name); | 1549 | idx, tty->name); |
@@ -1556,21 +1561,21 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1556 | if (tty->driver->other && | 1561 | if (tty->driver->other && |
1557 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | 1562 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { |
1558 | if (o_tty != tty->driver->other->ttys[idx]) { | 1563 | if (o_tty != tty->driver->other->ttys[idx]) { |
1559 | unlock_kernel(); | 1564 | tty_unlock(); |
1560 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " | 1565 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " |
1561 | "not o_tty for (%s)\n", | 1566 | "not o_tty for (%s)\n", |
1562 | idx, tty->name); | 1567 | idx, tty->name); |
1563 | return 0 ; | 1568 | return 0 ; |
1564 | } | 1569 | } |
1565 | if (o_tty->termios != tty->driver->other->termios[idx]) { | 1570 | if (o_tty->termios != tty->driver->other->termios[idx]) { |
1566 | unlock_kernel(); | 1571 | tty_unlock(); |
1567 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " | 1572 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " |
1568 | "not o_termios for (%s)\n", | 1573 | "not o_termios for (%s)\n", |
1569 | idx, tty->name); | 1574 | idx, tty->name); |
1570 | return 0; | 1575 | return 0; |
1571 | } | 1576 | } |
1572 | if (o_tty->link != tty) { | 1577 | if (o_tty->link != tty) { |
1573 | unlock_kernel(); | 1578 | tty_unlock(); |
1574 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); | 1579 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); |
1575 | return 0; | 1580 | return 0; |
1576 | } | 1581 | } |
@@ -1579,7 +1584,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1579 | if (tty->ops->close) | 1584 | if (tty->ops->close) |
1580 | tty->ops->close(tty, filp); | 1585 | tty->ops->close(tty, filp); |
1581 | 1586 | ||
1582 | unlock_kernel(); | 1587 | tty_unlock(); |
1583 | /* | 1588 | /* |
1584 | * Sanity check: if tty->count is going to zero, there shouldn't be | 1589 | * Sanity check: if tty->count is going to zero, there shouldn't be |
1585 | * any waiters on tty->read_wait or tty->write_wait. We test the | 1590 | * any waiters on tty->read_wait or tty->write_wait. We test the |
@@ -1602,7 +1607,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1602 | opens on /dev/tty */ | 1607 | opens on /dev/tty */ |
1603 | 1608 | ||
1604 | mutex_lock(&tty_mutex); | 1609 | mutex_lock(&tty_mutex); |
1605 | lock_kernel(); | 1610 | tty_lock(); |
1606 | tty_closing = tty->count <= 1; | 1611 | tty_closing = tty->count <= 1; |
1607 | o_tty_closing = o_tty && | 1612 | o_tty_closing = o_tty && |
1608 | (o_tty->count <= (pty_master ? 1 : 0)); | 1613 | (o_tty->count <= (pty_master ? 1 : 0)); |
@@ -1633,7 +1638,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1633 | 1638 | ||
1634 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " | 1639 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " |
1635 | "active!\n", tty_name(tty, buf)); | 1640 | "active!\n", tty_name(tty, buf)); |
1636 | unlock_kernel(); | 1641 | tty_unlock(); |
1637 | mutex_unlock(&tty_mutex); | 1642 | mutex_unlock(&tty_mutex); |
1638 | schedule(); | 1643 | schedule(); |
1639 | } | 1644 | } |
@@ -1698,7 +1703,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1698 | 1703 | ||
1699 | /* check whether both sides are closing ... */ | 1704 | /* check whether both sides are closing ... */ |
1700 | if (!tty_closing || (o_tty && !o_tty_closing)) { | 1705 | if (!tty_closing || (o_tty && !o_tty_closing)) { |
1701 | unlock_kernel(); | 1706 | tty_unlock(); |
1702 | return 0; | 1707 | return 0; |
1703 | } | 1708 | } |
1704 | 1709 | ||
@@ -1718,7 +1723,7 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1718 | /* Make this pty number available for reallocation */ | 1723 | /* Make this pty number available for reallocation */ |
1719 | if (devpts) | 1724 | if (devpts) |
1720 | devpts_kill_index(inode, idx); | 1725 | devpts_kill_index(inode, idx); |
1721 | unlock_kernel(); | 1726 | tty_unlock(); |
1722 | return 0; | 1727 | return 0; |
1723 | } | 1728 | } |
1724 | 1729 | ||
@@ -1760,12 +1765,12 @@ retry_open: | |||
1760 | retval = 0; | 1765 | retval = 0; |
1761 | 1766 | ||
1762 | mutex_lock(&tty_mutex); | 1767 | mutex_lock(&tty_mutex); |
1763 | lock_kernel(); | 1768 | tty_lock(); |
1764 | 1769 | ||
1765 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { | 1770 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { |
1766 | tty = get_current_tty(); | 1771 | tty = get_current_tty(); |
1767 | if (!tty) { | 1772 | if (!tty) { |
1768 | unlock_kernel(); | 1773 | tty_unlock(); |
1769 | mutex_unlock(&tty_mutex); | 1774 | mutex_unlock(&tty_mutex); |
1770 | return -ENXIO; | 1775 | return -ENXIO; |
1771 | } | 1776 | } |
@@ -1797,14 +1802,14 @@ retry_open: | |||
1797 | goto got_driver; | 1802 | goto got_driver; |
1798 | } | 1803 | } |
1799 | } | 1804 | } |
1800 | unlock_kernel(); | 1805 | tty_unlock(); |
1801 | mutex_unlock(&tty_mutex); | 1806 | mutex_unlock(&tty_mutex); |
1802 | return -ENODEV; | 1807 | return -ENODEV; |
1803 | } | 1808 | } |
1804 | 1809 | ||
1805 | driver = get_tty_driver(device, &index); | 1810 | driver = get_tty_driver(device, &index); |
1806 | if (!driver) { | 1811 | if (!driver) { |
1807 | unlock_kernel(); | 1812 | tty_unlock(); |
1808 | mutex_unlock(&tty_mutex); | 1813 | mutex_unlock(&tty_mutex); |
1809 | return -ENODEV; | 1814 | return -ENODEV; |
1810 | } | 1815 | } |
@@ -1814,7 +1819,7 @@ got_driver: | |||
1814 | tty = tty_driver_lookup_tty(driver, inode, index); | 1819 | tty = tty_driver_lookup_tty(driver, inode, index); |
1815 | 1820 | ||
1816 | if (IS_ERR(tty)) { | 1821 | if (IS_ERR(tty)) { |
1817 | unlock_kernel(); | 1822 | tty_unlock(); |
1818 | mutex_unlock(&tty_mutex); | 1823 | mutex_unlock(&tty_mutex); |
1819 | return PTR_ERR(tty); | 1824 | return PTR_ERR(tty); |
1820 | } | 1825 | } |
@@ -1830,7 +1835,7 @@ got_driver: | |||
1830 | mutex_unlock(&tty_mutex); | 1835 | mutex_unlock(&tty_mutex); |
1831 | tty_driver_kref_put(driver); | 1836 | tty_driver_kref_put(driver); |
1832 | if (IS_ERR(tty)) { | 1837 | if (IS_ERR(tty)) { |
1833 | unlock_kernel(); | 1838 | tty_unlock(); |
1834 | return PTR_ERR(tty); | 1839 | return PTR_ERR(tty); |
1835 | } | 1840 | } |
1836 | 1841 | ||
@@ -1860,29 +1865,29 @@ got_driver: | |||
1860 | printk(KERN_DEBUG "error %d in opening %s...", retval, | 1865 | printk(KERN_DEBUG "error %d in opening %s...", retval, |
1861 | tty->name); | 1866 | tty->name); |
1862 | #endif | 1867 | #endif |
1868 | tty_unlock(); /* need to call tty_release without BTM */ | ||
1863 | tty_release(inode, filp); | 1869 | tty_release(inode, filp); |
1864 | if (retval != -ERESTARTSYS) { | 1870 | if (retval != -ERESTARTSYS) |
1865 | unlock_kernel(); | ||
1866 | return retval; | 1871 | return retval; |
1867 | } | 1872 | |
1868 | if (signal_pending(current)) { | 1873 | if (signal_pending(current)) |
1869 | unlock_kernel(); | ||
1870 | return retval; | 1874 | return retval; |
1871 | } | 1875 | |
1872 | schedule(); | 1876 | schedule(); |
1873 | /* | 1877 | /* |
1874 | * Need to reset f_op in case a hangup happened. | 1878 | * Need to reset f_op in case a hangup happened. |
1875 | */ | 1879 | */ |
1880 | tty_lock(); | ||
1876 | if (filp->f_op == &hung_up_tty_fops) | 1881 | if (filp->f_op == &hung_up_tty_fops) |
1877 | filp->f_op = &tty_fops; | 1882 | filp->f_op = &tty_fops; |
1878 | unlock_kernel(); | 1883 | tty_unlock(); |
1879 | goto retry_open; | 1884 | goto retry_open; |
1880 | } | 1885 | } |
1881 | unlock_kernel(); | 1886 | tty_unlock(); |
1882 | 1887 | ||
1883 | 1888 | ||
1884 | mutex_lock(&tty_mutex); | 1889 | mutex_lock(&tty_mutex); |
1885 | lock_kernel(); | 1890 | tty_lock(); |
1886 | spin_lock_irq(¤t->sighand->siglock); | 1891 | spin_lock_irq(¤t->sighand->siglock); |
1887 | if (!noctty && | 1892 | if (!noctty && |
1888 | current->signal->leader && | 1893 | current->signal->leader && |
@@ -1890,7 +1895,7 @@ got_driver: | |||
1890 | tty->session == NULL) | 1895 | tty->session == NULL) |
1891 | __proc_set_tty(current, tty); | 1896 | __proc_set_tty(current, tty); |
1892 | spin_unlock_irq(¤t->sighand->siglock); | 1897 | spin_unlock_irq(¤t->sighand->siglock); |
1893 | unlock_kernel(); | 1898 | tty_unlock(); |
1894 | mutex_unlock(&tty_mutex); | 1899 | mutex_unlock(&tty_mutex); |
1895 | return 0; | 1900 | return 0; |
1896 | } | 1901 | } |
@@ -1915,7 +1920,7 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) | |||
1915 | struct tty_ldisc *ld; | 1920 | struct tty_ldisc *ld; |
1916 | int ret = 0; | 1921 | int ret = 0; |
1917 | 1922 | ||
1918 | tty = (struct tty_struct *)filp->private_data; | 1923 | tty = filp->private_data; |
1919 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) | 1924 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) |
1920 | return 0; | 1925 | return 0; |
1921 | 1926 | ||
@@ -1926,14 +1931,13 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) | |||
1926 | return ret; | 1931 | return ret; |
1927 | } | 1932 | } |
1928 | 1933 | ||
1929 | static int tty_fasync(int fd, struct file *filp, int on) | 1934 | static int __tty_fasync(int fd, struct file *filp, int on) |
1930 | { | 1935 | { |
1931 | struct tty_struct *tty; | 1936 | struct tty_struct *tty; |
1932 | unsigned long flags; | 1937 | unsigned long flags; |
1933 | int retval = 0; | 1938 | int retval = 0; |
1934 | 1939 | ||
1935 | lock_kernel(); | 1940 | tty = filp->private_data; |
1936 | tty = (struct tty_struct *)filp->private_data; | ||
1937 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) | 1941 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) |
1938 | goto out; | 1942 | goto out; |
1939 | 1943 | ||
@@ -1966,7 +1970,15 @@ static int tty_fasync(int fd, struct file *filp, int on) | |||
1966 | } | 1970 | } |
1967 | retval = 0; | 1971 | retval = 0; |
1968 | out: | 1972 | out: |
1969 | unlock_kernel(); | 1973 | return retval; |
1974 | } | ||
1975 | |||
1976 | static int tty_fasync(int fd, struct file *filp, int on) | ||
1977 | { | ||
1978 | int retval; | ||
1979 | tty_lock(); | ||
1980 | retval = __tty_fasync(fd, filp, on); | ||
1981 | tty_unlock(); | ||
1970 | return retval; | 1982 | return retval; |
1971 | } | 1983 | } |
1972 | 1984 | ||
@@ -2485,7 +2497,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2485 | struct tty_ldisc *ld; | 2497 | struct tty_ldisc *ld; |
2486 | struct inode *inode = file->f_dentry->d_inode; | 2498 | struct inode *inode = file->f_dentry->d_inode; |
2487 | 2499 | ||
2488 | tty = (struct tty_struct *)file->private_data; | 2500 | tty = file->private_data; |
2489 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) | 2501 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) |
2490 | return -EINVAL; | 2502 | return -EINVAL; |
2491 | 2503 | ||
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 6bd5f8866c74..0c1889971459 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -517,19 +517,25 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) | |||
517 | 517 | ||
518 | /* See if packet mode change of state. */ | 518 | /* See if packet mode change of state. */ |
519 | if (tty->link && tty->link->packet) { | 519 | if (tty->link && tty->link->packet) { |
520 | int extproc = (old_termios.c_lflag & EXTPROC) | | ||
521 | (tty->termios->c_lflag & EXTPROC); | ||
520 | int old_flow = ((old_termios.c_iflag & IXON) && | 522 | int old_flow = ((old_termios.c_iflag & IXON) && |
521 | (old_termios.c_cc[VSTOP] == '\023') && | 523 | (old_termios.c_cc[VSTOP] == '\023') && |
522 | (old_termios.c_cc[VSTART] == '\021')); | 524 | (old_termios.c_cc[VSTART] == '\021')); |
523 | int new_flow = (I_IXON(tty) && | 525 | int new_flow = (I_IXON(tty) && |
524 | STOP_CHAR(tty) == '\023' && | 526 | STOP_CHAR(tty) == '\023' && |
525 | START_CHAR(tty) == '\021'); | 527 | START_CHAR(tty) == '\021'); |
526 | if (old_flow != new_flow) { | 528 | if ((old_flow != new_flow) || extproc) { |
527 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 529 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
528 | tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); | 530 | if (old_flow != new_flow) { |
529 | if (new_flow) | 531 | tty->ctrl_status &= ~(TIOCPKT_DOSTOP | TIOCPKT_NOSTOP); |
530 | tty->ctrl_status |= TIOCPKT_DOSTOP; | 532 | if (new_flow) |
531 | else | 533 | tty->ctrl_status |= TIOCPKT_DOSTOP; |
532 | tty->ctrl_status |= TIOCPKT_NOSTOP; | 534 | else |
535 | tty->ctrl_status |= TIOCPKT_NOSTOP; | ||
536 | } | ||
537 | if (extproc) | ||
538 | tty->ctrl_status |= TIOCPKT_IOCTL; | ||
533 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 539 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
534 | wake_up_interruptible(&tty->link->read_wait); | 540 | wake_up_interruptible(&tty->link->read_wait); |
535 | } | 541 | } |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 500e740ec5e4..412f9775d19c 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -440,6 +440,8 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
440 | * | 440 | * |
441 | * A helper opening method. Also a convenient debugging and check | 441 | * A helper opening method. Also a convenient debugging and check |
442 | * point. | 442 | * point. |
443 | * | ||
444 | * Locking: always called with BTM already held. | ||
443 | */ | 445 | */ |
444 | 446 | ||
445 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | 447 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) |
@@ -447,10 +449,9 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | |||
447 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); | 449 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); |
448 | if (ld->ops->open) { | 450 | if (ld->ops->open) { |
449 | int ret; | 451 | int ret; |
450 | /* BKL here locks verus a hangup event */ | 452 | /* BTM here locks versus a hangup event */ |
451 | lock_kernel(); | 453 | WARN_ON(!tty_locked()); |
452 | ret = ld->ops->open(tty); | 454 | ret = ld->ops->open(tty); |
453 | unlock_kernel(); | ||
454 | return ret; | 455 | return ret; |
455 | } | 456 | } |
456 | return 0; | 457 | return 0; |
@@ -553,7 +554,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
553 | if (IS_ERR(new_ldisc)) | 554 | if (IS_ERR(new_ldisc)) |
554 | return PTR_ERR(new_ldisc); | 555 | return PTR_ERR(new_ldisc); |
555 | 556 | ||
556 | lock_kernel(); | 557 | tty_lock(); |
557 | /* | 558 | /* |
558 | * We need to look at the tty locking here for pty/tty pairs | 559 | * We need to look at the tty locking here for pty/tty pairs |
559 | * when both sides try to change in parallel. | 560 | * when both sides try to change in parallel. |
@@ -567,12 +568,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
567 | */ | 568 | */ |
568 | 569 | ||
569 | if (tty->ldisc->ops->num == ldisc) { | 570 | if (tty->ldisc->ops->num == ldisc) { |
570 | unlock_kernel(); | 571 | tty_unlock(); |
571 | tty_ldisc_put(new_ldisc); | 572 | tty_ldisc_put(new_ldisc); |
572 | return 0; | 573 | return 0; |
573 | } | 574 | } |
574 | 575 | ||
575 | unlock_kernel(); | 576 | tty_unlock(); |
576 | /* | 577 | /* |
577 | * Problem: What do we do if this blocks ? | 578 | * Problem: What do we do if this blocks ? |
578 | * We could deadlock here | 579 | * We could deadlock here |
@@ -580,6 +581,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
580 | 581 | ||
581 | tty_wait_until_sent(tty, 0); | 582 | tty_wait_until_sent(tty, 0); |
582 | 583 | ||
584 | tty_lock(); | ||
583 | mutex_lock(&tty->ldisc_mutex); | 585 | mutex_lock(&tty->ldisc_mutex); |
584 | 586 | ||
585 | /* | 587 | /* |
@@ -589,13 +591,13 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
589 | 591 | ||
590 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | 592 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { |
591 | mutex_unlock(&tty->ldisc_mutex); | 593 | mutex_unlock(&tty->ldisc_mutex); |
594 | tty_unlock(); | ||
592 | wait_event(tty_ldisc_wait, | 595 | wait_event(tty_ldisc_wait, |
593 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | 596 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); |
597 | tty_lock(); | ||
594 | mutex_lock(&tty->ldisc_mutex); | 598 | mutex_lock(&tty->ldisc_mutex); |
595 | } | 599 | } |
596 | 600 | ||
597 | lock_kernel(); | ||
598 | |||
599 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | 601 | set_bit(TTY_LDISC_CHANGING, &tty->flags); |
600 | 602 | ||
601 | /* | 603 | /* |
@@ -607,7 +609,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
607 | 609 | ||
608 | o_ldisc = tty->ldisc; | 610 | o_ldisc = tty->ldisc; |
609 | 611 | ||
610 | unlock_kernel(); | 612 | tty_unlock(); |
611 | /* | 613 | /* |
612 | * Make sure we don't change while someone holds a | 614 | * Make sure we don't change while someone holds a |
613 | * reference to the line discipline. The TTY_LDISC bit | 615 | * reference to the line discipline. The TTY_LDISC bit |
@@ -632,15 +634,15 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
632 | 634 | ||
633 | flush_scheduled_work(); | 635 | flush_scheduled_work(); |
634 | 636 | ||
637 | tty_lock(); | ||
635 | mutex_lock(&tty->ldisc_mutex); | 638 | mutex_lock(&tty->ldisc_mutex); |
636 | lock_kernel(); | ||
637 | if (test_bit(TTY_HUPPED, &tty->flags)) { | 639 | if (test_bit(TTY_HUPPED, &tty->flags)) { |
638 | /* We were raced by the hangup method. It will have stomped | 640 | /* We were raced by the hangup method. It will have stomped |
639 | the ldisc data and closed the ldisc down */ | 641 | the ldisc data and closed the ldisc down */ |
640 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 642 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); |
641 | mutex_unlock(&tty->ldisc_mutex); | 643 | mutex_unlock(&tty->ldisc_mutex); |
642 | tty_ldisc_put(new_ldisc); | 644 | tty_ldisc_put(new_ldisc); |
643 | unlock_kernel(); | 645 | tty_unlock(); |
644 | return -EIO; | 646 | return -EIO; |
645 | } | 647 | } |
646 | 648 | ||
@@ -682,7 +684,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
682 | if (o_work) | 684 | if (o_work) |
683 | schedule_delayed_work(&o_tty->buf.work, 1); | 685 | schedule_delayed_work(&o_tty->buf.work, 1); |
684 | mutex_unlock(&tty->ldisc_mutex); | 686 | mutex_unlock(&tty->ldisc_mutex); |
685 | unlock_kernel(); | 687 | tty_unlock(); |
686 | return retval; | 688 | return retval; |
687 | } | 689 | } |
688 | 690 | ||
@@ -780,7 +782,20 @@ void tty_ldisc_hangup(struct tty_struct *tty) | |||
780 | * Avoid racing set_ldisc or tty_ldisc_release | 782 | * Avoid racing set_ldisc or tty_ldisc_release |
781 | */ | 783 | */ |
782 | mutex_lock(&tty->ldisc_mutex); | 784 | mutex_lock(&tty->ldisc_mutex); |
783 | tty_ldisc_halt(tty); | 785 | |
786 | /* | ||
787 | * this is like tty_ldisc_halt, but we need to give up | ||
788 | * the BTM before calling cancel_delayed_work_sync, | ||
789 | * which may need to wait for another function taking the BTM | ||
790 | */ | ||
791 | clear_bit(TTY_LDISC, &tty->flags); | ||
792 | tty_unlock(); | ||
793 | cancel_delayed_work_sync(&tty->buf.work); | ||
794 | mutex_unlock(&tty->ldisc_mutex); | ||
795 | |||
796 | tty_lock(); | ||
797 | mutex_lock(&tty->ldisc_mutex); | ||
798 | |||
784 | /* At this point we have a closed ldisc and we want to | 799 | /* At this point we have a closed ldisc and we want to |
785 | reopen it. We could defer this to the next open but | 800 | reopen it. We could defer this to the next open but |
786 | it means auditing a lot of other paths so this is | 801 | it means auditing a lot of other paths so this is |
@@ -851,8 +866,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
851 | * race with the set_ldisc code path. | 866 | * race with the set_ldisc code path. |
852 | */ | 867 | */ |
853 | 868 | ||
869 | tty_unlock(); | ||
854 | tty_ldisc_halt(tty); | 870 | tty_ldisc_halt(tty); |
855 | flush_scheduled_work(); | 871 | flush_scheduled_work(); |
872 | tty_lock(); | ||
856 | 873 | ||
857 | mutex_lock(&tty->ldisc_mutex); | 874 | mutex_lock(&tty->ldisc_mutex); |
858 | /* | 875 | /* |
diff --git a/drivers/char/tty_mutex.c b/drivers/char/tty_mutex.c new file mode 100644 index 000000000000..133697540c73 --- /dev/null +++ b/drivers/char/tty_mutex.c | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * drivers/char/tty_lock.c | ||
3 | */ | ||
4 | #include <linux/tty.h> | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/kallsyms.h> | ||
7 | #include <linux/semaphore.h> | ||
8 | #include <linux/sched.h> | ||
9 | |||
10 | /* | ||
11 | * The 'big tty mutex' | ||
12 | * | ||
13 | * This mutex is taken and released by tty_lock() and tty_unlock(), | ||
14 | * replacing the older big kernel lock. | ||
15 | * It can no longer be taken recursively, and does not get | ||
16 | * released implicitly while sleeping. | ||
17 | * | ||
18 | * Don't use in new code. | ||
19 | */ | ||
20 | static DEFINE_MUTEX(big_tty_mutex); | ||
21 | struct task_struct *__big_tty_mutex_owner; | ||
22 | EXPORT_SYMBOL_GPL(__big_tty_mutex_owner); | ||
23 | |||
24 | /* | ||
25 | * Getting the big tty mutex. | ||
26 | */ | ||
27 | void __lockfunc tty_lock(void) | ||
28 | { | ||
29 | struct task_struct *task = current; | ||
30 | |||
31 | WARN_ON(__big_tty_mutex_owner == task); | ||
32 | |||
33 | mutex_lock(&big_tty_mutex); | ||
34 | __big_tty_mutex_owner = task; | ||
35 | } | ||
36 | EXPORT_SYMBOL(tty_lock); | ||
37 | |||
38 | void __lockfunc tty_unlock(void) | ||
39 | { | ||
40 | struct task_struct *task = current; | ||
41 | |||
42 | WARN_ON(__big_tty_mutex_owner != task); | ||
43 | __big_tty_mutex_owner = NULL; | ||
44 | |||
45 | mutex_unlock(&big_tty_mutex); | ||
46 | } | ||
47 | EXPORT_SYMBOL(tty_unlock); | ||
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index a3bd1d0b66cf..33d37d230f8f 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
@@ -231,7 +231,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
231 | 231 | ||
232 | /* block if port is in the process of being closed */ | 232 | /* block if port is in the process of being closed */ |
233 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { | 233 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
234 | wait_event_interruptible(port->close_wait, | 234 | wait_event_interruptible_tty(port->close_wait, |
235 | !(port->flags & ASYNC_CLOSING)); | 235 | !(port->flags & ASYNC_CLOSING)); |
236 | if (port->flags & ASYNC_HUP_NOTIFY) | 236 | if (port->flags & ASYNC_HUP_NOTIFY) |
237 | return -EAGAIN; | 237 | return -EAGAIN; |
@@ -294,7 +294,9 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
294 | retval = -ERESTARTSYS; | 294 | retval = -ERESTARTSYS; |
295 | break; | 295 | break; |
296 | } | 296 | } |
297 | tty_unlock(); | ||
297 | schedule(); | 298 | schedule(); |
299 | tty_lock(); | ||
298 | } | 300 | } |
299 | finish_wait(&port->open_wait, &wait); | 301 | finish_wait(&port->open_wait, &wait); |
300 | 302 | ||
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index c1791a63d99d..bcce46c96b88 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c | |||
@@ -463,10 +463,10 @@ vcs_open(struct inode *inode, struct file *filp) | |||
463 | unsigned int currcons = iminor(inode) & 127; | 463 | unsigned int currcons = iminor(inode) & 127; |
464 | int ret = 0; | 464 | int ret = 0; |
465 | 465 | ||
466 | lock_kernel(); | 466 | tty_lock(); |
467 | if(currcons && !vc_cons_allocated(currcons-1)) | 467 | if(currcons && !vc_cons_allocated(currcons-1)) |
468 | ret = -ENXIO; | 468 | ret = -ENXIO; |
469 | unlock_kernel(); | 469 | tty_unlock(); |
470 | return ret; | 470 | return ret; |
471 | } | 471 | } |
472 | 472 | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 44f03ddd8871..c734f9b1263a 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -105,6 +105,7 @@ | |||
105 | #include <asm/system.h> | 105 | #include <asm/system.h> |
106 | #include <linux/uaccess.h> | 106 | #include <linux/uaccess.h> |
107 | #include <linux/kdb.h> | 107 | #include <linux/kdb.h> |
108 | #include <linux/ctype.h> | ||
108 | 109 | ||
109 | #define MAX_NR_CON_DRIVER 16 | 110 | #define MAX_NR_CON_DRIVER 16 |
110 | 111 | ||
@@ -286,8 +287,12 @@ static inline unsigned short *screenpos(struct vc_data *vc, int offset, int view | |||
286 | return p; | 287 | return p; |
287 | } | 288 | } |
288 | 289 | ||
290 | /* Called from the keyboard irq path.. */ | ||
289 | static inline void scrolldelta(int lines) | 291 | static inline void scrolldelta(int lines) |
290 | { | 292 | { |
293 | /* FIXME */ | ||
294 | /* scrolldelta needs some kind of consistency lock, but the BKL was | ||
295 | and still is not protecting versus the scheduled back end */ | ||
291 | scrollback_delta += lines; | 296 | scrollback_delta += lines; |
292 | schedule_console_callback(); | 297 | schedule_console_callback(); |
293 | } | 298 | } |
@@ -704,7 +709,10 @@ void redraw_screen(struct vc_data *vc, int is_switch) | |||
704 | update_attr(vc); | 709 | update_attr(vc); |
705 | clear_buffer_attributes(vc); | 710 | clear_buffer_attributes(vc); |
706 | } | 711 | } |
707 | if (update && vc->vc_mode != KD_GRAPHICS) | 712 | |
713 | /* Forcibly update if we're panicing */ | ||
714 | if ((update && vc->vc_mode != KD_GRAPHICS) || | ||
715 | vt_force_oops_output(vc)) | ||
708 | do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); | 716 | do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); |
709 | } | 717 | } |
710 | set_cursor(vc); | 718 | set_cursor(vc); |
@@ -742,6 +750,7 @@ static void visual_init(struct vc_data *vc, int num, int init) | |||
742 | vc->vc_hi_font_mask = 0; | 750 | vc->vc_hi_font_mask = 0; |
743 | vc->vc_complement_mask = 0; | 751 | vc->vc_complement_mask = 0; |
744 | vc->vc_can_do_color = 0; | 752 | vc->vc_can_do_color = 0; |
753 | vc->vc_panic_force_write = false; | ||
745 | vc->vc_sw->con_init(vc, init); | 754 | vc->vc_sw->con_init(vc, init); |
746 | if (!vc->vc_complement_mask) | 755 | if (!vc->vc_complement_mask) |
747 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; | 756 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; |
@@ -774,6 +783,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ | |||
774 | if (!vc) | 783 | if (!vc) |
775 | return -ENOMEM; | 784 | return -ENOMEM; |
776 | vc_cons[currcons].d = vc; | 785 | vc_cons[currcons].d = vc; |
786 | tty_port_init(&vc->port); | ||
777 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); | 787 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
778 | visual_init(vc, currcons, 1); | 788 | visual_init(vc, currcons, 1); |
779 | if (!*vc->vc_uni_pagedir_loc) | 789 | if (!*vc->vc_uni_pagedir_loc) |
@@ -963,12 +973,12 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, | |||
963 | * Resize a virtual console as seen from the console end of things. We | 973 | * Resize a virtual console as seen from the console end of things. We |
964 | * use the common vc_do_resize methods to update the structures. The | 974 | * use the common vc_do_resize methods to update the structures. The |
965 | * caller must hold the console sem to protect console internals and | 975 | * caller must hold the console sem to protect console internals and |
966 | * vc->vc_tty | 976 | * vc->port.tty |
967 | */ | 977 | */ |
968 | 978 | ||
969 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) | 979 | int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) |
970 | { | 980 | { |
971 | return vc_do_resize(vc->vc_tty, vc, cols, rows); | 981 | return vc_do_resize(vc->port.tty, vc, cols, rows); |
972 | } | 982 | } |
973 | 983 | ||
974 | /** | 984 | /** |
@@ -1796,8 +1806,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) | |||
1796 | vc->vc_state = ESnormal; | 1806 | vc->vc_state = ESnormal; |
1797 | return; | 1807 | return; |
1798 | case ESpalette: | 1808 | case ESpalette: |
1799 | if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) { | 1809 | if (isxdigit(c)) { |
1800 | vc->vc_par[vc->vc_npar++] = (c > '9' ? (c & 0xDF) - 'A' + 10 : c - '0'); | 1810 | vc->vc_par[vc->vc_npar++] = hex_to_bin(c); |
1801 | if (vc->vc_npar == 7) { | 1811 | if (vc->vc_npar == 7) { |
1802 | int i = vc->vc_par[0] * 3, j = 1; | 1812 | int i = vc->vc_par[0] * 3, j = 1; |
1803 | vc->vc_palette[i] = 16 * vc->vc_par[j++]; | 1813 | vc->vc_palette[i] = 16 * vc->vc_par[j++]; |
@@ -2505,7 +2515,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) | |||
2505 | goto quit; | 2515 | goto quit; |
2506 | } | 2516 | } |
2507 | 2517 | ||
2508 | if (vc->vc_mode != KD_TEXT) | 2518 | if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc)) |
2509 | goto quit; | 2519 | goto quit; |
2510 | 2520 | ||
2511 | /* undraw cursor first */ | 2521 | /* undraw cursor first */ |
@@ -2611,8 +2621,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
2611 | return -EFAULT; | 2621 | return -EFAULT; |
2612 | ret = 0; | 2622 | ret = 0; |
2613 | 2623 | ||
2614 | lock_kernel(); | ||
2615 | |||
2616 | switch (type) | 2624 | switch (type) |
2617 | { | 2625 | { |
2618 | case TIOCL_SETSEL: | 2626 | case TIOCL_SETSEL: |
@@ -2687,7 +2695,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
2687 | ret = -EINVAL; | 2695 | ret = -EINVAL; |
2688 | break; | 2696 | break; |
2689 | } | 2697 | } |
2690 | unlock_kernel(); | ||
2691 | return ret; | 2698 | return ret; |
2692 | } | 2699 | } |
2693 | 2700 | ||
@@ -2800,12 +2807,12 @@ static int con_open(struct tty_struct *tty, struct file *filp) | |||
2800 | struct vc_data *vc = vc_cons[currcons].d; | 2807 | struct vc_data *vc = vc_cons[currcons].d; |
2801 | 2808 | ||
2802 | /* Still being freed */ | 2809 | /* Still being freed */ |
2803 | if (vc->vc_tty) { | 2810 | if (vc->port.tty) { |
2804 | release_console_sem(); | 2811 | release_console_sem(); |
2805 | return -ERESTARTSYS; | 2812 | return -ERESTARTSYS; |
2806 | } | 2813 | } |
2807 | tty->driver_data = vc; | 2814 | tty->driver_data = vc; |
2808 | vc->vc_tty = tty; | 2815 | vc->port.tty = tty; |
2809 | 2816 | ||
2810 | if (!tty->winsize.ws_row && !tty->winsize.ws_col) { | 2817 | if (!tty->winsize.ws_row && !tty->winsize.ws_col) { |
2811 | tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; | 2818 | tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; |
@@ -2833,7 +2840,7 @@ static void con_shutdown(struct tty_struct *tty) | |||
2833 | struct vc_data *vc = tty->driver_data; | 2840 | struct vc_data *vc = tty->driver_data; |
2834 | BUG_ON(vc == NULL); | 2841 | BUG_ON(vc == NULL); |
2835 | acquire_console_sem(); | 2842 | acquire_console_sem(); |
2836 | vc->vc_tty = NULL; | 2843 | vc->port.tty = NULL; |
2837 | release_console_sem(); | 2844 | release_console_sem(); |
2838 | tty_shutdown(tty); | 2845 | tty_shutdown(tty); |
2839 | } | 2846 | } |
@@ -2915,6 +2922,7 @@ static int __init con_init(void) | |||
2915 | for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { | 2922 | for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { |
2916 | vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); | 2923 | vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); |
2917 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); | 2924 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
2925 | tty_port_init(&vc->port); | ||
2918 | visual_init(vc, currcons, 1); | 2926 | visual_init(vc, currcons, 1); |
2919 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); | 2927 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); |
2920 | vc_init(vc, vc->vc_rows, vc->vc_cols, | 2928 | vc_init(vc, vc->vc_rows, vc->vc_cols, |
@@ -3783,7 +3791,8 @@ void do_unblank_screen(int leaving_gfx) | |||
3783 | return; | 3791 | return; |
3784 | } | 3792 | } |
3785 | vc = vc_cons[fg_console].d; | 3793 | vc = vc_cons[fg_console].d; |
3786 | if (vc->vc_mode != KD_TEXT) | 3794 | /* Try to unblank in oops case too */ |
3795 | if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc)) | ||
3787 | return; /* but leave console_blanked != 0 */ | 3796 | return; /* but leave console_blanked != 0 */ |
3788 | 3797 | ||
3789 | if (blankinterval) { | 3798 | if (blankinterval) { |
@@ -3792,7 +3801,7 @@ void do_unblank_screen(int leaving_gfx) | |||
3792 | } | 3801 | } |
3793 | 3802 | ||
3794 | console_blanked = 0; | 3803 | console_blanked = 0; |
3795 | if (vc->vc_sw->con_blank(vc, 0, leaving_gfx)) | 3804 | if (vc->vc_sw->con_blank(vc, 0, leaving_gfx) || vt_force_oops_output(vc)) |
3796 | /* Low-level driver cannot restore -> do it ourselves */ | 3805 | /* Low-level driver cannot restore -> do it ourselves */ |
3797 | update_screen(vc); | 3806 | update_screen(vc); |
3798 | if (console_blank_hook) | 3807 | if (console_blank_hook) |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index cb19dbc52136..2bbeaaea46e9 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -133,7 +133,7 @@ static void vt_event_wait(struct vt_event_wait *vw) | |||
133 | list_add(&vw->list, &vt_events); | 133 | list_add(&vw->list, &vt_events); |
134 | spin_unlock_irqrestore(&vt_event_lock, flags); | 134 | spin_unlock_irqrestore(&vt_event_lock, flags); |
135 | /* Wait for it to pass */ | 135 | /* Wait for it to pass */ |
136 | wait_event_interruptible(vt_event_waitqueue, vw->done); | 136 | wait_event_interruptible_tty(vt_event_waitqueue, vw->done); |
137 | /* Dequeue it */ | 137 | /* Dequeue it */ |
138 | spin_lock_irqsave(&vt_event_lock, flags); | 138 | spin_lock_irqsave(&vt_event_lock, flags); |
139 | list_del(&vw->list); | 139 | list_del(&vw->list); |
@@ -509,7 +509,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
509 | 509 | ||
510 | console = vc->vc_num; | 510 | console = vc->vc_num; |
511 | 511 | ||
512 | lock_kernel(); | 512 | tty_lock(); |
513 | 513 | ||
514 | if (!vc_cons_allocated(console)) { /* impossible? */ | 514 | if (!vc_cons_allocated(console)) { /* impossible? */ |
515 | ret = -ENOIOCTLCMD; | 515 | ret = -ENOIOCTLCMD; |
@@ -1336,7 +1336,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
1336 | ret = -ENOIOCTLCMD; | 1336 | ret = -ENOIOCTLCMD; |
1337 | } | 1337 | } |
1338 | out: | 1338 | out: |
1339 | unlock_kernel(); | 1339 | tty_unlock(); |
1340 | return ret; | 1340 | return ret; |
1341 | eperm: | 1341 | eperm: |
1342 | ret = -EPERM; | 1342 | ret = -EPERM; |
@@ -1369,7 +1369,7 @@ void vc_SAK(struct work_struct *work) | |||
1369 | acquire_console_sem(); | 1369 | acquire_console_sem(); |
1370 | vc = vc_con->d; | 1370 | vc = vc_con->d; |
1371 | if (vc) { | 1371 | if (vc) { |
1372 | tty = vc->vc_tty; | 1372 | tty = vc->port.tty; |
1373 | /* | 1373 | /* |
1374 | * SAK should also work in all raw modes and reset | 1374 | * SAK should also work in all raw modes and reset |
1375 | * them properly. | 1375 | * them properly. |
@@ -1503,7 +1503,7 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, | |||
1503 | 1503 | ||
1504 | console = vc->vc_num; | 1504 | console = vc->vc_num; |
1505 | 1505 | ||
1506 | lock_kernel(); | 1506 | tty_lock(); |
1507 | 1507 | ||
1508 | if (!vc_cons_allocated(console)) { /* impossible? */ | 1508 | if (!vc_cons_allocated(console)) { /* impossible? */ |
1509 | ret = -ENOIOCTLCMD; | 1509 | ret = -ENOIOCTLCMD; |
@@ -1571,11 +1571,11 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, | |||
1571 | goto fallback; | 1571 | goto fallback; |
1572 | } | 1572 | } |
1573 | out: | 1573 | out: |
1574 | unlock_kernel(); | 1574 | tty_unlock(); |
1575 | return ret; | 1575 | return ret; |
1576 | 1576 | ||
1577 | fallback: | 1577 | fallback: |
1578 | unlock_kernel(); | 1578 | tty_unlock(); |
1579 | return vt_ioctl(tty, file, cmd, arg); | 1579 | return vt_ioctl(tty, file, cmd, arg); |
1580 | } | 1580 | } |
1581 | 1581 | ||
@@ -1761,10 +1761,13 @@ int vt_move_to_console(unsigned int vt, int alloc) | |||
1761 | return -EIO; | 1761 | return -EIO; |
1762 | } | 1762 | } |
1763 | release_console_sem(); | 1763 | release_console_sem(); |
1764 | tty_lock(); | ||
1764 | if (vt_waitactive(vt + 1)) { | 1765 | if (vt_waitactive(vt + 1)) { |
1765 | pr_debug("Suspend: Can't switch VCs."); | 1766 | pr_debug("Suspend: Can't switch VCs."); |
1767 | tty_unlock(); | ||
1766 | return -EINTR; | 1768 | return -EINTR; |
1767 | } | 1769 | } |
1770 | tty_unlock(); | ||
1768 | return prev; | 1771 | return prev; |
1769 | } | 1772 | } |
1770 | 1773 | ||
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 54acd8b534df..a79525f434a8 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
@@ -130,7 +130,7 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
130 | 130 | ||
131 | strcpy(info->fix.id, "inteldrmfb"); | 131 | strcpy(info->fix.id, "inteldrmfb"); |
132 | 132 | ||
133 | info->flags = FBINFO_DEFAULT; | 133 | info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; |
134 | info->fbops = &intelfb_ops; | 134 | info->fbops = &intelfb_ops; |
135 | 135 | ||
136 | /* setup aperture base/size for vesafb takeover */ | 136 | /* setup aperture base/size for vesafb takeover */ |
@@ -148,8 +148,6 @@ static int intelfb_create(struct intel_fbdev *ifbdev, | |||
148 | info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; | 148 | info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; |
149 | info->fix.smem_len = size; | 149 | info->fix.smem_len = size; |
150 | 150 | ||
151 | info->flags = FBINFO_DEFAULT; | ||
152 | |||
153 | info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset, | 151 | info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset, |
154 | size); | 152 | size); |
155 | if (!info->screen_base) { | 153 | if (!info->screen_base) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 2fb2444d2322..099f637264aa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -250,6 +250,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
250 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | | 250 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | |
251 | FBINFO_HWACCEL_FILLRECT | | 251 | FBINFO_HWACCEL_FILLRECT | |
252 | FBINFO_HWACCEL_IMAGEBLIT; | 252 | FBINFO_HWACCEL_IMAGEBLIT; |
253 | info->flags |= FBINFO_CAN_FORCE_OUTPUT; | ||
253 | info->fbops = &nouveau_fbcon_ops; | 254 | info->fbops = &nouveau_fbcon_ops; |
254 | info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - | 255 | info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - |
255 | dev_priv->vm_vram_base; | 256 | dev_priv->vm_vram_base; |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index dc1634bb0c11..dbf86962bdd1 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
@@ -224,7 +224,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, | |||
224 | 224 | ||
225 | drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); | 225 | drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); |
226 | 226 | ||
227 | info->flags = FBINFO_DEFAULT; | 227 | info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; |
228 | info->fbops = &radeonfb_ops; | 228 | info->fbops = &radeonfb_ops; |
229 | 229 | ||
230 | tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start; | 230 | tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start; |
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 8681f1345056..d89aa38c5cf0 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c | |||
@@ -216,7 +216,7 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, | |||
216 | struct ktermios *old) | 216 | struct ktermios *old) |
217 | { | 217 | { |
218 | unsigned long flags; | 218 | unsigned long flags; |
219 | unsigned int baud, quot, h_lcr; | 219 | unsigned int baud, quot, h_lcr, b; |
220 | 220 | ||
221 | /* | 221 | /* |
222 | * We don't support modem control lines. | 222 | * We don't support modem control lines. |
@@ -234,12 +234,8 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios, | |||
234 | */ | 234 | */ |
235 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); | 235 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); |
236 | quot = uart_get_divisor(port, baud); | 236 | quot = uart_get_divisor(port, baud); |
237 | 237 | b = port->uartclk / (16 * quot); | |
238 | if (port->state && port->state->port.tty) { | 238 | tty_termios_encode_baud_rate(termios, b, b); |
239 | struct tty_struct *tty = port->state->port.tty; | ||
240 | unsigned int b = port->uartclk / (16 * quot); | ||
241 | tty_encode_baud_rate(tty, b, b); | ||
242 | } | ||
243 | 239 | ||
244 | switch (termios->c_cflag & CSIZE) { | 240 | switch (termios->c_cflag & CSIZE) { |
245 | case CS5: | 241 | case CS5: |
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 30463862603b..7356a56ac458 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -78,10 +78,6 @@ struct m68k_serial *m68k_consinfo = 0; | |||
78 | 78 | ||
79 | #define M68K_CLOCK (16667000) /* FIXME: 16MHz is likely wrong */ | 79 | #define M68K_CLOCK (16667000) /* FIXME: 16MHz is likely wrong */ |
80 | 80 | ||
81 | #ifdef CONFIG_CONSOLE | ||
82 | extern wait_queue_head_t keypress_wait; | ||
83 | #endif | ||
84 | |||
85 | struct tty_driver *serial_driver; | 81 | struct tty_driver *serial_driver; |
86 | 82 | ||
87 | /* number of characters left in xmit buffer before we ask for more */ | 83 | /* number of characters left in xmit buffer before we ask for more */ |
@@ -102,19 +98,13 @@ static void change_speed(struct m68k_serial *info); | |||
102 | * Setup for console. Argument comes from the boot command line. | 98 | * Setup for console. Argument comes from the boot command line. |
103 | */ | 99 | */ |
104 | 100 | ||
105 | #if defined(CONFIG_M68EZ328ADS) || defined(CONFIG_ALMA_ANS) || defined(CONFIG_DRAGONIXVZ) | 101 | /* note: this is messy, but it works, again, perhaps defined somewhere else?*/ |
106 | #define CONSOLE_BAUD_RATE 115200 | 102 | #ifdef CONFIG_M68VZ328 |
107 | #define DEFAULT_CBAUD B115200 | 103 | #define CONSOLE_BAUD_RATE 19200 |
108 | #else | 104 | #define DEFAULT_CBAUD B19200 |
109 | /* (es) */ | ||
110 | /* note: this is messy, but it works, again, perhaps defined somewhere else?*/ | ||
111 | #ifdef CONFIG_M68VZ328 | ||
112 | #define CONSOLE_BAUD_RATE 19200 | ||
113 | #define DEFAULT_CBAUD B19200 | ||
114 | #endif | ||
115 | /* (/es) */ | ||
116 | #endif | 105 | #endif |
117 | 106 | ||
107 | |||
118 | #ifndef CONSOLE_BAUD_RATE | 108 | #ifndef CONSOLE_BAUD_RATE |
119 | #define CONSOLE_BAUD_RATE 9600 | 109 | #define CONSOLE_BAUD_RATE 9600 |
120 | #define DEFAULT_CBAUD B9600 | 110 | #define DEFAULT_CBAUD B9600 |
@@ -300,10 +290,6 @@ static void receive_chars(struct m68k_serial *info, unsigned short rx) | |||
300 | return; | 290 | return; |
301 | #endif /* CONFIG_MAGIC_SYSRQ */ | 291 | #endif /* CONFIG_MAGIC_SYSRQ */ |
302 | } | 292 | } |
303 | /* It is a 'keyboard interrupt' ;-) */ | ||
304 | #ifdef CONFIG_CONSOLE | ||
305 | wake_up(&keypress_wait); | ||
306 | #endif | ||
307 | } | 293 | } |
308 | 294 | ||
309 | if(!tty) | 295 | if(!tty) |
@@ -1243,7 +1229,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1243 | retval = -ERESTARTSYS; | 1229 | retval = -ERESTARTSYS; |
1244 | break; | 1230 | break; |
1245 | } | 1231 | } |
1232 | tty_unlock(); | ||
1246 | schedule(); | 1233 | schedule(); |
1234 | tty_lock(); | ||
1247 | } | 1235 | } |
1248 | current->state = TASK_RUNNING; | 1236 | current->state = TASK_RUNNING; |
1249 | remove_wait_queue(&info->open_wait, &wait); | 1237 | remove_wait_queue(&info->open_wait, &wait); |
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 768612f8e41e..0dff3bbddc8b 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c | |||
@@ -1705,7 +1705,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1705 | printk("jiff=%lu...", jiffies); | 1705 | printk("jiff=%lu...", jiffies); |
1706 | #endif | 1706 | #endif |
1707 | 1707 | ||
1708 | lock_kernel(); | ||
1709 | /* We go through the loop at least once because we can't tell | 1708 | /* We go through the loop at least once because we can't tell |
1710 | * exactly when the last character exits the shifter. There can | 1709 | * exactly when the last character exits the shifter. There can |
1711 | * be at least two characters waiting to be sent after the buffers | 1710 | * be at least two characters waiting to be sent after the buffers |
@@ -1734,7 +1733,6 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1734 | bdp--; | 1733 | bdp--; |
1735 | } while (bdp->status & BD_SC_READY); | 1734 | } while (bdp->status & BD_SC_READY); |
1736 | current->state = TASK_RUNNING; | 1735 | current->state = TASK_RUNNING; |
1737 | unlock_kernel(); | ||
1738 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 1736 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
1739 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 1737 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); |
1740 | #endif | 1738 | #endif |
@@ -1862,7 +1860,9 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
1862 | printk("block_til_ready blocking: ttys%d, count = %d\n", | 1860 | printk("block_til_ready blocking: ttys%d, count = %d\n", |
1863 | info->line, state->count); | 1861 | info->line, state->count); |
1864 | #endif | 1862 | #endif |
1863 | tty_unlock(); | ||
1865 | schedule(); | 1864 | schedule(); |
1865 | tty_lock(); | ||
1866 | } | 1866 | } |
1867 | current->state = TASK_RUNNING; | 1867 | current->state = TASK_RUNNING; |
1868 | remove_wait_queue(&info->open_wait, &wait); | 1868 | remove_wait_queue(&info->open_wait, &wait); |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 09ef57034c9c..24110f6f61e0 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -241,7 +241,7 @@ static const struct serial8250_config uart_config[] = { | |||
241 | .fifo_size = 128, | 241 | .fifo_size = 128, |
242 | .tx_loadsz = 128, | 242 | .tx_loadsz = 128, |
243 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | 243 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, |
244 | .flags = UART_CAP_FIFO, | 244 | .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, |
245 | }, | 245 | }, |
246 | [PORT_16654] = { | 246 | [PORT_16654] = { |
247 | .name = "ST16654", | 247 | .name = "ST16654", |
@@ -300,6 +300,13 @@ static const struct serial8250_config uart_config[] = { | |||
300 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, | 300 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, |
301 | .flags = UART_CAP_FIFO | UART_CAP_AFE, | 301 | .flags = UART_CAP_FIFO | UART_CAP_AFE, |
302 | }, | 302 | }, |
303 | [PORT_U6_16550A] = { | ||
304 | .name = "U6_16550A", | ||
305 | .fifo_size = 64, | ||
306 | .tx_loadsz = 64, | ||
307 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | ||
308 | .flags = UART_CAP_FIFO | UART_CAP_AFE, | ||
309 | }, | ||
303 | }; | 310 | }; |
304 | 311 | ||
305 | #if defined(CONFIG_MIPS_ALCHEMY) | 312 | #if defined(CONFIG_MIPS_ALCHEMY) |
@@ -1070,6 +1077,15 @@ static void autoconfig_16550a(struct uart_8250_port *up) | |||
1070 | DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); | 1077 | DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); |
1071 | } | 1078 | } |
1072 | serial_outp(up, UART_IER, iersave); | 1079 | serial_outp(up, UART_IER, iersave); |
1080 | |||
1081 | /* | ||
1082 | * We distinguish between 16550A and U6 16550A by counting | ||
1083 | * how many bytes are in the FIFO. | ||
1084 | */ | ||
1085 | if (up->port.type == PORT_16550A && size_fifo(up) == 64) { | ||
1086 | up->port.type = PORT_U6_16550A; | ||
1087 | up->capabilities |= UART_CAP_AFE; | ||
1088 | } | ||
1073 | } | 1089 | } |
1074 | 1090 | ||
1075 | /* | 1091 | /* |
@@ -2224,9 +2240,9 @@ static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int | |||
2224 | return quot; | 2240 | return quot; |
2225 | } | 2241 | } |
2226 | 2242 | ||
2227 | static void | 2243 | void |
2228 | serial8250_set_termios(struct uart_port *port, struct ktermios *termios, | 2244 | serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, |
2229 | struct ktermios *old) | 2245 | struct ktermios *old) |
2230 | { | 2246 | { |
2231 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 2247 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
2232 | unsigned char cval, fcr = 0; | 2248 | unsigned char cval, fcr = 0; |
@@ -2402,16 +2418,22 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, | |||
2402 | if (tty_termios_baud_rate(termios)) | 2418 | if (tty_termios_baud_rate(termios)) |
2403 | tty_termios_encode_baud_rate(termios, baud, baud); | 2419 | tty_termios_encode_baud_rate(termios, baud, baud); |
2404 | } | 2420 | } |
2421 | EXPORT_SYMBOL(serial8250_do_set_termios); | ||
2405 | 2422 | ||
2406 | static void | 2423 | static void |
2407 | serial8250_set_ldisc(struct uart_port *port) | 2424 | serial8250_set_termios(struct uart_port *port, struct ktermios *termios, |
2425 | struct ktermios *old) | ||
2408 | { | 2426 | { |
2409 | int line = port->line; | 2427 | if (port->set_termios) |
2410 | 2428 | port->set_termios(port, termios, old); | |
2411 | if (line >= port->state->port.tty->driver->num) | 2429 | else |
2412 | return; | 2430 | serial8250_do_set_termios(port, termios, old); |
2431 | } | ||
2413 | 2432 | ||
2414 | if (port->state->port.tty->ldisc->ops->num == N_PPS) { | 2433 | static void |
2434 | serial8250_set_ldisc(struct uart_port *port, int new) | ||
2435 | { | ||
2436 | if (new == N_PPS) { | ||
2415 | port->flags |= UPF_HARDPPS_CD; | 2437 | port->flags |= UPF_HARDPPS_CD; |
2416 | serial8250_enable_ms(port); | 2438 | serial8250_enable_ms(port); |
2417 | } else | 2439 | } else |
@@ -2987,6 +3009,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
2987 | port.type = p->type; | 3009 | port.type = p->type; |
2988 | port.serial_in = p->serial_in; | 3010 | port.serial_in = p->serial_in; |
2989 | port.serial_out = p->serial_out; | 3011 | port.serial_out = p->serial_out; |
3012 | port.set_termios = p->set_termios; | ||
2990 | port.dev = &dev->dev; | 3013 | port.dev = &dev->dev; |
2991 | port.irqflags |= irqflag; | 3014 | port.irqflags |= irqflag; |
2992 | ret = serial8250_register_port(&port); | 3015 | ret = serial8250_register_port(&port); |
@@ -3150,6 +3173,9 @@ int serial8250_register_port(struct uart_port *port) | |||
3150 | uart->port.serial_in = port->serial_in; | 3173 | uart->port.serial_in = port->serial_in; |
3151 | if (port->serial_out) | 3174 | if (port->serial_out) |
3152 | uart->port.serial_out = port->serial_out; | 3175 | uart->port.serial_out = port->serial_out; |
3176 | /* Possibly override set_termios call */ | ||
3177 | if (port->set_termios) | ||
3178 | uart->port.set_termios = port->set_termios; | ||
3153 | 3179 | ||
3154 | ret = uart_add_one_port(&serial8250_reg, &uart->port); | 3180 | ret = uart_add_one_port(&serial8250_reg, &uart->port); |
3155 | if (ret == 0) | 3181 | if (ret == 0) |
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index f279745e9fef..b745792ec25a 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c | |||
@@ -19,9 +19,11 @@ | |||
19 | * The user can specify the device directly, e.g., | 19 | * The user can specify the device directly, e.g., |
20 | * earlycon=uart8250,io,0x3f8,9600n8 | 20 | * earlycon=uart8250,io,0x3f8,9600n8 |
21 | * earlycon=uart8250,mmio,0xff5e0000,115200n8 | 21 | * earlycon=uart8250,mmio,0xff5e0000,115200n8 |
22 | * earlycon=uart8250,mmio32,0xff5e0000,115200n8 | ||
22 | * or | 23 | * or |
23 | * console=uart8250,io,0x3f8,9600n8 | 24 | * console=uart8250,io,0x3f8,9600n8 |
24 | * console=uart8250,mmio,0xff5e0000,115200n8 | 25 | * console=uart8250,mmio,0xff5e0000,115200n8 |
26 | * console=uart8250,mmio32,0xff5e0000,115200n8 | ||
25 | */ | 27 | */ |
26 | 28 | ||
27 | #include <linux/tty.h> | 29 | #include <linux/tty.h> |
@@ -48,18 +50,31 @@ static struct early_serial8250_device early_device; | |||
48 | 50 | ||
49 | static unsigned int __init serial_in(struct uart_port *port, int offset) | 51 | static unsigned int __init serial_in(struct uart_port *port, int offset) |
50 | { | 52 | { |
51 | if (port->iotype == UPIO_MEM) | 53 | switch (port->iotype) { |
54 | case UPIO_MEM: | ||
52 | return readb(port->membase + offset); | 55 | return readb(port->membase + offset); |
53 | else | 56 | case UPIO_MEM32: |
57 | return readl(port->membase + (offset << 2)); | ||
58 | case UPIO_PORT: | ||
54 | return inb(port->iobase + offset); | 59 | return inb(port->iobase + offset); |
60 | default: | ||
61 | return 0; | ||
62 | } | ||
55 | } | 63 | } |
56 | 64 | ||
57 | static void __init serial_out(struct uart_port *port, int offset, int value) | 65 | static void __init serial_out(struct uart_port *port, int offset, int value) |
58 | { | 66 | { |
59 | if (port->iotype == UPIO_MEM) | 67 | switch (port->iotype) { |
68 | case UPIO_MEM: | ||
60 | writeb(value, port->membase + offset); | 69 | writeb(value, port->membase + offset); |
61 | else | 70 | break; |
71 | case UPIO_MEM32: | ||
72 | writel(value, port->membase + (offset << 2)); | ||
73 | break; | ||
74 | case UPIO_PORT: | ||
62 | outb(value, port->iobase + offset); | 75 | outb(value, port->iobase + offset); |
76 | break; | ||
77 | } | ||
63 | } | 78 | } |
64 | 79 | ||
65 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) | 80 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) |
@@ -137,15 +152,21 @@ static int __init parse_options(struct early_serial8250_device *device, | |||
137 | char *options) | 152 | char *options) |
138 | { | 153 | { |
139 | struct uart_port *port = &device->port; | 154 | struct uart_port *port = &device->port; |
140 | int mmio, length; | 155 | int mmio, mmio32, length; |
141 | 156 | ||
142 | if (!options) | 157 | if (!options) |
143 | return -ENODEV; | 158 | return -ENODEV; |
144 | 159 | ||
145 | port->uartclk = BASE_BAUD * 16; | 160 | port->uartclk = BASE_BAUD * 16; |
146 | if (!strncmp(options, "mmio,", 5)) { | 161 | |
147 | port->iotype = UPIO_MEM; | 162 | mmio = !strncmp(options, "mmio,", 5); |
148 | port->mapbase = simple_strtoul(options + 5, &options, 0); | 163 | mmio32 = !strncmp(options, "mmio32,", 7); |
164 | if (mmio || mmio32) { | ||
165 | port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32); | ||
166 | port->mapbase = simple_strtoul(options + (mmio ? 5 : 7), | ||
167 | &options, 0); | ||
168 | if (mmio32) | ||
169 | port->regshift = 2; | ||
149 | #ifdef CONFIG_FIX_EARLYCON_MEM | 170 | #ifdef CONFIG_FIX_EARLYCON_MEM |
150 | set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, | 171 | set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, |
151 | port->mapbase & PAGE_MASK); | 172 | port->mapbase & PAGE_MASK); |
@@ -157,11 +178,10 @@ static int __init parse_options(struct early_serial8250_device *device, | |||
157 | if (!port->membase) { | 178 | if (!port->membase) { |
158 | printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n", | 179 | printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n", |
159 | __func__, | 180 | __func__, |
160 | (unsigned long long)port->mapbase); | 181 | (unsigned long long) port->mapbase); |
161 | return -ENOMEM; | 182 | return -ENOMEM; |
162 | } | 183 | } |
163 | #endif | 184 | #endif |
164 | mmio = 1; | ||
165 | } else if (!strncmp(options, "io,", 3)) { | 185 | } else if (!strncmp(options, "io,", 3)) { |
166 | port->iotype = UPIO_PORT; | 186 | port->iotype = UPIO_PORT; |
167 | port->iobase = simple_strtoul(options + 3, &options, 0); | 187 | port->iobase = simple_strtoul(options + 3, &options, 0); |
@@ -181,11 +201,18 @@ static int __init parse_options(struct early_serial8250_device *device, | |||
181 | device->baud); | 201 | device->baud); |
182 | } | 202 | } |
183 | 203 | ||
184 | printk(KERN_INFO "Early serial console at %s 0x%llx (options '%s')\n", | 204 | if (mmio || mmio32) |
185 | mmio ? "MMIO" : "I/O port", | 205 | printk(KERN_INFO |
186 | mmio ? (unsigned long long) port->mapbase | 206 | "Early serial console at MMIO%s 0x%llu (options '%s')\n", |
187 | : (unsigned long long) port->iobase, | 207 | mmio32 ? "32" : "", |
188 | device->options); | 208 | (unsigned long long)port->mapbase, |
209 | device->options); | ||
210 | else | ||
211 | printk(KERN_INFO | ||
212 | "Early serial console at I/O port 0x%lu (options '%s')\n", | ||
213 | port->iobase, | ||
214 | device->options); | ||
215 | |||
189 | return 0; | 216 | return 0; |
190 | } | 217 | } |
191 | 218 | ||
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 746a44621d91..53be4d35a0aa 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
@@ -994,6 +994,7 @@ static int skip_tx_en_setup(struct serial_private *priv, | |||
994 | #define PCI_DEVICE_ID_TITAN_800E 0xA014 | 994 | #define PCI_DEVICE_ID_TITAN_800E 0xA014 |
995 | #define PCI_DEVICE_ID_TITAN_200EI 0xA016 | 995 | #define PCI_DEVICE_ID_TITAN_200EI 0xA016 |
996 | #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 | 996 | #define PCI_DEVICE_ID_TITAN_200EISI 0xA017 |
997 | #define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 | ||
997 | 998 | ||
998 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ | 999 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ |
999 | #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 | 1000 | #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 |
@@ -1542,6 +1543,8 @@ enum pci_board_num_t { | |||
1542 | pbn_b2_4_921600, | 1543 | pbn_b2_4_921600, |
1543 | pbn_b2_8_921600, | 1544 | pbn_b2_8_921600, |
1544 | 1545 | ||
1546 | pbn_b2_8_1152000, | ||
1547 | |||
1545 | pbn_b2_bt_1_115200, | 1548 | pbn_b2_bt_1_115200, |
1546 | pbn_b2_bt_2_115200, | 1549 | pbn_b2_bt_2_115200, |
1547 | pbn_b2_bt_4_115200, | 1550 | pbn_b2_bt_4_115200, |
@@ -1960,6 +1963,13 @@ static struct pciserial_board pci_boards[] __devinitdata = { | |||
1960 | .uart_offset = 8, | 1963 | .uart_offset = 8, |
1961 | }, | 1964 | }, |
1962 | 1965 | ||
1966 | [pbn_b2_8_1152000] = { | ||
1967 | .flags = FL_BASE2, | ||
1968 | .num_ports = 8, | ||
1969 | .base_baud = 1152000, | ||
1970 | .uart_offset = 8, | ||
1971 | }, | ||
1972 | |||
1963 | [pbn_b2_bt_1_115200] = { | 1973 | [pbn_b2_bt_1_115200] = { |
1964 | .flags = FL_BASE2|FL_BASE_BARS, | 1974 | .flags = FL_BASE2|FL_BASE_BARS, |
1965 | .num_ports = 1, | 1975 | .num_ports = 1, |
@@ -2875,6 +2885,9 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
2875 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952, | 2885 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952, |
2876 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 2886 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
2877 | pbn_b0_bt_2_921600 }, | 2887 | pbn_b0_bt_2_921600 }, |
2888 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958, | ||
2889 | PCI_ANY_ID , PCI_ANY_ID, 0, 0, | ||
2890 | pbn_b2_8_1152000 }, | ||
2878 | 2891 | ||
2879 | /* | 2892 | /* |
2880 | * Oxford Semiconductor Inc. Tornado PCI express device range. | 2893 | * Oxford Semiconductor Inc. Tornado PCI express device range. |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index e437ce8c1748..a22e60c06f48 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -542,6 +542,7 @@ config SERIAL_S5PV210 | |||
542 | help | 542 | help |
543 | Serial port support for Samsung's S5P Family of SoC's | 543 | Serial port support for Samsung's S5P Family of SoC's |
544 | 544 | ||
545 | |||
545 | config SERIAL_MAX3100 | 546 | config SERIAL_MAX3100 |
546 | tristate "MAX3100 support" | 547 | tristate "MAX3100 support" |
547 | depends on SPI | 548 | depends on SPI |
@@ -549,6 +550,22 @@ config SERIAL_MAX3100 | |||
549 | help | 550 | help |
550 | MAX3100 chip support | 551 | MAX3100 chip support |
551 | 552 | ||
553 | config SERIAL_MAX3107 | ||
554 | tristate "MAX3107 support" | ||
555 | depends on SPI | ||
556 | select SERIAL_CORE | ||
557 | help | ||
558 | MAX3107 chip support | ||
559 | |||
560 | config SERIAL_MAX3107_AAVA | ||
561 | tristate "MAX3107 AAVA platform support" | ||
562 | depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB | ||
563 | select SERIAL_CORE | ||
564 | help | ||
565 | Support for the MAX3107 chip configuration found on the AAVA | ||
566 | platform. Includes the extra initialisation and GPIO support | ||
567 | neded for this device. | ||
568 | |||
552 | config SERIAL_DZ | 569 | config SERIAL_DZ |
553 | bool "DECstation DZ serial driver" | 570 | bool "DECstation DZ serial driver" |
554 | depends on MACH_DECSTATION && 32BIT | 571 | depends on MACH_DECSTATION && 32BIT |
@@ -690,6 +707,33 @@ config SERIAL_SA1100_CONSOLE | |||
690 | your boot loader (lilo or loadlin) about how to pass options to the | 707 | your boot loader (lilo or loadlin) about how to pass options to the |
691 | kernel at boot time.) | 708 | kernel at boot time.) |
692 | 709 | ||
710 | config SERIAL_MRST_MAX3110 | ||
711 | tristate "SPI UART driver for Max3110" | ||
712 | depends on SPI_DW_PCI | ||
713 | select SERIAL_CORE | ||
714 | select SERIAL_CORE_CONSOLE | ||
715 | help | ||
716 | This is the UART protocol driver for the MAX3110 device on | ||
717 | the Intel Moorestown platform. On other systems use the max3100 | ||
718 | driver. | ||
719 | |||
720 | config MRST_MAX3110_IRQ | ||
721 | boolean "Enable GPIO IRQ for Max3110 over Moorestown" | ||
722 | default n | ||
723 | depends on SERIAL_MRST_MAX3110 && GPIO_LANGWELL | ||
724 | help | ||
725 | This has to be enabled after Moorestown GPIO driver is loaded | ||
726 | |||
727 | config SERIAL_MFD_HSU | ||
728 | tristate "Medfield High Speed UART support" | ||
729 | depends on PCI | ||
730 | select SERIAL_CORE | ||
731 | |||
732 | config SERIAL_MFD_HSU_CONSOLE | ||
733 | boolean "Medfile HSU serial console support" | ||
734 | depends on SERIAL_MFD_HSU=y | ||
735 | select SERIAL_CORE_CONSOLE | ||
736 | |||
693 | config SERIAL_BFIN | 737 | config SERIAL_BFIN |
694 | tristate "Blackfin serial port support" | 738 | tristate "Blackfin serial port support" |
695 | depends on BLACKFIN | 739 | depends on BLACKFIN |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 208a85572c32..1ca4fd599ffe 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
@@ -46,6 +46,8 @@ obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o | |||
46 | obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o | 46 | obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o |
47 | obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o | 47 | obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o |
48 | obj-$(CONFIG_SERIAL_MAX3100) += max3100.o | 48 | obj-$(CONFIG_SERIAL_MAX3100) += max3100.o |
49 | obj-$(CONFIG_SERIAL_MAX3107) += max3107.o | ||
50 | obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o | ||
49 | obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o | 51 | obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o |
50 | obj-$(CONFIG_SERIAL_MUX) += mux.o | 52 | obj-$(CONFIG_SERIAL_MUX) += mux.o |
51 | obj-$(CONFIG_SERIAL_68328) += 68328serial.o | 53 | obj-$(CONFIG_SERIAL_68328) += 68328serial.o |
@@ -84,3 +86,5 @@ obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o | |||
84 | obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o | 86 | obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o |
85 | obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o | 87 | obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o |
86 | obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o | 88 | obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o |
89 | obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o | ||
90 | obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o | ||
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c index 0f1189605d21..f8d8a00554da 100644 --- a/drivers/serial/altera_uart.c +++ b/drivers/serial/altera_uart.c | |||
@@ -394,7 +394,7 @@ int __init early_altera_uart_setup(struct altera_uart_platform_uart *platp) | |||
394 | static void altera_uart_console_putc(struct uart_port *port, const char c) | 394 | static void altera_uart_console_putc(struct uart_port *port, const char c) |
395 | { | 395 | { |
396 | while (!(readl(port->membase + ALTERA_UART_STATUS_REG) & | 396 | while (!(readl(port->membase + ALTERA_UART_STATUS_REG) & |
397 | ALTERA_UART_STATUS_TRDY_MSK)) | 397 | ALTERA_UART_STATUS_TRDY_MSK)) |
398 | cpu_relax(); | 398 | cpu_relax(); |
399 | 399 | ||
400 | writel(c, port->membase + ALTERA_UART_TXDATA_REG); | 400 | writel(c, port->membase + ALTERA_UART_TXDATA_REG); |
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index a182def7007d..3892666b5fbd 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c | |||
@@ -217,7 +217,8 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) | |||
217 | if (rs485conf->flags & SER_RS485_ENABLED) { | 217 | if (rs485conf->flags & SER_RS485_ENABLED) { |
218 | dev_dbg(port->dev, "Setting UART to RS485\n"); | 218 | dev_dbg(port->dev, "Setting UART to RS485\n"); |
219 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; | 219 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; |
220 | UART_PUT_TTGR(port, rs485conf->delay_rts_before_send); | 220 | if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND) |
221 | UART_PUT_TTGR(port, rs485conf->delay_rts_after_send); | ||
221 | mode |= ATMEL_US_USMODE_RS485; | 222 | mode |= ATMEL_US_USMODE_RS485; |
222 | } else { | 223 | } else { |
223 | dev_dbg(port->dev, "Setting UART to RS232\n"); | 224 | dev_dbg(port->dev, "Setting UART to RS232\n"); |
@@ -292,7 +293,9 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) | |||
292 | 293 | ||
293 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | 294 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { |
294 | dev_dbg(port->dev, "Setting UART to RS485\n"); | 295 | dev_dbg(port->dev, "Setting UART to RS485\n"); |
295 | UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); | 296 | if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) |
297 | UART_PUT_TTGR(port, | ||
298 | atmel_port->rs485.delay_rts_after_send); | ||
296 | mode |= ATMEL_US_USMODE_RS485; | 299 | mode |= ATMEL_US_USMODE_RS485; |
297 | } else { | 300 | } else { |
298 | dev_dbg(port->dev, "Setting UART to RS232\n"); | 301 | dev_dbg(port->dev, "Setting UART to RS232\n"); |
@@ -1211,7 +1214,9 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, | |||
1211 | 1214 | ||
1212 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | 1215 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { |
1213 | dev_dbg(port->dev, "Setting UART to RS485\n"); | 1216 | dev_dbg(port->dev, "Setting UART to RS485\n"); |
1214 | UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); | 1217 | if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND) |
1218 | UART_PUT_TTGR(port, | ||
1219 | atmel_port->rs485.delay_rts_after_send); | ||
1215 | mode |= ATMEL_US_USMODE_RS485; | 1220 | mode |= ATMEL_US_USMODE_RS485; |
1216 | } else { | 1221 | } else { |
1217 | dev_dbg(port->dev, "Setting UART to RS232\n"); | 1222 | dev_dbg(port->dev, "Setting UART to RS232\n"); |
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 511cbf687877..a9eff2b18eab 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
@@ -957,15 +957,12 @@ bfin_serial_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
957 | * Enable the IrDA function if tty->ldisc.num is N_IRDA. | 957 | * Enable the IrDA function if tty->ldisc.num is N_IRDA. |
958 | * In other cases, disable IrDA function. | 958 | * In other cases, disable IrDA function. |
959 | */ | 959 | */ |
960 | static void bfin_serial_set_ldisc(struct uart_port *port) | 960 | static void bfin_serial_set_ldisc(struct uart_port *port, int ld) |
961 | { | 961 | { |
962 | int line = port->line; | 962 | int line = port->line; |
963 | unsigned short val; | 963 | unsigned short val; |
964 | 964 | ||
965 | if (line >= port->state->port.tty->driver->num) | 965 | switch (ld) { |
966 | return; | ||
967 | |||
968 | switch (port->state->port.tty->termios->c_line) { | ||
969 | case N_IRDA: | 966 | case N_IRDA: |
970 | val = UART_GET_GCTL(&bfin_serial_ports[line]); | 967 | val = UART_GET_GCTL(&bfin_serial_ports[line]); |
971 | val |= (IREN | RPOLC); | 968 | val |= (IREN | RPOLC); |
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 30626440a062..c856905bb3bd 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c | |||
@@ -3935,7 +3935,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
3935 | * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO | 3935 | * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO |
3936 | * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k) | 3936 | * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k) |
3937 | */ | 3937 | */ |
3938 | lock_kernel(); | ||
3939 | orig_jiffies = jiffies; | 3938 | orig_jiffies = jiffies; |
3940 | while (info->xmit.head != info->xmit.tail || /* More in send queue */ | 3939 | while (info->xmit.head != info->xmit.tail || /* More in send queue */ |
3941 | (*info->ostatusadr & 0x007f) || /* more in FIFO */ | 3940 | (*info->ostatusadr & 0x007f) || /* more in FIFO */ |
@@ -3952,7 +3951,6 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
3952 | curr_time_usec - info->last_tx_active_usec; | 3951 | curr_time_usec - info->last_tx_active_usec; |
3953 | } | 3952 | } |
3954 | set_current_state(TASK_RUNNING); | 3953 | set_current_state(TASK_RUNNING); |
3955 | unlock_kernel(); | ||
3956 | } | 3954 | } |
3957 | 3955 | ||
3958 | /* | 3956 | /* |
@@ -3992,7 +3990,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp, | |||
3992 | */ | 3990 | */ |
3993 | if (tty_hung_up_p(filp) || | 3991 | if (tty_hung_up_p(filp) || |
3994 | (info->flags & ASYNC_CLOSING)) { | 3992 | (info->flags & ASYNC_CLOSING)) { |
3995 | wait_event_interruptible(info->close_wait, | 3993 | wait_event_interruptible_tty(info->close_wait, |
3996 | !(info->flags & ASYNC_CLOSING)); | 3994 | !(info->flags & ASYNC_CLOSING)); |
3997 | #ifdef SERIAL_DO_RESTART | 3995 | #ifdef SERIAL_DO_RESTART |
3998 | if (info->flags & ASYNC_HUP_NOTIFY) | 3996 | if (info->flags & ASYNC_HUP_NOTIFY) |
@@ -4068,7 +4066,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp, | |||
4068 | printk("block_til_ready blocking: ttyS%d, count = %d\n", | 4066 | printk("block_til_ready blocking: ttyS%d, count = %d\n", |
4069 | info->line, info->count); | 4067 | info->line, info->count); |
4070 | #endif | 4068 | #endif |
4069 | tty_unlock(); | ||
4071 | schedule(); | 4070 | schedule(); |
4071 | tty_lock(); | ||
4072 | } | 4072 | } |
4073 | set_current_state(TASK_RUNNING); | 4073 | set_current_state(TASK_RUNNING); |
4074 | remove_wait_queue(&info->open_wait, &wait); | 4074 | remove_wait_queue(&info->open_wait, &wait); |
@@ -4150,7 +4150,7 @@ rs_open(struct tty_struct *tty, struct file * filp) | |||
4150 | */ | 4150 | */ |
4151 | if (tty_hung_up_p(filp) || | 4151 | if (tty_hung_up_p(filp) || |
4152 | (info->flags & ASYNC_CLOSING)) { | 4152 | (info->flags & ASYNC_CLOSING)) { |
4153 | wait_event_interruptible(info->close_wait, | 4153 | wait_event_interruptible_tty(info->close_wait, |
4154 | !(info->flags & ASYNC_CLOSING)); | 4154 | !(info->flags & ASYNC_CLOSING)); |
4155 | #ifdef SERIAL_DO_RESTART | 4155 | #ifdef SERIAL_DO_RESTART |
4156 | return ((info->flags & ASYNC_HUP_NOTIFY) ? | 4156 | return ((info->flags & ASYNC_HUP_NOTIFY) ? |
@@ -4533,8 +4533,8 @@ static int __init rs_init(void) | |||
4533 | INIT_WORK(&info->work, do_softint); | 4533 | INIT_WORK(&info->work, do_softint); |
4534 | 4534 | ||
4535 | if (info->enabled) { | 4535 | if (info->enabled) { |
4536 | printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n", | 4536 | printk(KERN_INFO "%s%d at %p is a builtin UART with DMA\n", |
4537 | serial_driver->name, info->line, (unsigned int)info->ioport); | 4537 | serial_driver->name, info->line, info->ioport); |
4538 | } | 4538 | } |
4539 | } | 4539 | } |
4540 | #ifdef CONFIG_ETRAX_FAST_TIMER | 4540 | #ifdef CONFIG_ETRAX_FAST_TIMER |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index eacb588a9345..66ecc7ab6dab 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -909,13 +909,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, | |||
909 | rational_best_approximation(16 * div * baud, sport->port.uartclk, | 909 | rational_best_approximation(16 * div * baud, sport->port.uartclk, |
910 | 1 << 16, 1 << 16, &num, &denom); | 910 | 1 << 16, 1 << 16, &num, &denom); |
911 | 911 | ||
912 | if (port->state && port->state->port.tty) { | 912 | tdiv64 = sport->port.uartclk; |
913 | tdiv64 = sport->port.uartclk; | 913 | tdiv64 *= num; |
914 | tdiv64 *= num; | 914 | do_div(tdiv64, denom * 16 * div); |
915 | do_div(tdiv64, denom * 16 * div); | 915 | tty_termios_encode_baud_rate(termios, |
916 | tty_encode_baud_rate(sport->port.state->port.tty, | ||
917 | (speed_t)tdiv64, (speed_t)tdiv64); | 916 | (speed_t)tdiv64, (speed_t)tdiv64); |
918 | } | ||
919 | 917 | ||
920 | num -= 1; | 918 | num -= 1; |
921 | denom -= 1; | 919 | denom -= 1; |
diff --git a/drivers/serial/ioc3_serial.c b/drivers/serial/ioc3_serial.c index f164ba4eba02..93de907b1208 100644 --- a/drivers/serial/ioc3_serial.c +++ b/drivers/serial/ioc3_serial.c | |||
@@ -954,12 +954,13 @@ ioc3_change_speed(struct uart_port *the_port, | |||
954 | struct ktermios *new_termios, struct ktermios *old_termios) | 954 | struct ktermios *new_termios, struct ktermios *old_termios) |
955 | { | 955 | { |
956 | struct ioc3_port *port = get_ioc3_port(the_port); | 956 | struct ioc3_port *port = get_ioc3_port(the_port); |
957 | unsigned int cflag; | 957 | unsigned int cflag, iflag; |
958 | int baud; | 958 | int baud; |
959 | int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; | 959 | int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; |
960 | struct uart_state *state = the_port->state; | 960 | struct uart_state *state = the_port->state; |
961 | 961 | ||
962 | cflag = new_termios->c_cflag; | 962 | cflag = new_termios->c_cflag; |
963 | iflag = new_termios->c_iflag; | ||
963 | 964 | ||
964 | switch (cflag & CSIZE) { | 965 | switch (cflag & CSIZE) { |
965 | case CS5: | 966 | case CS5: |
@@ -1000,12 +1001,12 @@ ioc3_change_speed(struct uart_port *the_port, | |||
1000 | 1001 | ||
1001 | state->port.tty->low_latency = 1; | 1002 | state->port.tty->low_latency = 1; |
1002 | 1003 | ||
1003 | if (I_IGNPAR(state->port.tty)) | 1004 | if (iflag & IGNPAR) |
1004 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR | 1005 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR |
1005 | | N_FRAMING_ERROR); | 1006 | | N_FRAMING_ERROR); |
1006 | if (I_IGNBRK(state->port.tty)) { | 1007 | if (iflag & IGNBRK) { |
1007 | the_port->ignore_status_mask &= ~N_BREAK; | 1008 | the_port->ignore_status_mask &= ~N_BREAK; |
1008 | if (I_IGNPAR(state->port.tty)) | 1009 | if (iflag & IGNPAR) |
1009 | the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; | 1010 | the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; |
1010 | } | 1011 | } |
1011 | if (!(cflag & CREAD)) { | 1012 | if (!(cflag & CREAD)) { |
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 8ad28fc64926..fcfe82653ac8 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c | |||
@@ -1685,11 +1685,12 @@ ioc4_change_speed(struct uart_port *the_port, | |||
1685 | { | 1685 | { |
1686 | struct ioc4_port *port = get_ioc4_port(the_port, 0); | 1686 | struct ioc4_port *port = get_ioc4_port(the_port, 0); |
1687 | int baud, bits; | 1687 | int baud, bits; |
1688 | unsigned cflag; | 1688 | unsigned cflag, iflag; |
1689 | int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; | 1689 | int new_parity = 0, new_parity_enable = 0, new_stop = 0, new_data = 8; |
1690 | struct uart_state *state = the_port->state; | 1690 | struct uart_state *state = the_port->state; |
1691 | 1691 | ||
1692 | cflag = new_termios->c_cflag; | 1692 | cflag = new_termios->c_cflag; |
1693 | iflag = new_termios->c_iflag; | ||
1693 | 1694 | ||
1694 | switch (cflag & CSIZE) { | 1695 | switch (cflag & CSIZE) { |
1695 | case CS5: | 1696 | case CS5: |
@@ -1741,12 +1742,12 @@ ioc4_change_speed(struct uart_port *the_port, | |||
1741 | 1742 | ||
1742 | state->port.tty->low_latency = 1; | 1743 | state->port.tty->low_latency = 1; |
1743 | 1744 | ||
1744 | if (I_IGNPAR(state->port.tty)) | 1745 | if (iflag & IGNPAR) |
1745 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR | 1746 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR |
1746 | | N_FRAMING_ERROR); | 1747 | | N_FRAMING_ERROR); |
1747 | if (I_IGNBRK(state->port.tty)) { | 1748 | if (iflag & IGNBRK) { |
1748 | the_port->ignore_status_mask &= ~N_BREAK; | 1749 | the_port->ignore_status_mask &= ~N_BREAK; |
1749 | if (I_IGNPAR(state->port.tty)) | 1750 | if (iflag & IGNPAR) |
1750 | the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; | 1751 | the_port->ignore_status_mask &= ~N_OVERRUN_ERROR; |
1751 | } | 1752 | } |
1752 | if (!(cflag & CREAD)) { | 1753 | if (!(cflag & CREAD)) { |
diff --git a/drivers/serial/max3100.c b/drivers/serial/max3100.c index 3351c3bd59e4..beb1afa27d8d 100644 --- a/drivers/serial/max3100.c +++ b/drivers/serial/max3100.c | |||
@@ -430,17 +430,14 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios, | |||
430 | int baud = 0; | 430 | int baud = 0; |
431 | unsigned cflag; | 431 | unsigned cflag; |
432 | u32 param_new, param_mask, parity = 0; | 432 | u32 param_new, param_mask, parity = 0; |
433 | struct tty_struct *tty = s->port.state->port.tty; | ||
434 | 433 | ||
435 | dev_dbg(&s->spi->dev, "%s\n", __func__); | 434 | dev_dbg(&s->spi->dev, "%s\n", __func__); |
436 | if (!tty) | ||
437 | return; | ||
438 | 435 | ||
439 | cflag = termios->c_cflag; | 436 | cflag = termios->c_cflag; |
440 | param_new = 0; | 437 | param_new = 0; |
441 | param_mask = 0; | 438 | param_mask = 0; |
442 | 439 | ||
443 | baud = tty_get_baud_rate(tty); | 440 | baud = tty_termios_baud_rate(termios); |
444 | param_new = s->conf & MAX3100_BAUD; | 441 | param_new = s->conf & MAX3100_BAUD; |
445 | switch (baud) { | 442 | switch (baud) { |
446 | case 300: | 443 | case 300: |
@@ -485,7 +482,7 @@ max3100_set_termios(struct uart_port *port, struct ktermios *termios, | |||
485 | default: | 482 | default: |
486 | baud = s->baud; | 483 | baud = s->baud; |
487 | } | 484 | } |
488 | tty_encode_baud_rate(tty, baud, baud); | 485 | tty_termios_encode_baud_rate(termios, baud, baud); |
489 | s->baud = baud; | 486 | s->baud = baud; |
490 | param_mask |= MAX3100_BAUD; | 487 | param_mask |= MAX3100_BAUD; |
491 | 488 | ||
diff --git a/drivers/serial/max3107-aava.c b/drivers/serial/max3107-aava.c new file mode 100644 index 000000000000..a1fe304f2f52 --- /dev/null +++ b/drivers/serial/max3107-aava.c | |||
@@ -0,0 +1,344 @@ | |||
1 | /* | ||
2 | * max3107.c - spi uart protocol driver for Maxim 3107 | ||
3 | * Based on max3100.c | ||
4 | * by Christian Pellegrin <chripell@evolware.org> | ||
5 | * and max3110.c | ||
6 | * by Feng Tang <feng.tang@intel.com> | ||
7 | * | ||
8 | * Copyright (C) Aavamobile 2009 | ||
9 | * | ||
10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include <linux/delay.h> | ||
31 | #include <linux/device.h> | ||
32 | #include <linux/serial_core.h> | ||
33 | #include <linux/serial.h> | ||
34 | #include <linux/spi/spi.h> | ||
35 | #include <linux/freezer.h> | ||
36 | #include <linux/platform_device.h> | ||
37 | #include <linux/gpio.h> | ||
38 | #include <linux/sfi.h> | ||
39 | #include <asm/mrst.h> | ||
40 | #include "max3107.h" | ||
41 | |||
42 | /* GPIO direction to input function */ | ||
43 | static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | ||
44 | { | ||
45 | struct max3107_port *s = container_of(chip, struct max3107_port, chip); | ||
46 | u16 buf[1]; /* Buffer for SPI transfer */ | ||
47 | |||
48 | if (offset >= MAX3107_GPIO_COUNT) { | ||
49 | dev_err(&s->spi->dev, "Invalid GPIO\n"); | ||
50 | return -EINVAL; | ||
51 | } | ||
52 | |||
53 | /* Read current GPIO configuration register */ | ||
54 | buf[0] = MAX3107_GPIOCFG_REG; | ||
55 | /* Perform SPI transfer */ | ||
56 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { | ||
57 | dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n"); | ||
58 | return -EIO; | ||
59 | } | ||
60 | buf[0] &= MAX3107_SPI_RX_DATA_MASK; | ||
61 | |||
62 | /* Set GPIO to input */ | ||
63 | buf[0] &= ~(0x0001 << offset); | ||
64 | |||
65 | /* Write new GPIO configuration register value */ | ||
66 | buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); | ||
67 | /* Perform SPI transfer */ | ||
68 | if (max3107_rw(s, (u8 *)buf, NULL, 2)) { | ||
69 | dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n"); | ||
70 | return -EIO; | ||
71 | } | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | /* GPIO direction to output function */ | ||
76 | static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset, | ||
77 | int value) | ||
78 | { | ||
79 | struct max3107_port *s = container_of(chip, struct max3107_port, chip); | ||
80 | u16 buf[2]; /* Buffer for SPI transfers */ | ||
81 | |||
82 | if (offset >= MAX3107_GPIO_COUNT) { | ||
83 | dev_err(&s->spi->dev, "Invalid GPIO\n"); | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | |||
87 | /* Read current GPIO configuration and data registers */ | ||
88 | buf[0] = MAX3107_GPIOCFG_REG; | ||
89 | buf[1] = MAX3107_GPIODATA_REG; | ||
90 | /* Perform SPI transfer */ | ||
91 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { | ||
92 | dev_err(&s->spi->dev, "SPI transfer gpio failed\n"); | ||
93 | return -EIO; | ||
94 | } | ||
95 | buf[0] &= MAX3107_SPI_RX_DATA_MASK; | ||
96 | buf[1] &= MAX3107_SPI_RX_DATA_MASK; | ||
97 | |||
98 | /* Set GPIO to output */ | ||
99 | buf[0] |= (0x0001 << offset); | ||
100 | /* Set value */ | ||
101 | if (value) | ||
102 | buf[1] |= (0x0001 << offset); | ||
103 | else | ||
104 | buf[1] &= ~(0x0001 << offset); | ||
105 | |||
106 | /* Write new GPIO configuration and data register values */ | ||
107 | buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG); | ||
108 | buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); | ||
109 | /* Perform SPI transfer */ | ||
110 | if (max3107_rw(s, (u8 *)buf, NULL, 4)) { | ||
111 | dev_err(&s->spi->dev, | ||
112 | "SPI transfer for GPIO conf data w failed\n"); | ||
113 | return -EIO; | ||
114 | } | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | /* GPIO value query function */ | ||
119 | static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
120 | { | ||
121 | struct max3107_port *s = container_of(chip, struct max3107_port, chip); | ||
122 | u16 buf[1]; /* Buffer for SPI transfer */ | ||
123 | |||
124 | if (offset >= MAX3107_GPIO_COUNT) { | ||
125 | dev_err(&s->spi->dev, "Invalid GPIO\n"); | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | /* Read current GPIO data register */ | ||
130 | buf[0] = MAX3107_GPIODATA_REG; | ||
131 | /* Perform SPI transfer */ | ||
132 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { | ||
133 | dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n"); | ||
134 | return -EIO; | ||
135 | } | ||
136 | buf[0] &= MAX3107_SPI_RX_DATA_MASK; | ||
137 | |||
138 | /* Return value */ | ||
139 | return buf[0] & (0x0001 << offset); | ||
140 | } | ||
141 | |||
142 | /* GPIO value set function */ | ||
143 | static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
144 | { | ||
145 | struct max3107_port *s = container_of(chip, struct max3107_port, chip); | ||
146 | u16 buf[2]; /* Buffer for SPI transfers */ | ||
147 | |||
148 | if (offset >= MAX3107_GPIO_COUNT) { | ||
149 | dev_err(&s->spi->dev, "Invalid GPIO\n"); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | /* Read current GPIO configuration registers*/ | ||
154 | buf[0] = MAX3107_GPIODATA_REG; | ||
155 | buf[1] = MAX3107_GPIOCFG_REG; | ||
156 | /* Perform SPI transfer */ | ||
157 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) { | ||
158 | dev_err(&s->spi->dev, | ||
159 | "SPI transfer for GPIO data and config read failed\n"); | ||
160 | return; | ||
161 | } | ||
162 | buf[0] &= MAX3107_SPI_RX_DATA_MASK; | ||
163 | buf[1] &= MAX3107_SPI_RX_DATA_MASK; | ||
164 | |||
165 | if (!(buf[1] & (0x0001 << offset))) { | ||
166 | /* Configured as input, can't set value */ | ||
167 | dev_warn(&s->spi->dev, | ||
168 | "Trying to set value for input GPIO\n"); | ||
169 | return; | ||
170 | } | ||
171 | |||
172 | /* Set value */ | ||
173 | if (value) | ||
174 | buf[0] |= (0x0001 << offset); | ||
175 | else | ||
176 | buf[0] &= ~(0x0001 << offset); | ||
177 | |||
178 | /* Write new GPIO data register value */ | ||
179 | buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG); | ||
180 | /* Perform SPI transfer */ | ||
181 | if (max3107_rw(s, (u8 *)buf, NULL, 2)) | ||
182 | dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n"); | ||
183 | } | ||
184 | |||
185 | /* GPIO chip data */ | ||
186 | static struct gpio_chip max3107_gpio_chip = { | ||
187 | .owner = THIS_MODULE, | ||
188 | .direction_input = max3107_gpio_direction_in, | ||
189 | .direction_output = max3107_gpio_direction_out, | ||
190 | .get = max3107_gpio_get, | ||
191 | .set = max3107_gpio_set, | ||
192 | .can_sleep = 1, | ||
193 | .base = MAX3107_GPIO_BASE, | ||
194 | .ngpio = MAX3107_GPIO_COUNT, | ||
195 | }; | ||
196 | |||
197 | /** | ||
198 | * max3107_aava_reset - reset on AAVA systems | ||
199 | * @spi: The SPI device we are probing | ||
200 | * | ||
201 | * Reset the device ready for probing. | ||
202 | */ | ||
203 | |||
204 | static int max3107_aava_reset(struct spi_device *spi) | ||
205 | { | ||
206 | /* Reset the chip */ | ||
207 | if (gpio_request(MAX3107_RESET_GPIO, "max3107")) { | ||
208 | pr_err("Requesting RESET GPIO failed\n"); | ||
209 | return -EIO; | ||
210 | } | ||
211 | if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) { | ||
212 | pr_err("Setting RESET GPIO to 0 failed\n"); | ||
213 | gpio_free(MAX3107_RESET_GPIO); | ||
214 | return -EIO; | ||
215 | } | ||
216 | msleep(MAX3107_RESET_DELAY); | ||
217 | if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) { | ||
218 | pr_err("Setting RESET GPIO to 1 failed\n"); | ||
219 | gpio_free(MAX3107_RESET_GPIO); | ||
220 | return -EIO; | ||
221 | } | ||
222 | gpio_free(MAX3107_RESET_GPIO); | ||
223 | msleep(MAX3107_WAKEUP_DELAY); | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int max3107_aava_configure(struct max3107_port *s) | ||
228 | { | ||
229 | int retval; | ||
230 | |||
231 | /* Initialize GPIO chip data */ | ||
232 | s->chip = max3107_gpio_chip; | ||
233 | s->chip.label = s->spi->modalias; | ||
234 | s->chip.dev = &s->spi->dev; | ||
235 | |||
236 | /* Add GPIO chip */ | ||
237 | retval = gpiochip_add(&s->chip); | ||
238 | if (retval) { | ||
239 | dev_err(&s->spi->dev, "Adding GPIO chip failed\n"); | ||
240 | return retval; | ||
241 | } | ||
242 | |||
243 | /* Temporary fix for EV2 boot problems, set modem reset to 0 */ | ||
244 | max3107_gpio_direction_out(&s->chip, 3, 0); | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | #if 0 | ||
249 | /* This will get enabled once we have the board stuff merged for this | ||
250 | specific case */ | ||
251 | |||
252 | static const struct baud_table brg13_ext[] = { | ||
253 | { 300, MAX3107_BRG13_B300 }, | ||
254 | { 600, MAX3107_BRG13_B600 }, | ||
255 | { 1200, MAX3107_BRG13_B1200 }, | ||
256 | { 2400, MAX3107_BRG13_B2400 }, | ||
257 | { 4800, MAX3107_BRG13_B4800 }, | ||
258 | { 9600, MAX3107_BRG13_B9600 }, | ||
259 | { 19200, MAX3107_BRG13_B19200 }, | ||
260 | { 57600, MAX3107_BRG13_B57600 }, | ||
261 | { 115200, MAX3107_BRG13_B115200 }, | ||
262 | { 230400, MAX3107_BRG13_B230400 }, | ||
263 | { 460800, MAX3107_BRG13_B460800 }, | ||
264 | { 921600, MAX3107_BRG13_B921600 }, | ||
265 | { 0, 0 } | ||
266 | }; | ||
267 | |||
268 | static void max3107_aava_init(struct max3107_port *s) | ||
269 | { | ||
270 | /*override for AAVA SC specific*/ | ||
271 | if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) { | ||
272 | if (get_koski_build_id() <= KOSKI_EV2) | ||
273 | if (s->ext_clk) { | ||
274 | s->brg_cfg = MAX3107_BRG13_B9600; | ||
275 | s->baud_tbl = (struct baud_table *)brg13_ext; | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | #endif | ||
280 | |||
281 | static int __devexit max3107_aava_remove(struct spi_device *spi) | ||
282 | { | ||
283 | struct max3107_port *s = dev_get_drvdata(&spi->dev); | ||
284 | |||
285 | /* Remove GPIO chip */ | ||
286 | if (gpiochip_remove(&s->chip)) | ||
287 | dev_warn(&spi->dev, "Removing GPIO chip failed\n"); | ||
288 | |||
289 | /* Then do the default remove */ | ||
290 | return max3107_remove(spi); | ||
291 | } | ||
292 | |||
293 | /* Platform data */ | ||
294 | static struct max3107_plat aava_plat_data = { | ||
295 | .loopback = 0, | ||
296 | .ext_clk = 1, | ||
297 | /* .init = max3107_aava_init, */ | ||
298 | .configure = max3107_aava_configure, | ||
299 | .hw_suspend = max3107_hw_susp, | ||
300 | .polled_mode = 0, | ||
301 | .poll_time = 0, | ||
302 | }; | ||
303 | |||
304 | |||
305 | static int __devinit max3107_probe_aava(struct spi_device *spi) | ||
306 | { | ||
307 | int err = max3107_aava_reset(spi); | ||
308 | if (err < 0) | ||
309 | return err; | ||
310 | return max3107_probe(spi, &aava_plat_data); | ||
311 | } | ||
312 | |||
313 | /* Spi driver data */ | ||
314 | static struct spi_driver max3107_driver = { | ||
315 | .driver = { | ||
316 | .name = "aava-max3107", | ||
317 | .bus = &spi_bus_type, | ||
318 | .owner = THIS_MODULE, | ||
319 | }, | ||
320 | .probe = max3107_probe_aava, | ||
321 | .remove = __devexit_p(max3107_aava_remove), | ||
322 | .suspend = max3107_suspend, | ||
323 | .resume = max3107_resume, | ||
324 | }; | ||
325 | |||
326 | /* Driver init function */ | ||
327 | static int __init max3107_init(void) | ||
328 | { | ||
329 | return spi_register_driver(&max3107_driver); | ||
330 | } | ||
331 | |||
332 | /* Driver exit function */ | ||
333 | static void __exit max3107_exit(void) | ||
334 | { | ||
335 | spi_unregister_driver(&max3107_driver); | ||
336 | } | ||
337 | |||
338 | module_init(max3107_init); | ||
339 | module_exit(max3107_exit); | ||
340 | |||
341 | MODULE_DESCRIPTION("MAX3107 driver"); | ||
342 | MODULE_AUTHOR("Aavamobile"); | ||
343 | MODULE_ALIAS("aava-max3107-spi"); | ||
344 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/serial/max3107.c b/drivers/serial/max3107.c new file mode 100644 index 000000000000..67283c1a57ff --- /dev/null +++ b/drivers/serial/max3107.c | |||
@@ -0,0 +1,1197 @@ | |||
1 | /* | ||
2 | * max3107.c - spi uart protocol driver for Maxim 3107 | ||
3 | * Based on max3100.c | ||
4 | * by Christian Pellegrin <chripell@evolware.org> | ||
5 | * and max3110.c | ||
6 | * by Feng Tang <feng.tang@intel.com> | ||
7 | * | ||
8 | * Copyright (C) Aavamobile 2009 | ||
9 | * | ||
10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
27 | * | ||
28 | */ | ||
29 | |||
30 | #include <linux/delay.h> | ||
31 | #include <linux/device.h> | ||
32 | #include <linux/serial_core.h> | ||
33 | #include <linux/serial.h> | ||
34 | #include <linux/gpio.h> | ||
35 | #include <linux/spi/spi.h> | ||
36 | #include <linux/freezer.h> | ||
37 | #include "max3107.h" | ||
38 | |||
39 | static const struct baud_table brg26_ext[] = { | ||
40 | { 300, MAX3107_BRG26_B300 }, | ||
41 | { 600, MAX3107_BRG26_B600 }, | ||
42 | { 1200, MAX3107_BRG26_B1200 }, | ||
43 | { 2400, MAX3107_BRG26_B2400 }, | ||
44 | { 4800, MAX3107_BRG26_B4800 }, | ||
45 | { 9600, MAX3107_BRG26_B9600 }, | ||
46 | { 19200, MAX3107_BRG26_B19200 }, | ||
47 | { 57600, MAX3107_BRG26_B57600 }, | ||
48 | { 115200, MAX3107_BRG26_B115200 }, | ||
49 | { 230400, MAX3107_BRG26_B230400 }, | ||
50 | { 460800, MAX3107_BRG26_B460800 }, | ||
51 | { 921600, MAX3107_BRG26_B921600 }, | ||
52 | { 0, 0 } | ||
53 | }; | ||
54 | |||
55 | static const struct baud_table brg13_int[] = { | ||
56 | { 300, MAX3107_BRG13_IB300 }, | ||
57 | { 600, MAX3107_BRG13_IB600 }, | ||
58 | { 1200, MAX3107_BRG13_IB1200 }, | ||
59 | { 2400, MAX3107_BRG13_IB2400 }, | ||
60 | { 4800, MAX3107_BRG13_IB4800 }, | ||
61 | { 9600, MAX3107_BRG13_IB9600 }, | ||
62 | { 19200, MAX3107_BRG13_IB19200 }, | ||
63 | { 57600, MAX3107_BRG13_IB57600 }, | ||
64 | { 115200, MAX3107_BRG13_IB115200 }, | ||
65 | { 230400, MAX3107_BRG13_IB230400 }, | ||
66 | { 460800, MAX3107_BRG13_IB460800 }, | ||
67 | { 921600, MAX3107_BRG13_IB921600 }, | ||
68 | { 0, 0 } | ||
69 | }; | ||
70 | |||
71 | static u32 get_new_brg(int baud, struct max3107_port *s) | ||
72 | { | ||
73 | int i; | ||
74 | const struct baud_table *baud_tbl = s->baud_tbl; | ||
75 | |||
76 | for (i = 0; i < 13; i++) { | ||
77 | if (baud == baud_tbl[i].baud) | ||
78 | return baud_tbl[i].new_brg; | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | /* Perform SPI transfer for write/read of device register(s) */ | ||
85 | int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len) | ||
86 | { | ||
87 | struct spi_message spi_msg; | ||
88 | struct spi_transfer spi_xfer; | ||
89 | |||
90 | /* Initialize SPI ,message */ | ||
91 | spi_message_init(&spi_msg); | ||
92 | |||
93 | /* Initialize SPI transfer */ | ||
94 | memset(&spi_xfer, 0, sizeof spi_xfer); | ||
95 | spi_xfer.len = len; | ||
96 | spi_xfer.tx_buf = tx; | ||
97 | spi_xfer.rx_buf = rx; | ||
98 | spi_xfer.speed_hz = MAX3107_SPI_SPEED; | ||
99 | |||
100 | /* Add SPI transfer to SPI message */ | ||
101 | spi_message_add_tail(&spi_xfer, &spi_msg); | ||
102 | |||
103 | #ifdef DBG_TRACE_SPI_DATA | ||
104 | { | ||
105 | int i; | ||
106 | pr_info("tx len %d:\n", spi_xfer.len); | ||
107 | for (i = 0 ; i < spi_xfer.len && i < 32 ; i++) | ||
108 | pr_info(" %x", ((u8 *)spi_xfer.tx_buf)[i]); | ||
109 | pr_info("\n"); | ||
110 | } | ||
111 | #endif | ||
112 | |||
113 | /* Perform synchronous SPI transfer */ | ||
114 | if (spi_sync(s->spi, &spi_msg)) { | ||
115 | dev_err(&s->spi->dev, "spi_sync failure\n"); | ||
116 | return -EIO; | ||
117 | } | ||
118 | |||
119 | #ifdef DBG_TRACE_SPI_DATA | ||
120 | if (spi_xfer.rx_buf) { | ||
121 | int i; | ||
122 | pr_info("rx len %d:\n", spi_xfer.len); | ||
123 | for (i = 0 ; i < spi_xfer.len && i < 32 ; i++) | ||
124 | pr_info(" %x", ((u8 *)spi_xfer.rx_buf)[i]); | ||
125 | pr_info("\n"); | ||
126 | } | ||
127 | #endif | ||
128 | return 0; | ||
129 | } | ||
130 | EXPORT_SYMBOL_GPL(max3107_rw); | ||
131 | |||
132 | /* Puts received data to circular buffer */ | ||
133 | static void put_data_to_circ_buf(struct max3107_port *s, unsigned char *data, | ||
134 | int len) | ||
135 | { | ||
136 | struct uart_port *port = &s->port; | ||
137 | struct tty_struct *tty; | ||
138 | |||
139 | if (!port->state) | ||
140 | return; | ||
141 | |||
142 | tty = port->state->port.tty; | ||
143 | if (!tty) | ||
144 | return; | ||
145 | |||
146 | /* Insert received data */ | ||
147 | tty_insert_flip_string(tty, data, len); | ||
148 | /* Update RX counter */ | ||
149 | port->icount.rx += len; | ||
150 | } | ||
151 | |||
152 | /* Handle data receiving */ | ||
153 | static void max3107_handlerx(struct max3107_port *s, u16 rxlvl) | ||
154 | { | ||
155 | int i; | ||
156 | int j; | ||
157 | int len; /* SPI transfer buffer length */ | ||
158 | u16 *buf; | ||
159 | u8 *valid_str; | ||
160 | |||
161 | if (!s->rx_enabled) | ||
162 | /* RX is disabled */ | ||
163 | return; | ||
164 | |||
165 | if (rxlvl == 0) { | ||
166 | /* RX fifo is empty */ | ||
167 | return; | ||
168 | } else if (rxlvl >= MAX3107_RX_FIFO_SIZE) { | ||
169 | dev_warn(&s->spi->dev, "Possible RX FIFO overrun %d\n", rxlvl); | ||
170 | /* Ensure sanity of RX level */ | ||
171 | rxlvl = MAX3107_RX_FIFO_SIZE; | ||
172 | } | ||
173 | if ((s->rxbuf == 0) || (s->rxstr == 0)) { | ||
174 | dev_warn(&s->spi->dev, "Rx buffer/str isn't ready\n"); | ||
175 | return; | ||
176 | } | ||
177 | buf = s->rxbuf; | ||
178 | valid_str = s->rxstr; | ||
179 | while (rxlvl) { | ||
180 | pr_debug("rxlvl %d\n", rxlvl); | ||
181 | /* Clear buffer */ | ||
182 | memset(buf, 0, sizeof(u16) * (MAX3107_RX_FIFO_SIZE + 2)); | ||
183 | len = 0; | ||
184 | if (s->irqen_reg & MAX3107_IRQ_RXFIFO_BIT) { | ||
185 | /* First disable RX FIFO interrupt */ | ||
186 | pr_debug("Disabling RX INT\n"); | ||
187 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); | ||
188 | s->irqen_reg &= ~MAX3107_IRQ_RXFIFO_BIT; | ||
189 | buf[0] |= s->irqen_reg; | ||
190 | len++; | ||
191 | } | ||
192 | /* Just increase the length by amount of words in FIFO since | ||
193 | * buffer was zeroed and SPI transfer of 0x0000 means reading | ||
194 | * from RX FIFO | ||
195 | */ | ||
196 | len += rxlvl; | ||
197 | /* Append RX level query */ | ||
198 | buf[len] = MAX3107_RXFIFOLVL_REG; | ||
199 | len++; | ||
200 | |||
201 | /* Perform the SPI transfer */ | ||
202 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, len * 2)) { | ||
203 | dev_err(&s->spi->dev, "SPI transfer for RX h failed\n"); | ||
204 | return; | ||
205 | } | ||
206 | |||
207 | /* Skip RX FIFO interrupt disabling word if it was added */ | ||
208 | j = ((len - 1) - rxlvl); | ||
209 | /* Read received words */ | ||
210 | for (i = 0; i < rxlvl; i++, j++) | ||
211 | valid_str[i] = (u8)buf[j]; | ||
212 | put_data_to_circ_buf(s, valid_str, rxlvl); | ||
213 | /* Get new RX level */ | ||
214 | rxlvl = (buf[len - 1] & MAX3107_SPI_RX_DATA_MASK); | ||
215 | } | ||
216 | |||
217 | if (s->rx_enabled) { | ||
218 | /* RX still enabled, re-enable RX FIFO interrupt */ | ||
219 | pr_debug("Enabling RX INT\n"); | ||
220 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); | ||
221 | s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT; | ||
222 | buf[0] |= s->irqen_reg; | ||
223 | if (max3107_rw(s, (u8 *)buf, NULL, 2)) | ||
224 | dev_err(&s->spi->dev, "RX FIFO INT enabling failed\n"); | ||
225 | } | ||
226 | |||
227 | /* Push the received data to receivers */ | ||
228 | if (s->port.state->port.tty) | ||
229 | tty_flip_buffer_push(s->port.state->port.tty); | ||
230 | } | ||
231 | |||
232 | |||
233 | /* Handle data sending */ | ||
234 | static void max3107_handletx(struct max3107_port *s) | ||
235 | { | ||
236 | struct circ_buf *xmit = &s->port.state->xmit; | ||
237 | int i; | ||
238 | unsigned long flags; | ||
239 | int len; /* SPI transfer buffer length */ | ||
240 | u16 *buf; | ||
241 | |||
242 | if (!s->tx_fifo_empty) | ||
243 | /* Don't send more data before previous data is sent */ | ||
244 | return; | ||
245 | |||
246 | if (uart_circ_empty(xmit) || uart_tx_stopped(&s->port)) | ||
247 | /* No data to send or TX is stopped */ | ||
248 | return; | ||
249 | |||
250 | if (!s->txbuf) { | ||
251 | dev_warn(&s->spi->dev, "Txbuf isn't ready\n"); | ||
252 | return; | ||
253 | } | ||
254 | buf = s->txbuf; | ||
255 | /* Get length of data pending in circular buffer */ | ||
256 | len = uart_circ_chars_pending(xmit); | ||
257 | if (len) { | ||
258 | /* Limit to size of TX FIFO */ | ||
259 | if (len > MAX3107_TX_FIFO_SIZE) | ||
260 | len = MAX3107_TX_FIFO_SIZE; | ||
261 | |||
262 | pr_debug("txlen %d\n", len); | ||
263 | |||
264 | /* Update TX counter */ | ||
265 | s->port.icount.tx += len; | ||
266 | |||
267 | /* TX FIFO will no longer be empty */ | ||
268 | s->tx_fifo_empty = 0; | ||
269 | |||
270 | i = 0; | ||
271 | if (s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT) { | ||
272 | /* First disable TX empty interrupt */ | ||
273 | pr_debug("Disabling TE INT\n"); | ||
274 | buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); | ||
275 | s->irqen_reg &= ~MAX3107_IRQ_TXEMPTY_BIT; | ||
276 | buf[i] |= s->irqen_reg; | ||
277 | i++; | ||
278 | len++; | ||
279 | } | ||
280 | /* Add data to send */ | ||
281 | spin_lock_irqsave(&s->port.lock, flags); | ||
282 | for ( ; i < len ; i++) { | ||
283 | buf[i] = (MAX3107_WRITE_BIT | MAX3107_THR_REG); | ||
284 | buf[i] |= ((u16)xmit->buf[xmit->tail] & | ||
285 | MAX3107_SPI_TX_DATA_MASK); | ||
286 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
287 | } | ||
288 | spin_unlock_irqrestore(&s->port.lock, flags); | ||
289 | if (!(s->irqen_reg & MAX3107_IRQ_TXEMPTY_BIT)) { | ||
290 | /* Enable TX empty interrupt */ | ||
291 | pr_debug("Enabling TE INT\n"); | ||
292 | buf[i] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG); | ||
293 | s->irqen_reg |= MAX3107_IRQ_TXEMPTY_BIT; | ||
294 | buf[i] |= s->irqen_reg; | ||
295 | i++; | ||
296 | len++; | ||
297 | } | ||
298 | if (!s->tx_enabled) { | ||
299 | /* Enable TX */ | ||
300 | pr_debug("Enable TX\n"); | ||
301 | buf[i] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); | ||
302 | spin_lock_irqsave(&s->data_lock, flags); | ||
303 | s->mode1_reg &= ~MAX3107_MODE1_TXDIS_BIT; | ||
304 | buf[i] |= s->mode1_reg; | ||
305 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
306 | s->tx_enabled = 1; | ||
307 | i++; | ||
308 | len++; | ||
309 | } | ||
310 | |||
311 | /* Perform the SPI transfer */ | ||
312 | if (max3107_rw(s, (u8 *)buf, NULL, len*2)) { | ||
313 | dev_err(&s->spi->dev, | ||
314 | "SPI transfer TX handling failed\n"); | ||
315 | return; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | /* Indicate wake up if circular buffer is getting low on data */ | ||
320 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
321 | uart_write_wakeup(&s->port); | ||
322 | |||
323 | } | ||
324 | |||
325 | /* Handle interrupts | ||
326 | * Also reads and returns current RX FIFO level | ||
327 | */ | ||
328 | static u16 handle_interrupt(struct max3107_port *s) | ||
329 | { | ||
330 | u16 buf[4]; /* Buffer for SPI transfers */ | ||
331 | u8 irq_status; | ||
332 | u16 rx_level; | ||
333 | unsigned long flags; | ||
334 | |||
335 | /* Read IRQ status register */ | ||
336 | buf[0] = MAX3107_IRQSTS_REG; | ||
337 | /* Read status IRQ status register */ | ||
338 | buf[1] = MAX3107_STS_IRQSTS_REG; | ||
339 | /* Read LSR IRQ status register */ | ||
340 | buf[2] = MAX3107_LSR_IRQSTS_REG; | ||
341 | /* Query RX level */ | ||
342 | buf[3] = MAX3107_RXFIFOLVL_REG; | ||
343 | |||
344 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 8)) { | ||
345 | dev_err(&s->spi->dev, | ||
346 | "SPI transfer for INTR handling failed\n"); | ||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | irq_status = (u8)buf[0]; | ||
351 | pr_debug("IRQSTS %x\n", irq_status); | ||
352 | rx_level = (buf[3] & MAX3107_SPI_RX_DATA_MASK); | ||
353 | |||
354 | if (irq_status & MAX3107_IRQ_LSR_BIT) { | ||
355 | /* LSR interrupt */ | ||
356 | if (buf[2] & MAX3107_LSR_RXTO_BIT) | ||
357 | /* RX timeout interrupt, | ||
358 | * handled by normal RX handling | ||
359 | */ | ||
360 | pr_debug("RX TO INT\n"); | ||
361 | } | ||
362 | |||
363 | if (irq_status & MAX3107_IRQ_TXEMPTY_BIT) { | ||
364 | /* Tx empty interrupt, | ||
365 | * disable TX and set tx_fifo_empty flag | ||
366 | */ | ||
367 | pr_debug("TE INT, disabling TX\n"); | ||
368 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); | ||
369 | spin_lock_irqsave(&s->data_lock, flags); | ||
370 | s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT; | ||
371 | buf[0] |= s->mode1_reg; | ||
372 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
373 | if (max3107_rw(s, (u8 *)buf, NULL, 2)) | ||
374 | dev_err(&s->spi->dev, "SPI transfer TX dis failed\n"); | ||
375 | s->tx_enabled = 0; | ||
376 | s->tx_fifo_empty = 1; | ||
377 | } | ||
378 | |||
379 | if (irq_status & MAX3107_IRQ_RXFIFO_BIT) | ||
380 | /* RX FIFO interrupt, | ||
381 | * handled by normal RX handling | ||
382 | */ | ||
383 | pr_debug("RFIFO INT\n"); | ||
384 | |||
385 | /* Return RX level */ | ||
386 | return rx_level; | ||
387 | } | ||
388 | |||
389 | /* Trigger work thread*/ | ||
390 | static void max3107_dowork(struct max3107_port *s) | ||
391 | { | ||
392 | if (!work_pending(&s->work) && !freezing(current) && !s->suspended) | ||
393 | queue_work(s->workqueue, &s->work); | ||
394 | else | ||
395 | dev_warn(&s->spi->dev, "interrup isn't serviced normally!\n"); | ||
396 | } | ||
397 | |||
398 | /* Work thread */ | ||
399 | static void max3107_work(struct work_struct *w) | ||
400 | { | ||
401 | struct max3107_port *s = container_of(w, struct max3107_port, work); | ||
402 | u16 rxlvl = 0; | ||
403 | int len; /* SPI transfer buffer length */ | ||
404 | u16 buf[5]; /* Buffer for SPI transfers */ | ||
405 | unsigned long flags; | ||
406 | |||
407 | /* Start by reading current RX FIFO level */ | ||
408 | buf[0] = MAX3107_RXFIFOLVL_REG; | ||
409 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { | ||
410 | dev_err(&s->spi->dev, "SPI transfer RX lev failed\n"); | ||
411 | rxlvl = 0; | ||
412 | } else { | ||
413 | rxlvl = (buf[0] & MAX3107_SPI_RX_DATA_MASK); | ||
414 | } | ||
415 | |||
416 | do { | ||
417 | pr_debug("rxlvl %d\n", rxlvl); | ||
418 | |||
419 | /* Handle RX */ | ||
420 | max3107_handlerx(s, rxlvl); | ||
421 | rxlvl = 0; | ||
422 | |||
423 | if (s->handle_irq) { | ||
424 | /* Handle pending interrupts | ||
425 | * We also get new RX FIFO level since new data may | ||
426 | * have been received while pushing received data to | ||
427 | * receivers | ||
428 | */ | ||
429 | s->handle_irq = 0; | ||
430 | rxlvl = handle_interrupt(s); | ||
431 | } | ||
432 | |||
433 | /* Handle TX */ | ||
434 | max3107_handletx(s); | ||
435 | |||
436 | /* Handle configuration changes */ | ||
437 | len = 0; | ||
438 | spin_lock_irqsave(&s->data_lock, flags); | ||
439 | if (s->mode1_commit) { | ||
440 | pr_debug("mode1_commit\n"); | ||
441 | buf[len] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); | ||
442 | buf[len++] |= s->mode1_reg; | ||
443 | s->mode1_commit = 0; | ||
444 | } | ||
445 | if (s->lcr_commit) { | ||
446 | pr_debug("lcr_commit\n"); | ||
447 | buf[len] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG); | ||
448 | buf[len++] |= s->lcr_reg; | ||
449 | s->lcr_commit = 0; | ||
450 | } | ||
451 | if (s->brg_commit) { | ||
452 | pr_debug("brg_commit\n"); | ||
453 | buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG); | ||
454 | buf[len++] |= ((s->brg_cfg >> 16) & | ||
455 | MAX3107_SPI_TX_DATA_MASK); | ||
456 | buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG); | ||
457 | buf[len++] |= ((s->brg_cfg >> 8) & | ||
458 | MAX3107_SPI_TX_DATA_MASK); | ||
459 | buf[len] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG); | ||
460 | buf[len++] |= ((s->brg_cfg) & 0xff); | ||
461 | s->brg_commit = 0; | ||
462 | } | ||
463 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
464 | |||
465 | if (len > 0) { | ||
466 | if (max3107_rw(s, (u8 *)buf, NULL, len * 2)) | ||
467 | dev_err(&s->spi->dev, | ||
468 | "SPI transfer config failed\n"); | ||
469 | } | ||
470 | |||
471 | /* Reloop if interrupt handling indicated data in RX FIFO */ | ||
472 | } while (rxlvl); | ||
473 | |||
474 | } | ||
475 | |||
476 | /* Set sleep mode */ | ||
477 | static void max3107_set_sleep(struct max3107_port *s, int mode) | ||
478 | { | ||
479 | u16 buf[1]; /* Buffer for SPI transfer */ | ||
480 | unsigned long flags; | ||
481 | pr_debug("enter, mode %d\n", mode); | ||
482 | |||
483 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG); | ||
484 | spin_lock_irqsave(&s->data_lock, flags); | ||
485 | switch (mode) { | ||
486 | case MAX3107_DISABLE_FORCED_SLEEP: | ||
487 | s->mode1_reg &= ~MAX3107_MODE1_FORCESLEEP_BIT; | ||
488 | break; | ||
489 | case MAX3107_ENABLE_FORCED_SLEEP: | ||
490 | s->mode1_reg |= MAX3107_MODE1_FORCESLEEP_BIT; | ||
491 | break; | ||
492 | case MAX3107_DISABLE_AUTOSLEEP: | ||
493 | s->mode1_reg &= ~MAX3107_MODE1_AUTOSLEEP_BIT; | ||
494 | break; | ||
495 | case MAX3107_ENABLE_AUTOSLEEP: | ||
496 | s->mode1_reg |= MAX3107_MODE1_AUTOSLEEP_BIT; | ||
497 | break; | ||
498 | default: | ||
499 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
500 | dev_warn(&s->spi->dev, "invalid sleep mode\n"); | ||
501 | return; | ||
502 | } | ||
503 | buf[0] |= s->mode1_reg; | ||
504 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
505 | |||
506 | if (max3107_rw(s, (u8 *)buf, NULL, 2)) | ||
507 | dev_err(&s->spi->dev, "SPI transfer sleep mode failed\n"); | ||
508 | |||
509 | if (mode == MAX3107_DISABLE_AUTOSLEEP || | ||
510 | mode == MAX3107_DISABLE_FORCED_SLEEP) | ||
511 | msleep(MAX3107_WAKEUP_DELAY); | ||
512 | } | ||
513 | |||
514 | /* Perform full register initialization */ | ||
515 | static void max3107_register_init(struct max3107_port *s) | ||
516 | { | ||
517 | u16 buf[11]; /* Buffer for SPI transfers */ | ||
518 | |||
519 | /* 1. Configure baud rate, 9600 as default */ | ||
520 | s->baud = 9600; | ||
521 | /* the below is default*/ | ||
522 | if (s->ext_clk) { | ||
523 | s->brg_cfg = MAX3107_BRG26_B9600; | ||
524 | s->baud_tbl = (struct baud_table *)brg26_ext; | ||
525 | } else { | ||
526 | s->brg_cfg = MAX3107_BRG13_IB9600; | ||
527 | s->baud_tbl = (struct baud_table *)brg13_int; | ||
528 | } | ||
529 | |||
530 | if (s->pdata->init) | ||
531 | s->pdata->init(s); | ||
532 | |||
533 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVMSB_REG) | ||
534 | | ((s->brg_cfg >> 16) & MAX3107_SPI_TX_DATA_MASK); | ||
535 | buf[1] = (MAX3107_WRITE_BIT | MAX3107_BRGDIVLSB_REG) | ||
536 | | ((s->brg_cfg >> 8) & MAX3107_SPI_TX_DATA_MASK); | ||
537 | buf[2] = (MAX3107_WRITE_BIT | MAX3107_BRGCFG_REG) | ||
538 | | ((s->brg_cfg) & 0xff); | ||
539 | |||
540 | /* 2. Configure LCR register, 8N1 mode by default */ | ||
541 | s->lcr_reg = MAX3107_LCR_WORD_LEN_8; | ||
542 | buf[3] = (MAX3107_WRITE_BIT | MAX3107_LCR_REG) | ||
543 | | s->lcr_reg; | ||
544 | |||
545 | /* 3. Configure MODE 1 register */ | ||
546 | s->mode1_reg = 0; | ||
547 | /* Enable IRQ pin */ | ||
548 | s->mode1_reg |= MAX3107_MODE1_IRQSEL_BIT; | ||
549 | /* Disable TX */ | ||
550 | s->mode1_reg |= MAX3107_MODE1_TXDIS_BIT; | ||
551 | s->tx_enabled = 0; | ||
552 | /* RX is enabled */ | ||
553 | s->rx_enabled = 1; | ||
554 | buf[4] = (MAX3107_WRITE_BIT | MAX3107_MODE1_REG) | ||
555 | | s->mode1_reg; | ||
556 | |||
557 | /* 4. Configure MODE 2 register */ | ||
558 | buf[5] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG); | ||
559 | if (s->loopback) { | ||
560 | /* Enable loopback */ | ||
561 | buf[5] |= MAX3107_MODE2_LOOPBACK_BIT; | ||
562 | } | ||
563 | /* Reset FIFOs */ | ||
564 | buf[5] |= MAX3107_MODE2_FIFORST_BIT; | ||
565 | s->tx_fifo_empty = 1; | ||
566 | |||
567 | /* 5. Configure FIFO trigger level register */ | ||
568 | buf[6] = (MAX3107_WRITE_BIT | MAX3107_FIFOTRIGLVL_REG); | ||
569 | /* RX FIFO trigger for 16 words, TX FIFO trigger not used */ | ||
570 | buf[6] |= (MAX3107_FIFOTRIGLVL_RX(16) | MAX3107_FIFOTRIGLVL_TX(0)); | ||
571 | |||
572 | /* 6. Configure flow control levels */ | ||
573 | buf[7] = (MAX3107_WRITE_BIT | MAX3107_FLOWLVL_REG); | ||
574 | /* Flow control halt level 96, resume level 48 */ | ||
575 | buf[7] |= (MAX3107_FLOWLVL_RES(48) | MAX3107_FLOWLVL_HALT(96)); | ||
576 | |||
577 | /* 7. Configure flow control */ | ||
578 | buf[8] = (MAX3107_WRITE_BIT | MAX3107_FLOWCTRL_REG); | ||
579 | /* Enable auto CTS and auto RTS flow control */ | ||
580 | buf[8] |= (MAX3107_FLOWCTRL_AUTOCTS_BIT | MAX3107_FLOWCTRL_AUTORTS_BIT); | ||
581 | |||
582 | /* 8. Configure RX timeout register */ | ||
583 | buf[9] = (MAX3107_WRITE_BIT | MAX3107_RXTO_REG); | ||
584 | /* Timeout after 48 character intervals */ | ||
585 | buf[9] |= 0x0030; | ||
586 | |||
587 | /* 9. Configure LSR interrupt enable register */ | ||
588 | buf[10] = (MAX3107_WRITE_BIT | MAX3107_LSR_IRQEN_REG); | ||
589 | /* Enable RX timeout interrupt */ | ||
590 | buf[10] |= MAX3107_LSR_RXTO_BIT; | ||
591 | |||
592 | /* Perform SPI transfer */ | ||
593 | if (max3107_rw(s, (u8 *)buf, NULL, 22)) | ||
594 | dev_err(&s->spi->dev, "SPI transfer for init failed\n"); | ||
595 | |||
596 | /* 10. Clear IRQ status register by reading it */ | ||
597 | buf[0] = MAX3107_IRQSTS_REG; | ||
598 | |||
599 | /* 11. Configure interrupt enable register */ | ||
600 | /* Enable LSR interrupt */ | ||
601 | s->irqen_reg = MAX3107_IRQ_LSR_BIT; | ||
602 | /* Enable RX FIFO interrupt */ | ||
603 | s->irqen_reg |= MAX3107_IRQ_RXFIFO_BIT; | ||
604 | buf[1] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG) | ||
605 | | s->irqen_reg; | ||
606 | |||
607 | /* 12. Clear FIFO reset that was set in step 6 */ | ||
608 | buf[2] = (MAX3107_WRITE_BIT | MAX3107_MODE2_REG); | ||
609 | if (s->loopback) { | ||
610 | /* Keep loopback enabled */ | ||
611 | buf[2] |= MAX3107_MODE2_LOOPBACK_BIT; | ||
612 | } | ||
613 | |||
614 | /* Perform SPI transfer */ | ||
615 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 6)) | ||
616 | dev_err(&s->spi->dev, "SPI transfer for init failed\n"); | ||
617 | |||
618 | } | ||
619 | |||
620 | /* IRQ handler */ | ||
621 | static irqreturn_t max3107_irq(int irqno, void *dev_id) | ||
622 | { | ||
623 | struct max3107_port *s = dev_id; | ||
624 | |||
625 | if (irqno != s->spi->irq) { | ||
626 | /* Unexpected IRQ */ | ||
627 | return IRQ_NONE; | ||
628 | } | ||
629 | |||
630 | /* Indicate irq */ | ||
631 | s->handle_irq = 1; | ||
632 | |||
633 | /* Trigger work thread */ | ||
634 | max3107_dowork(s); | ||
635 | |||
636 | return IRQ_HANDLED; | ||
637 | } | ||
638 | |||
639 | /* HW suspension function | ||
640 | * | ||
641 | * Currently autosleep is used to decrease current consumption, alternative | ||
642 | * approach would be to set the chip to reset mode if UART is not being | ||
643 | * used but that would mess the GPIOs | ||
644 | * | ||
645 | */ | ||
646 | void max3107_hw_susp(struct max3107_port *s, int suspend) | ||
647 | { | ||
648 | pr_debug("enter, suspend %d\n", suspend); | ||
649 | |||
650 | if (suspend) { | ||
651 | /* Suspend requested, | ||
652 | * enable autosleep to decrease current consumption | ||
653 | */ | ||
654 | s->suspended = 1; | ||
655 | max3107_set_sleep(s, MAX3107_ENABLE_AUTOSLEEP); | ||
656 | } else { | ||
657 | /* Resume requested, | ||
658 | * disable autosleep | ||
659 | */ | ||
660 | s->suspended = 0; | ||
661 | max3107_set_sleep(s, MAX3107_DISABLE_AUTOSLEEP); | ||
662 | } | ||
663 | } | ||
664 | EXPORT_SYMBOL_GPL(max3107_hw_susp); | ||
665 | |||
666 | /* Modem status IRQ enabling */ | ||
667 | static void max3107_enable_ms(struct uart_port *port) | ||
668 | { | ||
669 | /* Modem status not supported */ | ||
670 | } | ||
671 | |||
672 | /* Data send function */ | ||
673 | static void max3107_start_tx(struct uart_port *port) | ||
674 | { | ||
675 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
676 | |||
677 | /* Trigger work thread for sending data */ | ||
678 | max3107_dowork(s); | ||
679 | } | ||
680 | |||
681 | /* Function for checking that there is no pending transfers */ | ||
682 | static unsigned int max3107_tx_empty(struct uart_port *port) | ||
683 | { | ||
684 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
685 | |||
686 | pr_debug("returning %d\n", | ||
687 | (s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit))); | ||
688 | return s->tx_fifo_empty && uart_circ_empty(&s->port.state->xmit); | ||
689 | } | ||
690 | |||
691 | /* Function for stopping RX */ | ||
692 | static void max3107_stop_rx(struct uart_port *port) | ||
693 | { | ||
694 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
695 | unsigned long flags; | ||
696 | |||
697 | /* Set RX disabled in MODE 1 register */ | ||
698 | spin_lock_irqsave(&s->data_lock, flags); | ||
699 | s->mode1_reg |= MAX3107_MODE1_RXDIS_BIT; | ||
700 | s->mode1_commit = 1; | ||
701 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
702 | /* Set RX disabled */ | ||
703 | s->rx_enabled = 0; | ||
704 | /* Trigger work thread for doing the actual configuration change */ | ||
705 | max3107_dowork(s); | ||
706 | } | ||
707 | |||
708 | /* Function for returning control pin states */ | ||
709 | static unsigned int max3107_get_mctrl(struct uart_port *port) | ||
710 | { | ||
711 | /* DCD and DSR are not wired and CTS/RTS is handled automatically | ||
712 | * so just indicate DSR and CAR asserted | ||
713 | */ | ||
714 | return TIOCM_DSR | TIOCM_CAR; | ||
715 | } | ||
716 | |||
717 | /* Function for setting control pin states */ | ||
718 | static void max3107_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
719 | { | ||
720 | /* DCD and DSR are not wired and CTS/RTS is hadnled automatically | ||
721 | * so do nothing | ||
722 | */ | ||
723 | } | ||
724 | |||
725 | /* Function for configuring UART parameters */ | ||
726 | static void max3107_set_termios(struct uart_port *port, | ||
727 | struct ktermios *termios, | ||
728 | struct ktermios *old) | ||
729 | { | ||
730 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
731 | struct tty_struct *tty; | ||
732 | int baud; | ||
733 | u16 new_lcr = 0; | ||
734 | u32 new_brg = 0; | ||
735 | unsigned long flags; | ||
736 | |||
737 | if (!port->state) | ||
738 | return; | ||
739 | |||
740 | tty = port->state->port.tty; | ||
741 | if (!tty) | ||
742 | return; | ||
743 | |||
744 | /* Get new LCR register values */ | ||
745 | /* Word size */ | ||
746 | if ((termios->c_cflag & CSIZE) == CS7) | ||
747 | new_lcr |= MAX3107_LCR_WORD_LEN_7; | ||
748 | else | ||
749 | new_lcr |= MAX3107_LCR_WORD_LEN_8; | ||
750 | |||
751 | /* Parity */ | ||
752 | if (termios->c_cflag & PARENB) { | ||
753 | new_lcr |= MAX3107_LCR_PARITY_BIT; | ||
754 | if (!(termios->c_cflag & PARODD)) | ||
755 | new_lcr |= MAX3107_LCR_EVENPARITY_BIT; | ||
756 | } | ||
757 | |||
758 | /* Stop bits */ | ||
759 | if (termios->c_cflag & CSTOPB) { | ||
760 | /* 2 stop bits */ | ||
761 | new_lcr |= MAX3107_LCR_STOPLEN_BIT; | ||
762 | } | ||
763 | |||
764 | /* Mask termios capabilities we don't support */ | ||
765 | termios->c_cflag &= ~CMSPAR; | ||
766 | |||
767 | /* Set status ignore mask */ | ||
768 | s->port.ignore_status_mask = 0; | ||
769 | if (termios->c_iflag & IGNPAR) | ||
770 | s->port.ignore_status_mask |= MAX3107_ALL_ERRORS; | ||
771 | |||
772 | /* Set low latency to immediately handle pushed data */ | ||
773 | s->port.state->port.tty->low_latency = 1; | ||
774 | |||
775 | /* Get new baud rate generator configuration */ | ||
776 | baud = tty_get_baud_rate(tty); | ||
777 | |||
778 | spin_lock_irqsave(&s->data_lock, flags); | ||
779 | new_brg = get_new_brg(baud, s); | ||
780 | /* if can't find the corrent config, use previous */ | ||
781 | if (!new_brg) { | ||
782 | baud = s->baud; | ||
783 | new_brg = s->brg_cfg; | ||
784 | } | ||
785 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
786 | tty_termios_encode_baud_rate(termios, baud, baud); | ||
787 | s->baud = baud; | ||
788 | |||
789 | /* Update timeout according to new baud rate */ | ||
790 | uart_update_timeout(port, termios->c_cflag, baud); | ||
791 | |||
792 | spin_lock_irqsave(&s->data_lock, flags); | ||
793 | if (s->lcr_reg != new_lcr) { | ||
794 | s->lcr_reg = new_lcr; | ||
795 | s->lcr_commit = 1; | ||
796 | } | ||
797 | if (s->brg_cfg != new_brg) { | ||
798 | s->brg_cfg = new_brg; | ||
799 | s->brg_commit = 1; | ||
800 | } | ||
801 | spin_unlock_irqrestore(&s->data_lock, flags); | ||
802 | |||
803 | /* Trigger work thread for doing the actual configuration change */ | ||
804 | max3107_dowork(s); | ||
805 | } | ||
806 | |||
807 | /* Port shutdown function */ | ||
808 | static void max3107_shutdown(struct uart_port *port) | ||
809 | { | ||
810 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
811 | |||
812 | if (s->suspended && s->pdata->hw_suspend) | ||
813 | s->pdata->hw_suspend(s, 0); | ||
814 | |||
815 | /* Free the interrupt */ | ||
816 | free_irq(s->spi->irq, s); | ||
817 | |||
818 | if (s->workqueue) { | ||
819 | /* Flush and destroy work queue */ | ||
820 | flush_workqueue(s->workqueue); | ||
821 | destroy_workqueue(s->workqueue); | ||
822 | s->workqueue = NULL; | ||
823 | } | ||
824 | |||
825 | /* Suspend HW */ | ||
826 | if (s->pdata->hw_suspend) | ||
827 | s->pdata->hw_suspend(s, 1); | ||
828 | } | ||
829 | |||
830 | /* Port startup function */ | ||
831 | static int max3107_startup(struct uart_port *port) | ||
832 | { | ||
833 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
834 | |||
835 | /* Initialize work queue */ | ||
836 | s->workqueue = create_freezeable_workqueue("max3107"); | ||
837 | if (!s->workqueue) { | ||
838 | dev_err(&s->spi->dev, "Workqueue creation failed\n"); | ||
839 | return -EBUSY; | ||
840 | } | ||
841 | INIT_WORK(&s->work, max3107_work); | ||
842 | |||
843 | /* Setup IRQ */ | ||
844 | if (request_irq(s->spi->irq, max3107_irq, IRQF_TRIGGER_FALLING, | ||
845 | "max3107", s)) { | ||
846 | dev_err(&s->spi->dev, "IRQ reguest failed\n"); | ||
847 | destroy_workqueue(s->workqueue); | ||
848 | s->workqueue = NULL; | ||
849 | return -EBUSY; | ||
850 | } | ||
851 | |||
852 | /* Resume HW */ | ||
853 | if (s->pdata->hw_suspend) | ||
854 | s->pdata->hw_suspend(s, 0); | ||
855 | |||
856 | /* Init registers */ | ||
857 | max3107_register_init(s); | ||
858 | |||
859 | return 0; | ||
860 | } | ||
861 | |||
862 | /* Port type function */ | ||
863 | static const char *max3107_type(struct uart_port *port) | ||
864 | { | ||
865 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
866 | return s->spi->modalias; | ||
867 | } | ||
868 | |||
869 | /* Port release function */ | ||
870 | static void max3107_release_port(struct uart_port *port) | ||
871 | { | ||
872 | /* Do nothing */ | ||
873 | } | ||
874 | |||
875 | /* Port request function */ | ||
876 | static int max3107_request_port(struct uart_port *port) | ||
877 | { | ||
878 | /* Do nothing */ | ||
879 | return 0; | ||
880 | } | ||
881 | |||
882 | /* Port config function */ | ||
883 | static void max3107_config_port(struct uart_port *port, int flags) | ||
884 | { | ||
885 | struct max3107_port *s = container_of(port, struct max3107_port, port); | ||
886 | s->port.type = PORT_MAX3107; | ||
887 | } | ||
888 | |||
889 | /* Port verify function */ | ||
890 | static int max3107_verify_port(struct uart_port *port, | ||
891 | struct serial_struct *ser) | ||
892 | { | ||
893 | if (ser->type == PORT_UNKNOWN || ser->type == PORT_MAX3107) | ||
894 | return 0; | ||
895 | |||
896 | return -EINVAL; | ||
897 | } | ||
898 | |||
899 | /* Port stop TX function */ | ||
900 | static void max3107_stop_tx(struct uart_port *port) | ||
901 | { | ||
902 | /* Do nothing */ | ||
903 | } | ||
904 | |||
905 | /* Port break control function */ | ||
906 | static void max3107_break_ctl(struct uart_port *port, int break_state) | ||
907 | { | ||
908 | /* We don't support break control, do nothing */ | ||
909 | } | ||
910 | |||
911 | |||
912 | /* Port functions */ | ||
913 | static struct uart_ops max3107_ops = { | ||
914 | .tx_empty = max3107_tx_empty, | ||
915 | .set_mctrl = max3107_set_mctrl, | ||
916 | .get_mctrl = max3107_get_mctrl, | ||
917 | .stop_tx = max3107_stop_tx, | ||
918 | .start_tx = max3107_start_tx, | ||
919 | .stop_rx = max3107_stop_rx, | ||
920 | .enable_ms = max3107_enable_ms, | ||
921 | .break_ctl = max3107_break_ctl, | ||
922 | .startup = max3107_startup, | ||
923 | .shutdown = max3107_shutdown, | ||
924 | .set_termios = max3107_set_termios, | ||
925 | .type = max3107_type, | ||
926 | .release_port = max3107_release_port, | ||
927 | .request_port = max3107_request_port, | ||
928 | .config_port = max3107_config_port, | ||
929 | .verify_port = max3107_verify_port, | ||
930 | }; | ||
931 | |||
932 | /* UART driver data */ | ||
933 | static struct uart_driver max3107_uart_driver = { | ||
934 | .owner = THIS_MODULE, | ||
935 | .driver_name = "ttyMAX", | ||
936 | .dev_name = "ttyMAX", | ||
937 | .nr = 1, | ||
938 | }; | ||
939 | |||
940 | static int driver_registered = 0; | ||
941 | |||
942 | |||
943 | |||
944 | /* 'Generic' platform data */ | ||
945 | static struct max3107_plat generic_plat_data = { | ||
946 | .loopback = 0, | ||
947 | .ext_clk = 1, | ||
948 | .hw_suspend = max3107_hw_susp, | ||
949 | .polled_mode = 0, | ||
950 | .poll_time = 0, | ||
951 | }; | ||
952 | |||
953 | |||
954 | /*******************************************************************/ | ||
955 | |||
956 | /** | ||
957 | * max3107_probe - SPI bus probe entry point | ||
958 | * @spi: the spi device | ||
959 | * | ||
960 | * SPI wants us to probe this device and if appropriate claim it. | ||
961 | * Perform any platform specific requirements and then initialise | ||
962 | * the device. | ||
963 | */ | ||
964 | |||
965 | int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata) | ||
966 | { | ||
967 | struct max3107_port *s; | ||
968 | u16 buf[2]; /* Buffer for SPI transfers */ | ||
969 | int retval; | ||
970 | |||
971 | pr_info("enter max3107 probe\n"); | ||
972 | |||
973 | /* Allocate port structure */ | ||
974 | s = kzalloc(sizeof(*s), GFP_KERNEL); | ||
975 | if (!s) { | ||
976 | pr_err("Allocating port structure failed\n"); | ||
977 | return -ENOMEM; | ||
978 | } | ||
979 | |||
980 | s->pdata = pdata; | ||
981 | |||
982 | /* SPI Rx buffer | ||
983 | * +2 for RX FIFO interrupt | ||
984 | * disabling and RX level query | ||
985 | */ | ||
986 | s->rxbuf = kzalloc(sizeof(u16) * (MAX3107_RX_FIFO_SIZE+2), GFP_KERNEL); | ||
987 | if (!s->rxbuf) { | ||
988 | pr_err("Allocating RX buffer failed\n"); | ||
989 | return -ENOMEM; | ||
990 | } | ||
991 | s->rxstr = kzalloc(sizeof(u8) * MAX3107_RX_FIFO_SIZE, GFP_KERNEL); | ||
992 | if (!s->rxstr) { | ||
993 | pr_err("Allocating RX buffer failed\n"); | ||
994 | return -ENOMEM; | ||
995 | } | ||
996 | /* SPI Tx buffer | ||
997 | * SPI transfer buffer | ||
998 | * +3 for TX FIFO empty | ||
999 | * interrupt disabling and | ||
1000 | * enabling and TX enabling | ||
1001 | */ | ||
1002 | s->txbuf = kzalloc(sizeof(u16) * MAX3107_TX_FIFO_SIZE + 3, GFP_KERNEL); | ||
1003 | if (!s->txbuf) { | ||
1004 | pr_err("Allocating TX buffer failed\n"); | ||
1005 | return -ENOMEM; | ||
1006 | } | ||
1007 | /* Initialize shared data lock */ | ||
1008 | spin_lock_init(&s->data_lock); | ||
1009 | |||
1010 | /* SPI intializations */ | ||
1011 | dev_set_drvdata(&spi->dev, s); | ||
1012 | spi->mode = SPI_MODE_0; | ||
1013 | spi->dev.platform_data = pdata; | ||
1014 | spi->bits_per_word = 16; | ||
1015 | s->ext_clk = pdata->ext_clk; | ||
1016 | s->loopback = pdata->loopback; | ||
1017 | spi_setup(spi); | ||
1018 | s->spi = spi; | ||
1019 | |||
1020 | /* Check REV ID to ensure we are talking to what we expect */ | ||
1021 | buf[0] = MAX3107_REVID_REG; | ||
1022 | if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) { | ||
1023 | dev_err(&s->spi->dev, "SPI transfer for REVID read failed\n"); | ||
1024 | return -EIO; | ||
1025 | } | ||
1026 | if ((buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID1 && | ||
1027 | (buf[0] & MAX3107_SPI_RX_DATA_MASK) != MAX3107_REVID2) { | ||
1028 | dev_err(&s->spi->dev, "REVID %x does not match\n", | ||
1029 | (buf[0] & MAX3107_SPI_RX_DATA_MASK)); | ||
1030 | return -ENODEV; | ||
1031 | } | ||
1032 | |||
1033 | /* Disable all interrupts */ | ||
1034 | buf[0] = (MAX3107_WRITE_BIT | MAX3107_IRQEN_REG | 0x0000); | ||
1035 | buf[0] |= 0x0000; | ||
1036 | |||
1037 | /* Configure clock source */ | ||
1038 | buf[1] = (MAX3107_WRITE_BIT | MAX3107_CLKSRC_REG); | ||
1039 | if (s->ext_clk) { | ||
1040 | /* External clock */ | ||
1041 | buf[1] |= MAX3107_CLKSRC_EXTCLK_BIT; | ||
1042 | } | ||
1043 | |||
1044 | /* PLL bypass ON */ | ||
1045 | buf[1] |= MAX3107_CLKSRC_PLLBYP_BIT; | ||
1046 | |||
1047 | /* Perform SPI transfer */ | ||
1048 | if (max3107_rw(s, (u8 *)buf, NULL, 4)) { | ||
1049 | dev_err(&s->spi->dev, "SPI transfer for init failed\n"); | ||
1050 | return -EIO; | ||
1051 | } | ||
1052 | |||
1053 | /* Register UART driver */ | ||
1054 | if (!driver_registered) { | ||
1055 | retval = uart_register_driver(&max3107_uart_driver); | ||
1056 | if (retval) { | ||
1057 | dev_err(&s->spi->dev, "Registering UART driver failed\n"); | ||
1058 | return retval; | ||
1059 | } | ||
1060 | driver_registered = 1; | ||
1061 | } | ||
1062 | |||
1063 | /* Initialize UART port data */ | ||
1064 | s->port.fifosize = 128; | ||
1065 | s->port.ops = &max3107_ops; | ||
1066 | s->port.line = 0; | ||
1067 | s->port.dev = &spi->dev; | ||
1068 | s->port.uartclk = 9600; | ||
1069 | s->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; | ||
1070 | s->port.irq = s->spi->irq; | ||
1071 | s->port.type = PORT_MAX3107; | ||
1072 | |||
1073 | /* Add UART port */ | ||
1074 | retval = uart_add_one_port(&max3107_uart_driver, &s->port); | ||
1075 | if (retval < 0) { | ||
1076 | dev_err(&s->spi->dev, "Adding UART port failed\n"); | ||
1077 | return retval; | ||
1078 | } | ||
1079 | |||
1080 | if (pdata->configure) { | ||
1081 | retval = pdata->configure(s); | ||
1082 | if (retval < 0) | ||
1083 | return retval; | ||
1084 | } | ||
1085 | |||
1086 | /* Go to suspend mode */ | ||
1087 | if (pdata->hw_suspend) | ||
1088 | pdata->hw_suspend(s, 1); | ||
1089 | |||
1090 | return 0; | ||
1091 | } | ||
1092 | EXPORT_SYMBOL_GPL(max3107_probe); | ||
1093 | |||
1094 | /* Driver remove function */ | ||
1095 | int max3107_remove(struct spi_device *spi) | ||
1096 | { | ||
1097 | struct max3107_port *s = dev_get_drvdata(&spi->dev); | ||
1098 | |||
1099 | pr_info("enter max3107 remove\n"); | ||
1100 | |||
1101 | /* Remove port */ | ||
1102 | if (uart_remove_one_port(&max3107_uart_driver, &s->port)) | ||
1103 | dev_warn(&s->spi->dev, "Removing UART port failed\n"); | ||
1104 | |||
1105 | |||
1106 | /* Free TxRx buffer */ | ||
1107 | kfree(s->rxbuf); | ||
1108 | kfree(s->rxstr); | ||
1109 | kfree(s->txbuf); | ||
1110 | |||
1111 | /* Free port structure */ | ||
1112 | kfree(s); | ||
1113 | |||
1114 | return 0; | ||
1115 | } | ||
1116 | EXPORT_SYMBOL_GPL(max3107_remove); | ||
1117 | |||
1118 | /* Driver suspend function */ | ||
1119 | int max3107_suspend(struct spi_device *spi, pm_message_t state) | ||
1120 | { | ||
1121 | #ifdef CONFIG_PM | ||
1122 | struct max3107_port *s = dev_get_drvdata(&spi->dev); | ||
1123 | |||
1124 | pr_debug("enter suspend\n"); | ||
1125 | |||
1126 | /* Suspend UART port */ | ||
1127 | uart_suspend_port(&max3107_uart_driver, &s->port); | ||
1128 | |||
1129 | /* Go to suspend mode */ | ||
1130 | if (s->pdata->hw_suspend) | ||
1131 | s->pdata->hw_suspend(s, 1); | ||
1132 | #endif /* CONFIG_PM */ | ||
1133 | return 0; | ||
1134 | } | ||
1135 | EXPORT_SYMBOL_GPL(max3107_suspend); | ||
1136 | |||
1137 | /* Driver resume function */ | ||
1138 | int max3107_resume(struct spi_device *spi) | ||
1139 | { | ||
1140 | #ifdef CONFIG_PM | ||
1141 | struct max3107_port *s = dev_get_drvdata(&spi->dev); | ||
1142 | |||
1143 | pr_debug("enter resume\n"); | ||
1144 | |||
1145 | /* Resume from suspend */ | ||
1146 | if (s->pdata->hw_suspend) | ||
1147 | s->pdata->hw_suspend(s, 0); | ||
1148 | |||
1149 | /* Resume UART port */ | ||
1150 | uart_resume_port(&max3107_uart_driver, &s->port); | ||
1151 | #endif /* CONFIG_PM */ | ||
1152 | return 0; | ||
1153 | } | ||
1154 | EXPORT_SYMBOL_GPL(max3107_resume); | ||
1155 | |||
1156 | static int max3107_probe_generic(struct spi_device *spi) | ||
1157 | { | ||
1158 | return max3107_probe(spi, &generic_plat_data); | ||
1159 | } | ||
1160 | |||
1161 | /* Spi driver data */ | ||
1162 | static struct spi_driver max3107_driver = { | ||
1163 | .driver = { | ||
1164 | .name = "max3107", | ||
1165 | .bus = &spi_bus_type, | ||
1166 | .owner = THIS_MODULE, | ||
1167 | }, | ||
1168 | .probe = max3107_probe_generic, | ||
1169 | .remove = __devexit_p(max3107_remove), | ||
1170 | .suspend = max3107_suspend, | ||
1171 | .resume = max3107_resume, | ||
1172 | }; | ||
1173 | |||
1174 | /* Driver init function */ | ||
1175 | static int __init max3107_init(void) | ||
1176 | { | ||
1177 | pr_info("enter max3107 init\n"); | ||
1178 | return spi_register_driver(&max3107_driver); | ||
1179 | } | ||
1180 | |||
1181 | /* Driver exit function */ | ||
1182 | static void __exit max3107_exit(void) | ||
1183 | { | ||
1184 | pr_info("enter max3107 exit\n"); | ||
1185 | /* Unregister UART driver */ | ||
1186 | if (driver_registered) | ||
1187 | uart_unregister_driver(&max3107_uart_driver); | ||
1188 | spi_unregister_driver(&max3107_driver); | ||
1189 | } | ||
1190 | |||
1191 | module_init(max3107_init); | ||
1192 | module_exit(max3107_exit); | ||
1193 | |||
1194 | MODULE_DESCRIPTION("MAX3107 driver"); | ||
1195 | MODULE_AUTHOR("Aavamobile"); | ||
1196 | MODULE_ALIAS("max3107-spi"); | ||
1197 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/serial/max3107.h b/drivers/serial/max3107.h new file mode 100644 index 000000000000..7ab632392502 --- /dev/null +++ b/drivers/serial/max3107.h | |||
@@ -0,0 +1,441 @@ | |||
1 | /* | ||
2 | * max3107.h - spi uart protocol driver header for Maxim 3107 | ||
3 | * | ||
4 | * Copyright (C) Aavamobile 2009 | ||
5 | * Based on serial_max3100.h by Christian Pellegrin | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #ifndef _MAX3107_H | ||
14 | #define _MAX3107_H | ||
15 | |||
16 | /* Serial error status definitions */ | ||
17 | #define MAX3107_PARITY_ERROR 1 | ||
18 | #define MAX3107_FRAME_ERROR 2 | ||
19 | #define MAX3107_OVERRUN_ERROR 4 | ||
20 | #define MAX3107_ALL_ERRORS (MAX3107_PARITY_ERROR | \ | ||
21 | MAX3107_FRAME_ERROR | \ | ||
22 | MAX3107_OVERRUN_ERROR) | ||
23 | |||
24 | /* GPIO definitions */ | ||
25 | #define MAX3107_GPIO_BASE 88 | ||
26 | #define MAX3107_GPIO_COUNT 4 | ||
27 | |||
28 | |||
29 | /* GPIO connected to chip's reset pin */ | ||
30 | #define MAX3107_RESET_GPIO 87 | ||
31 | |||
32 | |||
33 | /* Chip reset delay */ | ||
34 | #define MAX3107_RESET_DELAY 10 | ||
35 | |||
36 | /* Chip wakeup delay */ | ||
37 | #define MAX3107_WAKEUP_DELAY 50 | ||
38 | |||
39 | |||
40 | /* Sleep mode definitions */ | ||
41 | #define MAX3107_DISABLE_FORCED_SLEEP 0 | ||
42 | #define MAX3107_ENABLE_FORCED_SLEEP 1 | ||
43 | #define MAX3107_DISABLE_AUTOSLEEP 2 | ||
44 | #define MAX3107_ENABLE_AUTOSLEEP 3 | ||
45 | |||
46 | |||
47 | /* Definitions for register access with SPI transfers | ||
48 | * | ||
49 | * SPI transfer format: | ||
50 | * | ||
51 | * Master to slave bits xzzzzzzzyyyyyyyy | ||
52 | * Slave to master bits aaaaaaaabbbbbbbb | ||
53 | * | ||
54 | * where: | ||
55 | * x = 0 for reads, 1 for writes | ||
56 | * z = register address | ||
57 | * y = new register value if write, 0 if read | ||
58 | * a = unspecified | ||
59 | * b = register value if read, unspecified if write | ||
60 | */ | ||
61 | |||
62 | /* SPI speed */ | ||
63 | #define MAX3107_SPI_SPEED (3125000 * 2) | ||
64 | |||
65 | /* Write bit */ | ||
66 | #define MAX3107_WRITE_BIT (1 << 15) | ||
67 | |||
68 | /* SPI TX data mask */ | ||
69 | #define MAX3107_SPI_RX_DATA_MASK (0x00ff) | ||
70 | |||
71 | /* SPI RX data mask */ | ||
72 | #define MAX3107_SPI_TX_DATA_MASK (0x00ff) | ||
73 | |||
74 | /* Register access masks */ | ||
75 | #define MAX3107_RHR_REG (0x0000) /* RX FIFO */ | ||
76 | #define MAX3107_THR_REG (0x0000) /* TX FIFO */ | ||
77 | #define MAX3107_IRQEN_REG (0x0100) /* IRQ enable */ | ||
78 | #define MAX3107_IRQSTS_REG (0x0200) /* IRQ status */ | ||
79 | #define MAX3107_LSR_IRQEN_REG (0x0300) /* LSR IRQ enable */ | ||
80 | #define MAX3107_LSR_IRQSTS_REG (0x0400) /* LSR IRQ status */ | ||
81 | #define MAX3107_SPCHR_IRQEN_REG (0x0500) /* Special char IRQ enable */ | ||
82 | #define MAX3107_SPCHR_IRQSTS_REG (0x0600) /* Special char IRQ status */ | ||
83 | #define MAX3107_STS_IRQEN_REG (0x0700) /* Status IRQ enable */ | ||
84 | #define MAX3107_STS_IRQSTS_REG (0x0800) /* Status IRQ status */ | ||
85 | #define MAX3107_MODE1_REG (0x0900) /* MODE1 */ | ||
86 | #define MAX3107_MODE2_REG (0x0a00) /* MODE2 */ | ||
87 | #define MAX3107_LCR_REG (0x0b00) /* LCR */ | ||
88 | #define MAX3107_RXTO_REG (0x0c00) /* RX timeout */ | ||
89 | #define MAX3107_HDPIXDELAY_REG (0x0d00) /* Auto transceiver delays */ | ||
90 | #define MAX3107_IRDA_REG (0x0e00) /* IRDA settings */ | ||
91 | #define MAX3107_FLOWLVL_REG (0x0f00) /* Flow control levels */ | ||
92 | #define MAX3107_FIFOTRIGLVL_REG (0x1000) /* FIFO IRQ trigger levels */ | ||
93 | #define MAX3107_TXFIFOLVL_REG (0x1100) /* TX FIFO level */ | ||
94 | #define MAX3107_RXFIFOLVL_REG (0x1200) /* RX FIFO level */ | ||
95 | #define MAX3107_FLOWCTRL_REG (0x1300) /* Flow control */ | ||
96 | #define MAX3107_XON1_REG (0x1400) /* XON1 character */ | ||
97 | #define MAX3107_XON2_REG (0x1500) /* XON2 character */ | ||
98 | #define MAX3107_XOFF1_REG (0x1600) /* XOFF1 character */ | ||
99 | #define MAX3107_XOFF2_REG (0x1700) /* XOFF2 character */ | ||
100 | #define MAX3107_GPIOCFG_REG (0x1800) /* GPIO config */ | ||
101 | #define MAX3107_GPIODATA_REG (0x1900) /* GPIO data */ | ||
102 | #define MAX3107_PLLCFG_REG (0x1a00) /* PLL config */ | ||
103 | #define MAX3107_BRGCFG_REG (0x1b00) /* Baud rate generator conf */ | ||
104 | #define MAX3107_BRGDIVLSB_REG (0x1c00) /* Baud rate divisor LSB */ | ||
105 | #define MAX3107_BRGDIVMSB_REG (0x1d00) /* Baud rate divisor MSB */ | ||
106 | #define MAX3107_CLKSRC_REG (0x1e00) /* Clock source */ | ||
107 | #define MAX3107_REVID_REG (0x1f00) /* Revision identification */ | ||
108 | |||
109 | /* IRQ register bits */ | ||
110 | #define MAX3107_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */ | ||
111 | #define MAX3107_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */ | ||
112 | #define MAX3107_IRQ_STS_BIT (1 << 2) /* Status interrupt */ | ||
113 | #define MAX3107_IRQ_RXFIFO_BIT (1 << 3) /* RX FIFO interrupt */ | ||
114 | #define MAX3107_IRQ_TXFIFO_BIT (1 << 4) /* TX FIFO interrupt */ | ||
115 | #define MAX3107_IRQ_TXEMPTY_BIT (1 << 5) /* TX FIFO empty interrupt */ | ||
116 | #define MAX3107_IRQ_RXEMPTY_BIT (1 << 6) /* RX FIFO empty interrupt */ | ||
117 | #define MAX3107_IRQ_CTS_BIT (1 << 7) /* CTS interrupt */ | ||
118 | |||
119 | /* LSR register bits */ | ||
120 | #define MAX3107_LSR_RXTO_BIT (1 << 0) /* RX timeout */ | ||
121 | #define MAX3107_LSR_RXOVR_BIT (1 << 1) /* RX overrun */ | ||
122 | #define MAX3107_LSR_RXPAR_BIT (1 << 2) /* RX parity error */ | ||
123 | #define MAX3107_LSR_FRERR_BIT (1 << 3) /* Frame error */ | ||
124 | #define MAX3107_LSR_RXBRK_BIT (1 << 4) /* RX break */ | ||
125 | #define MAX3107_LSR_RXNOISE_BIT (1 << 5) /* RX noise */ | ||
126 | #define MAX3107_LSR_UNDEF6_BIT (1 << 6) /* Undefined/not used */ | ||
127 | #define MAX3107_LSR_CTS_BIT (1 << 7) /* CTS pin state */ | ||
128 | |||
129 | /* Special character register bits */ | ||
130 | #define MAX3107_SPCHR_XON1_BIT (1 << 0) /* XON1 character */ | ||
131 | #define MAX3107_SPCHR_XON2_BIT (1 << 1) /* XON2 character */ | ||
132 | #define MAX3107_SPCHR_XOFF1_BIT (1 << 2) /* XOFF1 character */ | ||
133 | #define MAX3107_SPCHR_XOFF2_BIT (1 << 3) /* XOFF2 character */ | ||
134 | #define MAX3107_SPCHR_BREAK_BIT (1 << 4) /* RX break */ | ||
135 | #define MAX3107_SPCHR_MULTIDROP_BIT (1 << 5) /* 9-bit multidrop addr char */ | ||
136 | #define MAX3107_SPCHR_UNDEF6_BIT (1 << 6) /* Undefined/not used */ | ||
137 | #define MAX3107_SPCHR_UNDEF7_BIT (1 << 7) /* Undefined/not used */ | ||
138 | |||
139 | /* Status register bits */ | ||
140 | #define MAX3107_STS_GPIO0_BIT (1 << 0) /* GPIO 0 interrupt */ | ||
141 | #define MAX3107_STS_GPIO1_BIT (1 << 1) /* GPIO 1 interrupt */ | ||
142 | #define MAX3107_STS_GPIO2_BIT (1 << 2) /* GPIO 2 interrupt */ | ||
143 | #define MAX3107_STS_GPIO3_BIT (1 << 3) /* GPIO 3 interrupt */ | ||
144 | #define MAX3107_STS_UNDEF4_BIT (1 << 4) /* Undefined/not used */ | ||
145 | #define MAX3107_STS_CLKREADY_BIT (1 << 5) /* Clock ready */ | ||
146 | #define MAX3107_STS_SLEEP_BIT (1 << 6) /* Sleep interrupt */ | ||
147 | #define MAX3107_STS_UNDEF7_BIT (1 << 7) /* Undefined/not used */ | ||
148 | |||
149 | /* MODE1 register bits */ | ||
150 | #define MAX3107_MODE1_RXDIS_BIT (1 << 0) /* RX disable */ | ||
151 | #define MAX3107_MODE1_TXDIS_BIT (1 << 1) /* TX disable */ | ||
152 | #define MAX3107_MODE1_TXHIZ_BIT (1 << 2) /* TX pin three-state */ | ||
153 | #define MAX3107_MODE1_RTSHIZ_BIT (1 << 3) /* RTS pin three-state */ | ||
154 | #define MAX3107_MODE1_TRNSCVCTRL_BIT (1 << 4) /* Transceiver ctrl enable */ | ||
155 | #define MAX3107_MODE1_FORCESLEEP_BIT (1 << 5) /* Force sleep mode */ | ||
156 | #define MAX3107_MODE1_AUTOSLEEP_BIT (1 << 6) /* Auto sleep enable */ | ||
157 | #define MAX3107_MODE1_IRQSEL_BIT (1 << 7) /* IRQ pin enable */ | ||
158 | |||
159 | /* MODE2 register bits */ | ||
160 | #define MAX3107_MODE2_RST_BIT (1 << 0) /* Chip reset */ | ||
161 | #define MAX3107_MODE2_FIFORST_BIT (1 << 1) /* FIFO reset */ | ||
162 | #define MAX3107_MODE2_RXTRIGINV_BIT (1 << 2) /* RX FIFO INT invert */ | ||
163 | #define MAX3107_MODE2_RXEMPTINV_BIT (1 << 3) /* RX FIFO empty INT invert */ | ||
164 | #define MAX3107_MODE2_SPCHR_BIT (1 << 4) /* Special chr detect enable */ | ||
165 | #define MAX3107_MODE2_LOOPBACK_BIT (1 << 5) /* Internal loopback enable */ | ||
166 | #define MAX3107_MODE2_MULTIDROP_BIT (1 << 6) /* 9-bit multidrop enable */ | ||
167 | #define MAX3107_MODE2_ECHOSUPR_BIT (1 << 7) /* ECHO suppression enable */ | ||
168 | |||
169 | /* LCR register bits */ | ||
170 | #define MAX3107_LCR_LENGTH0_BIT (1 << 0) /* Word length bit 0 */ | ||
171 | #define MAX3107_LCR_LENGTH1_BIT (1 << 1) /* Word length bit 1 | ||
172 | * | ||
173 | * Word length bits table: | ||
174 | * 00 -> 5 bit words | ||
175 | * 01 -> 6 bit words | ||
176 | * 10 -> 7 bit words | ||
177 | * 11 -> 8 bit words | ||
178 | */ | ||
179 | #define MAX3107_LCR_STOPLEN_BIT (1 << 2) /* STOP length bit | ||
180 | * | ||
181 | * STOP length bit table: | ||
182 | * 0 -> 1 stop bit | ||
183 | * 1 -> 1-1.5 stop bits if | ||
184 | * word length is 5, | ||
185 | * 2 stop bits otherwise | ||
186 | */ | ||
187 | #define MAX3107_LCR_PARITY_BIT (1 << 3) /* Parity bit enable */ | ||
188 | #define MAX3107_LCR_EVENPARITY_BIT (1 << 4) /* Even parity bit enable */ | ||
189 | #define MAX3107_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */ | ||
190 | #define MAX3107_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */ | ||
191 | #define MAX3107_LCR_RTS_BIT (1 << 7) /* RTS pin control */ | ||
192 | #define MAX3107_LCR_WORD_LEN_5 (0x0000) | ||
193 | #define MAX3107_LCR_WORD_LEN_6 (0x0001) | ||
194 | #define MAX3107_LCR_WORD_LEN_7 (0x0002) | ||
195 | #define MAX3107_LCR_WORD_LEN_8 (0x0003) | ||
196 | |||
197 | |||
198 | /* IRDA register bits */ | ||
199 | #define MAX3107_IRDA_IRDAEN_BIT (1 << 0) /* IRDA mode enable */ | ||
200 | #define MAX3107_IRDA_SIR_BIT (1 << 1) /* SIR mode enable */ | ||
201 | #define MAX3107_IRDA_SHORTIR_BIT (1 << 2) /* Short SIR mode enable */ | ||
202 | #define MAX3107_IRDA_MIR_BIT (1 << 3) /* MIR mode enable */ | ||
203 | #define MAX3107_IRDA_RXINV_BIT (1 << 4) /* RX logic inversion enable */ | ||
204 | #define MAX3107_IRDA_TXINV_BIT (1 << 5) /* TX logic inversion enable */ | ||
205 | #define MAX3107_IRDA_UNDEF6_BIT (1 << 6) /* Undefined/not used */ | ||
206 | #define MAX3107_IRDA_UNDEF7_BIT (1 << 7) /* Undefined/not used */ | ||
207 | |||
208 | /* Flow control trigger level register masks */ | ||
209 | #define MAX3107_FLOWLVL_HALT_MASK (0x000f) /* Flow control halt level */ | ||
210 | #define MAX3107_FLOWLVL_RES_MASK (0x00f0) /* Flow control resume level */ | ||
211 | #define MAX3107_FLOWLVL_HALT(words) ((words/8) & 0x000f) | ||
212 | #define MAX3107_FLOWLVL_RES(words) (((words/8) & 0x000f) << 4) | ||
213 | |||
214 | /* FIFO interrupt trigger level register masks */ | ||
215 | #define MAX3107_FIFOTRIGLVL_TX_MASK (0x000f) /* TX FIFO trigger level */ | ||
216 | #define MAX3107_FIFOTRIGLVL_RX_MASK (0x00f0) /* RX FIFO trigger level */ | ||
217 | #define MAX3107_FIFOTRIGLVL_TX(words) ((words/8) & 0x000f) | ||
218 | #define MAX3107_FIFOTRIGLVL_RX(words) (((words/8) & 0x000f) << 4) | ||
219 | |||
220 | /* Flow control register bits */ | ||
221 | #define MAX3107_FLOWCTRL_AUTORTS_BIT (1 << 0) /* Auto RTS flow ctrl enable */ | ||
222 | #define MAX3107_FLOWCTRL_AUTOCTS_BIT (1 << 1) /* Auto CTS flow ctrl enable */ | ||
223 | #define MAX3107_FLOWCTRL_GPIADDR_BIT (1 << 2) /* Enables that GPIO inputs | ||
224 | * are used in conjunction with | ||
225 | * XOFF2 for definition of | ||
226 | * special character */ | ||
227 | #define MAX3107_FLOWCTRL_SWFLOWEN_BIT (1 << 3) /* Auto SW flow ctrl enable */ | ||
228 | #define MAX3107_FLOWCTRL_SWFLOW0_BIT (1 << 4) /* SWFLOW bit 0 */ | ||
229 | #define MAX3107_FLOWCTRL_SWFLOW1_BIT (1 << 5) /* SWFLOW bit 1 | ||
230 | * | ||
231 | * SWFLOW bits 1 & 0 table: | ||
232 | * 00 -> no transmitter flow | ||
233 | * control | ||
234 | * 01 -> receiver compares | ||
235 | * XON2 and XOFF2 | ||
236 | * and controls | ||
237 | * transmitter | ||
238 | * 10 -> receiver compares | ||
239 | * XON1 and XOFF1 | ||
240 | * and controls | ||
241 | * transmitter | ||
242 | * 11 -> receiver compares | ||
243 | * XON1, XON2, XOFF1 and | ||
244 | * XOFF2 and controls | ||
245 | * transmitter | ||
246 | */ | ||
247 | #define MAX3107_FLOWCTRL_SWFLOW2_BIT (1 << 6) /* SWFLOW bit 2 */ | ||
248 | #define MAX3107_FLOWCTRL_SWFLOW3_BIT (1 << 7) /* SWFLOW bit 3 | ||
249 | * | ||
250 | * SWFLOW bits 3 & 2 table: | ||
251 | * 00 -> no received flow | ||
252 | * control | ||
253 | * 01 -> transmitter generates | ||
254 | * XON2 and XOFF2 | ||
255 | * 10 -> transmitter generates | ||
256 | * XON1 and XOFF1 | ||
257 | * 11 -> transmitter generates | ||
258 | * XON1, XON2, XOFF1 and | ||
259 | * XOFF2 | ||
260 | */ | ||
261 | |||
262 | /* GPIO configuration register bits */ | ||
263 | #define MAX3107_GPIOCFG_GP0OUT_BIT (1 << 0) /* GPIO 0 output enable */ | ||
264 | #define MAX3107_GPIOCFG_GP1OUT_BIT (1 << 1) /* GPIO 1 output enable */ | ||
265 | #define MAX3107_GPIOCFG_GP2OUT_BIT (1 << 2) /* GPIO 2 output enable */ | ||
266 | #define MAX3107_GPIOCFG_GP3OUT_BIT (1 << 3) /* GPIO 3 output enable */ | ||
267 | #define MAX3107_GPIOCFG_GP0OD_BIT (1 << 4) /* GPIO 0 open-drain enable */ | ||
268 | #define MAX3107_GPIOCFG_GP1OD_BIT (1 << 5) /* GPIO 1 open-drain enable */ | ||
269 | #define MAX3107_GPIOCFG_GP2OD_BIT (1 << 6) /* GPIO 2 open-drain enable */ | ||
270 | #define MAX3107_GPIOCFG_GP3OD_BIT (1 << 7) /* GPIO 3 open-drain enable */ | ||
271 | |||
272 | /* GPIO DATA register bits */ | ||
273 | #define MAX3107_GPIODATA_GP0OUT_BIT (1 << 0) /* GPIO 0 output value */ | ||
274 | #define MAX3107_GPIODATA_GP1OUT_BIT (1 << 1) /* GPIO 1 output value */ | ||
275 | #define MAX3107_GPIODATA_GP2OUT_BIT (1 << 2) /* GPIO 2 output value */ | ||
276 | #define MAX3107_GPIODATA_GP3OUT_BIT (1 << 3) /* GPIO 3 output value */ | ||
277 | #define MAX3107_GPIODATA_GP0IN_BIT (1 << 4) /* GPIO 0 input value */ | ||
278 | #define MAX3107_GPIODATA_GP1IN_BIT (1 << 5) /* GPIO 1 input value */ | ||
279 | #define MAX3107_GPIODATA_GP2IN_BIT (1 << 6) /* GPIO 2 input value */ | ||
280 | #define MAX3107_GPIODATA_GP3IN_BIT (1 << 7) /* GPIO 3 input value */ | ||
281 | |||
282 | /* PLL configuration register masks */ | ||
283 | #define MAX3107_PLLCFG_PREDIV_MASK (0x003f) /* PLL predivision value */ | ||
284 | #define MAX3107_PLLCFG_PLLFACTOR_MASK (0x00c0) /* PLL multiplication factor */ | ||
285 | |||
286 | /* Baud rate generator configuration register masks and bits */ | ||
287 | #define MAX3107_BRGCFG_FRACT_MASK (0x000f) /* Fractional portion of | ||
288 | * Baud rate generator divisor | ||
289 | */ | ||
290 | #define MAX3107_BRGCFG_2XMODE_BIT (1 << 4) /* Double baud rate */ | ||
291 | #define MAX3107_BRGCFG_4XMODE_BIT (1 << 5) /* Quadruple baud rate */ | ||
292 | #define MAX3107_BRGCFG_UNDEF6_BIT (1 << 6) /* Undefined/not used */ | ||
293 | #define MAX3107_BRGCFG_UNDEF7_BIT (1 << 7) /* Undefined/not used */ | ||
294 | |||
295 | /* Clock source register bits */ | ||
296 | #define MAX3107_CLKSRC_INTOSC_BIT (1 << 0) /* Internal osc enable */ | ||
297 | #define MAX3107_CLKSRC_CRYST_BIT (1 << 1) /* Crystal osc enable */ | ||
298 | #define MAX3107_CLKSRC_PLL_BIT (1 << 2) /* PLL enable */ | ||
299 | #define MAX3107_CLKSRC_PLLBYP_BIT (1 << 3) /* PLL bypass */ | ||
300 | #define MAX3107_CLKSRC_EXTCLK_BIT (1 << 4) /* External clock enable */ | ||
301 | #define MAX3107_CLKSRC_UNDEF5_BIT (1 << 5) /* Undefined/not used */ | ||
302 | #define MAX3107_CLKSRC_UNDEF6_BIT (1 << 6) /* Undefined/not used */ | ||
303 | #define MAX3107_CLKSRC_CLK2RTS_BIT (1 << 7) /* Baud clk to RTS pin */ | ||
304 | |||
305 | |||
306 | /* HW definitions */ | ||
307 | #define MAX3107_RX_FIFO_SIZE 128 | ||
308 | #define MAX3107_TX_FIFO_SIZE 128 | ||
309 | #define MAX3107_REVID1 0x00a0 | ||
310 | #define MAX3107_REVID2 0x00a1 | ||
311 | |||
312 | |||
313 | /* Baud rate generator configuration values for external clock 13MHz */ | ||
314 | #define MAX3107_BRG13_B300 (0x0A9400 | 0x05) | ||
315 | #define MAX3107_BRG13_B600 (0x054A00 | 0x03) | ||
316 | #define MAX3107_BRG13_B1200 (0x02A500 | 0x01) | ||
317 | #define MAX3107_BRG13_B2400 (0x015200 | 0x09) | ||
318 | #define MAX3107_BRG13_B4800 (0x00A900 | 0x04) | ||
319 | #define MAX3107_BRG13_B9600 (0x005400 | 0x0A) | ||
320 | #define MAX3107_BRG13_B19200 (0x002A00 | 0x05) | ||
321 | #define MAX3107_BRG13_B38400 (0x001500 | 0x03) | ||
322 | #define MAX3107_BRG13_B57600 (0x000E00 | 0x02) | ||
323 | #define MAX3107_BRG13_B115200 (0x000700 | 0x01) | ||
324 | #define MAX3107_BRG13_B230400 (0x000300 | 0x08) | ||
325 | #define MAX3107_BRG13_B460800 (0x000100 | 0x0c) | ||
326 | #define MAX3107_BRG13_B921600 (0x000100 | 0x1c) | ||
327 | |||
328 | /* Baud rate generator configuration values for external clock 26MHz */ | ||
329 | #define MAX3107_BRG26_B300 (0x152800 | 0x0A) | ||
330 | #define MAX3107_BRG26_B600 (0x0A9400 | 0x05) | ||
331 | #define MAX3107_BRG26_B1200 (0x054A00 | 0x03) | ||
332 | #define MAX3107_BRG26_B2400 (0x02A500 | 0x01) | ||
333 | #define MAX3107_BRG26_B4800 (0x015200 | 0x09) | ||
334 | #define MAX3107_BRG26_B9600 (0x00A900 | 0x04) | ||
335 | #define MAX3107_BRG26_B19200 (0x005400 | 0x0A) | ||
336 | #define MAX3107_BRG26_B38400 (0x002A00 | 0x05) | ||
337 | #define MAX3107_BRG26_B57600 (0x001C00 | 0x03) | ||
338 | #define MAX3107_BRG26_B115200 (0x000E00 | 0x02) | ||
339 | #define MAX3107_BRG26_B230400 (0x000700 | 0x01) | ||
340 | #define MAX3107_BRG26_B460800 (0x000300 | 0x08) | ||
341 | #define MAX3107_BRG26_B921600 (0x000100 | 0x0C) | ||
342 | |||
343 | /* Baud rate generator configuration values for internal clock */ | ||
344 | #define MAX3107_BRG13_IB300 (0x008000 | 0x00) | ||
345 | #define MAX3107_BRG13_IB600 (0x004000 | 0x00) | ||
346 | #define MAX3107_BRG13_IB1200 (0x002000 | 0x00) | ||
347 | #define MAX3107_BRG13_IB2400 (0x001000 | 0x00) | ||
348 | #define MAX3107_BRG13_IB4800 (0x000800 | 0x00) | ||
349 | #define MAX3107_BRG13_IB9600 (0x000400 | 0x00) | ||
350 | #define MAX3107_BRG13_IB19200 (0x000200 | 0x00) | ||
351 | #define MAX3107_BRG13_IB38400 (0x000100 | 0x00) | ||
352 | #define MAX3107_BRG13_IB57600 (0x000000 | 0x0B) | ||
353 | #define MAX3107_BRG13_IB115200 (0x000000 | 0x05) | ||
354 | #define MAX3107_BRG13_IB230400 (0x000000 | 0x03) | ||
355 | #define MAX3107_BRG13_IB460800 (0x000000 | 0x00) | ||
356 | #define MAX3107_BRG13_IB921600 (0x000000 | 0x00) | ||
357 | |||
358 | |||
359 | struct baud_table { | ||
360 | int baud; | ||
361 | u32 new_brg; | ||
362 | }; | ||
363 | |||
364 | struct max3107_port { | ||
365 | /* UART port structure */ | ||
366 | struct uart_port port; | ||
367 | |||
368 | /* SPI device structure */ | ||
369 | struct spi_device *spi; | ||
370 | |||
371 | #if defined(CONFIG_GPIOLIB) | ||
372 | /* GPIO chip stucture */ | ||
373 | struct gpio_chip chip; | ||
374 | #endif | ||
375 | |||
376 | /* Workqueue that does all the magic */ | ||
377 | struct workqueue_struct *workqueue; | ||
378 | struct work_struct work; | ||
379 | |||
380 | /* Lock for shared data */ | ||
381 | spinlock_t data_lock; | ||
382 | |||
383 | /* Device configuration */ | ||
384 | int ext_clk; /* 1 if external clock used */ | ||
385 | int loopback; /* Current loopback mode state */ | ||
386 | int baud; /* Current baud rate */ | ||
387 | |||
388 | /* State flags */ | ||
389 | int suspended; /* Indicates suspend mode */ | ||
390 | int tx_fifo_empty; /* Flag for TX FIFO state */ | ||
391 | int rx_enabled; /* Flag for receiver state */ | ||
392 | int tx_enabled; /* Flag for transmitter state */ | ||
393 | |||
394 | u16 irqen_reg; /* Current IRQ enable register value */ | ||
395 | /* Shared data */ | ||
396 | u16 mode1_reg; /* Current mode1 register value*/ | ||
397 | int mode1_commit; /* Flag for setting new mode1 register value */ | ||
398 | u16 lcr_reg; /* Current LCR register value */ | ||
399 | int lcr_commit; /* Flag for setting new LCR register value */ | ||
400 | u32 brg_cfg; /* Current Baud rate generator config */ | ||
401 | int brg_commit; /* Flag for setting new baud rate generator | ||
402 | * config | ||
403 | */ | ||
404 | struct baud_table *baud_tbl; | ||
405 | int handle_irq; /* Indicates that IRQ should be handled */ | ||
406 | |||
407 | /* Rx buffer and str*/ | ||
408 | u16 *rxbuf; | ||
409 | u8 *rxstr; | ||
410 | /* Tx buffer*/ | ||
411 | u16 *txbuf; | ||
412 | |||
413 | struct max3107_plat *pdata; /* Platform data */ | ||
414 | }; | ||
415 | |||
416 | /* Platform data structure */ | ||
417 | struct max3107_plat { | ||
418 | /* Loopback mode enable */ | ||
419 | int loopback; | ||
420 | /* External clock enable */ | ||
421 | int ext_clk; | ||
422 | /* Called during the register initialisation */ | ||
423 | void (*init)(struct max3107_port *s); | ||
424 | /* Called when the port is found and configured */ | ||
425 | int (*configure)(struct max3107_port *s); | ||
426 | /* HW suspend function */ | ||
427 | void (*hw_suspend) (struct max3107_port *s, int suspend); | ||
428 | /* Polling mode enable */ | ||
429 | int polled_mode; | ||
430 | /* Polling period if polling mode enabled */ | ||
431 | int poll_time; | ||
432 | }; | ||
433 | |||
434 | extern int max3107_rw(struct max3107_port *s, u8 *tx, u8 *rx, int len); | ||
435 | extern void max3107_hw_susp(struct max3107_port *s, int suspend); | ||
436 | extern int max3107_probe(struct spi_device *spi, struct max3107_plat *pdata); | ||
437 | extern int max3107_remove(struct spi_device *spi); | ||
438 | extern int max3107_suspend(struct spi_device *spi, pm_message_t state); | ||
439 | extern int max3107_resume(struct spi_device *spi); | ||
440 | |||
441 | #endif /* _LINUX_SERIAL_MAX3107_H */ | ||
diff --git a/drivers/serial/mcf.c b/drivers/serial/mcf.c index b5aaef965f24..3394b7cc1722 100644 --- a/drivers/serial/mcf.c +++ b/drivers/serial/mcf.c | |||
@@ -70,16 +70,14 @@ static unsigned int mcf_tx_empty(struct uart_port *port) | |||
70 | static unsigned int mcf_get_mctrl(struct uart_port *port) | 70 | static unsigned int mcf_get_mctrl(struct uart_port *port) |
71 | { | 71 | { |
72 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 72 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
73 | unsigned long flags; | ||
74 | unsigned int sigs; | 73 | unsigned int sigs; |
75 | 74 | ||
76 | spin_lock_irqsave(&port->lock, flags); | ||
77 | sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ? | 75 | sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ? |
78 | 0 : TIOCM_CTS; | 76 | 0 : TIOCM_CTS; |
79 | sigs |= (pp->sigs & TIOCM_RTS); | 77 | sigs |= (pp->sigs & TIOCM_RTS); |
80 | sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0); | 78 | sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0); |
81 | sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0); | 79 | sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0); |
82 | spin_unlock_irqrestore(&port->lock, flags); | 80 | |
83 | return sigs; | 81 | return sigs; |
84 | } | 82 | } |
85 | 83 | ||
@@ -88,16 +86,13 @@ static unsigned int mcf_get_mctrl(struct uart_port *port) | |||
88 | static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) | 86 | static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) |
89 | { | 87 | { |
90 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 88 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
91 | unsigned long flags; | ||
92 | 89 | ||
93 | spin_lock_irqsave(&port->lock, flags); | ||
94 | pp->sigs = sigs; | 90 | pp->sigs = sigs; |
95 | mcf_setppdtr(port->line, (sigs & TIOCM_DTR)); | 91 | mcf_setppdtr(port->line, (sigs & TIOCM_DTR)); |
96 | if (sigs & TIOCM_RTS) | 92 | if (sigs & TIOCM_RTS) |
97 | writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); | 93 | writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); |
98 | else | 94 | else |
99 | writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0); | 95 | writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0); |
100 | spin_unlock_irqrestore(&port->lock, flags); | ||
101 | } | 96 | } |
102 | 97 | ||
103 | /****************************************************************************/ | 98 | /****************************************************************************/ |
@@ -105,12 +100,9 @@ static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) | |||
105 | static void mcf_start_tx(struct uart_port *port) | 100 | static void mcf_start_tx(struct uart_port *port) |
106 | { | 101 | { |
107 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 102 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
108 | unsigned long flags; | ||
109 | 103 | ||
110 | spin_lock_irqsave(&port->lock, flags); | ||
111 | pp->imr |= MCFUART_UIR_TXREADY; | 104 | pp->imr |= MCFUART_UIR_TXREADY; |
112 | writeb(pp->imr, port->membase + MCFUART_UIMR); | 105 | writeb(pp->imr, port->membase + MCFUART_UIMR); |
113 | spin_unlock_irqrestore(&port->lock, flags); | ||
114 | } | 106 | } |
115 | 107 | ||
116 | /****************************************************************************/ | 108 | /****************************************************************************/ |
@@ -118,12 +110,9 @@ static void mcf_start_tx(struct uart_port *port) | |||
118 | static void mcf_stop_tx(struct uart_port *port) | 110 | static void mcf_stop_tx(struct uart_port *port) |
119 | { | 111 | { |
120 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 112 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
121 | unsigned long flags; | ||
122 | 113 | ||
123 | spin_lock_irqsave(&port->lock, flags); | ||
124 | pp->imr &= ~MCFUART_UIR_TXREADY; | 114 | pp->imr &= ~MCFUART_UIR_TXREADY; |
125 | writeb(pp->imr, port->membase + MCFUART_UIMR); | 115 | writeb(pp->imr, port->membase + MCFUART_UIMR); |
126 | spin_unlock_irqrestore(&port->lock, flags); | ||
127 | } | 116 | } |
128 | 117 | ||
129 | /****************************************************************************/ | 118 | /****************************************************************************/ |
@@ -131,12 +120,9 @@ static void mcf_stop_tx(struct uart_port *port) | |||
131 | static void mcf_stop_rx(struct uart_port *port) | 120 | static void mcf_stop_rx(struct uart_port *port) |
132 | { | 121 | { |
133 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 122 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
134 | unsigned long flags; | ||
135 | 123 | ||
136 | spin_lock_irqsave(&port->lock, flags); | ||
137 | pp->imr &= ~MCFUART_UIR_RXREADY; | 124 | pp->imr &= ~MCFUART_UIR_RXREADY; |
138 | writeb(pp->imr, port->membase + MCFUART_UIMR); | 125 | writeb(pp->imr, port->membase + MCFUART_UIMR); |
139 | spin_unlock_irqrestore(&port->lock, flags); | ||
140 | } | 126 | } |
141 | 127 | ||
142 | /****************************************************************************/ | 128 | /****************************************************************************/ |
@@ -366,13 +352,22 @@ static irqreturn_t mcf_interrupt(int irq, void *data) | |||
366 | struct uart_port *port = data; | 352 | struct uart_port *port = data; |
367 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); | 353 | struct mcf_uart *pp = container_of(port, struct mcf_uart, port); |
368 | unsigned int isr; | 354 | unsigned int isr; |
355 | irqreturn_t ret = IRQ_NONE; | ||
369 | 356 | ||
370 | isr = readb(port->membase + MCFUART_UISR) & pp->imr; | 357 | isr = readb(port->membase + MCFUART_UISR) & pp->imr; |
371 | if (isr & MCFUART_UIR_RXREADY) | 358 | |
359 | spin_lock(&port->lock); | ||
360 | if (isr & MCFUART_UIR_RXREADY) { | ||
372 | mcf_rx_chars(pp); | 361 | mcf_rx_chars(pp); |
373 | if (isr & MCFUART_UIR_TXREADY) | 362 | ret = IRQ_HANDLED; |
363 | } | ||
364 | if (isr & MCFUART_UIR_TXREADY) { | ||
374 | mcf_tx_chars(pp); | 365 | mcf_tx_chars(pp); |
375 | return IRQ_HANDLED; | 366 | ret = IRQ_HANDLED; |
367 | } | ||
368 | spin_unlock(&port->lock); | ||
369 | |||
370 | return ret; | ||
376 | } | 371 | } |
377 | 372 | ||
378 | /****************************************************************************/ | 373 | /****************************************************************************/ |
diff --git a/drivers/serial/mfd.c b/drivers/serial/mfd.c new file mode 100644 index 000000000000..bc9af503907f --- /dev/null +++ b/drivers/serial/mfd.c | |||
@@ -0,0 +1,1498 @@ | |||
1 | /* | ||
2 | * mfd.c: driver for High Speed UART device of Intel Medfield platform | ||
3 | * | ||
4 | * Refer pxa.c, 8250.c and some other drivers in drivers/serial/ | ||
5 | * | ||
6 | * (C) Copyright 2010 Intel Corporation | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; version 2 | ||
11 | * of the License. | ||
12 | */ | ||
13 | |||
14 | /* Notes: | ||
15 | * 1. DMA channel allocation: 0/1 channel are assigned to port 0, | ||
16 | * 2/3 chan to port 1, 4/5 chan to port 3. Even number chans | ||
17 | * are used for RX, odd chans for TX | ||
18 | * | ||
19 | * 2. In A0 stepping, UART will not support TX half empty flag | ||
20 | * | ||
21 | * 3. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always | ||
22 | * asserted, only when the HW is reset the DDCD and DDSR will | ||
23 | * be triggered | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/console.h> | ||
29 | #include <linux/sysrq.h> | ||
30 | #include <linux/serial_reg.h> | ||
31 | #include <linux/circ_buf.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/tty.h> | ||
35 | #include <linux/tty_flip.h> | ||
36 | #include <linux/serial_core.h> | ||
37 | #include <linux/serial_mfd.h> | ||
38 | #include <linux/dma-mapping.h> | ||
39 | #include <linux/pci.h> | ||
40 | #include <linux/io.h> | ||
41 | #include <linux/debugfs.h> | ||
42 | |||
43 | #define MFD_HSU_A0_STEPPING 1 | ||
44 | |||
45 | #define HSU_DMA_BUF_SIZE 2048 | ||
46 | |||
47 | #define chan_readl(chan, offset) readl(chan->reg + offset) | ||
48 | #define chan_writel(chan, offset, val) writel(val, chan->reg + offset) | ||
49 | |||
50 | #define mfd_readl(obj, offset) readl(obj->reg + offset) | ||
51 | #define mfd_writel(obj, offset, val) writel(val, obj->reg + offset) | ||
52 | |||
53 | #define HSU_DMA_TIMEOUT_CHECK_FREQ (HZ/10) | ||
54 | |||
55 | struct hsu_dma_buffer { | ||
56 | u8 *buf; | ||
57 | dma_addr_t dma_addr; | ||
58 | u32 dma_size; | ||
59 | u32 ofs; | ||
60 | }; | ||
61 | |||
62 | struct hsu_dma_chan { | ||
63 | u32 id; | ||
64 | enum dma_data_direction dirt; | ||
65 | struct uart_hsu_port *uport; | ||
66 | void __iomem *reg; | ||
67 | struct timer_list rx_timer; /* only needed by RX channel */ | ||
68 | }; | ||
69 | |||
70 | struct uart_hsu_port { | ||
71 | struct uart_port port; | ||
72 | unsigned char ier; | ||
73 | unsigned char lcr; | ||
74 | unsigned char mcr; | ||
75 | unsigned int lsr_break_flag; | ||
76 | char name[12]; | ||
77 | int index; | ||
78 | struct device *dev; | ||
79 | |||
80 | struct hsu_dma_chan *txc; | ||
81 | struct hsu_dma_chan *rxc; | ||
82 | struct hsu_dma_buffer txbuf; | ||
83 | struct hsu_dma_buffer rxbuf; | ||
84 | int use_dma; /* flag for DMA/PIO */ | ||
85 | int running; | ||
86 | int dma_tx_on; | ||
87 | }; | ||
88 | |||
89 | /* Top level data structure of HSU */ | ||
90 | struct hsu_port { | ||
91 | void __iomem *reg; | ||
92 | unsigned long paddr; | ||
93 | unsigned long iolen; | ||
94 | u32 irq; | ||
95 | |||
96 | struct uart_hsu_port port[3]; | ||
97 | struct hsu_dma_chan chans[10]; | ||
98 | |||
99 | struct dentry *debugfs; | ||
100 | }; | ||
101 | |||
102 | static inline unsigned int serial_in(struct uart_hsu_port *up, int offset) | ||
103 | { | ||
104 | unsigned int val; | ||
105 | |||
106 | if (offset > UART_MSR) { | ||
107 | offset <<= 2; | ||
108 | val = readl(up->port.membase + offset); | ||
109 | } else | ||
110 | val = (unsigned int)readb(up->port.membase + offset); | ||
111 | |||
112 | return val; | ||
113 | } | ||
114 | |||
115 | static inline void serial_out(struct uart_hsu_port *up, int offset, int value) | ||
116 | { | ||
117 | if (offset > UART_MSR) { | ||
118 | offset <<= 2; | ||
119 | writel(value, up->port.membase + offset); | ||
120 | } else { | ||
121 | unsigned char val = value & 0xff; | ||
122 | writeb(val, up->port.membase + offset); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | #ifdef CONFIG_DEBUG_FS | ||
127 | |||
128 | #define HSU_REGS_BUFSIZE 1024 | ||
129 | |||
130 | static int hsu_show_regs_open(struct inode *inode, struct file *file) | ||
131 | { | ||
132 | file->private_data = inode->i_private; | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static ssize_t port_show_regs(struct file *file, char __user *user_buf, | ||
137 | size_t count, loff_t *ppos) | ||
138 | { | ||
139 | struct uart_hsu_port *up = file->private_data; | ||
140 | char *buf; | ||
141 | u32 len = 0; | ||
142 | ssize_t ret; | ||
143 | |||
144 | buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL); | ||
145 | if (!buf) | ||
146 | return 0; | ||
147 | |||
148 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
149 | "MFD HSU port[%d] regs:\n", up->index); | ||
150 | |||
151 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
152 | "=================================\n"); | ||
153 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
154 | "IER: \t\t0x%08x\n", serial_in(up, UART_IER)); | ||
155 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
156 | "IIR: \t\t0x%08x\n", serial_in(up, UART_IIR)); | ||
157 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
158 | "LCR: \t\t0x%08x\n", serial_in(up, UART_LCR)); | ||
159 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
160 | "MCR: \t\t0x%08x\n", serial_in(up, UART_MCR)); | ||
161 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
162 | "LSR: \t\t0x%08x\n", serial_in(up, UART_LSR)); | ||
163 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
164 | "MSR: \t\t0x%08x\n", serial_in(up, UART_MSR)); | ||
165 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
166 | "FOR: \t\t0x%08x\n", serial_in(up, UART_FOR)); | ||
167 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
168 | "PS: \t\t0x%08x\n", serial_in(up, UART_PS)); | ||
169 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
170 | "MUL: \t\t0x%08x\n", serial_in(up, UART_MUL)); | ||
171 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
172 | "DIV: \t\t0x%08x\n", serial_in(up, UART_DIV)); | ||
173 | |||
174 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
175 | kfree(buf); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | static ssize_t dma_show_regs(struct file *file, char __user *user_buf, | ||
180 | size_t count, loff_t *ppos) | ||
181 | { | ||
182 | struct hsu_dma_chan *chan = file->private_data; | ||
183 | char *buf; | ||
184 | u32 len = 0; | ||
185 | ssize_t ret; | ||
186 | |||
187 | buf = kzalloc(HSU_REGS_BUFSIZE, GFP_KERNEL); | ||
188 | if (!buf) | ||
189 | return 0; | ||
190 | |||
191 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
192 | "MFD HSU DMA channel [%d] regs:\n", chan->id); | ||
193 | |||
194 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
195 | "=================================\n"); | ||
196 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
197 | "CR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_CR)); | ||
198 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
199 | "DCR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_DCR)); | ||
200 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
201 | "BSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_BSR)); | ||
202 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
203 | "MOTSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_MOTSR)); | ||
204 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
205 | "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0SAR)); | ||
206 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
207 | "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D0TSR)); | ||
208 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
209 | "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1SAR)); | ||
210 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
211 | "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D1TSR)); | ||
212 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
213 | "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2SAR)); | ||
214 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
215 | "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D2TSR)); | ||
216 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
217 | "D0SAR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3SAR)); | ||
218 | len += snprintf(buf + len, HSU_REGS_BUFSIZE - len, | ||
219 | "D0TSR: \t\t0x%08x\n", chan_readl(chan, HSU_CH_D3TSR)); | ||
220 | |||
221 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
222 | kfree(buf); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static const struct file_operations port_regs_ops = { | ||
227 | .owner = THIS_MODULE, | ||
228 | .open = hsu_show_regs_open, | ||
229 | .read = port_show_regs, | ||
230 | }; | ||
231 | |||
232 | static const struct file_operations dma_regs_ops = { | ||
233 | .owner = THIS_MODULE, | ||
234 | .open = hsu_show_regs_open, | ||
235 | .read = dma_show_regs, | ||
236 | }; | ||
237 | |||
238 | static int hsu_debugfs_init(struct hsu_port *hsu) | ||
239 | { | ||
240 | int i; | ||
241 | char name[32]; | ||
242 | |||
243 | hsu->debugfs = debugfs_create_dir("hsu", NULL); | ||
244 | if (!hsu->debugfs) | ||
245 | return -ENOMEM; | ||
246 | |||
247 | for (i = 0; i < 3; i++) { | ||
248 | snprintf(name, sizeof(name), "port_%d_regs", i); | ||
249 | debugfs_create_file(name, S_IFREG | S_IRUGO, | ||
250 | hsu->debugfs, (void *)(&hsu->port[i]), &port_regs_ops); | ||
251 | } | ||
252 | |||
253 | for (i = 0; i < 6; i++) { | ||
254 | snprintf(name, sizeof(name), "dma_chan_%d_regs", i); | ||
255 | debugfs_create_file(name, S_IFREG | S_IRUGO, | ||
256 | hsu->debugfs, (void *)&hsu->chans[i], &dma_regs_ops); | ||
257 | } | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static void hsu_debugfs_remove(struct hsu_port *hsu) | ||
263 | { | ||
264 | if (hsu->debugfs) | ||
265 | debugfs_remove_recursive(hsu->debugfs); | ||
266 | } | ||
267 | |||
268 | #else | ||
269 | static inline int hsu_debugfs_init(struct hsu_port *hsu) | ||
270 | { | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static inline void hsu_debugfs_remove(struct hsu_port *hsu) | ||
275 | { | ||
276 | } | ||
277 | #endif /* CONFIG_DEBUG_FS */ | ||
278 | |||
279 | static void serial_hsu_enable_ms(struct uart_port *port) | ||
280 | { | ||
281 | struct uart_hsu_port *up = | ||
282 | container_of(port, struct uart_hsu_port, port); | ||
283 | |||
284 | up->ier |= UART_IER_MSI; | ||
285 | serial_out(up, UART_IER, up->ier); | ||
286 | } | ||
287 | |||
288 | void hsu_dma_tx(struct uart_hsu_port *up) | ||
289 | { | ||
290 | struct circ_buf *xmit = &up->port.state->xmit; | ||
291 | struct hsu_dma_buffer *dbuf = &up->txbuf; | ||
292 | int count; | ||
293 | |||
294 | /* test_and_set_bit may be better, but anyway it's in lock protected mode */ | ||
295 | if (up->dma_tx_on) | ||
296 | return; | ||
297 | |||
298 | /* Update the circ buf info */ | ||
299 | xmit->tail += dbuf->ofs; | ||
300 | xmit->tail &= UART_XMIT_SIZE - 1; | ||
301 | |||
302 | up->port.icount.tx += dbuf->ofs; | ||
303 | dbuf->ofs = 0; | ||
304 | |||
305 | /* Disable the channel */ | ||
306 | chan_writel(up->txc, HSU_CH_CR, 0x0); | ||
307 | |||
308 | if (!uart_circ_empty(xmit) && !uart_tx_stopped(&up->port)) { | ||
309 | dma_sync_single_for_device(up->port.dev, | ||
310 | dbuf->dma_addr, | ||
311 | dbuf->dma_size, | ||
312 | DMA_TO_DEVICE); | ||
313 | |||
314 | count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE); | ||
315 | dbuf->ofs = count; | ||
316 | |||
317 | /* Reprogram the channel */ | ||
318 | chan_writel(up->txc, HSU_CH_D0SAR, dbuf->dma_addr + xmit->tail); | ||
319 | chan_writel(up->txc, HSU_CH_D0TSR, count); | ||
320 | |||
321 | /* Reenable the channel */ | ||
322 | chan_writel(up->txc, HSU_CH_DCR, 0x1 | ||
323 | | (0x1 << 8) | ||
324 | | (0x1 << 16) | ||
325 | | (0x1 << 24)); | ||
326 | up->dma_tx_on = 1; | ||
327 | chan_writel(up->txc, HSU_CH_CR, 0x1); | ||
328 | } | ||
329 | |||
330 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
331 | uart_write_wakeup(&up->port); | ||
332 | } | ||
333 | |||
334 | /* The buffer is already cache coherent */ | ||
335 | void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf) | ||
336 | { | ||
337 | dbuf->ofs = 0; | ||
338 | |||
339 | chan_writel(rxc, HSU_CH_BSR, 32); | ||
340 | chan_writel(rxc, HSU_CH_MOTSR, 4); | ||
341 | |||
342 | chan_writel(rxc, HSU_CH_D0SAR, dbuf->dma_addr); | ||
343 | chan_writel(rxc, HSU_CH_D0TSR, dbuf->dma_size); | ||
344 | chan_writel(rxc, HSU_CH_DCR, 0x1 | (0x1 << 8) | ||
345 | | (0x1 << 16) | ||
346 | | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ | ||
347 | ); | ||
348 | chan_writel(rxc, HSU_CH_CR, 0x3); | ||
349 | |||
350 | mod_timer(&rxc->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ); | ||
351 | } | ||
352 | |||
353 | /* Protected by spin_lock_irqsave(port->lock) */ | ||
354 | static void serial_hsu_start_tx(struct uart_port *port) | ||
355 | { | ||
356 | struct uart_hsu_port *up = | ||
357 | container_of(port, struct uart_hsu_port, port); | ||
358 | |||
359 | if (up->use_dma) { | ||
360 | hsu_dma_tx(up); | ||
361 | } else if (!(up->ier & UART_IER_THRI)) { | ||
362 | up->ier |= UART_IER_THRI; | ||
363 | serial_out(up, UART_IER, up->ier); | ||
364 | } | ||
365 | } | ||
366 | |||
367 | static void serial_hsu_stop_tx(struct uart_port *port) | ||
368 | { | ||
369 | struct uart_hsu_port *up = | ||
370 | container_of(port, struct uart_hsu_port, port); | ||
371 | struct hsu_dma_chan *txc = up->txc; | ||
372 | |||
373 | if (up->use_dma) | ||
374 | chan_writel(txc, HSU_CH_CR, 0x0); | ||
375 | else if (up->ier & UART_IER_THRI) { | ||
376 | up->ier &= ~UART_IER_THRI; | ||
377 | serial_out(up, UART_IER, up->ier); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | /* This is always called in spinlock protected mode, so | ||
382 | * modify timeout timer is safe here */ | ||
383 | void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts) | ||
384 | { | ||
385 | struct hsu_dma_buffer *dbuf = &up->rxbuf; | ||
386 | struct hsu_dma_chan *chan = up->rxc; | ||
387 | struct uart_port *port = &up->port; | ||
388 | struct tty_struct *tty = port->state->port.tty; | ||
389 | int count; | ||
390 | |||
391 | if (!tty) | ||
392 | return; | ||
393 | |||
394 | /* | ||
395 | * First need to know how many is already transferred, | ||
396 | * then check if its a timeout DMA irq, and return | ||
397 | * the trail bytes out, push them up and reenable the | ||
398 | * channel | ||
399 | */ | ||
400 | |||
401 | /* Timeout IRQ, need wait some time, see Errata 2 */ | ||
402 | if (int_sts & 0xf00) | ||
403 | udelay(2); | ||
404 | |||
405 | /* Stop the channel */ | ||
406 | chan_writel(chan, HSU_CH_CR, 0x0); | ||
407 | |||
408 | count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; | ||
409 | if (!count) { | ||
410 | /* Restart the channel before we leave */ | ||
411 | chan_writel(chan, HSU_CH_CR, 0x3); | ||
412 | return; | ||
413 | } | ||
414 | del_timer(&chan->rx_timer); | ||
415 | |||
416 | dma_sync_single_for_cpu(port->dev, dbuf->dma_addr, | ||
417 | dbuf->dma_size, DMA_FROM_DEVICE); | ||
418 | |||
419 | /* | ||
420 | * Head will only wrap around when we recycle | ||
421 | * the DMA buffer, and when that happens, we | ||
422 | * explicitly set tail to 0. So head will | ||
423 | * always be greater than tail. | ||
424 | */ | ||
425 | tty_insert_flip_string(tty, dbuf->buf, count); | ||
426 | port->icount.rx += count; | ||
427 | |||
428 | dma_sync_single_for_device(up->port.dev, dbuf->dma_addr, | ||
429 | dbuf->dma_size, DMA_FROM_DEVICE); | ||
430 | |||
431 | /* Reprogram the channel */ | ||
432 | chan_writel(chan, HSU_CH_D0SAR, dbuf->dma_addr); | ||
433 | chan_writel(chan, HSU_CH_D0TSR, dbuf->dma_size); | ||
434 | chan_writel(chan, HSU_CH_DCR, 0x1 | ||
435 | | (0x1 << 8) | ||
436 | | (0x1 << 16) | ||
437 | | (0x1 << 24) /* timeout bit, see HSU Errata 1 */ | ||
438 | ); | ||
439 | tty_flip_buffer_push(tty); | ||
440 | |||
441 | chan_writel(chan, HSU_CH_CR, 0x3); | ||
442 | chan->rx_timer.expires = jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ; | ||
443 | add_timer(&chan->rx_timer); | ||
444 | |||
445 | } | ||
446 | |||
447 | static void serial_hsu_stop_rx(struct uart_port *port) | ||
448 | { | ||
449 | struct uart_hsu_port *up = | ||
450 | container_of(port, struct uart_hsu_port, port); | ||
451 | struct hsu_dma_chan *chan = up->rxc; | ||
452 | |||
453 | if (up->use_dma) | ||
454 | chan_writel(chan, HSU_CH_CR, 0x2); | ||
455 | else { | ||
456 | up->ier &= ~UART_IER_RLSI; | ||
457 | up->port.read_status_mask &= ~UART_LSR_DR; | ||
458 | serial_out(up, UART_IER, up->ier); | ||
459 | } | ||
460 | } | ||
461 | |||
462 | static inline void receive_chars(struct uart_hsu_port *up, int *status) | ||
463 | { | ||
464 | struct tty_struct *tty = up->port.state->port.tty; | ||
465 | unsigned int ch, flag; | ||
466 | unsigned int max_count = 256; | ||
467 | |||
468 | if (!tty) | ||
469 | return; | ||
470 | |||
471 | do { | ||
472 | ch = serial_in(up, UART_RX); | ||
473 | flag = TTY_NORMAL; | ||
474 | up->port.icount.rx++; | ||
475 | |||
476 | if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | | ||
477 | UART_LSR_FE | UART_LSR_OE))) { | ||
478 | |||
479 | dev_warn(up->dev, "We really rush into ERR/BI case" | ||
480 | "status = 0x%02x", *status); | ||
481 | /* For statistics only */ | ||
482 | if (*status & UART_LSR_BI) { | ||
483 | *status &= ~(UART_LSR_FE | UART_LSR_PE); | ||
484 | up->port.icount.brk++; | ||
485 | /* | ||
486 | * We do the SysRQ and SAK checking | ||
487 | * here because otherwise the break | ||
488 | * may get masked by ignore_status_mask | ||
489 | * or read_status_mask. | ||
490 | */ | ||
491 | if (uart_handle_break(&up->port)) | ||
492 | goto ignore_char; | ||
493 | } else if (*status & UART_LSR_PE) | ||
494 | up->port.icount.parity++; | ||
495 | else if (*status & UART_LSR_FE) | ||
496 | up->port.icount.frame++; | ||
497 | if (*status & UART_LSR_OE) | ||
498 | up->port.icount.overrun++; | ||
499 | |||
500 | /* Mask off conditions which should be ignored. */ | ||
501 | *status &= up->port.read_status_mask; | ||
502 | |||
503 | #ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE | ||
504 | if (up->port.cons && | ||
505 | up->port.cons->index == up->port.line) { | ||
506 | /* Recover the break flag from console xmit */ | ||
507 | *status |= up->lsr_break_flag; | ||
508 | up->lsr_break_flag = 0; | ||
509 | } | ||
510 | #endif | ||
511 | if (*status & UART_LSR_BI) { | ||
512 | flag = TTY_BREAK; | ||
513 | } else if (*status & UART_LSR_PE) | ||
514 | flag = TTY_PARITY; | ||
515 | else if (*status & UART_LSR_FE) | ||
516 | flag = TTY_FRAME; | ||
517 | } | ||
518 | |||
519 | if (uart_handle_sysrq_char(&up->port, ch)) | ||
520 | goto ignore_char; | ||
521 | |||
522 | uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag); | ||
523 | ignore_char: | ||
524 | *status = serial_in(up, UART_LSR); | ||
525 | } while ((*status & UART_LSR_DR) && max_count--); | ||
526 | tty_flip_buffer_push(tty); | ||
527 | } | ||
528 | |||
529 | static void transmit_chars(struct uart_hsu_port *up) | ||
530 | { | ||
531 | struct circ_buf *xmit = &up->port.state->xmit; | ||
532 | int count; | ||
533 | |||
534 | if (up->port.x_char) { | ||
535 | serial_out(up, UART_TX, up->port.x_char); | ||
536 | up->port.icount.tx++; | ||
537 | up->port.x_char = 0; | ||
538 | return; | ||
539 | } | ||
540 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | ||
541 | serial_hsu_stop_tx(&up->port); | ||
542 | return; | ||
543 | } | ||
544 | |||
545 | #ifndef MFD_HSU_A0_STEPPING | ||
546 | count = up->port.fifosize / 2; | ||
547 | #else | ||
548 | /* | ||
549 | * A0 only supports fully empty IRQ, and the first char written | ||
550 | * into it won't clear the EMPT bit, so we may need be cautious | ||
551 | * by useing a shorter buffer | ||
552 | */ | ||
553 | count = up->port.fifosize - 4; | ||
554 | #endif | ||
555 | do { | ||
556 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); | ||
557 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
558 | |||
559 | up->port.icount.tx++; | ||
560 | if (uart_circ_empty(xmit)) | ||
561 | break; | ||
562 | } while (--count > 0); | ||
563 | |||
564 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
565 | uart_write_wakeup(&up->port); | ||
566 | |||
567 | if (uart_circ_empty(xmit)) | ||
568 | serial_hsu_stop_tx(&up->port); | ||
569 | } | ||
570 | |||
571 | static inline void check_modem_status(struct uart_hsu_port *up) | ||
572 | { | ||
573 | int status; | ||
574 | |||
575 | status = serial_in(up, UART_MSR); | ||
576 | |||
577 | if ((status & UART_MSR_ANY_DELTA) == 0) | ||
578 | return; | ||
579 | |||
580 | if (status & UART_MSR_TERI) | ||
581 | up->port.icount.rng++; | ||
582 | if (status & UART_MSR_DDSR) | ||
583 | up->port.icount.dsr++; | ||
584 | /* We may only get DDCD when HW init and reset */ | ||
585 | if (status & UART_MSR_DDCD) | ||
586 | uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); | ||
587 | /* Will start/stop_tx accordingly */ | ||
588 | if (status & UART_MSR_DCTS) | ||
589 | uart_handle_cts_change(&up->port, status & UART_MSR_CTS); | ||
590 | |||
591 | wake_up_interruptible(&up->port.state->port.delta_msr_wait); | ||
592 | } | ||
593 | |||
594 | /* | ||
595 | * This handles the interrupt from one port. | ||
596 | */ | ||
597 | static irqreturn_t port_irq(int irq, void *dev_id) | ||
598 | { | ||
599 | struct uart_hsu_port *up = dev_id; | ||
600 | unsigned int iir, lsr; | ||
601 | unsigned long flags; | ||
602 | |||
603 | if (unlikely(!up->running)) | ||
604 | return IRQ_NONE; | ||
605 | |||
606 | spin_lock_irqsave(&up->port.lock, flags); | ||
607 | if (up->use_dma) { | ||
608 | lsr = serial_in(up, UART_LSR); | ||
609 | if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE | | ||
610 | UART_LSR_FE | UART_LSR_OE))) | ||
611 | dev_warn(up->dev, | ||
612 | "Got lsr irq while using DMA, lsr = 0x%2x\n", | ||
613 | lsr); | ||
614 | check_modem_status(up); | ||
615 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
616 | return IRQ_HANDLED; | ||
617 | } | ||
618 | |||
619 | iir = serial_in(up, UART_IIR); | ||
620 | if (iir & UART_IIR_NO_INT) { | ||
621 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
622 | return IRQ_NONE; | ||
623 | } | ||
624 | |||
625 | lsr = serial_in(up, UART_LSR); | ||
626 | if (lsr & UART_LSR_DR) | ||
627 | receive_chars(up, &lsr); | ||
628 | check_modem_status(up); | ||
629 | |||
630 | /* lsr will be renewed during the receive_chars */ | ||
631 | if (lsr & UART_LSR_THRE) | ||
632 | transmit_chars(up); | ||
633 | |||
634 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
635 | return IRQ_HANDLED; | ||
636 | } | ||
637 | |||
638 | static inline void dma_chan_irq(struct hsu_dma_chan *chan) | ||
639 | { | ||
640 | struct uart_hsu_port *up = chan->uport; | ||
641 | unsigned long flags; | ||
642 | u32 int_sts; | ||
643 | |||
644 | spin_lock_irqsave(&up->port.lock, flags); | ||
645 | |||
646 | if (!up->use_dma || !up->running) | ||
647 | goto exit; | ||
648 | |||
649 | /* | ||
650 | * No matter what situation, need read clear the IRQ status | ||
651 | * There is a bug, see Errata 5, HSD 2900918 | ||
652 | */ | ||
653 | int_sts = chan_readl(chan, HSU_CH_SR); | ||
654 | |||
655 | /* Rx channel */ | ||
656 | if (chan->dirt == DMA_FROM_DEVICE) | ||
657 | hsu_dma_rx(up, int_sts); | ||
658 | |||
659 | /* Tx channel */ | ||
660 | if (chan->dirt == DMA_TO_DEVICE) { | ||
661 | chan_writel(chan, HSU_CH_CR, 0x0); | ||
662 | up->dma_tx_on = 0; | ||
663 | hsu_dma_tx(up); | ||
664 | } | ||
665 | |||
666 | exit: | ||
667 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
668 | return; | ||
669 | } | ||
670 | |||
671 | static irqreturn_t dma_irq(int irq, void *dev_id) | ||
672 | { | ||
673 | struct hsu_port *hsu = dev_id; | ||
674 | u32 int_sts, i; | ||
675 | |||
676 | int_sts = mfd_readl(hsu, HSU_GBL_DMAISR); | ||
677 | |||
678 | /* Currently we only have 6 channels may be used */ | ||
679 | for (i = 0; i < 6; i++) { | ||
680 | if (int_sts & 0x1) | ||
681 | dma_chan_irq(&hsu->chans[i]); | ||
682 | int_sts >>= 1; | ||
683 | } | ||
684 | |||
685 | return IRQ_HANDLED; | ||
686 | } | ||
687 | |||
688 | static unsigned int serial_hsu_tx_empty(struct uart_port *port) | ||
689 | { | ||
690 | struct uart_hsu_port *up = | ||
691 | container_of(port, struct uart_hsu_port, port); | ||
692 | unsigned long flags; | ||
693 | unsigned int ret; | ||
694 | |||
695 | spin_lock_irqsave(&up->port.lock, flags); | ||
696 | ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; | ||
697 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
698 | |||
699 | return ret; | ||
700 | } | ||
701 | |||
702 | static unsigned int serial_hsu_get_mctrl(struct uart_port *port) | ||
703 | { | ||
704 | struct uart_hsu_port *up = | ||
705 | container_of(port, struct uart_hsu_port, port); | ||
706 | unsigned char status; | ||
707 | unsigned int ret; | ||
708 | |||
709 | status = serial_in(up, UART_MSR); | ||
710 | |||
711 | ret = 0; | ||
712 | if (status & UART_MSR_DCD) | ||
713 | ret |= TIOCM_CAR; | ||
714 | if (status & UART_MSR_RI) | ||
715 | ret |= TIOCM_RNG; | ||
716 | if (status & UART_MSR_DSR) | ||
717 | ret |= TIOCM_DSR; | ||
718 | if (status & UART_MSR_CTS) | ||
719 | ret |= TIOCM_CTS; | ||
720 | return ret; | ||
721 | } | ||
722 | |||
723 | static void serial_hsu_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
724 | { | ||
725 | struct uart_hsu_port *up = | ||
726 | container_of(port, struct uart_hsu_port, port); | ||
727 | unsigned char mcr = 0; | ||
728 | |||
729 | if (mctrl & TIOCM_RTS) | ||
730 | mcr |= UART_MCR_RTS; | ||
731 | if (mctrl & TIOCM_DTR) | ||
732 | mcr |= UART_MCR_DTR; | ||
733 | if (mctrl & TIOCM_OUT1) | ||
734 | mcr |= UART_MCR_OUT1; | ||
735 | if (mctrl & TIOCM_OUT2) | ||
736 | mcr |= UART_MCR_OUT2; | ||
737 | if (mctrl & TIOCM_LOOP) | ||
738 | mcr |= UART_MCR_LOOP; | ||
739 | |||
740 | mcr |= up->mcr; | ||
741 | |||
742 | serial_out(up, UART_MCR, mcr); | ||
743 | } | ||
744 | |||
745 | static void serial_hsu_break_ctl(struct uart_port *port, int break_state) | ||
746 | { | ||
747 | struct uart_hsu_port *up = | ||
748 | container_of(port, struct uart_hsu_port, port); | ||
749 | unsigned long flags; | ||
750 | |||
751 | spin_lock_irqsave(&up->port.lock, flags); | ||
752 | if (break_state == -1) | ||
753 | up->lcr |= UART_LCR_SBC; | ||
754 | else | ||
755 | up->lcr &= ~UART_LCR_SBC; | ||
756 | serial_out(up, UART_LCR, up->lcr); | ||
757 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
758 | } | ||
759 | |||
760 | /* | ||
761 | * What special to do: | ||
762 | * 1. chose the 64B fifo mode | ||
763 | * 2. make sure not to select half empty mode for A0 stepping | ||
764 | * 3. start dma or pio depends on configuration | ||
765 | * 4. we only allocate dma memory when needed | ||
766 | */ | ||
767 | static int serial_hsu_startup(struct uart_port *port) | ||
768 | { | ||
769 | struct uart_hsu_port *up = | ||
770 | container_of(port, struct uart_hsu_port, port); | ||
771 | unsigned long flags; | ||
772 | |||
773 | /* | ||
774 | * Clear the FIFO buffers and disable them. | ||
775 | * (they will be reenabled in set_termios()) | ||
776 | */ | ||
777 | serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); | ||
778 | serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | | ||
779 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); | ||
780 | serial_out(up, UART_FCR, 0); | ||
781 | |||
782 | /* Clear the interrupt registers. */ | ||
783 | (void) serial_in(up, UART_LSR); | ||
784 | (void) serial_in(up, UART_RX); | ||
785 | (void) serial_in(up, UART_IIR); | ||
786 | (void) serial_in(up, UART_MSR); | ||
787 | |||
788 | /* Now, initialize the UART, default is 8n1 */ | ||
789 | serial_out(up, UART_LCR, UART_LCR_WLEN8); | ||
790 | |||
791 | spin_lock_irqsave(&up->port.lock, flags); | ||
792 | |||
793 | up->port.mctrl |= TIOCM_OUT2; | ||
794 | serial_hsu_set_mctrl(&up->port, up->port.mctrl); | ||
795 | |||
796 | /* | ||
797 | * Finally, enable interrupts. Note: Modem status interrupts | ||
798 | * are set via set_termios(), which will be occurring imminently | ||
799 | * anyway, so we don't enable them here. | ||
800 | */ | ||
801 | if (!up->use_dma) | ||
802 | up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE; | ||
803 | else | ||
804 | up->ier = 0; | ||
805 | serial_out(up, UART_IER, up->ier); | ||
806 | |||
807 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
808 | |||
809 | /* DMA init */ | ||
810 | if (up->use_dma) { | ||
811 | struct hsu_dma_buffer *dbuf; | ||
812 | struct circ_buf *xmit = &port->state->xmit; | ||
813 | |||
814 | up->dma_tx_on = 0; | ||
815 | |||
816 | /* First allocate the RX buffer */ | ||
817 | dbuf = &up->rxbuf; | ||
818 | dbuf->buf = kzalloc(HSU_DMA_BUF_SIZE, GFP_KERNEL); | ||
819 | if (!dbuf->buf) { | ||
820 | up->use_dma = 0; | ||
821 | goto exit; | ||
822 | } | ||
823 | dbuf->dma_addr = dma_map_single(port->dev, | ||
824 | dbuf->buf, | ||
825 | HSU_DMA_BUF_SIZE, | ||
826 | DMA_FROM_DEVICE); | ||
827 | dbuf->dma_size = HSU_DMA_BUF_SIZE; | ||
828 | |||
829 | /* Start the RX channel right now */ | ||
830 | hsu_dma_start_rx_chan(up->rxc, dbuf); | ||
831 | |||
832 | /* Next init the TX DMA */ | ||
833 | dbuf = &up->txbuf; | ||
834 | dbuf->buf = xmit->buf; | ||
835 | dbuf->dma_addr = dma_map_single(port->dev, | ||
836 | dbuf->buf, | ||
837 | UART_XMIT_SIZE, | ||
838 | DMA_TO_DEVICE); | ||
839 | dbuf->dma_size = UART_XMIT_SIZE; | ||
840 | |||
841 | /* This should not be changed all around */ | ||
842 | chan_writel(up->txc, HSU_CH_BSR, 32); | ||
843 | chan_writel(up->txc, HSU_CH_MOTSR, 4); | ||
844 | dbuf->ofs = 0; | ||
845 | } | ||
846 | |||
847 | exit: | ||
848 | /* And clear the interrupt registers again for luck. */ | ||
849 | (void) serial_in(up, UART_LSR); | ||
850 | (void) serial_in(up, UART_RX); | ||
851 | (void) serial_in(up, UART_IIR); | ||
852 | (void) serial_in(up, UART_MSR); | ||
853 | |||
854 | up->running = 1; | ||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | static void serial_hsu_shutdown(struct uart_port *port) | ||
859 | { | ||
860 | struct uart_hsu_port *up = | ||
861 | container_of(port, struct uart_hsu_port, port); | ||
862 | unsigned long flags; | ||
863 | |||
864 | del_timer_sync(&up->rxc->rx_timer); | ||
865 | |||
866 | /* Disable interrupts from this port */ | ||
867 | up->ier = 0; | ||
868 | serial_out(up, UART_IER, 0); | ||
869 | up->running = 0; | ||
870 | |||
871 | spin_lock_irqsave(&up->port.lock, flags); | ||
872 | up->port.mctrl &= ~TIOCM_OUT2; | ||
873 | serial_hsu_set_mctrl(&up->port, up->port.mctrl); | ||
874 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
875 | |||
876 | /* Disable break condition and FIFOs */ | ||
877 | serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC); | ||
878 | serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | | ||
879 | UART_FCR_CLEAR_RCVR | | ||
880 | UART_FCR_CLEAR_XMIT); | ||
881 | serial_out(up, UART_FCR, 0); | ||
882 | } | ||
883 | |||
884 | static void | ||
885 | serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios, | ||
886 | struct ktermios *old) | ||
887 | { | ||
888 | struct uart_hsu_port *up = | ||
889 | container_of(port, struct uart_hsu_port, port); | ||
890 | struct tty_struct *tty = port->state->port.tty; | ||
891 | unsigned char cval, fcr = 0; | ||
892 | unsigned long flags; | ||
893 | unsigned int baud, quot; | ||
894 | u32 mul = 0x3600; | ||
895 | u32 ps = 0x10; | ||
896 | |||
897 | switch (termios->c_cflag & CSIZE) { | ||
898 | case CS5: | ||
899 | cval = UART_LCR_WLEN5; | ||
900 | break; | ||
901 | case CS6: | ||
902 | cval = UART_LCR_WLEN6; | ||
903 | break; | ||
904 | case CS7: | ||
905 | cval = UART_LCR_WLEN7; | ||
906 | break; | ||
907 | default: | ||
908 | case CS8: | ||
909 | cval = UART_LCR_WLEN8; | ||
910 | break; | ||
911 | } | ||
912 | |||
913 | /* CMSPAR isn't supported by this driver */ | ||
914 | if (tty) | ||
915 | tty->termios->c_cflag &= ~CMSPAR; | ||
916 | |||
917 | if (termios->c_cflag & CSTOPB) | ||
918 | cval |= UART_LCR_STOP; | ||
919 | if (termios->c_cflag & PARENB) | ||
920 | cval |= UART_LCR_PARITY; | ||
921 | if (!(termios->c_cflag & PARODD)) | ||
922 | cval |= UART_LCR_EPAR; | ||
923 | |||
924 | /* | ||
925 | * For those basic low baud rate we can get the direct | ||
926 | * scalar from 2746800, like 115200 = 2746800/24, for those | ||
927 | * higher baud rate, we have to handle them case by case, | ||
928 | * but DIV reg is never touched as its default value 0x3d09 | ||
929 | */ | ||
930 | baud = uart_get_baud_rate(port, termios, old, 0, 4000000); | ||
931 | quot = uart_get_divisor(port, baud); | ||
932 | |||
933 | switch (baud) { | ||
934 | case 3500000: | ||
935 | mul = 0x3345; | ||
936 | ps = 0xC; | ||
937 | quot = 1; | ||
938 | break; | ||
939 | case 2500000: | ||
940 | mul = 0x2710; | ||
941 | ps = 0x10; | ||
942 | quot = 1; | ||
943 | break; | ||
944 | case 18432000: | ||
945 | mul = 0x2400; | ||
946 | ps = 0x10; | ||
947 | quot = 1; | ||
948 | break; | ||
949 | case 1500000: | ||
950 | mul = 0x1D4C; | ||
951 | ps = 0xc; | ||
952 | quot = 1; | ||
953 | break; | ||
954 | default: | ||
955 | ; | ||
956 | } | ||
957 | |||
958 | if ((up->port.uartclk / quot) < (2400 * 16)) | ||
959 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_1B; | ||
960 | else if ((up->port.uartclk / quot) < (230400 * 16)) | ||
961 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_16B; | ||
962 | else | ||
963 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B; | ||
964 | |||
965 | fcr |= UART_FCR_HSU_64B_FIFO; | ||
966 | #ifdef MFD_HSU_A0_STEPPING | ||
967 | /* A0 doesn't support half empty IRQ */ | ||
968 | fcr |= UART_FCR_FULL_EMPT_TXI; | ||
969 | #endif | ||
970 | |||
971 | /* | ||
972 | * Ok, we're now changing the port state. Do it with | ||
973 | * interrupts disabled. | ||
974 | */ | ||
975 | spin_lock_irqsave(&up->port.lock, flags); | ||
976 | |||
977 | /* Update the per-port timeout */ | ||
978 | uart_update_timeout(port, termios->c_cflag, baud); | ||
979 | |||
980 | up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | ||
981 | if (termios->c_iflag & INPCK) | ||
982 | up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; | ||
983 | if (termios->c_iflag & (BRKINT | PARMRK)) | ||
984 | up->port.read_status_mask |= UART_LSR_BI; | ||
985 | |||
986 | /* Characters to ignore */ | ||
987 | up->port.ignore_status_mask = 0; | ||
988 | if (termios->c_iflag & IGNPAR) | ||
989 | up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; | ||
990 | if (termios->c_iflag & IGNBRK) { | ||
991 | up->port.ignore_status_mask |= UART_LSR_BI; | ||
992 | /* | ||
993 | * If we're ignoring parity and break indicators, | ||
994 | * ignore overruns too (for real raw support). | ||
995 | */ | ||
996 | if (termios->c_iflag & IGNPAR) | ||
997 | up->port.ignore_status_mask |= UART_LSR_OE; | ||
998 | } | ||
999 | |||
1000 | /* Ignore all characters if CREAD is not set */ | ||
1001 | if ((termios->c_cflag & CREAD) == 0) | ||
1002 | up->port.ignore_status_mask |= UART_LSR_DR; | ||
1003 | |||
1004 | /* | ||
1005 | * CTS flow control flag and modem status interrupts, disable | ||
1006 | * MSI by default | ||
1007 | */ | ||
1008 | up->ier &= ~UART_IER_MSI; | ||
1009 | if (UART_ENABLE_MS(&up->port, termios->c_cflag)) | ||
1010 | up->ier |= UART_IER_MSI; | ||
1011 | |||
1012 | serial_out(up, UART_IER, up->ier); | ||
1013 | |||
1014 | if (termios->c_cflag & CRTSCTS) | ||
1015 | up->mcr |= UART_MCR_AFE | UART_MCR_RTS; | ||
1016 | else | ||
1017 | up->mcr &= ~UART_MCR_AFE; | ||
1018 | |||
1019 | serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ | ||
1020 | serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ | ||
1021 | serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ | ||
1022 | serial_out(up, UART_LCR, cval); /* reset DLAB */ | ||
1023 | serial_out(up, UART_MUL, mul); /* set MUL */ | ||
1024 | serial_out(up, UART_PS, ps); /* set PS */ | ||
1025 | up->lcr = cval; /* Save LCR */ | ||
1026 | serial_hsu_set_mctrl(&up->port, up->port.mctrl); | ||
1027 | serial_out(up, UART_FCR, fcr); | ||
1028 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
1029 | } | ||
1030 | |||
1031 | static void | ||
1032 | serial_hsu_pm(struct uart_port *port, unsigned int state, | ||
1033 | unsigned int oldstate) | ||
1034 | { | ||
1035 | } | ||
1036 | |||
1037 | static void serial_hsu_release_port(struct uart_port *port) | ||
1038 | { | ||
1039 | } | ||
1040 | |||
1041 | static int serial_hsu_request_port(struct uart_port *port) | ||
1042 | { | ||
1043 | return 0; | ||
1044 | } | ||
1045 | |||
1046 | static void serial_hsu_config_port(struct uart_port *port, int flags) | ||
1047 | { | ||
1048 | struct uart_hsu_port *up = | ||
1049 | container_of(port, struct uart_hsu_port, port); | ||
1050 | up->port.type = PORT_MFD; | ||
1051 | } | ||
1052 | |||
1053 | static int | ||
1054 | serial_hsu_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
1055 | { | ||
1056 | /* We don't want the core code to modify any port params */ | ||
1057 | return -EINVAL; | ||
1058 | } | ||
1059 | |||
1060 | static const char * | ||
1061 | serial_hsu_type(struct uart_port *port) | ||
1062 | { | ||
1063 | struct uart_hsu_port *up = | ||
1064 | container_of(port, struct uart_hsu_port, port); | ||
1065 | return up->name; | ||
1066 | } | ||
1067 | |||
1068 | /* Mainly for uart console use */ | ||
1069 | static struct uart_hsu_port *serial_hsu_ports[3]; | ||
1070 | static struct uart_driver serial_hsu_reg; | ||
1071 | |||
1072 | #ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE | ||
1073 | |||
1074 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) | ||
1075 | |||
1076 | /* Wait for transmitter & holding register to empty */ | ||
1077 | static inline void wait_for_xmitr(struct uart_hsu_port *up) | ||
1078 | { | ||
1079 | unsigned int status, tmout = 1000; | ||
1080 | |||
1081 | /* Wait up to 1ms for the character to be sent. */ | ||
1082 | do { | ||
1083 | status = serial_in(up, UART_LSR); | ||
1084 | |||
1085 | if (status & UART_LSR_BI) | ||
1086 | up->lsr_break_flag = UART_LSR_BI; | ||
1087 | |||
1088 | if (--tmout == 0) | ||
1089 | break; | ||
1090 | udelay(1); | ||
1091 | } while (!(status & BOTH_EMPTY)); | ||
1092 | |||
1093 | /* Wait up to 1s for flow control if necessary */ | ||
1094 | if (up->port.flags & UPF_CONS_FLOW) { | ||
1095 | tmout = 1000000; | ||
1096 | while (--tmout && | ||
1097 | ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) | ||
1098 | udelay(1); | ||
1099 | } | ||
1100 | } | ||
1101 | |||
1102 | static void serial_hsu_console_putchar(struct uart_port *port, int ch) | ||
1103 | { | ||
1104 | struct uart_hsu_port *up = | ||
1105 | container_of(port, struct uart_hsu_port, port); | ||
1106 | |||
1107 | wait_for_xmitr(up); | ||
1108 | serial_out(up, UART_TX, ch); | ||
1109 | } | ||
1110 | |||
1111 | /* | ||
1112 | * Print a string to the serial port trying not to disturb | ||
1113 | * any possible real use of the port... | ||
1114 | * | ||
1115 | * The console_lock must be held when we get here. | ||
1116 | */ | ||
1117 | static void | ||
1118 | serial_hsu_console_write(struct console *co, const char *s, unsigned int count) | ||
1119 | { | ||
1120 | struct uart_hsu_port *up = serial_hsu_ports[co->index]; | ||
1121 | unsigned long flags; | ||
1122 | unsigned int ier; | ||
1123 | int locked = 1; | ||
1124 | |||
1125 | local_irq_save(flags); | ||
1126 | if (up->port.sysrq) | ||
1127 | locked = 0; | ||
1128 | else if (oops_in_progress) { | ||
1129 | locked = spin_trylock(&up->port.lock); | ||
1130 | } else | ||
1131 | spin_lock(&up->port.lock); | ||
1132 | |||
1133 | /* First save the IER then disable the interrupts */ | ||
1134 | ier = serial_in(up, UART_IER); | ||
1135 | serial_out(up, UART_IER, 0); | ||
1136 | |||
1137 | uart_console_write(&up->port, s, count, serial_hsu_console_putchar); | ||
1138 | |||
1139 | /* | ||
1140 | * Finally, wait for transmitter to become empty | ||
1141 | * and restore the IER | ||
1142 | */ | ||
1143 | wait_for_xmitr(up); | ||
1144 | serial_out(up, UART_IER, ier); | ||
1145 | |||
1146 | if (locked) | ||
1147 | spin_unlock(&up->port.lock); | ||
1148 | local_irq_restore(flags); | ||
1149 | } | ||
1150 | |||
1151 | static struct console serial_hsu_console; | ||
1152 | |||
1153 | static int __init | ||
1154 | serial_hsu_console_setup(struct console *co, char *options) | ||
1155 | { | ||
1156 | struct uart_hsu_port *up; | ||
1157 | int baud = 115200; | ||
1158 | int bits = 8; | ||
1159 | int parity = 'n'; | ||
1160 | int flow = 'n'; | ||
1161 | int ret; | ||
1162 | |||
1163 | if (co->index == -1 || co->index >= serial_hsu_reg.nr) | ||
1164 | co->index = 0; | ||
1165 | up = serial_hsu_ports[co->index]; | ||
1166 | if (!up) | ||
1167 | return -ENODEV; | ||
1168 | |||
1169 | if (options) | ||
1170 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
1171 | |||
1172 | ret = uart_set_options(&up->port, co, baud, parity, bits, flow); | ||
1173 | |||
1174 | return ret; | ||
1175 | } | ||
1176 | |||
1177 | static struct console serial_hsu_console = { | ||
1178 | .name = "ttyMFD", | ||
1179 | .write = serial_hsu_console_write, | ||
1180 | .device = uart_console_device, | ||
1181 | .setup = serial_hsu_console_setup, | ||
1182 | .flags = CON_PRINTBUFFER, | ||
1183 | .index = 2, | ||
1184 | .data = &serial_hsu_reg, | ||
1185 | }; | ||
1186 | #endif | ||
1187 | |||
1188 | struct uart_ops serial_hsu_pops = { | ||
1189 | .tx_empty = serial_hsu_tx_empty, | ||
1190 | .set_mctrl = serial_hsu_set_mctrl, | ||
1191 | .get_mctrl = serial_hsu_get_mctrl, | ||
1192 | .stop_tx = serial_hsu_stop_tx, | ||
1193 | .start_tx = serial_hsu_start_tx, | ||
1194 | .stop_rx = serial_hsu_stop_rx, | ||
1195 | .enable_ms = serial_hsu_enable_ms, | ||
1196 | .break_ctl = serial_hsu_break_ctl, | ||
1197 | .startup = serial_hsu_startup, | ||
1198 | .shutdown = serial_hsu_shutdown, | ||
1199 | .set_termios = serial_hsu_set_termios, | ||
1200 | .pm = serial_hsu_pm, | ||
1201 | .type = serial_hsu_type, | ||
1202 | .release_port = serial_hsu_release_port, | ||
1203 | .request_port = serial_hsu_request_port, | ||
1204 | .config_port = serial_hsu_config_port, | ||
1205 | .verify_port = serial_hsu_verify_port, | ||
1206 | }; | ||
1207 | |||
1208 | static struct uart_driver serial_hsu_reg = { | ||
1209 | .owner = THIS_MODULE, | ||
1210 | .driver_name = "MFD serial", | ||
1211 | .dev_name = "ttyMFD", | ||
1212 | .major = TTY_MAJOR, | ||
1213 | .minor = 128, | ||
1214 | .nr = 3, | ||
1215 | }; | ||
1216 | |||
1217 | #ifdef CONFIG_PM | ||
1218 | static int serial_hsu_suspend(struct pci_dev *pdev, pm_message_t state) | ||
1219 | { | ||
1220 | void *priv = pci_get_drvdata(pdev); | ||
1221 | struct uart_hsu_port *up; | ||
1222 | |||
1223 | /* Make sure this is not the internal dma controller */ | ||
1224 | if (priv && (pdev->device != 0x081E)) { | ||
1225 | up = priv; | ||
1226 | uart_suspend_port(&serial_hsu_reg, &up->port); | ||
1227 | } | ||
1228 | |||
1229 | pci_save_state(pdev); | ||
1230 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
1231 | return 0; | ||
1232 | } | ||
1233 | |||
1234 | static int serial_hsu_resume(struct pci_dev *pdev) | ||
1235 | { | ||
1236 | void *priv = pci_get_drvdata(pdev); | ||
1237 | struct uart_hsu_port *up; | ||
1238 | int ret; | ||
1239 | |||
1240 | pci_set_power_state(pdev, PCI_D0); | ||
1241 | pci_restore_state(pdev); | ||
1242 | |||
1243 | ret = pci_enable_device(pdev); | ||
1244 | if (ret) | ||
1245 | dev_warn(&pdev->dev, | ||
1246 | "HSU: can't re-enable device, try to continue\n"); | ||
1247 | |||
1248 | if (priv && (pdev->device != 0x081E)) { | ||
1249 | up = priv; | ||
1250 | uart_resume_port(&serial_hsu_reg, &up->port); | ||
1251 | } | ||
1252 | return 0; | ||
1253 | } | ||
1254 | #else | ||
1255 | #define serial_hsu_suspend NULL | ||
1256 | #define serial_hsu_resume NULL | ||
1257 | #endif | ||
1258 | |||
1259 | /* temp global pointer before we settle down on using one or four PCI dev */ | ||
1260 | static struct hsu_port *phsu; | ||
1261 | |||
1262 | static int serial_hsu_probe(struct pci_dev *pdev, | ||
1263 | const struct pci_device_id *ent) | ||
1264 | { | ||
1265 | struct uart_hsu_port *uport; | ||
1266 | int index, ret; | ||
1267 | |||
1268 | printk(KERN_INFO "HSU: found PCI Serial controller(ID: %04x:%04x)\n", | ||
1269 | pdev->vendor, pdev->device); | ||
1270 | |||
1271 | switch (pdev->device) { | ||
1272 | case 0x081B: | ||
1273 | index = 0; | ||
1274 | break; | ||
1275 | case 0x081C: | ||
1276 | index = 1; | ||
1277 | break; | ||
1278 | case 0x081D: | ||
1279 | index = 2; | ||
1280 | break; | ||
1281 | case 0x081E: | ||
1282 | /* internal DMA controller */ | ||
1283 | index = 3; | ||
1284 | break; | ||
1285 | default: | ||
1286 | dev_err(&pdev->dev, "HSU: out of index!"); | ||
1287 | return -ENODEV; | ||
1288 | } | ||
1289 | |||
1290 | ret = pci_enable_device(pdev); | ||
1291 | if (ret) | ||
1292 | return ret; | ||
1293 | |||
1294 | if (index == 3) { | ||
1295 | /* DMA controller */ | ||
1296 | ret = request_irq(pdev->irq, dma_irq, 0, "hsu_dma", phsu); | ||
1297 | if (ret) { | ||
1298 | dev_err(&pdev->dev, "can not get IRQ\n"); | ||
1299 | goto err_disable; | ||
1300 | } | ||
1301 | pci_set_drvdata(pdev, phsu); | ||
1302 | } else { | ||
1303 | /* UART port 0~2 */ | ||
1304 | uport = &phsu->port[index]; | ||
1305 | uport->port.irq = pdev->irq; | ||
1306 | uport->port.dev = &pdev->dev; | ||
1307 | uport->dev = &pdev->dev; | ||
1308 | |||
1309 | ret = request_irq(pdev->irq, port_irq, 0, uport->name, uport); | ||
1310 | if (ret) { | ||
1311 | dev_err(&pdev->dev, "can not get IRQ\n"); | ||
1312 | goto err_disable; | ||
1313 | } | ||
1314 | uart_add_one_port(&serial_hsu_reg, &uport->port); | ||
1315 | |||
1316 | #ifdef CONFIG_SERIAL_MFD_HSU_CONSOLE | ||
1317 | if (index == 2) { | ||
1318 | register_console(&serial_hsu_console); | ||
1319 | uport->port.cons = &serial_hsu_console; | ||
1320 | } | ||
1321 | #endif | ||
1322 | pci_set_drvdata(pdev, uport); | ||
1323 | } | ||
1324 | |||
1325 | return 0; | ||
1326 | |||
1327 | err_disable: | ||
1328 | pci_disable_device(pdev); | ||
1329 | return ret; | ||
1330 | } | ||
1331 | |||
1332 | static void hsu_dma_rx_timeout(unsigned long data) | ||
1333 | { | ||
1334 | struct hsu_dma_chan *chan = (void *)data; | ||
1335 | struct uart_hsu_port *up = chan->uport; | ||
1336 | struct hsu_dma_buffer *dbuf = &up->rxbuf; | ||
1337 | int count = 0; | ||
1338 | unsigned long flags; | ||
1339 | |||
1340 | spin_lock_irqsave(&up->port.lock, flags); | ||
1341 | |||
1342 | count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr; | ||
1343 | |||
1344 | if (!count) { | ||
1345 | mod_timer(&chan->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ); | ||
1346 | goto exit; | ||
1347 | } | ||
1348 | |||
1349 | hsu_dma_rx(up, 0); | ||
1350 | exit: | ||
1351 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
1352 | } | ||
1353 | |||
1354 | static void hsu_global_init(void) | ||
1355 | { | ||
1356 | struct hsu_port *hsu; | ||
1357 | struct uart_hsu_port *uport; | ||
1358 | struct hsu_dma_chan *dchan; | ||
1359 | int i, ret; | ||
1360 | |||
1361 | hsu = kzalloc(sizeof(struct hsu_port), GFP_KERNEL); | ||
1362 | if (!hsu) | ||
1363 | return; | ||
1364 | |||
1365 | /* Get basic io resource and map it */ | ||
1366 | hsu->paddr = 0xffa28000; | ||
1367 | hsu->iolen = 0x1000; | ||
1368 | |||
1369 | if (!(request_mem_region(hsu->paddr, hsu->iolen, "HSU global"))) | ||
1370 | pr_warning("HSU: error in request mem region\n"); | ||
1371 | |||
1372 | hsu->reg = ioremap_nocache((unsigned long)hsu->paddr, hsu->iolen); | ||
1373 | if (!hsu->reg) { | ||
1374 | pr_err("HSU: error in ioremap\n"); | ||
1375 | ret = -ENOMEM; | ||
1376 | goto err_free_region; | ||
1377 | } | ||
1378 | |||
1379 | /* Initialise the 3 UART ports */ | ||
1380 | uport = hsu->port; | ||
1381 | for (i = 0; i < 3; i++) { | ||
1382 | uport->port.type = PORT_MFD; | ||
1383 | uport->port.iotype = UPIO_MEM; | ||
1384 | uport->port.mapbase = (resource_size_t)hsu->paddr | ||
1385 | + HSU_PORT_REG_OFFSET | ||
1386 | + i * HSU_PORT_REG_LENGTH; | ||
1387 | uport->port.membase = hsu->reg + HSU_PORT_REG_OFFSET | ||
1388 | + i * HSU_PORT_REG_LENGTH; | ||
1389 | |||
1390 | sprintf(uport->name, "hsu_port%d", i); | ||
1391 | uport->port.fifosize = 64; | ||
1392 | uport->port.ops = &serial_hsu_pops; | ||
1393 | uport->port.line = i; | ||
1394 | uport->port.flags = UPF_IOREMAP; | ||
1395 | /* set the scalable maxim support rate to 2746800 bps */ | ||
1396 | uport->port.uartclk = 115200 * 24 * 16; | ||
1397 | |||
1398 | uport->running = 0; | ||
1399 | uport->txc = &hsu->chans[i * 2]; | ||
1400 | uport->rxc = &hsu->chans[i * 2 + 1]; | ||
1401 | |||
1402 | serial_hsu_ports[i] = uport; | ||
1403 | uport->index = i; | ||
1404 | uport++; | ||
1405 | } | ||
1406 | |||
1407 | /* Initialise 6 dma channels */ | ||
1408 | dchan = hsu->chans; | ||
1409 | for (i = 0; i < 6; i++) { | ||
1410 | dchan->id = i; | ||
1411 | dchan->dirt = (i & 0x1) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
1412 | dchan->uport = &hsu->port[i/2]; | ||
1413 | dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET + | ||
1414 | i * HSU_DMA_CHANS_REG_LENGTH; | ||
1415 | |||
1416 | /* Work around for RX */ | ||
1417 | if (dchan->dirt == DMA_FROM_DEVICE) { | ||
1418 | init_timer(&dchan->rx_timer); | ||
1419 | dchan->rx_timer.function = hsu_dma_rx_timeout; | ||
1420 | dchan->rx_timer.data = (unsigned long)dchan; | ||
1421 | } | ||
1422 | dchan++; | ||
1423 | } | ||
1424 | |||
1425 | phsu = hsu; | ||
1426 | |||
1427 | hsu_debugfs_init(hsu); | ||
1428 | return; | ||
1429 | |||
1430 | err_free_region: | ||
1431 | release_mem_region(hsu->paddr, hsu->iolen); | ||
1432 | kfree(hsu); | ||
1433 | return; | ||
1434 | } | ||
1435 | |||
1436 | static void serial_hsu_remove(struct pci_dev *pdev) | ||
1437 | { | ||
1438 | struct hsu_port *hsu; | ||
1439 | int i; | ||
1440 | |||
1441 | hsu = pci_get_drvdata(pdev); | ||
1442 | if (!hsu) | ||
1443 | return; | ||
1444 | |||
1445 | for (i = 0; i < 3; i++) | ||
1446 | uart_remove_one_port(&serial_hsu_reg, &hsu->port[i].port); | ||
1447 | |||
1448 | pci_set_drvdata(pdev, NULL); | ||
1449 | free_irq(hsu->irq, hsu); | ||
1450 | pci_disable_device(pdev); | ||
1451 | } | ||
1452 | |||
1453 | /* First 3 are UART ports, and the 4th is the DMA */ | ||
1454 | static const struct pci_device_id pci_ids[] __devinitdata = { | ||
1455 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081B) }, | ||
1456 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081C) }, | ||
1457 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081D) }, | ||
1458 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081E) }, | ||
1459 | {}, | ||
1460 | }; | ||
1461 | |||
1462 | static struct pci_driver hsu_pci_driver = { | ||
1463 | .name = "HSU serial", | ||
1464 | .id_table = pci_ids, | ||
1465 | .probe = serial_hsu_probe, | ||
1466 | .remove = __devexit_p(serial_hsu_remove), | ||
1467 | .suspend = serial_hsu_suspend, | ||
1468 | .resume = serial_hsu_resume, | ||
1469 | }; | ||
1470 | |||
1471 | static int __init hsu_pci_init(void) | ||
1472 | { | ||
1473 | int ret; | ||
1474 | |||
1475 | hsu_global_init(); | ||
1476 | |||
1477 | ret = uart_register_driver(&serial_hsu_reg); | ||
1478 | if (ret) | ||
1479 | return ret; | ||
1480 | |||
1481 | return pci_register_driver(&hsu_pci_driver); | ||
1482 | } | ||
1483 | |||
1484 | static void __exit hsu_pci_exit(void) | ||
1485 | { | ||
1486 | pci_unregister_driver(&hsu_pci_driver); | ||
1487 | uart_unregister_driver(&serial_hsu_reg); | ||
1488 | |||
1489 | hsu_debugfs_remove(phsu); | ||
1490 | |||
1491 | kfree(phsu); | ||
1492 | } | ||
1493 | |||
1494 | module_init(hsu_pci_init); | ||
1495 | module_exit(hsu_pci_exit); | ||
1496 | |||
1497 | MODULE_LICENSE("GPL v2"); | ||
1498 | MODULE_ALIAS("platform:medfield-hsu"); | ||
diff --git a/drivers/serial/mrst_max3110.c b/drivers/serial/mrst_max3110.c new file mode 100644 index 000000000000..f6ad1ecbff79 --- /dev/null +++ b/drivers/serial/mrst_max3110.c | |||
@@ -0,0 +1,844 @@ | |||
1 | /* | ||
2 | * max3110.c - spi uart protocol driver for Maxim 3110 on Moorestown | ||
3 | * | ||
4 | * Copyright (C) Intel 2008 Feng Tang <feng.tang@intel.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | |||
20 | /* | ||
21 | * Note: | ||
22 | * 1. From Max3110 spec, the Rx FIFO has 8 words, while the Tx FIFO only has | ||
23 | * 1 word. If SPI master controller doesn't support sclk frequency change, | ||
24 | * then the char need be sent out one by one with some delay | ||
25 | * | ||
26 | * 2. Currently only RX availabe interrrupt is used, no need for waiting TXE | ||
27 | * interrupt for a low speed UART device | ||
28 | */ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/ioport.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/console.h> | ||
34 | #include <linux/sysrq.h> | ||
35 | #include <linux/platform_device.h> | ||
36 | #include <linux/tty.h> | ||
37 | #include <linux/tty_flip.h> | ||
38 | #include <linux/serial_core.h> | ||
39 | #include <linux/serial_reg.h> | ||
40 | |||
41 | #include <linux/kthread.h> | ||
42 | #include <linux/delay.h> | ||
43 | #include <asm/atomic.h> | ||
44 | #include <linux/spi/spi.h> | ||
45 | #include <linux/spi/dw_spi.h> | ||
46 | |||
47 | #include "mrst_max3110.h" | ||
48 | |||
49 | #define PR_FMT "mrst_max3110: " | ||
50 | |||
51 | #define UART_TX_NEEDED 1 | ||
52 | #define CON_TX_NEEDED 2 | ||
53 | #define BIT_IRQ_PENDING 3 | ||
54 | |||
55 | struct uart_max3110 { | ||
56 | struct uart_port port; | ||
57 | struct spi_device *spi; | ||
58 | char *name; | ||
59 | |||
60 | wait_queue_head_t wq; | ||
61 | struct task_struct *main_thread; | ||
62 | struct task_struct *read_thread; | ||
63 | struct mutex thread_mutex;; | ||
64 | |||
65 | u32 baud; | ||
66 | u16 cur_conf; | ||
67 | u8 clock; | ||
68 | u8 parity, word_7bits; | ||
69 | |||
70 | unsigned long uart_flags; | ||
71 | |||
72 | /* console related */ | ||
73 | struct circ_buf con_xmit; | ||
74 | |||
75 | /* irq related */ | ||
76 | u16 irq; | ||
77 | }; | ||
78 | |||
79 | /* global data structure, may need be removed */ | ||
80 | struct uart_max3110 *pmax; | ||
81 | static inline void receive_char(struct uart_max3110 *max, u8 ch); | ||
82 | static void receive_chars(struct uart_max3110 *max, | ||
83 | unsigned char *str, int len); | ||
84 | static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf); | ||
85 | static void max3110_console_receive(struct uart_max3110 *max); | ||
86 | |||
87 | int max3110_write_then_read(struct uart_max3110 *max, | ||
88 | const u8 *txbuf, u8 *rxbuf, unsigned len, int always_fast) | ||
89 | { | ||
90 | struct spi_device *spi = max->spi; | ||
91 | struct spi_message message; | ||
92 | struct spi_transfer x; | ||
93 | int ret; | ||
94 | |||
95 | if (!txbuf || !rxbuf) | ||
96 | return -EINVAL; | ||
97 | |||
98 | spi_message_init(&message); | ||
99 | memset(&x, 0, sizeof x); | ||
100 | x.len = len; | ||
101 | x.tx_buf = txbuf; | ||
102 | x.rx_buf = rxbuf; | ||
103 | spi_message_add_tail(&x, &message); | ||
104 | |||
105 | if (always_fast) | ||
106 | x.speed_hz = 3125000; | ||
107 | else if (max->baud) | ||
108 | x.speed_hz = max->baud; | ||
109 | |||
110 | /* Do the i/o */ | ||
111 | ret = spi_sync(spi, &message); | ||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | /* Write a u16 to the device, and return one u16 read back */ | ||
116 | int max3110_out(struct uart_max3110 *max, const u16 out) | ||
117 | { | ||
118 | u16 tmp; | ||
119 | int ret; | ||
120 | |||
121 | ret = max3110_write_then_read(max, (u8 *)&out, (u8 *)&tmp, 2, 1); | ||
122 | if (ret) | ||
123 | return ret; | ||
124 | |||
125 | /* If some valid data is read back */ | ||
126 | if (tmp & MAX3110_READ_DATA_AVAILABLE) | ||
127 | receive_char(max, (tmp & 0xff)); | ||
128 | |||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | #define MAX_READ_LEN 20 | ||
133 | /* | ||
134 | * This is usually used to read data from SPIC RX FIFO, which doesn't | ||
135 | * need any delay like flushing character out. It returns how many | ||
136 | * valide bytes are read back | ||
137 | */ | ||
138 | static int max3110_read_multi(struct uart_max3110 *max, int len, u8 *buf) | ||
139 | { | ||
140 | u16 out[MAX_READ_LEN], in[MAX_READ_LEN]; | ||
141 | u8 *pbuf, valid_str[MAX_READ_LEN]; | ||
142 | int i, j, bytelen; | ||
143 | |||
144 | if (len > MAX_READ_LEN) { | ||
145 | pr_err(PR_FMT "read len %d is too large\n", len); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | bytelen = len * 2; | ||
150 | memset(out, 0, bytelen); | ||
151 | memset(in, 0, bytelen); | ||
152 | |||
153 | if (max3110_write_then_read(max, (u8 *)out, (u8 *)in, bytelen, 1)) | ||
154 | return 0; | ||
155 | |||
156 | /* If caller don't provide a buffer, then handle received char */ | ||
157 | pbuf = buf ? buf : valid_str; | ||
158 | |||
159 | for (i = 0, j = 0; i < len; i++) { | ||
160 | if (in[i] & MAX3110_READ_DATA_AVAILABLE) | ||
161 | pbuf[j++] = (u8)(in[i] & 0xff); | ||
162 | } | ||
163 | |||
164 | if (j && (pbuf == valid_str)) | ||
165 | receive_chars(max, valid_str, j); | ||
166 | |||
167 | return j; | ||
168 | } | ||
169 | |||
170 | static void serial_m3110_con_putchar(struct uart_port *port, int ch) | ||
171 | { | ||
172 | struct uart_max3110 *max = | ||
173 | container_of(port, struct uart_max3110, port); | ||
174 | struct circ_buf *xmit = &max->con_xmit; | ||
175 | |||
176 | if (uart_circ_chars_free(xmit)) { | ||
177 | xmit->buf[xmit->head] = (char)ch; | ||
178 | xmit->head = (xmit->head + 1) & (PAGE_SIZE - 1); | ||
179 | } | ||
180 | |||
181 | |||
182 | if (!test_and_set_bit(CON_TX_NEEDED, &max->uart_flags)) | ||
183 | wake_up_process(max->main_thread); | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Print a string to the serial port trying not to disturb | ||
188 | * any possible real use of the port... | ||
189 | * | ||
190 | * The console_lock must be held when we get here. | ||
191 | */ | ||
192 | static void serial_m3110_con_write(struct console *co, | ||
193 | const char *s, unsigned int count) | ||
194 | { | ||
195 | if (!pmax) | ||
196 | return; | ||
197 | |||
198 | uart_console_write(&pmax->port, s, count, serial_m3110_con_putchar); | ||
199 | } | ||
200 | |||
201 | static int __init | ||
202 | serial_m3110_con_setup(struct console *co, char *options) | ||
203 | { | ||
204 | struct uart_max3110 *max = pmax; | ||
205 | int baud = 115200; | ||
206 | int bits = 8; | ||
207 | int parity = 'n'; | ||
208 | int flow = 'n'; | ||
209 | |||
210 | pr_info(PR_FMT "setting up console\n"); | ||
211 | |||
212 | if (!max) { | ||
213 | pr_err(PR_FMT "pmax is NULL, return"); | ||
214 | return -ENODEV; | ||
215 | } | ||
216 | |||
217 | if (options) | ||
218 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
219 | |||
220 | return uart_set_options(&max->port, co, baud, parity, bits, flow); | ||
221 | } | ||
222 | |||
223 | static struct tty_driver *serial_m3110_con_device(struct console *co, | ||
224 | int *index) | ||
225 | { | ||
226 | struct uart_driver *p = co->data; | ||
227 | *index = co->index; | ||
228 | return p->tty_driver; | ||
229 | } | ||
230 | |||
231 | static struct uart_driver serial_m3110_reg; | ||
232 | static struct console serial_m3110_console = { | ||
233 | .name = "ttyS", | ||
234 | .write = serial_m3110_con_write, | ||
235 | .device = serial_m3110_con_device, | ||
236 | .setup = serial_m3110_con_setup, | ||
237 | .flags = CON_PRINTBUFFER, | ||
238 | .index = -1, | ||
239 | .data = &serial_m3110_reg, | ||
240 | }; | ||
241 | |||
242 | #define MRST_CONSOLE (&serial_m3110_console) | ||
243 | |||
244 | static unsigned int serial_m3110_tx_empty(struct uart_port *port) | ||
245 | { | ||
246 | return 1; | ||
247 | } | ||
248 | |||
249 | static void serial_m3110_stop_tx(struct uart_port *port) | ||
250 | { | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | /* stop_rx will be called in spin_lock env */ | ||
255 | static void serial_m3110_stop_rx(struct uart_port *port) | ||
256 | { | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | #define WORDS_PER_XFER 128 | ||
261 | static inline void send_circ_buf(struct uart_max3110 *max, | ||
262 | struct circ_buf *xmit) | ||
263 | { | ||
264 | int len, left = 0; | ||
265 | u16 obuf[WORDS_PER_XFER], ibuf[WORDS_PER_XFER]; | ||
266 | u8 valid_str[WORDS_PER_XFER]; | ||
267 | int i, j; | ||
268 | |||
269 | while (!uart_circ_empty(xmit)) { | ||
270 | left = uart_circ_chars_pending(xmit); | ||
271 | while (left) { | ||
272 | len = (left >= WORDS_PER_XFER) ? WORDS_PER_XFER : left; | ||
273 | |||
274 | memset(obuf, 0, len * 2); | ||
275 | memset(ibuf, 0, len * 2); | ||
276 | for (i = 0; i < len; i++) { | ||
277 | obuf[i] = (u8)xmit->buf[xmit->tail] | WD_TAG; | ||
278 | xmit->tail = (xmit->tail + 1) & | ||
279 | (UART_XMIT_SIZE - 1); | ||
280 | } | ||
281 | max3110_write_then_read(max, (u8 *)obuf, | ||
282 | (u8 *)ibuf, len * 2, 0); | ||
283 | |||
284 | for (i = 0, j = 0; i < len; i++) { | ||
285 | if (ibuf[i] & MAX3110_READ_DATA_AVAILABLE) | ||
286 | valid_str[j++] = (u8)(ibuf[i] & 0xff); | ||
287 | } | ||
288 | |||
289 | if (j) | ||
290 | receive_chars(max, valid_str, j); | ||
291 | |||
292 | max->port.icount.tx += len; | ||
293 | left -= len; | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | |||
298 | static void transmit_char(struct uart_max3110 *max) | ||
299 | { | ||
300 | struct uart_port *port = &max->port; | ||
301 | struct circ_buf *xmit = &port->state->xmit; | ||
302 | |||
303 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) | ||
304 | return; | ||
305 | |||
306 | send_circ_buf(max, xmit); | ||
307 | |||
308 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
309 | uart_write_wakeup(port); | ||
310 | |||
311 | if (uart_circ_empty(xmit)) | ||
312 | serial_m3110_stop_tx(port); | ||
313 | } | ||
314 | |||
315 | /* This will be called by uart_write() and tty_write, can't | ||
316 | * go to sleep */ | ||
317 | static void serial_m3110_start_tx(struct uart_port *port) | ||
318 | { | ||
319 | struct uart_max3110 *max = | ||
320 | container_of(port, struct uart_max3110, port); | ||
321 | |||
322 | if (!test_and_set_bit(UART_TX_NEEDED, &max->uart_flags)) | ||
323 | wake_up_process(max->main_thread); | ||
324 | } | ||
325 | |||
326 | static void receive_chars(struct uart_max3110 *max, unsigned char *str, int len) | ||
327 | { | ||
328 | struct uart_port *port = &max->port; | ||
329 | struct tty_struct *tty; | ||
330 | int usable; | ||
331 | |||
332 | /* If uart is not opened, just return */ | ||
333 | if (!port->state) | ||
334 | return; | ||
335 | |||
336 | tty = port->state->port.tty; | ||
337 | if (!tty) | ||
338 | return; /* receive some char before the tty is opened */ | ||
339 | |||
340 | while (len) { | ||
341 | usable = tty_buffer_request_room(tty, len); | ||
342 | if (usable) { | ||
343 | tty_insert_flip_string(tty, str, usable); | ||
344 | str += usable; | ||
345 | port->icount.rx += usable; | ||
346 | tty_flip_buffer_push(tty); | ||
347 | } | ||
348 | len -= usable; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | static inline void receive_char(struct uart_max3110 *max, u8 ch) | ||
353 | { | ||
354 | receive_chars(max, &ch, 1); | ||
355 | } | ||
356 | |||
357 | static void max3110_console_receive(struct uart_max3110 *max) | ||
358 | { | ||
359 | int loop = 1, num, total = 0; | ||
360 | u8 recv_buf[512], *pbuf; | ||
361 | |||
362 | pbuf = recv_buf; | ||
363 | do { | ||
364 | num = max3110_read_multi(max, 8, pbuf); | ||
365 | |||
366 | if (num) { | ||
367 | loop = 10; | ||
368 | pbuf += num; | ||
369 | total += num; | ||
370 | |||
371 | if (total >= 500) { | ||
372 | receive_chars(max, recv_buf, total); | ||
373 | pbuf = recv_buf; | ||
374 | total = 0; | ||
375 | } | ||
376 | } | ||
377 | } while (--loop); | ||
378 | |||
379 | if (total) | ||
380 | receive_chars(max, recv_buf, total); | ||
381 | } | ||
382 | |||
383 | static int max3110_main_thread(void *_max) | ||
384 | { | ||
385 | struct uart_max3110 *max = _max; | ||
386 | wait_queue_head_t *wq = &max->wq; | ||
387 | int ret = 0; | ||
388 | struct circ_buf *xmit = &max->con_xmit; | ||
389 | |||
390 | init_waitqueue_head(wq); | ||
391 | pr_info(PR_FMT "start main thread\n"); | ||
392 | |||
393 | do { | ||
394 | wait_event_interruptible(*wq, max->uart_flags || kthread_should_stop()); | ||
395 | |||
396 | mutex_lock(&max->thread_mutex); | ||
397 | |||
398 | if (test_and_clear_bit(BIT_IRQ_PENDING, &max->uart_flags)) | ||
399 | max3110_console_receive(max); | ||
400 | |||
401 | /* first handle console output */ | ||
402 | if (test_and_clear_bit(CON_TX_NEEDED, &max->uart_flags)) | ||
403 | send_circ_buf(max, xmit); | ||
404 | |||
405 | /* handle uart output */ | ||
406 | if (test_and_clear_bit(UART_TX_NEEDED, &max->uart_flags)) | ||
407 | transmit_char(max); | ||
408 | |||
409 | mutex_unlock(&max->thread_mutex); | ||
410 | |||
411 | } while (!kthread_should_stop()); | ||
412 | |||
413 | return ret; | ||
414 | } | ||
415 | |||
416 | #ifdef CONFIG_MRST_MAX3110_IRQ | ||
417 | static irqreturn_t serial_m3110_irq(int irq, void *dev_id) | ||
418 | { | ||
419 | struct uart_max3110 *max = dev_id; | ||
420 | |||
421 | /* max3110's irq is a falling edge, not level triggered, | ||
422 | * so no need to disable the irq */ | ||
423 | if (!test_and_set_bit(BIT_IRQ_PENDING, &max->uart_flags)) | ||
424 | wake_up_process(max->main_thread); | ||
425 | |||
426 | return IRQ_HANDLED; | ||
427 | } | ||
428 | #else | ||
429 | /* if don't use RX IRQ, then need a thread to polling read */ | ||
430 | static int max3110_read_thread(void *_max) | ||
431 | { | ||
432 | struct uart_max3110 *max = _max; | ||
433 | |||
434 | pr_info(PR_FMT "start read thread\n"); | ||
435 | do { | ||
436 | mutex_lock(&max->thread_mutex); | ||
437 | max3110_console_receive(max); | ||
438 | mutex_unlock(&max->thread_mutex); | ||
439 | |||
440 | set_current_state(TASK_INTERRUPTIBLE); | ||
441 | schedule_timeout(HZ / 20); | ||
442 | } while (!kthread_should_stop()); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | #endif | ||
447 | |||
448 | static int serial_m3110_startup(struct uart_port *port) | ||
449 | { | ||
450 | struct uart_max3110 *max = | ||
451 | container_of(port, struct uart_max3110, port); | ||
452 | u16 config = 0; | ||
453 | int ret = 0; | ||
454 | |||
455 | if (port->line != 0) | ||
456 | pr_err(PR_FMT "uart port startup failed\n"); | ||
457 | |||
458 | /* firstly disable all IRQ and config it to 115200, 8n1 */ | ||
459 | config = WC_TAG | WC_FIFO_ENABLE | ||
460 | | WC_1_STOPBITS | ||
461 | | WC_8BIT_WORD | ||
462 | | WC_BAUD_DR2; | ||
463 | ret = max3110_out(max, config); | ||
464 | |||
465 | /* as we use thread to handle tx/rx, need set low latency */ | ||
466 | port->state->port.tty->low_latency = 1; | ||
467 | |||
468 | #ifdef CONFIG_MRST_MAX3110_IRQ | ||
469 | ret = request_irq(max->irq, serial_m3110_irq, | ||
470 | IRQ_TYPE_EDGE_FALLING, "max3110", max); | ||
471 | if (ret) | ||
472 | return ret; | ||
473 | |||
474 | /* enable RX IRQ only */ | ||
475 | config |= WC_RXA_IRQ_ENABLE; | ||
476 | max3110_out(max, config); | ||
477 | #else | ||
478 | /* if IRQ is disabled, start a read thread for input data */ | ||
479 | max->read_thread = | ||
480 | kthread_run(max3110_read_thread, max, "max3110_read"); | ||
481 | #endif | ||
482 | |||
483 | max->cur_conf = config; | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static void serial_m3110_shutdown(struct uart_port *port) | ||
488 | { | ||
489 | struct uart_max3110 *max = | ||
490 | container_of(port, struct uart_max3110, port); | ||
491 | u16 config; | ||
492 | |||
493 | if (max->read_thread) { | ||
494 | kthread_stop(max->read_thread); | ||
495 | max->read_thread = NULL; | ||
496 | } | ||
497 | |||
498 | #ifdef CONFIG_MRST_MAX3110_IRQ | ||
499 | free_irq(max->irq, max); | ||
500 | #endif | ||
501 | |||
502 | /* Disable interrupts from this port */ | ||
503 | config = WC_TAG | WC_SW_SHDI; | ||
504 | max3110_out(max, config); | ||
505 | } | ||
506 | |||
507 | static void serial_m3110_release_port(struct uart_port *port) | ||
508 | { | ||
509 | } | ||
510 | |||
511 | static int serial_m3110_request_port(struct uart_port *port) | ||
512 | { | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static void serial_m3110_config_port(struct uart_port *port, int flags) | ||
517 | { | ||
518 | /* give it fake type */ | ||
519 | port->type = PORT_PXA; | ||
520 | } | ||
521 | |||
522 | static int | ||
523 | serial_m3110_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
524 | { | ||
525 | /* we don't want the core code to modify any port params */ | ||
526 | return -EINVAL; | ||
527 | } | ||
528 | |||
529 | |||
530 | static const char *serial_m3110_type(struct uart_port *port) | ||
531 | { | ||
532 | struct uart_max3110 *max = | ||
533 | container_of(port, struct uart_max3110, port); | ||
534 | return max->name; | ||
535 | } | ||
536 | |||
537 | static void | ||
538 | serial_m3110_set_termios(struct uart_port *port, struct ktermios *termios, | ||
539 | struct ktermios *old) | ||
540 | { | ||
541 | struct uart_max3110 *max = | ||
542 | container_of(port, struct uart_max3110, port); | ||
543 | unsigned char cval; | ||
544 | unsigned int baud, parity = 0; | ||
545 | int clk_div = -1; | ||
546 | u16 new_conf = max->cur_conf; | ||
547 | |||
548 | switch (termios->c_cflag & CSIZE) { | ||
549 | case CS7: | ||
550 | cval = UART_LCR_WLEN7; | ||
551 | new_conf |= WC_7BIT_WORD; | ||
552 | break; | ||
553 | default: | ||
554 | case CS8: | ||
555 | cval = UART_LCR_WLEN8; | ||
556 | new_conf |= WC_8BIT_WORD; | ||
557 | break; | ||
558 | } | ||
559 | |||
560 | baud = uart_get_baud_rate(port, termios, old, 0, 230400); | ||
561 | |||
562 | /* first calc the div for 1.8MHZ clock case */ | ||
563 | switch (baud) { | ||
564 | case 300: | ||
565 | clk_div = WC_BAUD_DR384; | ||
566 | break; | ||
567 | case 600: | ||
568 | clk_div = WC_BAUD_DR192; | ||
569 | break; | ||
570 | case 1200: | ||
571 | clk_div = WC_BAUD_DR96; | ||
572 | break; | ||
573 | case 2400: | ||
574 | clk_div = WC_BAUD_DR48; | ||
575 | break; | ||
576 | case 4800: | ||
577 | clk_div = WC_BAUD_DR24; | ||
578 | break; | ||
579 | case 9600: | ||
580 | clk_div = WC_BAUD_DR12; | ||
581 | break; | ||
582 | case 19200: | ||
583 | clk_div = WC_BAUD_DR6; | ||
584 | break; | ||
585 | case 38400: | ||
586 | clk_div = WC_BAUD_DR3; | ||
587 | break; | ||
588 | case 57600: | ||
589 | clk_div = WC_BAUD_DR2; | ||
590 | break; | ||
591 | case 115200: | ||
592 | clk_div = WC_BAUD_DR1; | ||
593 | break; | ||
594 | case 230400: | ||
595 | if (max->clock & MAX3110_HIGH_CLK) | ||
596 | break; | ||
597 | default: | ||
598 | /* pick the previous baud rate */ | ||
599 | baud = max->baud; | ||
600 | clk_div = max->cur_conf & WC_BAUD_DIV_MASK; | ||
601 | tty_termios_encode_baud_rate(termios, baud, baud); | ||
602 | } | ||
603 | |||
604 | if (max->clock & MAX3110_HIGH_CLK) { | ||
605 | clk_div += 1; | ||
606 | /* high clk version max3110 doesn't support B300 */ | ||
607 | if (baud == 300) | ||
608 | baud = 600; | ||
609 | if (baud == 230400) | ||
610 | clk_div = WC_BAUD_DR1; | ||
611 | tty_termios_encode_baud_rate(termios, baud, baud); | ||
612 | } | ||
613 | |||
614 | new_conf = (new_conf & ~WC_BAUD_DIV_MASK) | clk_div; | ||
615 | if (termios->c_cflag & CSTOPB) | ||
616 | new_conf |= WC_2_STOPBITS; | ||
617 | else | ||
618 | new_conf &= ~WC_2_STOPBITS; | ||
619 | |||
620 | if (termios->c_cflag & PARENB) { | ||
621 | new_conf |= WC_PARITY_ENABLE; | ||
622 | parity |= UART_LCR_PARITY; | ||
623 | } else | ||
624 | new_conf &= ~WC_PARITY_ENABLE; | ||
625 | |||
626 | if (!(termios->c_cflag & PARODD)) | ||
627 | parity |= UART_LCR_EPAR; | ||
628 | max->parity = parity; | ||
629 | |||
630 | uart_update_timeout(port, termios->c_cflag, baud); | ||
631 | |||
632 | new_conf |= WC_TAG; | ||
633 | if (new_conf != max->cur_conf) { | ||
634 | max3110_out(max, new_conf); | ||
635 | max->cur_conf = new_conf; | ||
636 | max->baud = baud; | ||
637 | } | ||
638 | } | ||
639 | |||
640 | /* don't handle hw handshaking */ | ||
641 | static unsigned int serial_m3110_get_mctrl(struct uart_port *port) | ||
642 | { | ||
643 | return TIOCM_DSR | TIOCM_CAR | TIOCM_DSR; | ||
644 | } | ||
645 | |||
646 | static void serial_m3110_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
647 | { | ||
648 | } | ||
649 | |||
650 | static void serial_m3110_break_ctl(struct uart_port *port, int break_state) | ||
651 | { | ||
652 | } | ||
653 | |||
654 | static void serial_m3110_pm(struct uart_port *port, unsigned int state, | ||
655 | unsigned int oldstate) | ||
656 | { | ||
657 | } | ||
658 | |||
659 | static void serial_m3110_enable_ms(struct uart_port *port) | ||
660 | { | ||
661 | } | ||
662 | |||
663 | struct uart_ops serial_m3110_ops = { | ||
664 | .tx_empty = serial_m3110_tx_empty, | ||
665 | .set_mctrl = serial_m3110_set_mctrl, | ||
666 | .get_mctrl = serial_m3110_get_mctrl, | ||
667 | .stop_tx = serial_m3110_stop_tx, | ||
668 | .start_tx = serial_m3110_start_tx, | ||
669 | .stop_rx = serial_m3110_stop_rx, | ||
670 | .enable_ms = serial_m3110_enable_ms, | ||
671 | .break_ctl = serial_m3110_break_ctl, | ||
672 | .startup = serial_m3110_startup, | ||
673 | .shutdown = serial_m3110_shutdown, | ||
674 | .set_termios = serial_m3110_set_termios, /* must have */ | ||
675 | .pm = serial_m3110_pm, | ||
676 | .type = serial_m3110_type, | ||
677 | .release_port = serial_m3110_release_port, | ||
678 | .request_port = serial_m3110_request_port, | ||
679 | .config_port = serial_m3110_config_port, | ||
680 | .verify_port = serial_m3110_verify_port, | ||
681 | }; | ||
682 | |||
683 | static struct uart_driver serial_m3110_reg = { | ||
684 | .owner = THIS_MODULE, | ||
685 | .driver_name = "MRST serial", | ||
686 | .dev_name = "ttyS", | ||
687 | .major = TTY_MAJOR, | ||
688 | .minor = 64, | ||
689 | .nr = 1, | ||
690 | .cons = MRST_CONSOLE, | ||
691 | }; | ||
692 | |||
693 | static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state) | ||
694 | { | ||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | static int serial_m3110_resume(struct spi_device *spi) | ||
699 | { | ||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | static struct dw_spi_chip spi0_uart = { | ||
704 | .poll_mode = 1, | ||
705 | .enable_dma = 0, | ||
706 | .type = SPI_FRF_SPI, | ||
707 | }; | ||
708 | |||
709 | static int serial_m3110_probe(struct spi_device *spi) | ||
710 | { | ||
711 | struct uart_max3110 *max; | ||
712 | int ret; | ||
713 | unsigned char *buffer; | ||
714 | u16 res; | ||
715 | max = kzalloc(sizeof(*max), GFP_KERNEL); | ||
716 | if (!max) | ||
717 | return -ENOMEM; | ||
718 | |||
719 | /* set spi info */ | ||
720 | spi->mode = SPI_MODE_0; | ||
721 | spi->bits_per_word = 16; | ||
722 | max->clock = MAX3110_HIGH_CLK; | ||
723 | spi->controller_data = &spi0_uart; | ||
724 | |||
725 | spi_setup(spi); | ||
726 | |||
727 | max->port.type = PORT_PXA; /* need apply for a max3110 type */ | ||
728 | max->port.fifosize = 2; /* only have 16b buffer */ | ||
729 | max->port.ops = &serial_m3110_ops; | ||
730 | max->port.line = 0; | ||
731 | max->port.dev = &spi->dev; | ||
732 | max->port.uartclk = 115200; | ||
733 | |||
734 | max->spi = spi; | ||
735 | max->name = spi->modalias; /* use spi name as the name */ | ||
736 | max->irq = (u16)spi->irq; | ||
737 | |||
738 | mutex_init(&max->thread_mutex); | ||
739 | |||
740 | max->word_7bits = 0; | ||
741 | max->parity = 0; | ||
742 | max->baud = 0; | ||
743 | |||
744 | max->cur_conf = 0; | ||
745 | max->uart_flags = 0; | ||
746 | |||
747 | /* Check if reading configuration register returns something sane */ | ||
748 | |||
749 | res = RC_TAG; | ||
750 | ret = max3110_write_then_read(max, (u8 *)&res, (u8 *)&res, 2, 0); | ||
751 | if (ret < 0 || res == 0 || res == 0xffff) { | ||
752 | printk(KERN_ERR "MAX3111 deemed not present (conf reg %04x)", | ||
753 | res); | ||
754 | ret = -ENODEV; | ||
755 | goto err_get_page; | ||
756 | } | ||
757 | buffer = (unsigned char *)__get_free_page(GFP_KERNEL); | ||
758 | if (!buffer) { | ||
759 | ret = -ENOMEM; | ||
760 | goto err_get_page; | ||
761 | } | ||
762 | max->con_xmit.buf = (unsigned char *)buffer; | ||
763 | max->con_xmit.head = max->con_xmit.tail = 0; | ||
764 | |||
765 | max->main_thread = kthread_run(max3110_main_thread, | ||
766 | max, "max3110_main"); | ||
767 | if (IS_ERR(max->main_thread)) { | ||
768 | ret = PTR_ERR(max->main_thread); | ||
769 | goto err_kthread; | ||
770 | } | ||
771 | |||
772 | pmax = max; | ||
773 | /* give membase a psudo value to pass serial_core's check */ | ||
774 | max->port.membase = (void *)0xff110000; | ||
775 | uart_add_one_port(&serial_m3110_reg, &max->port); | ||
776 | |||
777 | return 0; | ||
778 | |||
779 | err_kthread: | ||
780 | free_page((unsigned long)buffer); | ||
781 | err_get_page: | ||
782 | pmax = NULL; | ||
783 | kfree(max); | ||
784 | return ret; | ||
785 | } | ||
786 | |||
787 | static int max3110_remove(struct spi_device *dev) | ||
788 | { | ||
789 | struct uart_max3110 *max = pmax; | ||
790 | |||
791 | if (!pmax) | ||
792 | return 0; | ||
793 | |||
794 | pmax = NULL; | ||
795 | uart_remove_one_port(&serial_m3110_reg, &max->port); | ||
796 | |||
797 | free_page((unsigned long)max->con_xmit.buf); | ||
798 | |||
799 | if (max->main_thread) | ||
800 | kthread_stop(max->main_thread); | ||
801 | |||
802 | kfree(max); | ||
803 | return 0; | ||
804 | } | ||
805 | |||
806 | static struct spi_driver uart_max3110_driver = { | ||
807 | .driver = { | ||
808 | .name = "spi_max3111", | ||
809 | .bus = &spi_bus_type, | ||
810 | .owner = THIS_MODULE, | ||
811 | }, | ||
812 | .probe = serial_m3110_probe, | ||
813 | .remove = __devexit_p(max3110_remove), | ||
814 | .suspend = serial_m3110_suspend, | ||
815 | .resume = serial_m3110_resume, | ||
816 | }; | ||
817 | |||
818 | |||
819 | int __init serial_m3110_init(void) | ||
820 | { | ||
821 | int ret = 0; | ||
822 | |||
823 | ret = uart_register_driver(&serial_m3110_reg); | ||
824 | if (ret) | ||
825 | return ret; | ||
826 | |||
827 | ret = spi_register_driver(&uart_max3110_driver); | ||
828 | if (ret) | ||
829 | uart_unregister_driver(&serial_m3110_reg); | ||
830 | |||
831 | return ret; | ||
832 | } | ||
833 | |||
834 | void __exit serial_m3110_exit(void) | ||
835 | { | ||
836 | spi_unregister_driver(&uart_max3110_driver); | ||
837 | uart_unregister_driver(&serial_m3110_reg); | ||
838 | } | ||
839 | |||
840 | module_init(serial_m3110_init); | ||
841 | module_exit(serial_m3110_exit); | ||
842 | |||
843 | MODULE_LICENSE("GPL"); | ||
844 | MODULE_ALIAS("max3110-uart"); | ||
diff --git a/drivers/serial/mrst_max3110.h b/drivers/serial/mrst_max3110.h new file mode 100644 index 000000000000..363478acb2c3 --- /dev/null +++ b/drivers/serial/mrst_max3110.h | |||
@@ -0,0 +1,59 @@ | |||
1 | #ifndef _MRST_MAX3110_H | ||
2 | #define _MRST_MAX3110_H | ||
3 | |||
4 | #define MAX3110_HIGH_CLK 0x1 /* 3.6864 MHZ */ | ||
5 | #define MAX3110_LOW_CLK 0x0 /* 1.8432 MHZ */ | ||
6 | |||
7 | /* status bits for all 4 MAX3110 operate modes */ | ||
8 | #define MAX3110_READ_DATA_AVAILABLE (1 << 15) | ||
9 | #define MAX3110_WRITE_BUF_EMPTY (1 << 14) | ||
10 | |||
11 | #define WC_TAG (3 << 14) | ||
12 | #define RC_TAG (1 << 14) | ||
13 | #define WD_TAG (2 << 14) | ||
14 | #define RD_TAG (0 << 14) | ||
15 | |||
16 | /* bits def for write configuration */ | ||
17 | #define WC_FIFO_ENABLE_MASK (1 << 13) | ||
18 | #define WC_FIFO_ENABLE (0 << 13) | ||
19 | |||
20 | #define WC_SW_SHDI (1 << 12) | ||
21 | |||
22 | #define WC_IRQ_MASK (0xF << 8) | ||
23 | #define WC_TXE_IRQ_ENABLE (1 << 11) /* TX empty irq */ | ||
24 | #define WC_RXA_IRQ_ENABLE (1 << 10) /* RX availabe irq */ | ||
25 | #define WC_PAR_HIGH_IRQ_ENABLE (1 << 9) | ||
26 | #define WC_REC_ACT_IRQ_ENABLE (1 << 8) | ||
27 | |||
28 | #define WC_IRDA_ENABLE (1 << 7) | ||
29 | |||
30 | #define WC_STOPBITS_MASK (1 << 6) | ||
31 | #define WC_2_STOPBITS (1 << 6) | ||
32 | #define WC_1_STOPBITS (0 << 6) | ||
33 | |||
34 | #define WC_PARITY_ENABLE_MASK (1 << 5) | ||
35 | #define WC_PARITY_ENABLE (1 << 5) | ||
36 | |||
37 | #define WC_WORDLEN_MASK (1 << 4) | ||
38 | #define WC_7BIT_WORD (1 << 4) | ||
39 | #define WC_8BIT_WORD (0 << 4) | ||
40 | |||
41 | #define WC_BAUD_DIV_MASK (0xF) | ||
42 | #define WC_BAUD_DR1 (0x0) | ||
43 | #define WC_BAUD_DR2 (0x1) | ||
44 | #define WC_BAUD_DR4 (0x2) | ||
45 | #define WC_BAUD_DR8 (0x3) | ||
46 | #define WC_BAUD_DR16 (0x4) | ||
47 | #define WC_BAUD_DR32 (0x5) | ||
48 | #define WC_BAUD_DR64 (0x6) | ||
49 | #define WC_BAUD_DR128 (0x7) | ||
50 | #define WC_BAUD_DR3 (0x8) | ||
51 | #define WC_BAUD_DR6 (0x9) | ||
52 | #define WC_BAUD_DR12 (0xA) | ||
53 | #define WC_BAUD_DR24 (0xB) | ||
54 | #define WC_BAUD_DR48 (0xC) | ||
55 | #define WC_BAUD_DR96 (0xD) | ||
56 | #define WC_BAUD_DR192 (0xE) | ||
57 | #define WC_BAUD_DR384 (0xF) | ||
58 | |||
59 | #endif | ||
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 7f2830709512..cd8511298bcb 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -58,9 +58,9 @@ static struct lock_class_key port_lock_key; | |||
58 | #define uart_console(port) (0) | 58 | #define uart_console(port) (0) |
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | static void uart_change_speed(struct uart_state *state, | 61 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, |
62 | struct ktermios *old_termios); | 62 | struct ktermios *old_termios); |
63 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout); | 63 | static void __uart_wait_until_sent(struct uart_port *port, int timeout); |
64 | static void uart_change_pm(struct uart_state *state, int pm_state); | 64 | static void uart_change_pm(struct uart_state *state, int pm_state); |
65 | 65 | ||
66 | /* | 66 | /* |
@@ -137,7 +137,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) | |||
137 | * Startup the port. This will be called once per open. All calls | 137 | * Startup the port. This will be called once per open. All calls |
138 | * will be serialised by the per-port mutex. | 138 | * will be serialised by the per-port mutex. |
139 | */ | 139 | */ |
140 | static int uart_startup(struct uart_state *state, int init_hw) | 140 | static int uart_startup(struct tty_struct *tty, struct uart_state *state, int init_hw) |
141 | { | 141 | { |
142 | struct uart_port *uport = state->uart_port; | 142 | struct uart_port *uport = state->uart_port; |
143 | struct tty_port *port = &state->port; | 143 | struct tty_port *port = &state->port; |
@@ -152,7 +152,7 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
152 | * once we have successfully opened the port. Also set | 152 | * once we have successfully opened the port. Also set |
153 | * up the tty->alt_speed kludge | 153 | * up the tty->alt_speed kludge |
154 | */ | 154 | */ |
155 | set_bit(TTY_IO_ERROR, &port->tty->flags); | 155 | set_bit(TTY_IO_ERROR, &tty->flags); |
156 | 156 | ||
157 | if (uport->type == PORT_UNKNOWN) | 157 | if (uport->type == PORT_UNKNOWN) |
158 | return 0; | 158 | return 0; |
@@ -177,26 +177,26 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
177 | /* | 177 | /* |
178 | * Initialise the hardware port settings. | 178 | * Initialise the hardware port settings. |
179 | */ | 179 | */ |
180 | uart_change_speed(state, NULL); | 180 | uart_change_speed(tty, state, NULL); |
181 | 181 | ||
182 | /* | 182 | /* |
183 | * Setup the RTS and DTR signals once the | 183 | * Setup the RTS and DTR signals once the |
184 | * port is open and ready to respond. | 184 | * port is open and ready to respond. |
185 | */ | 185 | */ |
186 | if (port->tty->termios->c_cflag & CBAUD) | 186 | if (tty->termios->c_cflag & CBAUD) |
187 | uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); | 187 | uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); |
188 | } | 188 | } |
189 | 189 | ||
190 | if (port->flags & ASYNC_CTS_FLOW) { | 190 | if (port->flags & ASYNC_CTS_FLOW) { |
191 | spin_lock_irq(&uport->lock); | 191 | spin_lock_irq(&uport->lock); |
192 | if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) | 192 | if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) |
193 | port->tty->hw_stopped = 1; | 193 | tty->hw_stopped = 1; |
194 | spin_unlock_irq(&uport->lock); | 194 | spin_unlock_irq(&uport->lock); |
195 | } | 195 | } |
196 | 196 | ||
197 | set_bit(ASYNCB_INITIALIZED, &port->flags); | 197 | set_bit(ASYNCB_INITIALIZED, &port->flags); |
198 | 198 | ||
199 | clear_bit(TTY_IO_ERROR, &port->tty->flags); | 199 | clear_bit(TTY_IO_ERROR, &tty->flags); |
200 | } | 200 | } |
201 | 201 | ||
202 | if (retval && capable(CAP_SYS_ADMIN)) | 202 | if (retval && capable(CAP_SYS_ADMIN)) |
@@ -210,11 +210,10 @@ static int uart_startup(struct uart_state *state, int init_hw) | |||
210 | * DTR is dropped if the hangup on close termio flag is on. Calls to | 210 | * DTR is dropped if the hangup on close termio flag is on. Calls to |
211 | * uart_shutdown are serialised by the per-port semaphore. | 211 | * uart_shutdown are serialised by the per-port semaphore. |
212 | */ | 212 | */ |
213 | static void uart_shutdown(struct uart_state *state) | 213 | static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) |
214 | { | 214 | { |
215 | struct uart_port *uport = state->uart_port; | 215 | struct uart_port *uport = state->uart_port; |
216 | struct tty_port *port = &state->port; | 216 | struct tty_port *port = &state->port; |
217 | struct tty_struct *tty = port->tty; | ||
218 | 217 | ||
219 | /* | 218 | /* |
220 | * Set the TTY IO error marker | 219 | * Set the TTY IO error marker |
@@ -430,11 +429,10 @@ uart_get_divisor(struct uart_port *port, unsigned int baud) | |||
430 | EXPORT_SYMBOL(uart_get_divisor); | 429 | EXPORT_SYMBOL(uart_get_divisor); |
431 | 430 | ||
432 | /* FIXME: Consistent locking policy */ | 431 | /* FIXME: Consistent locking policy */ |
433 | static void | 432 | static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, |
434 | uart_change_speed(struct uart_state *state, struct ktermios *old_termios) | 433 | struct ktermios *old_termios) |
435 | { | 434 | { |
436 | struct tty_port *port = &state->port; | 435 | struct tty_port *port = &state->port; |
437 | struct tty_struct *tty = port->tty; | ||
438 | struct uart_port *uport = state->uart_port; | 436 | struct uart_port *uport = state->uart_port; |
439 | struct ktermios *termios; | 437 | struct ktermios *termios; |
440 | 438 | ||
@@ -463,8 +461,8 @@ uart_change_speed(struct uart_state *state, struct ktermios *old_termios) | |||
463 | uport->ops->set_termios(uport, termios, old_termios); | 461 | uport->ops->set_termios(uport, termios, old_termios); |
464 | } | 462 | } |
465 | 463 | ||
466 | static inline int | 464 | static inline int __uart_put_char(struct uart_port *port, |
467 | __uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c) | 465 | struct circ_buf *circ, unsigned char c) |
468 | { | 466 | { |
469 | unsigned long flags; | 467 | unsigned long flags; |
470 | int ret = 0; | 468 | int ret = 0; |
@@ -494,8 +492,8 @@ static void uart_flush_chars(struct tty_struct *tty) | |||
494 | uart_start(tty); | 492 | uart_start(tty); |
495 | } | 493 | } |
496 | 494 | ||
497 | static int | 495 | static int uart_write(struct tty_struct *tty, |
498 | uart_write(struct tty_struct *tty, const unsigned char *buf, int count) | 496 | const unsigned char *buf, int count) |
499 | { | 497 | { |
500 | struct uart_state *state = tty->driver_data; | 498 | struct uart_state *state = tty->driver_data; |
501 | struct uart_port *port; | 499 | struct uart_port *port; |
@@ -675,7 +673,7 @@ static int uart_get_info(struct uart_state *state, | |||
675 | return 0; | 673 | return 0; |
676 | } | 674 | } |
677 | 675 | ||
678 | static int uart_set_info(struct uart_state *state, | 676 | static int uart_set_info(struct tty_struct *tty, struct uart_state *state, |
679 | struct serial_struct __user *newinfo) | 677 | struct serial_struct __user *newinfo) |
680 | { | 678 | { |
681 | struct serial_struct new_serial; | 679 | struct serial_struct new_serial; |
@@ -770,7 +768,7 @@ static int uart_set_info(struct uart_state *state, | |||
770 | * We need to shutdown the serial port at the old | 768 | * We need to shutdown the serial port at the old |
771 | * port/type/irq combination. | 769 | * port/type/irq combination. |
772 | */ | 770 | */ |
773 | uart_shutdown(state); | 771 | uart_shutdown(tty, state); |
774 | } | 772 | } |
775 | 773 | ||
776 | if (change_port) { | 774 | if (change_port) { |
@@ -869,25 +867,27 @@ static int uart_set_info(struct uart_state *state, | |||
869 | "is deprecated.\n", current->comm, | 867 | "is deprecated.\n", current->comm, |
870 | tty_name(port->tty, buf)); | 868 | tty_name(port->tty, buf)); |
871 | } | 869 | } |
872 | uart_change_speed(state, NULL); | 870 | uart_change_speed(tty, state, NULL); |
873 | } | 871 | } |
874 | } else | 872 | } else |
875 | retval = uart_startup(state, 1); | 873 | retval = uart_startup(tty, state, 1); |
876 | exit: | 874 | exit: |
877 | mutex_unlock(&port->mutex); | 875 | mutex_unlock(&port->mutex); |
878 | return retval; | 876 | return retval; |
879 | } | 877 | } |
880 | 878 | ||
881 | 879 | /** | |
882 | /* | 880 | * uart_get_lsr_info - get line status register info |
883 | * uart_get_lsr_info - get line status register info. | 881 | * @tty: tty associated with the UART |
884 | * Note: uart_ioctl protects us against hangups. | 882 | * @state: UART being queried |
883 | * @value: returned modem value | ||
884 | * | ||
885 | * Note: uart_ioctl protects us against hangups. | ||
885 | */ | 886 | */ |
886 | static int uart_get_lsr_info(struct uart_state *state, | 887 | static int uart_get_lsr_info(struct tty_struct *tty, |
887 | unsigned int __user *value) | 888 | struct uart_state *state, unsigned int __user *value) |
888 | { | 889 | { |
889 | struct uart_port *uport = state->uart_port; | 890 | struct uart_port *uport = state->uart_port; |
890 | struct tty_port *port = &state->port; | ||
891 | unsigned int result; | 891 | unsigned int result; |
892 | 892 | ||
893 | result = uport->ops->tx_empty(uport); | 893 | result = uport->ops->tx_empty(uport); |
@@ -900,7 +900,7 @@ static int uart_get_lsr_info(struct uart_state *state, | |||
900 | */ | 900 | */ |
901 | if (uport->x_char || | 901 | if (uport->x_char || |
902 | ((uart_circ_chars_pending(&state->xmit) > 0) && | 902 | ((uart_circ_chars_pending(&state->xmit) > 0) && |
903 | !port->tty->stopped && !port->tty->hw_stopped)) | 903 | !tty->stopped && !tty->hw_stopped)) |
904 | result &= ~TIOCSER_TEMT; | 904 | result &= ~TIOCSER_TEMT; |
905 | 905 | ||
906 | return put_user(result, value); | 906 | return put_user(result, value); |
@@ -961,7 +961,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state) | |||
961 | return 0; | 961 | return 0; |
962 | } | 962 | } |
963 | 963 | ||
964 | static int uart_do_autoconfig(struct uart_state *state) | 964 | static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state) |
965 | { | 965 | { |
966 | struct uart_port *uport = state->uart_port; | 966 | struct uart_port *uport = state->uart_port; |
967 | struct tty_port *port = &state->port; | 967 | struct tty_port *port = &state->port; |
@@ -980,7 +980,7 @@ static int uart_do_autoconfig(struct uart_state *state) | |||
980 | 980 | ||
981 | ret = -EBUSY; | 981 | ret = -EBUSY; |
982 | if (tty_port_users(port) == 1) { | 982 | if (tty_port_users(port) == 1) { |
983 | uart_shutdown(state); | 983 | uart_shutdown(tty, state); |
984 | 984 | ||
985 | /* | 985 | /* |
986 | * If we already have a port type configured, | 986 | * If we already have a port type configured, |
@@ -999,7 +999,7 @@ static int uart_do_autoconfig(struct uart_state *state) | |||
999 | */ | 999 | */ |
1000 | uport->ops->config_port(uport, flags); | 1000 | uport->ops->config_port(uport, flags); |
1001 | 1001 | ||
1002 | ret = uart_startup(state, 1); | 1002 | ret = uart_startup(tty, state, 1); |
1003 | } | 1003 | } |
1004 | mutex_unlock(&port->mutex); | 1004 | mutex_unlock(&port->mutex); |
1005 | return ret; | 1005 | return ret; |
@@ -1122,11 +1122,11 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, | |||
1122 | break; | 1122 | break; |
1123 | 1123 | ||
1124 | case TIOCSSERIAL: | 1124 | case TIOCSSERIAL: |
1125 | ret = uart_set_info(state, uarg); | 1125 | ret = uart_set_info(tty, state, uarg); |
1126 | break; | 1126 | break; |
1127 | 1127 | ||
1128 | case TIOCSERCONFIG: | 1128 | case TIOCSERCONFIG: |
1129 | ret = uart_do_autoconfig(state); | 1129 | ret = uart_do_autoconfig(tty, state); |
1130 | break; | 1130 | break; |
1131 | 1131 | ||
1132 | case TIOCSERGWILD: /* obsolete */ | 1132 | case TIOCSERGWILD: /* obsolete */ |
@@ -1172,7 +1172,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, | |||
1172 | */ | 1172 | */ |
1173 | switch (cmd) { | 1173 | switch (cmd) { |
1174 | case TIOCSERGETLSR: /* Get line status register */ | 1174 | case TIOCSERGETLSR: /* Get line status register */ |
1175 | ret = uart_get_lsr_info(state, uarg); | 1175 | ret = uart_get_lsr_info(tty, state, uarg); |
1176 | break; | 1176 | break; |
1177 | 1177 | ||
1178 | default: { | 1178 | default: { |
@@ -1194,7 +1194,7 @@ static void uart_set_ldisc(struct tty_struct *tty) | |||
1194 | struct uart_port *uport = state->uart_port; | 1194 | struct uart_port *uport = state->uart_port; |
1195 | 1195 | ||
1196 | if (uport->ops->set_ldisc) | 1196 | if (uport->ops->set_ldisc) |
1197 | uport->ops->set_ldisc(uport); | 1197 | uport->ops->set_ldisc(uport, tty->termios->c_line); |
1198 | } | 1198 | } |
1199 | 1199 | ||
1200 | static void uart_set_termios(struct tty_struct *tty, | 1200 | static void uart_set_termios(struct tty_struct *tty, |
@@ -1219,7 +1219,7 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1219 | return; | 1219 | return; |
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | uart_change_speed(state, old_termios); | 1222 | uart_change_speed(tty, state, old_termios); |
1223 | 1223 | ||
1224 | /* Handle transition to B0 status */ | 1224 | /* Handle transition to B0 status */ |
1225 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) | 1225 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) |
@@ -1272,8 +1272,9 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1272 | struct uart_state *state = tty->driver_data; | 1272 | struct uart_state *state = tty->driver_data; |
1273 | struct tty_port *port; | 1273 | struct tty_port *port; |
1274 | struct uart_port *uport; | 1274 | struct uart_port *uport; |
1275 | unsigned long flags; | ||
1275 | 1276 | ||
1276 | BUG_ON(!kernel_locked()); | 1277 | BUG_ON(!tty_locked()); |
1277 | 1278 | ||
1278 | if (!state) | 1279 | if (!state) |
1279 | return; | 1280 | return; |
@@ -1284,9 +1285,12 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1284 | pr_debug("uart_close(%d) called\n", uport->line); | 1285 | pr_debug("uart_close(%d) called\n", uport->line); |
1285 | 1286 | ||
1286 | mutex_lock(&port->mutex); | 1287 | mutex_lock(&port->mutex); |
1288 | spin_lock_irqsave(&port->lock, flags); | ||
1287 | 1289 | ||
1288 | if (tty_hung_up_p(filp)) | 1290 | if (tty_hung_up_p(filp)) { |
1291 | spin_unlock_irqrestore(&port->lock, flags); | ||
1289 | goto done; | 1292 | goto done; |
1293 | } | ||
1290 | 1294 | ||
1291 | if ((tty->count == 1) && (port->count != 1)) { | 1295 | if ((tty->count == 1) && (port->count != 1)) { |
1292 | /* | 1296 | /* |
@@ -1305,8 +1309,10 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1305 | tty->name, port->count); | 1309 | tty->name, port->count); |
1306 | port->count = 0; | 1310 | port->count = 0; |
1307 | } | 1311 | } |
1308 | if (port->count) | 1312 | if (port->count) { |
1313 | spin_unlock_irqrestore(&port->lock, flags); | ||
1309 | goto done; | 1314 | goto done; |
1315 | } | ||
1310 | 1316 | ||
1311 | /* | 1317 | /* |
1312 | * Now we wait for the transmit buffer to clear; and we notify | 1318 | * Now we wait for the transmit buffer to clear; and we notify |
@@ -1314,9 +1320,18 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1314 | * setting tty->closing. | 1320 | * setting tty->closing. |
1315 | */ | 1321 | */ |
1316 | tty->closing = 1; | 1322 | tty->closing = 1; |
1323 | spin_unlock_irqrestore(&port->lock, flags); | ||
1317 | 1324 | ||
1318 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 1325 | if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) { |
1319 | tty_wait_until_sent(tty, msecs_to_jiffies(port->closing_wait)); | 1326 | /* |
1327 | * hack: open-coded tty_wait_until_sent to avoid | ||
1328 | * recursive tty_lock | ||
1329 | */ | ||
1330 | long timeout = msecs_to_jiffies(port->closing_wait); | ||
1331 | if (wait_event_interruptible_timeout(tty->write_wait, | ||
1332 | !tty_chars_in_buffer(tty), timeout) >= 0) | ||
1333 | __uart_wait_until_sent(uport, timeout); | ||
1334 | } | ||
1320 | 1335 | ||
1321 | /* | 1336 | /* |
1322 | * At this point, we stop accepting input. To do this, we | 1337 | * At this point, we stop accepting input. To do this, we |
@@ -1332,45 +1347,47 @@ static void uart_close(struct tty_struct *tty, struct file *filp) | |||
1332 | * has completely drained; this is especially | 1347 | * has completely drained; this is especially |
1333 | * important if there is a transmit FIFO! | 1348 | * important if there is a transmit FIFO! |
1334 | */ | 1349 | */ |
1335 | uart_wait_until_sent(tty, uport->timeout); | 1350 | __uart_wait_until_sent(uport, uport->timeout); |
1336 | } | 1351 | } |
1337 | 1352 | ||
1338 | uart_shutdown(state); | 1353 | uart_shutdown(tty, state); |
1339 | uart_flush_buffer(tty); | 1354 | uart_flush_buffer(tty); |
1340 | 1355 | ||
1341 | tty_ldisc_flush(tty); | 1356 | tty_ldisc_flush(tty); |
1342 | 1357 | ||
1343 | tty->closing = 0; | ||
1344 | tty_port_tty_set(port, NULL); | 1358 | tty_port_tty_set(port, NULL); |
1359 | spin_lock_irqsave(&port->lock, flags); | ||
1360 | tty->closing = 0; | ||
1345 | 1361 | ||
1346 | if (port->blocked_open) { | 1362 | if (port->blocked_open) { |
1363 | spin_unlock_irqrestore(&port->lock, flags); | ||
1347 | if (port->close_delay) | 1364 | if (port->close_delay) |
1348 | msleep_interruptible(port->close_delay); | 1365 | msleep_interruptible(port->close_delay); |
1366 | spin_lock_irqsave(&port->lock, flags); | ||
1349 | } else if (!uart_console(uport)) { | 1367 | } else if (!uart_console(uport)) { |
1368 | spin_unlock_irqrestore(&port->lock, flags); | ||
1350 | uart_change_pm(state, 3); | 1369 | uart_change_pm(state, 3); |
1370 | spin_lock_irqsave(&port->lock, flags); | ||
1351 | } | 1371 | } |
1352 | 1372 | ||
1353 | /* | 1373 | /* |
1354 | * Wake up anyone trying to open this port. | 1374 | * Wake up anyone trying to open this port. |
1355 | */ | 1375 | */ |
1356 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | 1376 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
1377 | spin_unlock_irqrestore(&port->lock, flags); | ||
1357 | wake_up_interruptible(&port->open_wait); | 1378 | wake_up_interruptible(&port->open_wait); |
1358 | 1379 | ||
1359 | done: | 1380 | done: |
1360 | mutex_unlock(&port->mutex); | 1381 | mutex_unlock(&port->mutex); |
1361 | } | 1382 | } |
1362 | 1383 | ||
1363 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | 1384 | static void __uart_wait_until_sent(struct uart_port *port, int timeout) |
1364 | { | 1385 | { |
1365 | struct uart_state *state = tty->driver_data; | ||
1366 | struct uart_port *port = state->uart_port; | ||
1367 | unsigned long char_time, expire; | 1386 | unsigned long char_time, expire; |
1368 | 1387 | ||
1369 | if (port->type == PORT_UNKNOWN || port->fifosize == 0) | 1388 | if (port->type == PORT_UNKNOWN || port->fifosize == 0) |
1370 | return; | 1389 | return; |
1371 | 1390 | ||
1372 | lock_kernel(); | ||
1373 | |||
1374 | /* | 1391 | /* |
1375 | * Set the check interval to be 1/5 of the estimated time to | 1392 | * Set the check interval to be 1/5 of the estimated time to |
1376 | * send a single character, and make it at least 1. The check | 1393 | * send a single character, and make it at least 1. The check |
@@ -1416,7 +1433,16 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1416 | break; | 1433 | break; |
1417 | } | 1434 | } |
1418 | set_current_state(TASK_RUNNING); /* might not be needed */ | 1435 | set_current_state(TASK_RUNNING); /* might not be needed */ |
1419 | unlock_kernel(); | 1436 | } |
1437 | |||
1438 | static void uart_wait_until_sent(struct tty_struct *tty, int timeout) | ||
1439 | { | ||
1440 | struct uart_state *state = tty->driver_data; | ||
1441 | struct uart_port *port = state->uart_port; | ||
1442 | |||
1443 | tty_lock(); | ||
1444 | __uart_wait_until_sent(port, timeout); | ||
1445 | tty_unlock(); | ||
1420 | } | 1446 | } |
1421 | 1447 | ||
1422 | /* | 1448 | /* |
@@ -1429,16 +1455,19 @@ static void uart_hangup(struct tty_struct *tty) | |||
1429 | { | 1455 | { |
1430 | struct uart_state *state = tty->driver_data; | 1456 | struct uart_state *state = tty->driver_data; |
1431 | struct tty_port *port = &state->port; | 1457 | struct tty_port *port = &state->port; |
1458 | unsigned long flags; | ||
1432 | 1459 | ||
1433 | BUG_ON(!kernel_locked()); | 1460 | BUG_ON(!tty_locked()); |
1434 | pr_debug("uart_hangup(%d)\n", state->uart_port->line); | 1461 | pr_debug("uart_hangup(%d)\n", state->uart_port->line); |
1435 | 1462 | ||
1436 | mutex_lock(&port->mutex); | 1463 | mutex_lock(&port->mutex); |
1437 | if (port->flags & ASYNC_NORMAL_ACTIVE) { | 1464 | if (port->flags & ASYNC_NORMAL_ACTIVE) { |
1438 | uart_flush_buffer(tty); | 1465 | uart_flush_buffer(tty); |
1439 | uart_shutdown(state); | 1466 | uart_shutdown(tty, state); |
1467 | spin_lock_irqsave(&port->lock, flags); | ||
1440 | port->count = 0; | 1468 | port->count = 0; |
1441 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | 1469 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
1470 | spin_unlock_irqrestore(&port->lock, flags); | ||
1442 | tty_port_tty_set(port, NULL); | 1471 | tty_port_tty_set(port, NULL); |
1443 | wake_up_interruptible(&port->open_wait); | 1472 | wake_up_interruptible(&port->open_wait); |
1444 | wake_up_interruptible(&port->delta_msr_wait); | 1473 | wake_up_interruptible(&port->delta_msr_wait); |
@@ -1446,15 +1475,19 @@ static void uart_hangup(struct tty_struct *tty) | |||
1446 | mutex_unlock(&port->mutex); | 1475 | mutex_unlock(&port->mutex); |
1447 | } | 1476 | } |
1448 | 1477 | ||
1449 | /* | 1478 | /** |
1450 | * Copy across the serial console cflag setting into the termios settings | 1479 | * uart_update_termios - update the terminal hw settings |
1451 | * for the initial open of the port. This allows continuity between the | 1480 | * @tty: tty associated with UART |
1452 | * kernel settings, and the settings init adopts when it opens the port | 1481 | * @state: UART to update |
1453 | * for the first time. | 1482 | * |
1483 | * Copy across the serial console cflag setting into the termios settings | ||
1484 | * for the initial open of the port. This allows continuity between the | ||
1485 | * kernel settings, and the settings init adopts when it opens the port | ||
1486 | * for the first time. | ||
1454 | */ | 1487 | */ |
1455 | static void uart_update_termios(struct uart_state *state) | 1488 | static void uart_update_termios(struct tty_struct *tty, |
1489 | struct uart_state *state) | ||
1456 | { | 1490 | { |
1457 | struct tty_struct *tty = state->port.tty; | ||
1458 | struct uart_port *port = state->uart_port; | 1491 | struct uart_port *port = state->uart_port; |
1459 | 1492 | ||
1460 | if (uart_console(port) && port->cons->cflag) { | 1493 | if (uart_console(port) && port->cons->cflag) { |
@@ -1471,7 +1504,7 @@ static void uart_update_termios(struct uart_state *state) | |||
1471 | /* | 1504 | /* |
1472 | * Make termios settings take effect. | 1505 | * Make termios settings take effect. |
1473 | */ | 1506 | */ |
1474 | uart_change_speed(state, NULL); | 1507 | uart_change_speed(tty, state, NULL); |
1475 | 1508 | ||
1476 | /* | 1509 | /* |
1477 | * And finally enable the RTS and DTR signals. | 1510 | * And finally enable the RTS and DTR signals. |
@@ -1481,90 +1514,37 @@ static void uart_update_termios(struct uart_state *state) | |||
1481 | } | 1514 | } |
1482 | } | 1515 | } |
1483 | 1516 | ||
1484 | /* | 1517 | static int uart_carrier_raised(struct tty_port *port) |
1485 | * Block the open until the port is ready. We must be called with | ||
1486 | * the per-port semaphore held. | ||
1487 | */ | ||
1488 | static int | ||
1489 | uart_block_til_ready(struct file *filp, struct uart_state *state) | ||
1490 | { | 1518 | { |
1491 | DECLARE_WAITQUEUE(wait, current); | 1519 | struct uart_state *state = container_of(port, struct uart_state, port); |
1492 | struct uart_port *uport = state->uart_port; | 1520 | struct uart_port *uport = state->uart_port; |
1493 | struct tty_port *port = &state->port; | 1521 | int mctrl; |
1494 | unsigned int mctrl; | 1522 | spin_lock_irq(&uport->lock); |
1495 | 1523 | uport->ops->enable_ms(uport); | |
1496 | port->blocked_open++; | 1524 | mctrl = uport->ops->get_mctrl(uport); |
1497 | port->count--; | 1525 | spin_unlock_irq(&uport->lock); |
1498 | 1526 | if (mctrl & TIOCM_CAR) | |
1499 | add_wait_queue(&port->open_wait, &wait); | 1527 | return 1; |
1500 | while (1) { | 1528 | return 0; |
1501 | set_current_state(TASK_INTERRUPTIBLE); | 1529 | } |
1502 | |||
1503 | /* | ||
1504 | * If we have been hung up, tell userspace/restart open. | ||
1505 | */ | ||
1506 | if (tty_hung_up_p(filp) || port->tty == NULL) | ||
1507 | break; | ||
1508 | |||
1509 | /* | ||
1510 | * If the port has been closed, tell userspace/restart open. | ||
1511 | */ | ||
1512 | if (!(port->flags & ASYNC_INITIALIZED)) | ||
1513 | break; | ||
1514 | 1530 | ||
1515 | /* | 1531 | static void uart_dtr_rts(struct tty_port *port, int onoff) |
1516 | * If non-blocking mode is set, or CLOCAL mode is set, | 1532 | { |
1517 | * we don't want to wait for the modem status lines to | 1533 | struct uart_state *state = container_of(port, struct uart_state, port); |
1518 | * indicate that the port is ready. | 1534 | struct uart_port *uport = state->uart_port; |
1519 | * | ||
1520 | * Also, if the port is not enabled/configured, we want | ||
1521 | * to allow the open to succeed here. Note that we will | ||
1522 | * have set TTY_IO_ERROR for a non-existant port. | ||
1523 | */ | ||
1524 | if ((filp->f_flags & O_NONBLOCK) || | ||
1525 | (port->tty->termios->c_cflag & CLOCAL) || | ||
1526 | (port->tty->flags & (1 << TTY_IO_ERROR))) | ||
1527 | break; | ||
1528 | 1535 | ||
1529 | /* | 1536 | if (onoff) { |
1530 | * Set DTR to allow modem to know we're waiting. Do | 1537 | uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS); |
1531 | * not set RTS here - we want to make sure we catch | ||
1532 | * the data from the modem. | ||
1533 | */ | ||
1534 | if (port->tty->termios->c_cflag & CBAUD) | ||
1535 | uart_set_mctrl(uport, TIOCM_DTR); | ||
1536 | 1538 | ||
1537 | /* | 1539 | /* |
1538 | * and wait for the carrier to indicate that the | 1540 | * If this is the first open to succeed, |
1539 | * modem is ready for us. | 1541 | * adjust things to suit. |
1540 | */ | 1542 | */ |
1541 | spin_lock_irq(&uport->lock); | 1543 | if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags)) |
1542 | uport->ops->enable_ms(uport); | 1544 | uart_update_termios(port->tty, state); |
1543 | mctrl = uport->ops->get_mctrl(uport); | ||
1544 | spin_unlock_irq(&uport->lock); | ||
1545 | if (mctrl & TIOCM_CAR) | ||
1546 | break; | ||
1547 | |||
1548 | mutex_unlock(&port->mutex); | ||
1549 | schedule(); | ||
1550 | mutex_lock(&port->mutex); | ||
1551 | |||
1552 | if (signal_pending(current)) | ||
1553 | break; | ||
1554 | } | 1545 | } |
1555 | set_current_state(TASK_RUNNING); | 1546 | else |
1556 | remove_wait_queue(&port->open_wait, &wait); | 1547 | uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); |
1557 | |||
1558 | port->count++; | ||
1559 | port->blocked_open--; | ||
1560 | |||
1561 | if (signal_pending(current)) | ||
1562 | return -ERESTARTSYS; | ||
1563 | |||
1564 | if (!port->tty || tty_hung_up_p(filp)) | ||
1565 | return -EAGAIN; | ||
1566 | |||
1567 | return 0; | ||
1568 | } | 1548 | } |
1569 | 1549 | ||
1570 | static struct uart_state *uart_get(struct uart_driver *drv, int line) | 1550 | static struct uart_state *uart_get(struct uart_driver *drv, int line) |
@@ -1611,7 +1591,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1611 | struct tty_port *port; | 1591 | struct tty_port *port; |
1612 | int retval, line = tty->index; | 1592 | int retval, line = tty->index; |
1613 | 1593 | ||
1614 | BUG_ON(!kernel_locked()); | 1594 | BUG_ON(!tty_locked()); |
1615 | pr_debug("uart_open(%d) called\n", line); | 1595 | pr_debug("uart_open(%d) called\n", line); |
1616 | 1596 | ||
1617 | /* | 1597 | /* |
@@ -1668,23 +1648,14 @@ static int uart_open(struct tty_struct *tty, struct file *filp) | |||
1668 | /* | 1648 | /* |
1669 | * Start up the serial port. | 1649 | * Start up the serial port. |
1670 | */ | 1650 | */ |
1671 | retval = uart_startup(state, 0); | 1651 | retval = uart_startup(tty, state, 0); |
1672 | 1652 | ||
1673 | /* | 1653 | /* |
1674 | * If we succeeded, wait until the port is ready. | 1654 | * If we succeeded, wait until the port is ready. |
1675 | */ | 1655 | */ |
1676 | if (retval == 0) | ||
1677 | retval = uart_block_til_ready(filp, state); | ||
1678 | mutex_unlock(&port->mutex); | 1656 | mutex_unlock(&port->mutex); |
1679 | 1657 | if (retval == 0) | |
1680 | /* | 1658 | retval = tty_port_block_til_ready(port, tty, filp); |
1681 | * If this is the first open to succeed, adjust things to suit. | ||
1682 | */ | ||
1683 | if (retval == 0 && !(port->flags & ASYNC_NORMAL_ACTIVE)) { | ||
1684 | set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); | ||
1685 | |||
1686 | uart_update_termios(state); | ||
1687 | } | ||
1688 | 1659 | ||
1689 | fail: | 1660 | fail: |
1690 | return retval; | 1661 | return retval; |
@@ -2010,9 +1981,13 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) | |||
2010 | struct tty_port *port = &state->port; | 1981 | struct tty_port *port = &state->port; |
2011 | struct device *tty_dev; | 1982 | struct device *tty_dev; |
2012 | struct uart_match match = {uport, drv}; | 1983 | struct uart_match match = {uport, drv}; |
1984 | struct tty_struct *tty; | ||
2013 | 1985 | ||
2014 | mutex_lock(&port->mutex); | 1986 | mutex_lock(&port->mutex); |
2015 | 1987 | ||
1988 | /* Must be inside the mutex lock until we convert to tty_port */ | ||
1989 | tty = port->tty; | ||
1990 | |||
2016 | tty_dev = device_find_child(uport->dev, &match, serial_match_port); | 1991 | tty_dev = device_find_child(uport->dev, &match, serial_match_port); |
2017 | if (device_may_wakeup(tty_dev)) { | 1992 | if (device_may_wakeup(tty_dev)) { |
2018 | enable_irq_wake(uport->irq); | 1993 | enable_irq_wake(uport->irq); |
@@ -2105,9 +2080,12 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) | |||
2105 | ops->set_mctrl(uport, 0); | 2080 | ops->set_mctrl(uport, 0); |
2106 | spin_unlock_irq(&uport->lock); | 2081 | spin_unlock_irq(&uport->lock); |
2107 | if (console_suspend_enabled || !uart_console(uport)) { | 2082 | if (console_suspend_enabled || !uart_console(uport)) { |
2083 | /* Protected by port mutex for now */ | ||
2084 | struct tty_struct *tty = port->tty; | ||
2108 | ret = ops->startup(uport); | 2085 | ret = ops->startup(uport); |
2109 | if (ret == 0) { | 2086 | if (ret == 0) { |
2110 | uart_change_speed(state, NULL); | 2087 | if (tty) |
2088 | uart_change_speed(tty, state, NULL); | ||
2111 | spin_lock_irq(&uport->lock); | 2089 | spin_lock_irq(&uport->lock); |
2112 | ops->set_mctrl(uport, uport->mctrl); | 2090 | ops->set_mctrl(uport, uport->mctrl); |
2113 | ops->start_tx(uport); | 2091 | ops->start_tx(uport); |
@@ -2119,7 +2097,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) | |||
2119 | * Clear the "initialized" flag so we won't try | 2097 | * Clear the "initialized" flag so we won't try |
2120 | * to call the low level drivers shutdown method. | 2098 | * to call the low level drivers shutdown method. |
2121 | */ | 2099 | */ |
2122 | uart_shutdown(state); | 2100 | uart_shutdown(tty, state); |
2123 | } | 2101 | } |
2124 | } | 2102 | } |
2125 | 2103 | ||
@@ -2312,6 +2290,11 @@ static const struct tty_operations uart_ops = { | |||
2312 | #endif | 2290 | #endif |
2313 | }; | 2291 | }; |
2314 | 2292 | ||
2293 | static const struct tty_port_operations uart_port_ops = { | ||
2294 | .carrier_raised = uart_carrier_raised, | ||
2295 | .dtr_rts = uart_dtr_rts, | ||
2296 | }; | ||
2297 | |||
2315 | /** | 2298 | /** |
2316 | * uart_register_driver - register a driver with the uart core layer | 2299 | * uart_register_driver - register a driver with the uart core layer |
2317 | * @drv: low level driver structure | 2300 | * @drv: low level driver structure |
@@ -2368,6 +2351,7 @@ int uart_register_driver(struct uart_driver *drv) | |||
2368 | struct tty_port *port = &state->port; | 2351 | struct tty_port *port = &state->port; |
2369 | 2352 | ||
2370 | tty_port_init(port); | 2353 | tty_port_init(port); |
2354 | port->ops = &uart_port_ops; | ||
2371 | port->close_delay = 500; /* .5 seconds */ | 2355 | port->close_delay = 500; /* .5 seconds */ |
2372 | port->closing_wait = 30000; /* 30 seconds */ | 2356 | port->closing_wait = 30000; /* 30 seconds */ |
2373 | tasklet_init(&state->tlet, uart_tasklet_action, | 2357 | tasklet_init(&state->tlet, uart_tasklet_action, |
diff --git a/drivers/serial/timbuart.c b/drivers/serial/timbuart.c index 67ca642713b8..1f36b7eb7351 100644 --- a/drivers/serial/timbuart.c +++ b/drivers/serial/timbuart.c | |||
@@ -423,7 +423,7 @@ static struct uart_driver timbuart_driver = { | |||
423 | .nr = 1 | 423 | .nr = 1 |
424 | }; | 424 | }; |
425 | 425 | ||
426 | static int timbuart_probe(struct platform_device *dev) | 426 | static int __devinit timbuart_probe(struct platform_device *dev) |
427 | { | 427 | { |
428 | int err, irq; | 428 | int err, irq; |
429 | struct timbuart_port *uart; | 429 | struct timbuart_port *uart; |
@@ -489,7 +489,7 @@ err_mem: | |||
489 | return err; | 489 | return err; |
490 | } | 490 | } |
491 | 491 | ||
492 | static int timbuart_remove(struct platform_device *dev) | 492 | static int __devexit timbuart_remove(struct platform_device *dev) |
493 | { | 493 | { |
494 | struct timbuart_port *uart = platform_get_drvdata(dev); | 494 | struct timbuart_port *uart = platform_get_drvdata(dev); |
495 | 495 | ||
@@ -507,7 +507,7 @@ static struct platform_driver timbuart_platform_driver = { | |||
507 | .owner = THIS_MODULE, | 507 | .owner = THIS_MODULE, |
508 | }, | 508 | }, |
509 | .probe = timbuart_probe, | 509 | .probe = timbuart_probe, |
510 | .remove = timbuart_remove, | 510 | .remove = __devexit_p(timbuart_remove), |
511 | }; | 511 | }; |
512 | 512 | ||
513 | /*--------------------------------------------------------------------------*/ | 513 | /*--------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 89d260d6b031..1833b3a71515 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -636,19 +636,13 @@ static void acm_tty_unregister(struct acm *acm) | |||
636 | 636 | ||
637 | static int acm_tty_chars_in_buffer(struct tty_struct *tty); | 637 | static int acm_tty_chars_in_buffer(struct tty_struct *tty); |
638 | 638 | ||
639 | static void acm_port_down(struct acm *acm, int drain) | 639 | static void acm_port_down(struct acm *acm) |
640 | { | 640 | { |
641 | int i, nr = acm->rx_buflimit; | 641 | int i, nr = acm->rx_buflimit; |
642 | mutex_lock(&open_mutex); | 642 | mutex_lock(&open_mutex); |
643 | if (acm->dev) { | 643 | if (acm->dev) { |
644 | usb_autopm_get_interface(acm->control); | 644 | usb_autopm_get_interface(acm->control); |
645 | acm_set_control(acm, acm->ctrlout = 0); | 645 | acm_set_control(acm, acm->ctrlout = 0); |
646 | /* try letting the last writes drain naturally */ | ||
647 | if (drain) { | ||
648 | wait_event_interruptible_timeout(acm->drain_wait, | ||
649 | (ACM_NW == acm_wb_is_avail(acm)) || !acm->dev, | ||
650 | ACM_CLOSE_TIMEOUT * HZ); | ||
651 | } | ||
652 | usb_kill_urb(acm->ctrlurb); | 646 | usb_kill_urb(acm->ctrlurb); |
653 | for (i = 0; i < ACM_NW; i++) | 647 | for (i = 0; i < ACM_NW; i++) |
654 | usb_kill_urb(acm->wb[i].urb); | 648 | usb_kill_urb(acm->wb[i].urb); |
@@ -664,7 +658,7 @@ static void acm_tty_hangup(struct tty_struct *tty) | |||
664 | { | 658 | { |
665 | struct acm *acm = tty->driver_data; | 659 | struct acm *acm = tty->driver_data; |
666 | tty_port_hangup(&acm->port); | 660 | tty_port_hangup(&acm->port); |
667 | acm_port_down(acm, 0); | 661 | acm_port_down(acm); |
668 | } | 662 | } |
669 | 663 | ||
670 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) | 664 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) |
@@ -685,7 +679,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) | |||
685 | mutex_unlock(&open_mutex); | 679 | mutex_unlock(&open_mutex); |
686 | return; | 680 | return; |
687 | } | 681 | } |
688 | acm_port_down(acm, 0); | 682 | acm_port_down(acm); |
689 | tty_port_close_end(&acm->port, tty); | 683 | tty_port_close_end(&acm->port, tty); |
690 | tty_port_tty_set(&acm->port, NULL); | 684 | tty_port_tty_set(&acm->port, NULL); |
691 | } | 685 | } |
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index fd35f73b5721..b92070c103cd 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c | |||
@@ -609,8 +609,10 @@ static void digi_wakeup_write_lock(struct work_struct *work) | |||
609 | static void digi_wakeup_write(struct usb_serial_port *port) | 609 | static void digi_wakeup_write(struct usb_serial_port *port) |
610 | { | 610 | { |
611 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 611 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
612 | tty_wakeup(tty); | 612 | if (tty) { |
613 | tty_kref_put(tty); | 613 | tty_wakeup(tty); |
614 | tty_kref_put(tty); | ||
615 | } | ||
614 | } | 616 | } |
615 | 617 | ||
616 | 618 | ||
@@ -1682,7 +1684,7 @@ static int digi_read_inb_callback(struct urb *urb) | |||
1682 | priv->dp_throttle_restart = 1; | 1684 | priv->dp_throttle_restart = 1; |
1683 | 1685 | ||
1684 | /* receive data */ | 1686 | /* receive data */ |
1685 | if (opcode == DIGI_CMD_RECEIVE_DATA) { | 1687 | if (tty && opcode == DIGI_CMD_RECEIVE_DATA) { |
1686 | /* get flag from port_status */ | 1688 | /* get flag from port_status */ |
1687 | flag = 0; | 1689 | flag = 0; |
1688 | 1690 | ||
@@ -1763,10 +1765,12 @@ static int digi_read_oob_callback(struct urb *urb) | |||
1763 | return -1; | 1765 | return -1; |
1764 | 1766 | ||
1765 | tty = tty_port_tty_get(&port->port); | 1767 | tty = tty_port_tty_get(&port->port); |
1768 | |||
1766 | rts = 0; | 1769 | rts = 0; |
1767 | rts = tty->termios->c_cflag & CRTSCTS; | 1770 | if (tty) |
1771 | rts = tty->termios->c_cflag & CRTSCTS; | ||
1768 | 1772 | ||
1769 | if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) { | 1773 | if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) { |
1770 | spin_lock(&priv->dp_port_lock); | 1774 | spin_lock(&priv->dp_port_lock); |
1771 | /* convert from digi flags to termiox flags */ | 1775 | /* convert from digi flags to termiox flags */ |
1772 | if (val & DIGI_READ_INPUT_SIGNALS_CTS) { | 1776 | if (val & DIGI_READ_INPUT_SIGNALS_CTS) { |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 3b3f5749af92..26bf7cbfecc2 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -283,7 +283,8 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) | |||
283 | struct fbcon_ops *ops = info->fbcon_par; | 283 | struct fbcon_ops *ops = info->fbcon_par; |
284 | 284 | ||
285 | return (info->state != FBINFO_STATE_RUNNING || | 285 | return (info->state != FBINFO_STATE_RUNNING || |
286 | vc->vc_mode != KD_TEXT || ops->graphics); | 286 | vc->vc_mode != KD_TEXT || ops->graphics) && |
287 | !vt_force_oops_output(vc); | ||
287 | } | 288 | } |
288 | 289 | ||
289 | static inline int get_color(struct vc_data *vc, struct fb_info *info, | 290 | static inline int get_color(struct vc_data *vc, struct fb_info *info, |
@@ -1073,6 +1074,7 @@ static void fbcon_init(struct vc_data *vc, int init) | |||
1073 | if (p->userfont) | 1074 | if (p->userfont) |
1074 | charcnt = FNTCHARCNT(p->fontdata); | 1075 | charcnt = FNTCHARCNT(p->fontdata); |
1075 | 1076 | ||
1077 | vc->vc_panic_force_write = !!(info->flags & FBINFO_CAN_FORCE_OUTPUT); | ||
1076 | vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); | 1078 | vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); |
1077 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; | 1079 | vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; |
1078 | if (charcnt == 256) { | 1080 | if (charcnt == 256) { |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 182dd6f8aadd..54e32c513610 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -1108,7 +1108,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
1108 | charmap += 4 * cmapsz; | 1108 | charmap += 4 * cmapsz; |
1109 | #endif | 1109 | #endif |
1110 | 1110 | ||
1111 | unlock_kernel(); | ||
1112 | spin_lock_irq(&vga_lock); | 1111 | spin_lock_irq(&vga_lock); |
1113 | /* First, the Sequencer */ | 1112 | /* First, the Sequencer */ |
1114 | vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); | 1113 | vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); |
@@ -1192,7 +1191,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
1192 | vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); | 1191 | vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); |
1193 | } | 1192 | } |
1194 | spin_unlock_irq(&vga_lock); | 1193 | spin_unlock_irq(&vga_lock); |
1195 | lock_kernel(); | ||
1196 | return 0; | 1194 | return 0; |
1197 | } | 1195 | } |
1198 | 1196 | ||
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 5d9b936c458b..70227e0dc01d 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -946,6 +946,7 @@ COMPATIBLE_IOCTL(TIOCGPGRP) | |||
946 | COMPATIBLE_IOCTL(TIOCGPTN) | 946 | COMPATIBLE_IOCTL(TIOCGPTN) |
947 | COMPATIBLE_IOCTL(TIOCSPTLCK) | 947 | COMPATIBLE_IOCTL(TIOCSPTLCK) |
948 | COMPATIBLE_IOCTL(TIOCSERGETLSR) | 948 | COMPATIBLE_IOCTL(TIOCSERGETLSR) |
949 | COMPATIBLE_IOCTL(TIOCSIG) | ||
949 | #ifdef TCGETS2 | 950 | #ifdef TCGETS2 |
950 | COMPATIBLE_IOCTL(TCGETS2) | 951 | COMPATIBLE_IOCTL(TCGETS2) |
951 | COMPATIBLE_IOCTL(TCSETS2) | 952 | COMPATIBLE_IOCTL(TCSETS2) |
diff --git a/include/asm-generic/ioctls.h b/include/asm-generic/ioctls.h index a799e20a769e..8554cb6a81b9 100644 --- a/include/asm-generic/ioctls.h +++ b/include/asm-generic/ioctls.h | |||
@@ -69,6 +69,7 @@ | |||
69 | #define TCSETX 0x5433 | 69 | #define TCSETX 0x5433 |
70 | #define TCSETXF 0x5434 | 70 | #define TCSETXF 0x5434 |
71 | #define TCSETXW 0x5435 | 71 | #define TCSETXW 0x5435 |
72 | #define TIOCSIG _IOW('T', 0x36, int) /* pty: generate signal */ | ||
72 | 73 | ||
73 | #define FIONCLEX 0x5450 | 74 | #define FIONCLEX 0x5450 |
74 | #define FIOCLEX 0x5451 | 75 | #define FIOCLEX 0x5451 |
@@ -87,12 +88,10 @@ | |||
87 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ | 88 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ |
88 | 89 | ||
89 | /* | 90 | /* |
90 | * some architectures define FIOQSIZE as 0x545E, which is used for | 91 | * Some arches already define FIOQSIZE due to a historical |
91 | * TIOCGHAYESESP on others | 92 | * conflict with a Hayes modem-specific ioctl value. |
92 | */ | 93 | */ |
93 | #ifndef FIOQSIZE | 94 | #ifndef FIOQSIZE |
94 | # define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ | ||
95 | # define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ | ||
96 | # define FIOQSIZE 0x5460 | 95 | # define FIOQSIZE 0x5460 |
97 | #endif | 96 | #endif |
98 | 97 | ||
@@ -104,6 +103,7 @@ | |||
104 | #define TIOCPKT_START 8 | 103 | #define TIOCPKT_START 8 |
105 | #define TIOCPKT_NOSTOP 16 | 104 | #define TIOCPKT_NOSTOP 16 |
106 | #define TIOCPKT_DOSTOP 32 | 105 | #define TIOCPKT_DOSTOP 32 |
106 | #define TIOCPKT_IOCTL 64 | ||
107 | 107 | ||
108 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 108 | #define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
109 | 109 | ||
diff --git a/include/asm-generic/termbits.h b/include/asm-generic/termbits.h index 1c9773d48cb0..232b4781aef3 100644 --- a/include/asm-generic/termbits.h +++ b/include/asm-generic/termbits.h | |||
@@ -178,6 +178,7 @@ struct ktermios { | |||
178 | #define FLUSHO 0010000 | 178 | #define FLUSHO 0010000 |
179 | #define PENDIN 0040000 | 179 | #define PENDIN 0040000 |
180 | #define IEXTEN 0100000 | 180 | #define IEXTEN 0100000 |
181 | #define EXTPROC 0200000 | ||
181 | 182 | ||
182 | /* tcflow() and TCXONC use these */ | 183 | /* tcflow() and TCXONC use these */ |
183 | #define TCOOFF 0 | 184 | #define TCOOFF 0 |
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index 38fe59dc89ae..7f0c32908568 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h | |||
@@ -21,6 +21,8 @@ struct vt_struct; | |||
21 | #define NPAR 16 | 21 | #define NPAR 16 |
22 | 22 | ||
23 | struct vc_data { | 23 | struct vc_data { |
24 | struct tty_port port; /* Upper level data */ | ||
25 | |||
24 | unsigned short vc_num; /* Console number */ | 26 | unsigned short vc_num; /* Console number */ |
25 | unsigned int vc_cols; /* [#] Console size */ | 27 | unsigned int vc_cols; /* [#] Console size */ |
26 | unsigned int vc_rows; | 28 | unsigned int vc_rows; |
@@ -56,7 +58,6 @@ struct vc_data { | |||
56 | /* VT terminal data */ | 58 | /* VT terminal data */ |
57 | unsigned int vc_state; /* Escape sequence parser state */ | 59 | unsigned int vc_state; /* Escape sequence parser state */ |
58 | unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */ | 60 | unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */ |
59 | struct tty_struct *vc_tty; /* TTY we are attached to */ | ||
60 | /* data for manual vt switching */ | 61 | /* data for manual vt switching */ |
61 | struct vt_mode vt_mode; | 62 | struct vt_mode vt_mode; |
62 | struct pid *vt_pid; | 63 | struct pid *vt_pid; |
@@ -105,6 +106,7 @@ struct vc_data { | |||
105 | struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */ | 106 | struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */ |
106 | unsigned long vc_uni_pagedir; | 107 | unsigned long vc_uni_pagedir; |
107 | unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */ | 108 | unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */ |
109 | bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */ | ||
108 | /* additional information is in vt_kern.h */ | 110 | /* additional information is in vt_kern.h */ |
109 | }; | 111 | }; |
110 | 112 | ||
diff --git a/include/linux/fb.h b/include/linux/fb.h index 0c5659c41b01..f0268deca658 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -825,6 +825,10 @@ struct fb_tile_ops { | |||
825 | */ | 825 | */ |
826 | #define FBINFO_BE_MATH 0x100000 | 826 | #define FBINFO_BE_MATH 0x100000 |
827 | 827 | ||
828 | /* report to the VT layer that this fb driver can accept forced console | ||
829 | output like oopses */ | ||
830 | #define FBINFO_CAN_FORCE_OUTPUT 0x200000 | ||
831 | |||
828 | struct fb_info { | 832 | struct fb_info { |
829 | int node; | 833 | int node; |
830 | int flags; | 834 | int flags; |
diff --git a/include/linux/istallion.h b/include/linux/istallion.h index 7faca98c7d14..ad700a60c158 100644 --- a/include/linux/istallion.h +++ b/include/linux/istallion.h | |||
@@ -86,7 +86,7 @@ struct stlibrd { | |||
86 | unsigned long magic; | 86 | unsigned long magic; |
87 | unsigned int brdnr; | 87 | unsigned int brdnr; |
88 | unsigned int brdtype; | 88 | unsigned int brdtype; |
89 | unsigned int state; | 89 | unsigned long state; |
90 | unsigned int nrpanels; | 90 | unsigned int nrpanels; |
91 | unsigned int nrports; | 91 | unsigned int nrports; |
92 | unsigned int nrdevs; | 92 | unsigned int nrdevs; |
diff --git a/include/linux/serial.h b/include/linux/serial.h index c8613c3ff9d3..1ebc694a6d52 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h | |||
@@ -77,7 +77,8 @@ struct serial_struct { | |||
77 | #define PORT_16654 11 | 77 | #define PORT_16654 11 |
78 | #define PORT_16850 12 | 78 | #define PORT_16850 12 |
79 | #define PORT_RSA 13 /* RSA-DV II/S card */ | 79 | #define PORT_RSA 13 /* RSA-DV II/S card */ |
80 | #define PORT_MAX 13 | 80 | #define PORT_U6_16550A 14 |
81 | #define PORT_MAX 14 | ||
81 | 82 | ||
82 | #define SERIAL_IO_PORT 0 | 83 | #define SERIAL_IO_PORT 0 |
83 | #define SERIAL_IO_HUB6 1 | 84 | #define SERIAL_IO_HUB6 1 |
@@ -151,7 +152,7 @@ struct serial_uart_config { | |||
151 | #define ASYNC_BUGGY_UART (1U << ASYNCB_BUGGY_UART) | 152 | #define ASYNC_BUGGY_UART (1U << ASYNCB_BUGGY_UART) |
152 | #define ASYNC_AUTOPROBE (1U << ASYNCB_AUTOPROBE) | 153 | #define ASYNC_AUTOPROBE (1U << ASYNCB_AUTOPROBE) |
153 | 154 | ||
154 | #define ASYNC_FLAGS ((1U << ASYNCB_LAST_USER) - 1) | 155 | #define ASYNC_FLAGS ((1U << (ASYNCB_LAST_USER + 1)) - 1) |
155 | #define ASYNC_USR_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI| \ | 156 | #define ASYNC_USR_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI| \ |
156 | ASYNC_CALLOUT_NOHUP|ASYNC_SPD_SHI|ASYNC_LOW_LATENCY) | 157 | ASYNC_CALLOUT_NOHUP|ASYNC_SPD_SHI|ASYNC_LOW_LATENCY) |
157 | #define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI) | 158 | #define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI) |
@@ -210,8 +211,10 @@ struct serial_rs485 { | |||
210 | #define SER_RS485_ENABLED (1 << 0) | 211 | #define SER_RS485_ENABLED (1 << 0) |
211 | #define SER_RS485_RTS_ON_SEND (1 << 1) | 212 | #define SER_RS485_RTS_ON_SEND (1 << 1) |
212 | #define SER_RS485_RTS_AFTER_SEND (1 << 2) | 213 | #define SER_RS485_RTS_AFTER_SEND (1 << 2) |
214 | #define SER_RS485_RTS_BEFORE_SEND (1 << 3) | ||
213 | __u32 delay_rts_before_send; /* Milliseconds */ | 215 | __u32 delay_rts_before_send; /* Milliseconds */ |
214 | __u32 padding[6]; /* Memory is cheap, new structs | 216 | __u32 delay_rts_after_send; /* Milliseconds */ |
217 | __u32 padding[5]; /* Memory is cheap, new structs | ||
215 | are a royal PITA .. */ | 218 | are a royal PITA .. */ |
216 | }; | 219 | }; |
217 | 220 | ||
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index fb46aba11fb5..7638deaaba65 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h | |||
@@ -32,6 +32,9 @@ struct plat_serial8250_port { | |||
32 | unsigned int type; /* If UPF_FIXED_TYPE */ | 32 | unsigned int type; /* If UPF_FIXED_TYPE */ |
33 | unsigned int (*serial_in)(struct uart_port *, int); | 33 | unsigned int (*serial_in)(struct uart_port *, int); |
34 | void (*serial_out)(struct uart_port *, int, int); | 34 | void (*serial_out)(struct uart_port *, int, int); |
35 | void (*set_termios)(struct uart_port *, | ||
36 | struct ktermios *new, | ||
37 | struct ktermios *old); | ||
35 | }; | 38 | }; |
36 | 39 | ||
37 | /* | 40 | /* |
@@ -71,5 +74,7 @@ extern int early_serial_setup(struct uart_port *port); | |||
71 | extern int serial8250_find_port(struct uart_port *p); | 74 | extern int serial8250_find_port(struct uart_port *p); |
72 | extern int serial8250_find_port_for_earlycon(void); | 75 | extern int serial8250_find_port_for_earlycon(void); |
73 | extern int setup_early_serial8250_console(char *cmdline); | 76 | extern int setup_early_serial8250_console(char *cmdline); |
77 | extern void serial8250_do_set_termios(struct uart_port *port, | ||
78 | struct ktermios *termios, struct ktermios *old); | ||
74 | 79 | ||
75 | #endif | 80 | #endif |
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index f10db6e5f3b5..8129ca2d57e3 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -186,6 +186,12 @@ | |||
186 | #define PORT_ALTERA_JTAGUART 91 | 186 | #define PORT_ALTERA_JTAGUART 91 |
187 | #define PORT_ALTERA_UART 92 | 187 | #define PORT_ALTERA_UART 92 |
188 | 188 | ||
189 | /* MAX3107 */ | ||
190 | #define PORT_MAX3107 94 | ||
191 | |||
192 | /* High Speed UART for Medfield */ | ||
193 | #define PORT_MFD 95 | ||
194 | |||
189 | #ifdef __KERNEL__ | 195 | #ifdef __KERNEL__ |
190 | 196 | ||
191 | #include <linux/compiler.h> | 197 | #include <linux/compiler.h> |
@@ -220,7 +226,7 @@ struct uart_ops { | |||
220 | void (*flush_buffer)(struct uart_port *); | 226 | void (*flush_buffer)(struct uart_port *); |
221 | void (*set_termios)(struct uart_port *, struct ktermios *new, | 227 | void (*set_termios)(struct uart_port *, struct ktermios *new, |
222 | struct ktermios *old); | 228 | struct ktermios *old); |
223 | void (*set_ldisc)(struct uart_port *); | 229 | void (*set_ldisc)(struct uart_port *, int new); |
224 | void (*pm)(struct uart_port *, unsigned int state, | 230 | void (*pm)(struct uart_port *, unsigned int state, |
225 | unsigned int oldstate); | 231 | unsigned int oldstate); |
226 | int (*set_wake)(struct uart_port *, unsigned int state); | 232 | int (*set_wake)(struct uart_port *, unsigned int state); |
@@ -276,6 +282,9 @@ struct uart_port { | |||
276 | unsigned char __iomem *membase; /* read/write[bwl] */ | 282 | unsigned char __iomem *membase; /* read/write[bwl] */ |
277 | unsigned int (*serial_in)(struct uart_port *, int); | 283 | unsigned int (*serial_in)(struct uart_port *, int); |
278 | void (*serial_out)(struct uart_port *, int, int); | 284 | void (*serial_out)(struct uart_port *, int, int); |
285 | void (*set_termios)(struct uart_port *, | ||
286 | struct ktermios *new, | ||
287 | struct ktermios *old); | ||
279 | unsigned int irq; /* irq number */ | 288 | unsigned int irq; /* irq number */ |
280 | unsigned long irqflags; /* irq flags */ | 289 | unsigned long irqflags; /* irq flags */ |
281 | unsigned int uartclk; /* base uart clock */ | 290 | unsigned int uartclk; /* base uart clock */ |
diff --git a/include/linux/serial_mfd.h b/include/linux/serial_mfd.h new file mode 100644 index 000000000000..2b071e0b034d --- /dev/null +++ b/include/linux/serial_mfd.h | |||
@@ -0,0 +1,47 @@ | |||
1 | #ifndef _SERIAL_MFD_H_ | ||
2 | #define _SERIAL_MFD_H_ | ||
3 | |||
4 | /* HW register offset definition */ | ||
5 | #define UART_FOR 0x08 | ||
6 | #define UART_PS 0x0C | ||
7 | #define UART_MUL 0x0D | ||
8 | #define UART_DIV 0x0E | ||
9 | |||
10 | #define HSU_GBL_IEN 0x0 | ||
11 | #define HSU_GBL_IST 0x4 | ||
12 | |||
13 | #define HSU_GBL_INT_BIT_PORT0 0x0 | ||
14 | #define HSU_GBL_INT_BIT_PORT1 0x1 | ||
15 | #define HSU_GBL_INT_BIT_PORT2 0x2 | ||
16 | #define HSU_GBL_INT_BIT_IRI 0x3 | ||
17 | #define HSU_GBL_INT_BIT_HDLC 0x4 | ||
18 | #define HSU_GBL_INT_BIT_DMA 0x5 | ||
19 | |||
20 | #define HSU_GBL_ISR 0x8 | ||
21 | #define HSU_GBL_DMASR 0x400 | ||
22 | #define HSU_GBL_DMAISR 0x404 | ||
23 | |||
24 | #define HSU_PORT_REG_OFFSET 0x80 | ||
25 | #define HSU_PORT0_REG_OFFSET 0x80 | ||
26 | #define HSU_PORT1_REG_OFFSET 0x100 | ||
27 | #define HSU_PORT2_REG_OFFSET 0x180 | ||
28 | #define HSU_PORT_REG_LENGTH 0x80 | ||
29 | |||
30 | #define HSU_DMA_CHANS_REG_OFFSET 0x500 | ||
31 | #define HSU_DMA_CHANS_REG_LENGTH 0x40 | ||
32 | |||
33 | #define HSU_CH_SR 0x0 /* channel status reg */ | ||
34 | #define HSU_CH_CR 0x4 /* control reg */ | ||
35 | #define HSU_CH_DCR 0x8 /* descriptor control reg */ | ||
36 | #define HSU_CH_BSR 0x10 /* max fifo buffer size reg */ | ||
37 | #define HSU_CH_MOTSR 0x14 /* minimum ocp transfer size */ | ||
38 | #define HSU_CH_D0SAR 0x20 /* desc 0 start addr */ | ||
39 | #define HSU_CH_D0TSR 0x24 /* desc 0 transfer size */ | ||
40 | #define HSU_CH_D1SAR 0x28 | ||
41 | #define HSU_CH_D1TSR 0x2C | ||
42 | #define HSU_CH_D2SAR 0x30 | ||
43 | #define HSU_CH_D2TSR 0x34 | ||
44 | #define HSU_CH_D3SAR 0x38 | ||
45 | #define HSU_CH_D3TSR 0x3C | ||
46 | |||
47 | #endif | ||
diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h index cf9327c051ad..c7a0ce11cd47 100644 --- a/include/linux/serial_reg.h +++ b/include/linux/serial_reg.h | |||
@@ -221,8 +221,24 @@ | |||
221 | #define UART_FCR_PXAR16 0x80 /* receive FIFO threshold = 16 */ | 221 | #define UART_FCR_PXAR16 0x80 /* receive FIFO threshold = 16 */ |
222 | #define UART_FCR_PXAR32 0xc0 /* receive FIFO threshold = 32 */ | 222 | #define UART_FCR_PXAR32 0xc0 /* receive FIFO threshold = 32 */ |
223 | 223 | ||
224 | /* | ||
225 | * Intel MID on-chip HSU (High Speed UART) defined bits | ||
226 | */ | ||
227 | #define UART_FCR_HSU_64_1B 0x00 /* receive FIFO treshold = 1 */ | ||
228 | #define UART_FCR_HSU_64_16B 0x40 /* receive FIFO treshold = 16 */ | ||
229 | #define UART_FCR_HSU_64_32B 0x80 /* receive FIFO treshold = 32 */ | ||
230 | #define UART_FCR_HSU_64_56B 0xc0 /* receive FIFO treshold = 56 */ | ||
231 | |||
232 | #define UART_FCR_HSU_16_1B 0x00 /* receive FIFO treshold = 1 */ | ||
233 | #define UART_FCR_HSU_16_4B 0x40 /* receive FIFO treshold = 4 */ | ||
234 | #define UART_FCR_HSU_16_8B 0x80 /* receive FIFO treshold = 8 */ | ||
235 | #define UART_FCR_HSU_16_14B 0xc0 /* receive FIFO treshold = 14 */ | ||
224 | 236 | ||
237 | #define UART_FCR_HSU_64B_FIFO 0x20 /* chose 64 bytes FIFO */ | ||
238 | #define UART_FCR_HSU_16B_FIFO 0x00 /* chose 16 bytes FIFO */ | ||
225 | 239 | ||
240 | #define UART_FCR_HALF_EMPT_TXI 0x00 /* trigger TX_EMPT IRQ for half empty */ | ||
241 | #define UART_FCR_FULL_EMPT_TXI 0x08 /* trigger TX_EMPT IRQ for full empty */ | ||
226 | 242 | ||
227 | /* | 243 | /* |
228 | * These register definitions are for the 16C950 | 244 | * These register definitions are for the 16C950 |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 7802a243ee13..1437da3ddc62 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/tty_driver.h> | 13 | #include <linux/tty_driver.h> |
14 | #include <linux/tty_ldisc.h> | 14 | #include <linux/tty_ldisc.h> |
15 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
16 | #include <linux/smp_lock.h> | ||
16 | 17 | ||
17 | #include <asm/system.h> | 18 | #include <asm/system.h> |
18 | 19 | ||
@@ -179,6 +180,7 @@ struct tty_bufhead { | |||
179 | #define L_FLUSHO(tty) _L_FLAG((tty), FLUSHO) | 180 | #define L_FLUSHO(tty) _L_FLAG((tty), FLUSHO) |
180 | #define L_PENDIN(tty) _L_FLAG((tty), PENDIN) | 181 | #define L_PENDIN(tty) _L_FLAG((tty), PENDIN) |
181 | #define L_IEXTEN(tty) _L_FLAG((tty), IEXTEN) | 182 | #define L_IEXTEN(tty) _L_FLAG((tty), IEXTEN) |
183 | #define L_EXTPROC(tty) _L_FLAG((tty), EXTPROC) | ||
182 | 184 | ||
183 | struct device; | 185 | struct device; |
184 | struct signal_struct; | 186 | struct signal_struct; |
@@ -415,6 +417,7 @@ extern int is_ignored(int sig); | |||
415 | extern int tty_signal(int sig, struct tty_struct *tty); | 417 | extern int tty_signal(int sig, struct tty_struct *tty); |
416 | extern void tty_hangup(struct tty_struct *tty); | 418 | extern void tty_hangup(struct tty_struct *tty); |
417 | extern void tty_vhangup(struct tty_struct *tty); | 419 | extern void tty_vhangup(struct tty_struct *tty); |
420 | extern void tty_vhangup_locked(struct tty_struct *tty); | ||
418 | extern void tty_vhangup_self(void); | 421 | extern void tty_vhangup_self(void); |
419 | extern void tty_unhangup(struct file *filp); | 422 | extern void tty_unhangup(struct file *filp); |
420 | extern int tty_hung_up_p(struct file *filp); | 423 | extern int tty_hung_up_p(struct file *filp); |
@@ -575,5 +578,54 @@ extern int vt_ioctl(struct tty_struct *tty, struct file *file, | |||
575 | extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file, | 578 | extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file, |
576 | unsigned int cmd, unsigned long arg); | 579 | unsigned int cmd, unsigned long arg); |
577 | 580 | ||
581 | /* tty_mutex.c */ | ||
582 | /* functions for preparation of BKL removal */ | ||
583 | extern void __lockfunc tty_lock(void) __acquires(tty_lock); | ||
584 | extern void __lockfunc tty_unlock(void) __releases(tty_lock); | ||
585 | extern struct task_struct *__big_tty_mutex_owner; | ||
586 | #define tty_locked() (current == __big_tty_mutex_owner) | ||
587 | |||
588 | /* | ||
589 | * wait_event_interruptible_tty -- wait for a condition with the tty lock held | ||
590 | * | ||
591 | * The condition we are waiting for might take a long time to | ||
592 | * become true, or might depend on another thread taking the | ||
593 | * BTM. In either case, we need to drop the BTM to guarantee | ||
594 | * forward progress. This is a leftover from the conversion | ||
595 | * from the BKL and should eventually get removed as the BTM | ||
596 | * falls out of use. | ||
597 | * | ||
598 | * Do not use in new code. | ||
599 | */ | ||
600 | #define wait_event_interruptible_tty(wq, condition) \ | ||
601 | ({ \ | ||
602 | int __ret = 0; \ | ||
603 | if (!(condition)) { \ | ||
604 | __wait_event_interruptible_tty(wq, condition, __ret); \ | ||
605 | } \ | ||
606 | __ret; \ | ||
607 | }) | ||
608 | |||
609 | #define __wait_event_interruptible_tty(wq, condition, ret) \ | ||
610 | do { \ | ||
611 | DEFINE_WAIT(__wait); \ | ||
612 | \ | ||
613 | for (;;) { \ | ||
614 | prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \ | ||
615 | if (condition) \ | ||
616 | break; \ | ||
617 | if (!signal_pending(current)) { \ | ||
618 | tty_unlock(); \ | ||
619 | schedule(); \ | ||
620 | tty_lock(); \ | ||
621 | continue; \ | ||
622 | } \ | ||
623 | ret = -ERESTARTSYS; \ | ||
624 | break; \ | ||
625 | } \ | ||
626 | finish_wait(&wq, &__wait); \ | ||
627 | } while (0) | ||
628 | |||
629 | |||
578 | #endif /* __KERNEL__ */ | 630 | #endif /* __KERNEL__ */ |
579 | #endif | 631 | #endif |
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 7f56db4a79f0..6625cc1ab758 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h | |||
@@ -76,17 +76,52 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc); | |||
76 | #define vc_translate(vc, c) ((vc)->vc_translate[(c) | \ | 76 | #define vc_translate(vc, c) ((vc)->vc_translate[(c) | \ |
77 | ((vc)->vc_toggle_meta ? 0x80 : 0)]) | 77 | ((vc)->vc_toggle_meta ? 0x80 : 0)]) |
78 | #else | 78 | #else |
79 | #define con_set_trans_old(arg) (0) | 79 | static inline int con_set_trans_old(unsigned char __user *table) |
80 | #define con_get_trans_old(arg) (-EINVAL) | 80 | { |
81 | #define con_set_trans_new(arg) (0) | 81 | return 0; |
82 | #define con_get_trans_new(arg) (-EINVAL) | 82 | } |
83 | #define con_clear_unimap(vc, ui) (0) | 83 | static inline int con_get_trans_old(unsigned char __user *table) |
84 | #define con_set_unimap(vc, ct, list) (0) | 84 | { |
85 | #define con_set_default_unimap(vc) (0) | 85 | return -EINVAL; |
86 | #define con_copy_unimap(d, s) (0) | 86 | } |
87 | #define con_get_unimap(vc, ct, uct, list) (-EINVAL) | 87 | static inline int con_set_trans_new(unsigned short __user *table) |
88 | #define con_free_unimap(vc) do { ; } while (0) | 88 | { |
89 | #define con_protect_unimap(vc, rdonly) do { ; } while (0) | 89 | return 0; |
90 | } | ||
91 | static inline int con_get_trans_new(unsigned short __user *table) | ||
92 | { | ||
93 | return -EINVAL; | ||
94 | } | ||
95 | static inline int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui) | ||
96 | { | ||
97 | return 0; | ||
98 | } | ||
99 | static inline | ||
100 | int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) | ||
101 | { | ||
102 | return 0; | ||
103 | } | ||
104 | static inline | ||
105 | int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, | ||
106 | struct unipair __user *list) | ||
107 | { | ||
108 | return -EINVAL; | ||
109 | } | ||
110 | static inline int con_set_default_unimap(struct vc_data *vc) | ||
111 | { | ||
112 | return 0; | ||
113 | } | ||
114 | static inline void con_free_unimap(struct vc_data *vc) | ||
115 | { | ||
116 | } | ||
117 | static inline void con_protect_unimap(struct vc_data *vc, int rdonly) | ||
118 | { | ||
119 | } | ||
120 | static inline | ||
121 | int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc) | ||
122 | { | ||
123 | return 0; | ||
124 | } | ||
90 | 125 | ||
91 | #define vc_translate(vc, c) (c) | 126 | #define vc_translate(vc, c) (c) |
92 | #endif | 127 | #endif |
@@ -100,6 +135,13 @@ extern int unbind_con_driver(const struct consw *csw, int first, int last, | |||
100 | int deflt); | 135 | int deflt); |
101 | int vty_init(const struct file_operations *console_fops); | 136 | int vty_init(const struct file_operations *console_fops); |
102 | 137 | ||
138 | static inline bool vt_force_oops_output(struct vc_data *vc) | ||
139 | { | ||
140 | if (oops_in_progress && vc->vc_panic_force_write) | ||
141 | return true; | ||
142 | return false; | ||
143 | } | ||
144 | |||
103 | /* | 145 | /* |
104 | * vc_screen.c shares this temporary buffer with the console write code so that | 146 | * vc_screen.c shares this temporary buffer with the console write code so that |
105 | * we can easily avoid touching user space while holding the console spinlock. | 147 | * we can easily avoid touching user space while holding the console spinlock. |