diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 18:34:40 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-11 18:34:40 -0500 |
commit | 0f4974c439dd7826c85bae4e6a8088ce2db0f498 (patch) | |
tree | fdabc7d9bb7d7bc49aad547c0aac3a633ce01f09 | |
parent | 3126c136bc30225d7a43af741778aa50e95e467a (diff) | |
parent | 36ba782e9674cdc29ec7003757df0b375e99fa96 (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: (58 commits)
tty: split the lock up a bit further
tty: Move the leader test in disassociate
tty: Push the bkl down a bit in the hangup code
tty: Push the lock down further into the ldisc code
tty: push the BKL down into the handlers a bit
tty: moxa: split open lock
tty: moxa: Kill the use of lock_kernel
tty: moxa: Fix modem op locking
tty: moxa: Kill off the throttle method
tty: moxa: Locking clean up
tty: moxa: rework the locking a bit
tty: moxa: Use more tty_port ops
tty: isicom: fix deadlock on shutdown
tty: mxser: Use the new locking rules to fix setserial properly
tty: mxser: use the tty_port_open method
tty: isicom: sort out the board init logic
tty: isicom: switch to the new tty_port_open helper
tty: tty_port: Add a kref object to the tty port
tty: istallion: tty port open/close methods
tty: stallion: Convert to the tty_port_open/close methods
...
36 files changed, 921 insertions, 3820 deletions
diff --git a/Documentation/serial/hayes-esp.txt b/Documentation/serial/hayes-esp.txt deleted file mode 100644 index 09b5d5856758..000000000000 --- a/Documentation/serial/hayes-esp.txt +++ /dev/null | |||
@@ -1,154 +0,0 @@ | |||
1 | HAYES ESP DRIVER VERSION 2.1 | ||
2 | |||
3 | A big thanks to the people at Hayes, especially Alan Adamson. Their support | ||
4 | has enabled me to provide enhancements to the driver. | ||
5 | |||
6 | Please report your experiences with this driver to me (arobinso@nyx.net). I | ||
7 | am looking for both positive and negative feedback. | ||
8 | |||
9 | *** IMPORTANT CHANGES FOR 2.1 *** | ||
10 | Support for PIO mode. Five situations will cause PIO mode to be used: | ||
11 | 1) A multiport card is detected. PIO mode will always be used. (8 port cards | ||
12 | do not support DMA). | ||
13 | 2) The DMA channel is set to an invalid value (anything other than 1 or 3). | ||
14 | 3) The DMA buffer/channel could not be allocated. The port will revert to PIO | ||
15 | mode until it is reopened. | ||
16 | 4) Less than a specified number of bytes need to be transferred to/from the | ||
17 | FIFOs. PIO mode will be used for that transfer only. | ||
18 | 5) A port needs to do a DMA transfer and another port is already using the | ||
19 | DMA channel. PIO mode will be used for that transfer only. | ||
20 | |||
21 | Since the Hayes ESP seems to conflict with other cards (notably sound cards) | ||
22 | when using DMA, DMA is turned off by default. To use DMA, it must be turned | ||
23 | on explicitly, either with the "dma=" option described below or with | ||
24 | setserial. A multiport card can be forced into DMA mode by using setserial; | ||
25 | however, most multiport cards don't support DMA. | ||
26 | |||
27 | The latest version of setserial allows the enhanced configuration of the ESP | ||
28 | card to be viewed and modified. | ||
29 | *** | ||
30 | |||
31 | This package contains the files needed to compile a module to support the Hayes | ||
32 | ESP card. The drivers are basically a modified version of the serial drivers. | ||
33 | |||
34 | Features: | ||
35 | |||
36 | - Uses the enhanced mode of the ESP card, allowing a wider range of | ||
37 | interrupts and features than compatibility mode | ||
38 | - Uses DMA and 16 bit PIO mode to transfer data to and from the ESP's FIFOs, | ||
39 | reducing CPU load | ||
40 | - Supports primary and secondary ports | ||
41 | |||
42 | |||
43 | If the driver is compiled as a module, the IRQs to use can be specified by | ||
44 | using the irq= option. The format is: | ||
45 | |||
46 | irq=[0x100],[0x140],[0x180],[0x200],[0x240],[0x280],[0x300],[0x380] | ||
47 | |||
48 | The address in brackets is the base address of the card. The IRQ of | ||
49 | nonexistent cards can be set to 0. If an IRQ of a card that does exist is set | ||
50 | to 0, the driver will attempt to guess at the correct IRQ. For example, to set | ||
51 | the IRQ of the card at address 0x300 to 12, the insmod command would be: | ||
52 | |||
53 | insmod esp irq=0,0,0,0,0,0,12,0 | ||
54 | |||
55 | The custom divisor can be set by using the divisor= option. The format is the | ||
56 | same as for the irq= option. Each divisor value is a series of hex digits, | ||
57 | with each digit representing the divisor to use for a corresponding port. The | ||
58 | divisor value is constructed RIGHT TO LEFT. Specifying a nonzero divisor value | ||
59 | will automatically set the spd_cust flag. To calculate the divisor to use for | ||
60 | a certain baud rate, divide the port's base baud (generally 921600) by the | ||
61 | desired rate. For example, to set the divisor of the primary port at 0x300 to | ||
62 | 4 and the divisor of the secondary port at 0x308 to 8, the insmod command would | ||
63 | be: | ||
64 | |||
65 | insmod esp divisor=0,0,0,0,0,0,0x84,0 | ||
66 | |||
67 | The dma= option can be used to set the DMA channel. The channel can be either | ||
68 | 1 or 3. Specifying any other value will force the driver to use PIO mode. | ||
69 | For example, to set the DMA channel to 3, the insmod command would be: | ||
70 | |||
71 | insmod esp dma=3 | ||
72 | |||
73 | The rx_trigger= and tx_trigger= options can be used to set the FIFO trigger | ||
74 | levels. They specify when the ESP card should send an interrupt. Larger | ||
75 | values will decrease the number of interrupts; however, a value too high may | ||
76 | result in data loss. Valid values are 1 through 1023, with 768 being the | ||
77 | default. For example, to set the receive trigger level to 512 bytes and the | ||
78 | transmit trigger level to 700 bytes, the insmod command would be: | ||
79 | |||
80 | insmod esp rx_trigger=512 tx_trigger=700 | ||
81 | |||
82 | The flow_off= and flow_on= options can be used to set the hardware flow off/ | ||
83 | flow on levels. The flow on level must be lower than the flow off level, and | ||
84 | the flow off level should be higher than rx_trigger. Valid values are 1 | ||
85 | through 1023, with 1016 being the default flow off level and 944 being the | ||
86 | default flow on level. For example, to set the flow off level to 1000 bytes | ||
87 | and the flow on level to 935 bytes, the insmod command would be: | ||
88 | |||
89 | insmod esp flow_off=1000 flow_on=935 | ||
90 | |||
91 | The rx_timeout= option can be used to set the receive timeout value. This | ||
92 | value indicates how long after receiving the last character that the ESP card | ||
93 | should wait before signalling an interrupt. Valid values are 0 though 255, | ||
94 | with 128 being the default. A value too high will increase latency, and a | ||
95 | value too low will cause unnecessary interrupts. For example, to set the | ||
96 | receive timeout to 255, the insmod command would be: | ||
97 | |||
98 | insmod esp rx_timeout=255 | ||
99 | |||
100 | The pio_threshold= option sets the threshold (in number of characters) for | ||
101 | using PIO mode instead of DMA mode. For example, if this value is 32, | ||
102 | transfers of 32 bytes or less will always use PIO mode. | ||
103 | |||
104 | insmod esp pio_threshold=32 | ||
105 | |||
106 | Multiple options can be listed on the insmod command line by separating each | ||
107 | option with a space. For example: | ||
108 | |||
109 | insmod esp dma=3 trigger=512 | ||
110 | |||
111 | The esp module can be automatically loaded when needed. To cause this to | ||
112 | happen, add the following lines to /etc/modprobe.conf (replacing the last line | ||
113 | with options for your configuration): | ||
114 | |||
115 | alias char-major-57 esp | ||
116 | alias char-major-58 esp | ||
117 | options esp irq=0,0,0,0,0,0,3,0 divisor=0,0,0,0,0,0,0x4,0 | ||
118 | |||
119 | You may also need to run 'depmod -a'. | ||
120 | |||
121 | Devices must be created manually. To create the devices, note the output from | ||
122 | the module after it is inserted. The output will appear in the location where | ||
123 | kernel messages usually appear (usually /var/adm/messages). Create two devices | ||
124 | for each 'tty' mentioned, one with major of 57 and the other with major of 58. | ||
125 | The minor number should be the same as the tty number reported. The commands | ||
126 | would be (replace ? with the tty number): | ||
127 | |||
128 | mknod /dev/ttyP? c 57 ? | ||
129 | mknod /dev/cup? c 58 ? | ||
130 | |||
131 | For example, if the following line appears: | ||
132 | |||
133 | Oct 24 18:17:23 techno kernel: ttyP8 at 0x0140 (irq = 3) is an ESP primary port | ||
134 | |||
135 | ...two devices should be created: | ||
136 | |||
137 | mknod /dev/ttyP8 c 57 8 | ||
138 | mknod /dev/cup8 c 58 8 | ||
139 | |||
140 | You may need to set the permissions on the devices: | ||
141 | |||
142 | chmod 666 /dev/ttyP* | ||
143 | chmod 666 /dev/cup* | ||
144 | |||
145 | The ESP module and the serial module should not conflict (they can be used at | ||
146 | the same time). After the ESP module has been loaded the ports on the ESP card | ||
147 | will no longer be accessible by the serial driver. | ||
148 | |||
149 | If I/O errors are experienced when accessing the port, check for IRQ and DMA | ||
150 | conflicts ('cat /proc/interrupts' and 'cat /proc/dma' for a list of IRQs and | ||
151 | DMAs currently in use). | ||
152 | |||
153 | Enjoy! | ||
154 | Andrew J. Robinson <arobinso@nyx.net> | ||
diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt index 8e65c4498c52..5e5349a4fcd2 100644 --- a/Documentation/serial/tty.txt +++ b/Documentation/serial/tty.txt | |||
@@ -42,7 +42,8 @@ TTY side interfaces: | |||
42 | open() - Called when the line discipline is attached to | 42 | open() - Called when the line discipline is attached to |
43 | the terminal. No other call into the line | 43 | the terminal. No other call into the line |
44 | discipline for this tty will occur until it | 44 | discipline for this tty will occur until it |
45 | completes successfully. Can sleep. | 45 | completes successfully. Returning an error will |
46 | prevent the ldisc from being attached. Can sleep. | ||
46 | 47 | ||
47 | close() - This is called on a terminal when the line | 48 | close() - This is called on a terminal when the line |
48 | discipline is being unplugged. At the point of | 49 | discipline is being unplugged. At the point of |
@@ -52,7 +53,7 @@ close() - This is called on a terminal when the line | |||
52 | hangup() - Called when the tty line is hung up. | 53 | hangup() - Called when the tty line is hung up. |
53 | The line discipline should cease I/O to the tty. | 54 | The line discipline should cease I/O to the tty. |
54 | No further calls into the ldisc code will occur. | 55 | No further calls into the ldisc code will occur. |
55 | Can sleep. | 56 | The return value is ignored. Can sleep. |
56 | 57 | ||
57 | write() - A process is writing data through the line | 58 | write() - A process is writing data through the line |
58 | discipline. Multiple write calls are serialized | 59 | discipline. Multiple write calls are serialized |
@@ -83,6 +84,10 @@ ioctl() - Called when an ioctl is handed to the tty layer | |||
83 | that might be for the ldisc. Multiple ioctl calls | 84 | that might be for the ldisc. Multiple ioctl calls |
84 | may occur in parallel. May sleep. | 85 | may occur in parallel. May sleep. |
85 | 86 | ||
87 | compat_ioctl() - Called when a 32 bit ioctl is handed to the tty layer | ||
88 | that might be for the ldisc. Multiple ioctl calls | ||
89 | may occur in parallel. May sleep. | ||
90 | |||
86 | Driver Side Interfaces: | 91 | Driver Side Interfaces: |
87 | 92 | ||
88 | receive_buf() - Hand buffers of bytes from the driver to the ldisc | 93 | receive_buf() - Hand buffers of bytes from the driver to the ldisc |
diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 4c559cf7da2d..e60a1f57022f 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c | |||
@@ -196,7 +196,7 @@ static const struct file_operations rs_proc_fops = { | |||
196 | .release = single_release, | 196 | .release = single_release, |
197 | }; | 197 | }; |
198 | 198 | ||
199 | static struct tty_operations serial_ops = { | 199 | static const struct tty_operations serial_ops = { |
200 | .open = rs_open, | 200 | .open = rs_open, |
201 | .close = rs_close, | 201 | .close = rs_close, |
202 | .write = rs_write, | 202 | .write = rs_write, |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 6aad99ec4e0f..6f31c9472100 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -201,19 +201,6 @@ config DIGIEPCA | |||
201 | To compile this driver as a module, choose M here: the | 201 | To compile this driver as a module, choose M here: the |
202 | module will be called epca. | 202 | module will be called epca. |
203 | 203 | ||
204 | config ESPSERIAL | ||
205 | tristate "Hayes ESP serial port support" | ||
206 | depends on SERIAL_NONSTANDARD && ISA && ISA_DMA_API && BROKEN | ||
207 | help | ||
208 | This is a driver which supports Hayes ESP serial ports. Both single | ||
209 | port cards and multiport cards are supported. Make sure to read | ||
210 | <file:Documentation/hayes-esp.txt>. | ||
211 | |||
212 | To compile this driver as a module, choose M here: the | ||
213 | module will be called esp. | ||
214 | |||
215 | If unsure, say N. | ||
216 | |||
217 | config MOXA_INTELLIO | 204 | config MOXA_INTELLIO |
218 | tristate "Moxa Intellio support" | 205 | tristate "Moxa Intellio support" |
219 | depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) | 206 | depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 19a79dd79eee..f957edf7e45d 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -18,7 +18,6 @@ obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o | |||
18 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o | 18 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o |
19 | obj-$(CONFIG_AUDIT) += tty_audit.o | 19 | obj-$(CONFIG_AUDIT) += tty_audit.o |
20 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o | 20 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o |
21 | obj-$(CONFIG_ESPSERIAL) += esp.o | ||
22 | obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o | 21 | obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o |
23 | obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o | 22 | obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o |
24 | obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o | 23 | obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o |
diff --git a/drivers/char/bfin_jtag_comm.c b/drivers/char/bfin_jtag_comm.c index 1d7c34c73b20..2628c7415ea8 100644 --- a/drivers/char/bfin_jtag_comm.c +++ b/drivers/char/bfin_jtag_comm.c | |||
@@ -226,7 +226,7 @@ bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout) | |||
226 | } | 226 | } |
227 | } | 227 | } |
228 | 228 | ||
229 | static struct tty_operations bfin_jc_ops = { | 229 | static const struct tty_operations bfin_jc_ops = { |
230 | .open = bfin_jc_open, | 230 | .open = bfin_jc_open, |
231 | .close = bfin_jc_close, | 231 | .close = bfin_jc_close, |
232 | .write = bfin_jc_write, | 232 | .write = bfin_jc_write, |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index dde5134713e2..17b044a71e02 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -935,7 +935,7 @@ static int info_open(struct tty_struct *tty, struct file *filp) | |||
935 | return 0; | 935 | return 0; |
936 | } | 936 | } |
937 | 937 | ||
938 | static struct tty_operations info_ops = { | 938 | static const struct tty_operations info_ops = { |
939 | .open = info_open, | 939 | .open = info_open, |
940 | .ioctl = info_ioctl, | 940 | .ioctl = info_ioctl, |
941 | }; | 941 | }; |
diff --git a/drivers/char/esp.c b/drivers/char/esp.c deleted file mode 100644 index b19d43cd9542..000000000000 --- a/drivers/char/esp.c +++ /dev/null | |||
@@ -1,2533 +0,0 @@ | |||
1 | /* | ||
2 | * esp.c - driver for Hayes ESP serial cards | ||
3 | * | ||
4 | * --- Notices from serial.c, upon which this driver is based --- | ||
5 | * | ||
6 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
7 | * | ||
8 | * Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92. Now | ||
9 | * much more extensible to support other serial cards based on the | ||
10 | * 16450/16550A UART's. Added support for the AST FourPort and the | ||
11 | * Accent Async board. | ||
12 | * | ||
13 | * set_serial_info fixed to set the flags, custom divisor, and uart | ||
14 | * type fields. Fix suggested by Michael K. Johnson 12/12/92. | ||
15 | * | ||
16 | * 11/95: TIOCMIWAIT, TIOCGICOUNT by Angelo Haritsis <ah@doc.ic.ac.uk> | ||
17 | * | ||
18 | * 03/96: Modularised by Angelo Haritsis <ah@doc.ic.ac.uk> | ||
19 | * | ||
20 | * rs_set_termios fixed to look also for changes of the input | ||
21 | * flags INPCK, BRKINT, PARMRK, IGNPAR and IGNBRK. | ||
22 | * Bernd Anhäupl 05/17/96. | ||
23 | * | ||
24 | * --- End of notices from serial.c --- | ||
25 | * | ||
26 | * Support for the ESP serial card by Andrew J. Robinson | ||
27 | * <arobinso@nyx.net> (Card detection routine taken from a patch | ||
28 | * by Dennis J. Boylan). Patches to allow use with 2.1.x contributed | ||
29 | * by Chris Faylor. | ||
30 | * | ||
31 | * Most recent changes: (Andrew J. Robinson) | ||
32 | * Support for PIO mode. This allows the driver to work properly with | ||
33 | * multiport cards. | ||
34 | * | ||
35 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - | ||
36 | * several cleanups, use module_init/module_exit, etc | ||
37 | * | ||
38 | * This module exports the following rs232 io functions: | ||
39 | * | ||
40 | * int espserial_init(void); | ||
41 | */ | ||
42 | |||
43 | #include <linux/module.h> | ||
44 | #include <linux/errno.h> | ||
45 | #include <linux/signal.h> | ||
46 | #include <linux/sched.h> | ||
47 | #include <linux/interrupt.h> | ||
48 | #include <linux/tty.h> | ||
49 | #include <linux/tty_flip.h> | ||
50 | #include <linux/serial.h> | ||
51 | #include <linux/serialP.h> | ||
52 | #include <linux/serial_reg.h> | ||
53 | #include <linux/major.h> | ||
54 | #include <linux/string.h> | ||
55 | #include <linux/fcntl.h> | ||
56 | #include <linux/ptrace.h> | ||
57 | #include <linux/ioport.h> | ||
58 | #include <linux/mm.h> | ||
59 | #include <linux/init.h> | ||
60 | #include <linux/delay.h> | ||
61 | #include <linux/bitops.h> | ||
62 | |||
63 | #include <asm/system.h> | ||
64 | #include <linux/io.h> | ||
65 | |||
66 | #include <asm/dma.h> | ||
67 | #include <linux/slab.h> | ||
68 | #include <linux/uaccess.h> | ||
69 | |||
70 | #include <linux/hayesesp.h> | ||
71 | |||
72 | #define NR_PORTS 64 /* maximum number of ports */ | ||
73 | #define NR_PRIMARY 8 /* maximum number of primary ports */ | ||
74 | #define REGION_SIZE 8 /* size of io region to request */ | ||
75 | |||
76 | /* The following variables can be set by giving module options */ | ||
77 | static int irq[NR_PRIMARY]; /* IRQ for each base port */ | ||
78 | static unsigned int divisor[NR_PRIMARY]; /* custom divisor for each port */ | ||
79 | static unsigned int dma = ESP_DMA_CHANNEL; /* DMA channel */ | ||
80 | static unsigned int rx_trigger = ESP_RX_TRIGGER; | ||
81 | static unsigned int tx_trigger = ESP_TX_TRIGGER; | ||
82 | static unsigned int flow_off = ESP_FLOW_OFF; | ||
83 | static unsigned int flow_on = ESP_FLOW_ON; | ||
84 | static unsigned int rx_timeout = ESP_RX_TMOUT; | ||
85 | static unsigned int pio_threshold = ESP_PIO_THRESHOLD; | ||
86 | |||
87 | MODULE_LICENSE("GPL"); | ||
88 | |||
89 | module_param_array(irq, int, NULL, 0); | ||
90 | module_param_array(divisor, uint, NULL, 0); | ||
91 | module_param(dma, uint, 0); | ||
92 | module_param(rx_trigger, uint, 0); | ||
93 | module_param(tx_trigger, uint, 0); | ||
94 | module_param(flow_off, uint, 0); | ||
95 | module_param(flow_on, uint, 0); | ||
96 | module_param(rx_timeout, uint, 0); | ||
97 | module_param(pio_threshold, uint, 0); | ||
98 | |||
99 | /* END */ | ||
100 | |||
101 | static char *dma_buffer; | ||
102 | static int dma_bytes; | ||
103 | static struct esp_pio_buffer *free_pio_buf; | ||
104 | |||
105 | #define DMA_BUFFER_SZ 1024 | ||
106 | |||
107 | #define WAKEUP_CHARS 1024 | ||
108 | |||
109 | static char serial_name[] __initdata = "ESP serial driver"; | ||
110 | static char serial_version[] __initdata = "2.2"; | ||
111 | |||
112 | static struct tty_driver *esp_driver; | ||
113 | |||
114 | /* | ||
115 | * Serial driver configuration section. Here are the various options: | ||
116 | * | ||
117 | * SERIAL_PARANOIA_CHECK | ||
118 | * Check the magic number for the esp_structure where | ||
119 | * ever possible. | ||
120 | */ | ||
121 | |||
122 | #undef SERIAL_PARANOIA_CHECK | ||
123 | #define SERIAL_DO_RESTART | ||
124 | |||
125 | #undef SERIAL_DEBUG_INTR | ||
126 | #undef SERIAL_DEBUG_OPEN | ||
127 | #undef SERIAL_DEBUG_FLOW | ||
128 | |||
129 | #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) | ||
130 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \ | ||
131 | tty->name, info->port.flags, \ | ||
132 | serial_driver.refcount, \ | ||
133 | info->port.count, tty->count, s) | ||
134 | #else | ||
135 | #define DBG_CNT(s) | ||
136 | #endif | ||
137 | |||
138 | static struct esp_struct *ports; | ||
139 | |||
140 | static void change_speed(struct esp_struct *info); | ||
141 | static void rs_wait_until_sent(struct tty_struct *, int); | ||
142 | |||
143 | /* | ||
144 | * The ESP card has a clock rate of 14.7456 MHz (that is, 2**ESPC_SCALE | ||
145 | * times the normal 1.8432 Mhz clock of most serial boards). | ||
146 | */ | ||
147 | #define BASE_BAUD ((1843200 / 16) * (1 << ESPC_SCALE)) | ||
148 | |||
149 | /* Standard COM flags (except for COM4, because of the 8514 problem) */ | ||
150 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) | ||
151 | |||
152 | static inline int serial_paranoia_check(struct esp_struct *info, | ||
153 | char *name, const char *routine) | ||
154 | { | ||
155 | #ifdef SERIAL_PARANOIA_CHECK | ||
156 | static const char badmagic[] = KERN_WARNING | ||
157 | "Warning: bad magic number for serial struct (%s) in %s\n"; | ||
158 | static const char badinfo[] = KERN_WARNING | ||
159 | "Warning: null esp_struct for (%s) in %s\n"; | ||
160 | |||
161 | if (!info) { | ||
162 | printk(badinfo, name, routine); | ||
163 | return 1; | ||
164 | } | ||
165 | if (info->magic != ESP_MAGIC) { | ||
166 | printk(badmagic, name, routine); | ||
167 | return 1; | ||
168 | } | ||
169 | #endif | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static inline unsigned int serial_in(struct esp_struct *info, int offset) | ||
174 | { | ||
175 | return inb(info->io_port + offset); | ||
176 | } | ||
177 | |||
178 | static inline void serial_out(struct esp_struct *info, int offset, | ||
179 | unsigned char value) | ||
180 | { | ||
181 | outb(value, info->io_port+offset); | ||
182 | } | ||
183 | |||
184 | /* | ||
185 | * ------------------------------------------------------------ | ||
186 | * rs_stop() and rs_start() | ||
187 | * | ||
188 | * This routines are called before setting or resetting tty->stopped. | ||
189 | * They enable or disable transmitter interrupts, as necessary. | ||
190 | * ------------------------------------------------------------ | ||
191 | */ | ||
192 | static void rs_stop(struct tty_struct *tty) | ||
193 | { | ||
194 | struct esp_struct *info = tty->driver_data; | ||
195 | unsigned long flags; | ||
196 | |||
197 | if (serial_paranoia_check(info, tty->name, "rs_stop")) | ||
198 | return; | ||
199 | |||
200 | spin_lock_irqsave(&info->lock, flags); | ||
201 | if (info->IER & UART_IER_THRI) { | ||
202 | info->IER &= ~UART_IER_THRI; | ||
203 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
204 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
205 | } | ||
206 | spin_unlock_irqrestore(&info->lock, flags); | ||
207 | } | ||
208 | |||
209 | static void rs_start(struct tty_struct *tty) | ||
210 | { | ||
211 | struct esp_struct *info = tty->driver_data; | ||
212 | unsigned long flags; | ||
213 | |||
214 | if (serial_paranoia_check(info, tty->name, "rs_start")) | ||
215 | return; | ||
216 | |||
217 | spin_lock_irqsave(&info->lock, flags); | ||
218 | if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) { | ||
219 | info->IER |= UART_IER_THRI; | ||
220 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
221 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
222 | } | ||
223 | spin_unlock_irqrestore(&info->lock, flags); | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * ---------------------------------------------------------------------- | ||
228 | * | ||
229 | * Here starts the interrupt handling routines. All of the following | ||
230 | * subroutines are declared as inline and are folded into | ||
231 | * rs_interrupt(). They were separated out for readability's sake. | ||
232 | * | ||
233 | * Note: rs_interrupt() is a "fast" interrupt, which means that it | ||
234 | * runs with interrupts turned off. People who may want to modify | ||
235 | * rs_interrupt() should try to keep the interrupt handler as fast as | ||
236 | * possible. After you are done making modifications, it is not a bad | ||
237 | * idea to do: | ||
238 | * | ||
239 | * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c | ||
240 | * | ||
241 | * and look at the resulting assemble code in serial.s. | ||
242 | * | ||
243 | * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 | ||
244 | * ----------------------------------------------------------------------- | ||
245 | */ | ||
246 | |||
247 | static DEFINE_SPINLOCK(pio_lock); | ||
248 | |||
249 | static inline struct esp_pio_buffer *get_pio_buffer(void) | ||
250 | { | ||
251 | struct esp_pio_buffer *buf; | ||
252 | unsigned long flags; | ||
253 | |||
254 | spin_lock_irqsave(&pio_lock, flags); | ||
255 | if (free_pio_buf) { | ||
256 | buf = free_pio_buf; | ||
257 | free_pio_buf = buf->next; | ||
258 | } else { | ||
259 | buf = kmalloc(sizeof(struct esp_pio_buffer), GFP_ATOMIC); | ||
260 | } | ||
261 | spin_unlock_irqrestore(&pio_lock, flags); | ||
262 | return buf; | ||
263 | } | ||
264 | |||
265 | static inline void release_pio_buffer(struct esp_pio_buffer *buf) | ||
266 | { | ||
267 | unsigned long flags; | ||
268 | spin_lock_irqsave(&pio_lock, flags); | ||
269 | buf->next = free_pio_buf; | ||
270 | free_pio_buf = buf; | ||
271 | spin_unlock_irqrestore(&pio_lock, flags); | ||
272 | } | ||
273 | |||
274 | static inline void receive_chars_pio(struct esp_struct *info, int num_bytes) | ||
275 | { | ||
276 | struct tty_struct *tty = info->port.tty; | ||
277 | int i; | ||
278 | struct esp_pio_buffer *pio_buf; | ||
279 | struct esp_pio_buffer *err_buf; | ||
280 | unsigned char status_mask; | ||
281 | |||
282 | pio_buf = get_pio_buffer(); | ||
283 | |||
284 | if (!pio_buf) | ||
285 | return; | ||
286 | |||
287 | err_buf = get_pio_buffer(); | ||
288 | |||
289 | if (!err_buf) { | ||
290 | release_pio_buffer(pio_buf); | ||
291 | return; | ||
292 | } | ||
293 | |||
294 | status_mask = (info->read_status_mask >> 2) & 0x07; | ||
295 | |||
296 | for (i = 0; i < num_bytes - 1; i += 2) { | ||
297 | *((unsigned short *)(pio_buf->data + i)) = | ||
298 | inw(info->io_port + UART_ESI_RX); | ||
299 | err_buf->data[i] = serial_in(info, UART_ESI_RWS); | ||
300 | err_buf->data[i + 1] = (err_buf->data[i] >> 3) & status_mask; | ||
301 | err_buf->data[i] &= status_mask; | ||
302 | } | ||
303 | |||
304 | if (num_bytes & 0x0001) { | ||
305 | pio_buf->data[num_bytes - 1] = serial_in(info, UART_ESI_RX); | ||
306 | err_buf->data[num_bytes - 1] = | ||
307 | (serial_in(info, UART_ESI_RWS) >> 3) & status_mask; | ||
308 | } | ||
309 | |||
310 | /* make sure everything is still ok since interrupts were enabled */ | ||
311 | tty = info->port.tty; | ||
312 | |||
313 | if (!tty) { | ||
314 | release_pio_buffer(pio_buf); | ||
315 | release_pio_buffer(err_buf); | ||
316 | info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; | ||
317 | return; | ||
318 | } | ||
319 | |||
320 | status_mask = (info->ignore_status_mask >> 2) & 0x07; | ||
321 | |||
322 | for (i = 0; i < num_bytes; i++) { | ||
323 | if (!(err_buf->data[i] & status_mask)) { | ||
324 | int flag = 0; | ||
325 | |||
326 | if (err_buf->data[i] & 0x04) { | ||
327 | flag = TTY_BREAK; | ||
328 | if (info->port.flags & ASYNC_SAK) | ||
329 | do_SAK(tty); | ||
330 | } else if (err_buf->data[i] & 0x02) | ||
331 | flag = TTY_FRAME; | ||
332 | else if (err_buf->data[i] & 0x01) | ||
333 | flag = TTY_PARITY; | ||
334 | tty_insert_flip_char(tty, pio_buf->data[i], flag); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | tty_schedule_flip(tty); | ||
339 | |||
340 | info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; | ||
341 | release_pio_buffer(pio_buf); | ||
342 | release_pio_buffer(err_buf); | ||
343 | } | ||
344 | |||
345 | static void program_isa_dma(int dma, int dir, unsigned long addr, int len) | ||
346 | { | ||
347 | unsigned long flags; | ||
348 | |||
349 | flags = claim_dma_lock(); | ||
350 | disable_dma(dma); | ||
351 | clear_dma_ff(dma); | ||
352 | set_dma_mode(dma, dir); | ||
353 | set_dma_addr(dma, addr); | ||
354 | set_dma_count(dma, len); | ||
355 | enable_dma(dma); | ||
356 | release_dma_lock(flags); | ||
357 | } | ||
358 | |||
359 | static void receive_chars_dma(struct esp_struct *info, int num_bytes) | ||
360 | { | ||
361 | info->stat_flags &= ~ESP_STAT_RX_TIMEOUT; | ||
362 | dma_bytes = num_bytes; | ||
363 | info->stat_flags |= ESP_STAT_DMA_RX; | ||
364 | |||
365 | program_isa_dma(dma, DMA_MODE_READ, isa_virt_to_bus(dma_buffer), | ||
366 | dma_bytes); | ||
367 | serial_out(info, UART_ESI_CMD1, ESI_START_DMA_RX); | ||
368 | } | ||
369 | |||
370 | static inline void receive_chars_dma_done(struct esp_struct *info, | ||
371 | int status) | ||
372 | { | ||
373 | struct tty_struct *tty = info->port.tty; | ||
374 | int num_bytes; | ||
375 | unsigned long flags; | ||
376 | |||
377 | flags = claim_dma_lock(); | ||
378 | disable_dma(dma); | ||
379 | clear_dma_ff(dma); | ||
380 | |||
381 | info->stat_flags &= ~ESP_STAT_DMA_RX; | ||
382 | num_bytes = dma_bytes - get_dma_residue(dma); | ||
383 | release_dma_lock(flags); | ||
384 | |||
385 | info->icount.rx += num_bytes; | ||
386 | |||
387 | if (num_bytes > 0) { | ||
388 | tty_insert_flip_string(tty, dma_buffer, num_bytes - 1); | ||
389 | |||
390 | status &= (0x1c & info->read_status_mask); | ||
391 | |||
392 | /* Is the status significant or do we throw the last byte ? */ | ||
393 | if (!(status & info->ignore_status_mask)) { | ||
394 | int statflag = 0; | ||
395 | |||
396 | if (status & 0x10) { | ||
397 | statflag = TTY_BREAK; | ||
398 | (info->icount.brk)++; | ||
399 | if (info->port.flags & ASYNC_SAK) | ||
400 | do_SAK(tty); | ||
401 | } else if (status & 0x08) { | ||
402 | statflag = TTY_FRAME; | ||
403 | info->icount.frame++; | ||
404 | } else if (status & 0x04) { | ||
405 | statflag = TTY_PARITY; | ||
406 | info->icount.parity++; | ||
407 | } | ||
408 | tty_insert_flip_char(tty, dma_buffer[num_bytes - 1], | ||
409 | statflag); | ||
410 | } | ||
411 | tty_schedule_flip(tty); | ||
412 | } | ||
413 | |||
414 | if (dma_bytes != num_bytes) { | ||
415 | num_bytes = dma_bytes - num_bytes; | ||
416 | dma_bytes = 0; | ||
417 | receive_chars_dma(info, num_bytes); | ||
418 | } else | ||
419 | dma_bytes = 0; | ||
420 | } | ||
421 | |||
422 | /* Caller must hold info->lock */ | ||
423 | |||
424 | static inline void transmit_chars_pio(struct esp_struct *info, | ||
425 | int space_avail) | ||
426 | { | ||
427 | int i; | ||
428 | struct esp_pio_buffer *pio_buf; | ||
429 | |||
430 | pio_buf = get_pio_buffer(); | ||
431 | |||
432 | if (!pio_buf) | ||
433 | return; | ||
434 | |||
435 | while (space_avail && info->xmit_cnt) { | ||
436 | if (info->xmit_tail + space_avail <= ESP_XMIT_SIZE) { | ||
437 | memcpy(pio_buf->data, | ||
438 | &(info->xmit_buf[info->xmit_tail]), | ||
439 | space_avail); | ||
440 | } else { | ||
441 | i = ESP_XMIT_SIZE - info->xmit_tail; | ||
442 | memcpy(pio_buf->data, | ||
443 | &(info->xmit_buf[info->xmit_tail]), i); | ||
444 | memcpy(&(pio_buf->data[i]), info->xmit_buf, | ||
445 | space_avail - i); | ||
446 | } | ||
447 | |||
448 | info->xmit_cnt -= space_avail; | ||
449 | info->xmit_tail = (info->xmit_tail + space_avail) & | ||
450 | (ESP_XMIT_SIZE - 1); | ||
451 | |||
452 | for (i = 0; i < space_avail - 1; i += 2) { | ||
453 | outw(*((unsigned short *)(pio_buf->data + i)), | ||
454 | info->io_port + UART_ESI_TX); | ||
455 | } | ||
456 | |||
457 | if (space_avail & 0x0001) | ||
458 | serial_out(info, UART_ESI_TX, | ||
459 | pio_buf->data[space_avail - 1]); | ||
460 | |||
461 | if (info->xmit_cnt) { | ||
462 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
463 | serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); | ||
464 | space_avail = serial_in(info, UART_ESI_STAT1) << 8; | ||
465 | space_avail |= serial_in(info, UART_ESI_STAT2); | ||
466 | |||
467 | if (space_avail > info->xmit_cnt) | ||
468 | space_avail = info->xmit_cnt; | ||
469 | } | ||
470 | } | ||
471 | |||
472 | if (info->xmit_cnt < WAKEUP_CHARS) { | ||
473 | if (info->port.tty) | ||
474 | tty_wakeup(info->port.tty); | ||
475 | |||
476 | #ifdef SERIAL_DEBUG_INTR | ||
477 | printk("THRE..."); | ||
478 | #endif | ||
479 | |||
480 | if (info->xmit_cnt <= 0) { | ||
481 | info->IER &= ~UART_IER_THRI; | ||
482 | serial_out(info, UART_ESI_CMD1, | ||
483 | ESI_SET_SRV_MASK); | ||
484 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
485 | } | ||
486 | } | ||
487 | |||
488 | release_pio_buffer(pio_buf); | ||
489 | } | ||
490 | |||
491 | /* Caller must hold info->lock */ | ||
492 | static inline void transmit_chars_dma(struct esp_struct *info, int num_bytes) | ||
493 | { | ||
494 | dma_bytes = num_bytes; | ||
495 | |||
496 | if (info->xmit_tail + dma_bytes <= ESP_XMIT_SIZE) { | ||
497 | memcpy(dma_buffer, &(info->xmit_buf[info->xmit_tail]), | ||
498 | dma_bytes); | ||
499 | } else { | ||
500 | int i = ESP_XMIT_SIZE - info->xmit_tail; | ||
501 | memcpy(dma_buffer, &(info->xmit_buf[info->xmit_tail]), | ||
502 | i); | ||
503 | memcpy(&(dma_buffer[i]), info->xmit_buf, dma_bytes - i); | ||
504 | } | ||
505 | |||
506 | info->xmit_cnt -= dma_bytes; | ||
507 | info->xmit_tail = (info->xmit_tail + dma_bytes) & (ESP_XMIT_SIZE - 1); | ||
508 | |||
509 | if (info->xmit_cnt < WAKEUP_CHARS) { | ||
510 | if (info->port.tty) | ||
511 | tty_wakeup(info->port.tty); | ||
512 | |||
513 | #ifdef SERIAL_DEBUG_INTR | ||
514 | printk("THRE..."); | ||
515 | #endif | ||
516 | |||
517 | if (info->xmit_cnt <= 0) { | ||
518 | info->IER &= ~UART_IER_THRI; | ||
519 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
520 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | info->stat_flags |= ESP_STAT_DMA_TX; | ||
525 | |||
526 | program_isa_dma(dma, DMA_MODE_WRITE, isa_virt_to_bus(dma_buffer), | ||
527 | dma_bytes); | ||
528 | serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX); | ||
529 | } | ||
530 | |||
531 | static inline void transmit_chars_dma_done(struct esp_struct *info) | ||
532 | { | ||
533 | int num_bytes; | ||
534 | unsigned long flags; | ||
535 | |||
536 | flags = claim_dma_lock(); | ||
537 | disable_dma(dma); | ||
538 | clear_dma_ff(dma); | ||
539 | |||
540 | num_bytes = dma_bytes - get_dma_residue(dma); | ||
541 | info->icount.tx += dma_bytes; | ||
542 | release_dma_lock(flags); | ||
543 | |||
544 | if (dma_bytes != num_bytes) { | ||
545 | dma_bytes -= num_bytes; | ||
546 | memmove(dma_buffer, dma_buffer + num_bytes, dma_bytes); | ||
547 | |||
548 | program_isa_dma(dma, DMA_MODE_WRITE, | ||
549 | isa_virt_to_bus(dma_buffer), dma_bytes); | ||
550 | |||
551 | serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX); | ||
552 | } else { | ||
553 | dma_bytes = 0; | ||
554 | info->stat_flags &= ~ESP_STAT_DMA_TX; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | static void check_modem_status(struct esp_struct *info) | ||
559 | { | ||
560 | int status; | ||
561 | |||
562 | serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); | ||
563 | status = serial_in(info, UART_ESI_STAT2); | ||
564 | |||
565 | if (status & UART_MSR_ANY_DELTA) { | ||
566 | /* update input line counters */ | ||
567 | if (status & UART_MSR_TERI) | ||
568 | info->icount.rng++; | ||
569 | if (status & UART_MSR_DDSR) | ||
570 | info->icount.dsr++; | ||
571 | if (status & UART_MSR_DDCD) | ||
572 | info->icount.dcd++; | ||
573 | if (status & UART_MSR_DCTS) | ||
574 | info->icount.cts++; | ||
575 | wake_up_interruptible(&info->port.delta_msr_wait); | ||
576 | } | ||
577 | |||
578 | if ((info->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { | ||
579 | #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) | ||
580 | printk("ttys%d CD now %s...", info->line, | ||
581 | (status & UART_MSR_DCD) ? "on" : "off"); | ||
582 | #endif | ||
583 | if (status & UART_MSR_DCD) | ||
584 | wake_up_interruptible(&info->port.open_wait); | ||
585 | else { | ||
586 | #ifdef SERIAL_DEBUG_OPEN | ||
587 | printk("scheduling hangup..."); | ||
588 | #endif | ||
589 | tty_hangup(info->port.tty); | ||
590 | } | ||
591 | } | ||
592 | } | ||
593 | |||
594 | /* | ||
595 | * This is the serial driver's interrupt routine | ||
596 | */ | ||
597 | static irqreturn_t rs_interrupt_single(int irq, void *dev_id) | ||
598 | { | ||
599 | struct esp_struct *info; | ||
600 | unsigned err_status; | ||
601 | unsigned int scratch; | ||
602 | |||
603 | #ifdef SERIAL_DEBUG_INTR | ||
604 | printk("rs_interrupt_single(%d)...", irq); | ||
605 | #endif | ||
606 | info = (struct esp_struct *)dev_id; | ||
607 | err_status = 0; | ||
608 | scratch = serial_in(info, UART_ESI_SID); | ||
609 | |||
610 | spin_lock(&info->lock); | ||
611 | |||
612 | if (!info->port.tty) { | ||
613 | spin_unlock(&info->lock); | ||
614 | return IRQ_NONE; | ||
615 | } | ||
616 | |||
617 | if (scratch & 0x04) { /* error */ | ||
618 | serial_out(info, UART_ESI_CMD1, ESI_GET_ERR_STAT); | ||
619 | err_status = serial_in(info, UART_ESI_STAT1); | ||
620 | serial_in(info, UART_ESI_STAT2); | ||
621 | |||
622 | if (err_status & 0x01) | ||
623 | info->stat_flags |= ESP_STAT_RX_TIMEOUT; | ||
624 | |||
625 | if (err_status & 0x20) /* UART status */ | ||
626 | check_modem_status(info); | ||
627 | |||
628 | if (err_status & 0x80) /* Start break */ | ||
629 | wake_up_interruptible(&info->break_wait); | ||
630 | } | ||
631 | |||
632 | if ((scratch & 0x88) || /* DMA completed or timed out */ | ||
633 | (err_status & 0x1c) /* receive error */) { | ||
634 | if (info->stat_flags & ESP_STAT_DMA_RX) | ||
635 | receive_chars_dma_done(info, err_status); | ||
636 | else if (info->stat_flags & ESP_STAT_DMA_TX) | ||
637 | transmit_chars_dma_done(info); | ||
638 | } | ||
639 | |||
640 | if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) && | ||
641 | ((scratch & 0x01) || (info->stat_flags & ESP_STAT_RX_TIMEOUT)) && | ||
642 | (info->IER & UART_IER_RDI)) { | ||
643 | int num_bytes; | ||
644 | |||
645 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
646 | serial_out(info, UART_ESI_CMD1, ESI_GET_RX_AVAIL); | ||
647 | num_bytes = serial_in(info, UART_ESI_STAT1) << 8; | ||
648 | num_bytes |= serial_in(info, UART_ESI_STAT2); | ||
649 | |||
650 | num_bytes = tty_buffer_request_room(info->port.tty, num_bytes); | ||
651 | |||
652 | if (num_bytes) { | ||
653 | if (dma_bytes || | ||
654 | (info->stat_flags & ESP_STAT_USE_PIO) || | ||
655 | (num_bytes <= info->config.pio_threshold)) | ||
656 | receive_chars_pio(info, num_bytes); | ||
657 | else | ||
658 | receive_chars_dma(info, num_bytes); | ||
659 | } | ||
660 | } | ||
661 | |||
662 | if (!(info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) && | ||
663 | (scratch & 0x02) && (info->IER & UART_IER_THRI)) { | ||
664 | if ((info->xmit_cnt <= 0) || info->port.tty->stopped) { | ||
665 | info->IER &= ~UART_IER_THRI; | ||
666 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
667 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
668 | } else { | ||
669 | int num_bytes; | ||
670 | |||
671 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
672 | serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); | ||
673 | num_bytes = serial_in(info, UART_ESI_STAT1) << 8; | ||
674 | num_bytes |= serial_in(info, UART_ESI_STAT2); | ||
675 | |||
676 | if (num_bytes > info->xmit_cnt) | ||
677 | num_bytes = info->xmit_cnt; | ||
678 | |||
679 | if (num_bytes) { | ||
680 | if (dma_bytes || | ||
681 | (info->stat_flags & ESP_STAT_USE_PIO) || | ||
682 | (num_bytes <= info->config.pio_threshold)) | ||
683 | transmit_chars_pio(info, num_bytes); | ||
684 | else | ||
685 | transmit_chars_dma(info, num_bytes); | ||
686 | } | ||
687 | } | ||
688 | } | ||
689 | |||
690 | info->last_active = jiffies; | ||
691 | |||
692 | #ifdef SERIAL_DEBUG_INTR | ||
693 | printk("end.\n"); | ||
694 | #endif | ||
695 | spin_unlock(&info->lock); | ||
696 | return IRQ_HANDLED; | ||
697 | } | ||
698 | |||
699 | /* | ||
700 | * ------------------------------------------------------------------- | ||
701 | * Here ends the serial interrupt routines. | ||
702 | * ------------------------------------------------------------------- | ||
703 | */ | ||
704 | |||
705 | /* | ||
706 | * --------------------------------------------------------------- | ||
707 | * Low level utility subroutines for the serial driver: routines to | ||
708 | * figure out the appropriate timeout for an interrupt chain, routines | ||
709 | * to initialize and startup a serial port, and routines to shutdown a | ||
710 | * serial port. Useful stuff like that. | ||
711 | * | ||
712 | * Caller should hold lock | ||
713 | * --------------------------------------------------------------- | ||
714 | */ | ||
715 | |||
716 | static void esp_basic_init(struct esp_struct *info) | ||
717 | { | ||
718 | /* put ESPC in enhanced mode */ | ||
719 | serial_out(info, UART_ESI_CMD1, ESI_SET_MODE); | ||
720 | |||
721 | if (info->stat_flags & ESP_STAT_NEVER_DMA) | ||
722 | serial_out(info, UART_ESI_CMD2, 0x01); | ||
723 | else | ||
724 | serial_out(info, UART_ESI_CMD2, 0x31); | ||
725 | |||
726 | /* disable interrupts for now */ | ||
727 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
728 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
729 | |||
730 | /* set interrupt and DMA channel */ | ||
731 | serial_out(info, UART_ESI_CMD1, ESI_SET_IRQ); | ||
732 | |||
733 | if (info->stat_flags & ESP_STAT_NEVER_DMA) | ||
734 | serial_out(info, UART_ESI_CMD2, 0x01); | ||
735 | else | ||
736 | serial_out(info, UART_ESI_CMD2, (dma << 4) | 0x01); | ||
737 | |||
738 | serial_out(info, UART_ESI_CMD1, ESI_SET_ENH_IRQ); | ||
739 | |||
740 | if (info->line % 8) /* secondary port */ | ||
741 | serial_out(info, UART_ESI_CMD2, 0x0d); /* shared */ | ||
742 | else if (info->irq == 9) | ||
743 | serial_out(info, UART_ESI_CMD2, 0x02); | ||
744 | else | ||
745 | serial_out(info, UART_ESI_CMD2, info->irq); | ||
746 | |||
747 | /* set error status mask (check this) */ | ||
748 | serial_out(info, UART_ESI_CMD1, ESI_SET_ERR_MASK); | ||
749 | |||
750 | if (info->stat_flags & ESP_STAT_NEVER_DMA) | ||
751 | serial_out(info, UART_ESI_CMD2, 0xa1); | ||
752 | else | ||
753 | serial_out(info, UART_ESI_CMD2, 0xbd); | ||
754 | |||
755 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
756 | |||
757 | /* set DMA timeout */ | ||
758 | serial_out(info, UART_ESI_CMD1, ESI_SET_DMA_TMOUT); | ||
759 | serial_out(info, UART_ESI_CMD2, 0xff); | ||
760 | |||
761 | /* set FIFO trigger levels */ | ||
762 | serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER); | ||
763 | serial_out(info, UART_ESI_CMD2, info->config.rx_trigger >> 8); | ||
764 | serial_out(info, UART_ESI_CMD2, info->config.rx_trigger); | ||
765 | serial_out(info, UART_ESI_CMD2, info->config.tx_trigger >> 8); | ||
766 | serial_out(info, UART_ESI_CMD2, info->config.tx_trigger); | ||
767 | |||
768 | /* Set clock scaling and wait states */ | ||
769 | serial_out(info, UART_ESI_CMD1, ESI_SET_PRESCALAR); | ||
770 | serial_out(info, UART_ESI_CMD2, 0x04 | ESPC_SCALE); | ||
771 | |||
772 | /* set reinterrupt pacing */ | ||
773 | serial_out(info, UART_ESI_CMD1, ESI_SET_REINTR); | ||
774 | serial_out(info, UART_ESI_CMD2, 0xff); | ||
775 | } | ||
776 | |||
777 | static int startup(struct esp_struct *info) | ||
778 | { | ||
779 | unsigned long flags; | ||
780 | int retval = 0; | ||
781 | unsigned int num_chars; | ||
782 | |||
783 | spin_lock_irqsave(&info->lock, flags); | ||
784 | |||
785 | if (info->port.flags & ASYNC_INITIALIZED) | ||
786 | goto out; | ||
787 | |||
788 | if (!info->xmit_buf) { | ||
789 | info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_ATOMIC); | ||
790 | retval = -ENOMEM; | ||
791 | if (!info->xmit_buf) | ||
792 | goto out; | ||
793 | } | ||
794 | |||
795 | #ifdef SERIAL_DEBUG_OPEN | ||
796 | printk(KERN_DEBUG "starting up ttys%d (irq %d)...", | ||
797 | info->line, info->irq); | ||
798 | #endif | ||
799 | |||
800 | /* Flush the RX buffer. Using the ESI flush command may cause */ | ||
801 | /* wild interrupts, so read all the data instead. */ | ||
802 | |||
803 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
804 | serial_out(info, UART_ESI_CMD1, ESI_GET_RX_AVAIL); | ||
805 | num_chars = serial_in(info, UART_ESI_STAT1) << 8; | ||
806 | num_chars |= serial_in(info, UART_ESI_STAT2); | ||
807 | |||
808 | while (num_chars > 1) { | ||
809 | inw(info->io_port + UART_ESI_RX); | ||
810 | num_chars -= 2; | ||
811 | } | ||
812 | |||
813 | if (num_chars) | ||
814 | serial_in(info, UART_ESI_RX); | ||
815 | |||
816 | /* set receive character timeout */ | ||
817 | serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); | ||
818 | serial_out(info, UART_ESI_CMD2, info->config.rx_timeout); | ||
819 | |||
820 | /* clear all flags except the "never DMA" flag */ | ||
821 | info->stat_flags &= ESP_STAT_NEVER_DMA; | ||
822 | |||
823 | if (info->stat_flags & ESP_STAT_NEVER_DMA) | ||
824 | info->stat_flags |= ESP_STAT_USE_PIO; | ||
825 | |||
826 | spin_unlock_irqrestore(&info->lock, flags); | ||
827 | |||
828 | /* | ||
829 | * Allocate the IRQ | ||
830 | */ | ||
831 | |||
832 | retval = request_irq(info->irq, rs_interrupt_single, IRQF_SHARED, | ||
833 | "esp serial", info); | ||
834 | |||
835 | if (retval) { | ||
836 | if (capable(CAP_SYS_ADMIN)) { | ||
837 | if (info->port.tty) | ||
838 | set_bit(TTY_IO_ERROR, | ||
839 | &info->port.tty->flags); | ||
840 | retval = 0; | ||
841 | } | ||
842 | goto out_unlocked; | ||
843 | } | ||
844 | |||
845 | if (!(info->stat_flags & ESP_STAT_USE_PIO) && !dma_buffer) { | ||
846 | dma_buffer = (char *)__get_dma_pages( | ||
847 | GFP_KERNEL, get_order(DMA_BUFFER_SZ)); | ||
848 | |||
849 | /* use PIO mode if DMA buf/chan cannot be allocated */ | ||
850 | if (!dma_buffer) | ||
851 | info->stat_flags |= ESP_STAT_USE_PIO; | ||
852 | else if (request_dma(dma, "esp serial")) { | ||
853 | free_pages((unsigned long)dma_buffer, | ||
854 | get_order(DMA_BUFFER_SZ)); | ||
855 | dma_buffer = NULL; | ||
856 | info->stat_flags |= ESP_STAT_USE_PIO; | ||
857 | } | ||
858 | |||
859 | } | ||
860 | |||
861 | info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; | ||
862 | |||
863 | spin_lock_irqsave(&info->lock, flags); | ||
864 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
865 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
866 | serial_out(info, UART_ESI_CMD2, info->MCR); | ||
867 | |||
868 | /* | ||
869 | * Finally, enable interrupts | ||
870 | */ | ||
871 | /* info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; */ | ||
872 | info->IER = UART_IER_RLSI | UART_IER_RDI | UART_IER_DMA_TMOUT | | ||
873 | UART_IER_DMA_TC; | ||
874 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
875 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
876 | |||
877 | if (info->port.tty) | ||
878 | clear_bit(TTY_IO_ERROR, &info->port.tty->flags); | ||
879 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
880 | spin_unlock_irqrestore(&info->lock, flags); | ||
881 | |||
882 | /* | ||
883 | * Set up the tty->alt_speed kludge | ||
884 | */ | ||
885 | if (info->port.tty) { | ||
886 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | ||
887 | info->port.tty->alt_speed = 57600; | ||
888 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | ||
889 | info->port.tty->alt_speed = 115200; | ||
890 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | ||
891 | info->port.tty->alt_speed = 230400; | ||
892 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | ||
893 | info->port.tty->alt_speed = 460800; | ||
894 | } | ||
895 | |||
896 | /* | ||
897 | * set the speed of the serial port | ||
898 | */ | ||
899 | change_speed(info); | ||
900 | info->port.flags |= ASYNC_INITIALIZED; | ||
901 | return 0; | ||
902 | |||
903 | out: | ||
904 | spin_unlock_irqrestore(&info->lock, flags); | ||
905 | out_unlocked: | ||
906 | return retval; | ||
907 | } | ||
908 | |||
909 | /* | ||
910 | * This routine will shutdown a serial port; interrupts are disabled, and | ||
911 | * DTR is dropped if the hangup on close termio flag is on. | ||
912 | */ | ||
913 | static void shutdown(struct esp_struct *info) | ||
914 | { | ||
915 | unsigned long flags, f; | ||
916 | |||
917 | if (!(info->port.flags & ASYNC_INITIALIZED)) | ||
918 | return; | ||
919 | |||
920 | #ifdef SERIAL_DEBUG_OPEN | ||
921 | printk("Shutting down serial port %d (irq %d)....", info->line, | ||
922 | info->irq); | ||
923 | #endif | ||
924 | |||
925 | spin_lock_irqsave(&info->lock, flags); | ||
926 | /* | ||
927 | * clear delta_msr_wait queue to avoid mem leaks: we may free the irq | ||
928 | * here so the queue might never be waken up | ||
929 | */ | ||
930 | wake_up_interruptible(&info->port.delta_msr_wait); | ||
931 | wake_up_interruptible(&info->break_wait); | ||
932 | |||
933 | /* stop a DMA transfer on the port being closed */ | ||
934 | /* DMA lock is higher priority always */ | ||
935 | if (info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) { | ||
936 | f = claim_dma_lock(); | ||
937 | disable_dma(dma); | ||
938 | clear_dma_ff(dma); | ||
939 | release_dma_lock(f); | ||
940 | |||
941 | dma_bytes = 0; | ||
942 | } | ||
943 | |||
944 | /* | ||
945 | * Free the IRQ | ||
946 | */ | ||
947 | free_irq(info->irq, info); | ||
948 | |||
949 | if (dma_buffer) { | ||
950 | struct esp_struct *current_port = ports; | ||
951 | |||
952 | while (current_port) { | ||
953 | if ((current_port != info) && | ||
954 | (current_port->port.flags & ASYNC_INITIALIZED)) | ||
955 | break; | ||
956 | |||
957 | current_port = current_port->next_port; | ||
958 | } | ||
959 | |||
960 | if (!current_port) { | ||
961 | free_dma(dma); | ||
962 | free_pages((unsigned long)dma_buffer, | ||
963 | get_order(DMA_BUFFER_SZ)); | ||
964 | dma_buffer = NULL; | ||
965 | } | ||
966 | } | ||
967 | |||
968 | if (info->xmit_buf) { | ||
969 | free_page((unsigned long) info->xmit_buf); | ||
970 | info->xmit_buf = NULL; | ||
971 | } | ||
972 | |||
973 | info->IER = 0; | ||
974 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
975 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
976 | |||
977 | if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) | ||
978 | info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); | ||
979 | |||
980 | info->MCR &= ~UART_MCR_OUT2; | ||
981 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
982 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
983 | serial_out(info, UART_ESI_CMD2, info->MCR); | ||
984 | |||
985 | if (info->port.tty) | ||
986 | set_bit(TTY_IO_ERROR, &info->port.tty->flags); | ||
987 | |||
988 | info->port.flags &= ~ASYNC_INITIALIZED; | ||
989 | spin_unlock_irqrestore(&info->lock, flags); | ||
990 | } | ||
991 | |||
992 | /* | ||
993 | * This routine is called to set the UART divisor registers to match | ||
994 | * the specified baud rate for a serial port. | ||
995 | */ | ||
996 | static void change_speed(struct esp_struct *info) | ||
997 | { | ||
998 | unsigned short port; | ||
999 | int quot = 0; | ||
1000 | unsigned cflag, cval; | ||
1001 | int baud, bits; | ||
1002 | unsigned char flow1 = 0, flow2 = 0; | ||
1003 | unsigned long flags; | ||
1004 | |||
1005 | if (!info->port.tty || !info->port.tty->termios) | ||
1006 | return; | ||
1007 | cflag = info->port.tty->termios->c_cflag; | ||
1008 | port = info->io_port; | ||
1009 | |||
1010 | /* byte size and parity */ | ||
1011 | switch (cflag & CSIZE) { | ||
1012 | case CS5: cval = 0x00; bits = 7; break; | ||
1013 | case CS6: cval = 0x01; bits = 8; break; | ||
1014 | case CS7: cval = 0x02; bits = 9; break; | ||
1015 | case CS8: cval = 0x03; bits = 10; break; | ||
1016 | default: cval = 0x00; bits = 7; break; | ||
1017 | } | ||
1018 | if (cflag & CSTOPB) { | ||
1019 | cval |= 0x04; | ||
1020 | bits++; | ||
1021 | } | ||
1022 | if (cflag & PARENB) { | ||
1023 | cval |= UART_LCR_PARITY; | ||
1024 | bits++; | ||
1025 | } | ||
1026 | if (!(cflag & PARODD)) | ||
1027 | cval |= UART_LCR_EPAR; | ||
1028 | #ifdef CMSPAR | ||
1029 | if (cflag & CMSPAR) | ||
1030 | cval |= UART_LCR_SPAR; | ||
1031 | #endif | ||
1032 | baud = tty_get_baud_rate(info->port.tty); | ||
1033 | if (baud == 38400 && | ||
1034 | ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) | ||
1035 | quot = info->custom_divisor; | ||
1036 | else { | ||
1037 | if (baud == 134) /* Special case since 134 is really 134.5 */ | ||
1038 | quot = (2*BASE_BAUD / 269); | ||
1039 | else if (baud) | ||
1040 | quot = BASE_BAUD / baud; | ||
1041 | } | ||
1042 | /* If the quotient is ever zero, default to 9600 bps */ | ||
1043 | if (!quot) | ||
1044 | quot = BASE_BAUD / 9600; | ||
1045 | |||
1046 | if (baud) { | ||
1047 | /* Actual rate */ | ||
1048 | baud = BASE_BAUD/quot; | ||
1049 | tty_encode_baud_rate(info->port.tty, baud, baud); | ||
1050 | } | ||
1051 | info->timeout = ((1024 * HZ * bits * quot) / BASE_BAUD) + (HZ / 50); | ||
1052 | |||
1053 | /* CTS flow control flag and modem status interrupts */ | ||
1054 | /* info->IER &= ~UART_IER_MSI; */ | ||
1055 | if (cflag & CRTSCTS) { | ||
1056 | info->port.flags |= ASYNC_CTS_FLOW; | ||
1057 | /* info->IER |= UART_IER_MSI; */ | ||
1058 | flow1 = 0x04; | ||
1059 | flow2 = 0x10; | ||
1060 | } else | ||
1061 | info->port.flags &= ~ASYNC_CTS_FLOW; | ||
1062 | if (cflag & CLOCAL) | ||
1063 | info->port.flags &= ~ASYNC_CHECK_CD; | ||
1064 | else | ||
1065 | info->port.flags |= ASYNC_CHECK_CD; | ||
1066 | |||
1067 | /* | ||
1068 | * Set up parity check flag | ||
1069 | */ | ||
1070 | info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | ||
1071 | if (I_INPCK(info->port.tty)) | ||
1072 | info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; | ||
1073 | if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) | ||
1074 | info->read_status_mask |= UART_LSR_BI; | ||
1075 | |||
1076 | info->ignore_status_mask = 0; | ||
1077 | #if 0 | ||
1078 | /* This should be safe, but for some broken bits of hardware... */ | ||
1079 | if (I_IGNPAR(info->port.tty)) { | ||
1080 | info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; | ||
1081 | info->read_status_mask |= UART_LSR_PE | UART_LSR_FE; | ||
1082 | } | ||
1083 | #endif | ||
1084 | if (I_IGNBRK(info->port.tty)) { | ||
1085 | info->ignore_status_mask |= UART_LSR_BI; | ||
1086 | info->read_status_mask |= UART_LSR_BI; | ||
1087 | /* | ||
1088 | * If we're ignore parity and break indicators, ignore | ||
1089 | * overruns too. (For real raw support). | ||
1090 | */ | ||
1091 | if (I_IGNPAR(info->port.tty)) { | ||
1092 | info->ignore_status_mask |= UART_LSR_OE | \ | ||
1093 | UART_LSR_PE | UART_LSR_FE; | ||
1094 | info->read_status_mask |= UART_LSR_OE | \ | ||
1095 | UART_LSR_PE | UART_LSR_FE; | ||
1096 | } | ||
1097 | } | ||
1098 | |||
1099 | if (I_IXOFF(info->port.tty)) | ||
1100 | flow1 |= 0x81; | ||
1101 | |||
1102 | spin_lock_irqsave(&info->lock, flags); | ||
1103 | /* set baud */ | ||
1104 | serial_out(info, UART_ESI_CMD1, ESI_SET_BAUD); | ||
1105 | serial_out(info, UART_ESI_CMD2, quot >> 8); | ||
1106 | serial_out(info, UART_ESI_CMD2, quot & 0xff); | ||
1107 | |||
1108 | /* set data bits, parity, etc. */ | ||
1109 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
1110 | serial_out(info, UART_ESI_CMD2, UART_LCR); | ||
1111 | serial_out(info, UART_ESI_CMD2, cval); | ||
1112 | |||
1113 | /* Enable flow control */ | ||
1114 | serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_CNTL); | ||
1115 | serial_out(info, UART_ESI_CMD2, flow1); | ||
1116 | serial_out(info, UART_ESI_CMD2, flow2); | ||
1117 | |||
1118 | /* set flow control characters (XON/XOFF only) */ | ||
1119 | if (I_IXOFF(info->port.tty)) { | ||
1120 | serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_CHARS); | ||
1121 | serial_out(info, UART_ESI_CMD2, START_CHAR(info->port.tty)); | ||
1122 | serial_out(info, UART_ESI_CMD2, STOP_CHAR(info->port.tty)); | ||
1123 | serial_out(info, UART_ESI_CMD2, 0x10); | ||
1124 | serial_out(info, UART_ESI_CMD2, 0x21); | ||
1125 | switch (cflag & CSIZE) { | ||
1126 | case CS5: | ||
1127 | serial_out(info, UART_ESI_CMD2, 0x1f); | ||
1128 | break; | ||
1129 | case CS6: | ||
1130 | serial_out(info, UART_ESI_CMD2, 0x3f); | ||
1131 | break; | ||
1132 | case CS7: | ||
1133 | case CS8: | ||
1134 | serial_out(info, UART_ESI_CMD2, 0x7f); | ||
1135 | break; | ||
1136 | default: | ||
1137 | serial_out(info, UART_ESI_CMD2, 0xff); | ||
1138 | break; | ||
1139 | } | ||
1140 | } | ||
1141 | |||
1142 | /* Set high/low water */ | ||
1143 | serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL); | ||
1144 | serial_out(info, UART_ESI_CMD2, info->config.flow_off >> 8); | ||
1145 | serial_out(info, UART_ESI_CMD2, info->config.flow_off); | ||
1146 | serial_out(info, UART_ESI_CMD2, info->config.flow_on >> 8); | ||
1147 | serial_out(info, UART_ESI_CMD2, info->config.flow_on); | ||
1148 | |||
1149 | spin_unlock_irqrestore(&info->lock, flags); | ||
1150 | } | ||
1151 | |||
1152 | static int rs_put_char(struct tty_struct *tty, unsigned char ch) | ||
1153 | { | ||
1154 | struct esp_struct *info = tty->driver_data; | ||
1155 | unsigned long flags; | ||
1156 | int ret = 0; | ||
1157 | |||
1158 | if (serial_paranoia_check(info, tty->name, "rs_put_char")) | ||
1159 | return 0; | ||
1160 | |||
1161 | if (!info->xmit_buf) | ||
1162 | return 0; | ||
1163 | |||
1164 | spin_lock_irqsave(&info->lock, flags); | ||
1165 | if (info->xmit_cnt < ESP_XMIT_SIZE - 1) { | ||
1166 | info->xmit_buf[info->xmit_head++] = ch; | ||
1167 | info->xmit_head &= ESP_XMIT_SIZE-1; | ||
1168 | info->xmit_cnt++; | ||
1169 | ret = 1; | ||
1170 | } | ||
1171 | spin_unlock_irqrestore(&info->lock, flags); | ||
1172 | return ret; | ||
1173 | } | ||
1174 | |||
1175 | static void rs_flush_chars(struct tty_struct *tty) | ||
1176 | { | ||
1177 | struct esp_struct *info = tty->driver_data; | ||
1178 | unsigned long flags; | ||
1179 | |||
1180 | if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) | ||
1181 | return; | ||
1182 | |||
1183 | spin_lock_irqsave(&info->lock, flags); | ||
1184 | |||
1185 | if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf) | ||
1186 | goto out; | ||
1187 | |||
1188 | if (!(info->IER & UART_IER_THRI)) { | ||
1189 | info->IER |= UART_IER_THRI; | ||
1190 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
1191 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
1192 | } | ||
1193 | out: | ||
1194 | spin_unlock_irqrestore(&info->lock, flags); | ||
1195 | } | ||
1196 | |||
1197 | static int rs_write(struct tty_struct *tty, | ||
1198 | const unsigned char *buf, int count) | ||
1199 | { | ||
1200 | int c, t, ret = 0; | ||
1201 | struct esp_struct *info = tty->driver_data; | ||
1202 | unsigned long flags; | ||
1203 | |||
1204 | if (serial_paranoia_check(info, tty->name, "rs_write")) | ||
1205 | return 0; | ||
1206 | |||
1207 | if (!info->xmit_buf) | ||
1208 | return 0; | ||
1209 | |||
1210 | while (1) { | ||
1211 | /* Thanks to R. Wolff for suggesting how to do this with */ | ||
1212 | /* interrupts enabled */ | ||
1213 | |||
1214 | c = count; | ||
1215 | t = ESP_XMIT_SIZE - info->xmit_cnt - 1; | ||
1216 | |||
1217 | if (t < c) | ||
1218 | c = t; | ||
1219 | |||
1220 | t = ESP_XMIT_SIZE - info->xmit_head; | ||
1221 | |||
1222 | if (t < c) | ||
1223 | c = t; | ||
1224 | |||
1225 | if (c <= 0) | ||
1226 | break; | ||
1227 | |||
1228 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | ||
1229 | |||
1230 | info->xmit_head = (info->xmit_head + c) & (ESP_XMIT_SIZE-1); | ||
1231 | info->xmit_cnt += c; | ||
1232 | buf += c; | ||
1233 | count -= c; | ||
1234 | ret += c; | ||
1235 | } | ||
1236 | |||
1237 | spin_lock_irqsave(&info->lock, flags); | ||
1238 | |||
1239 | if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) { | ||
1240 | info->IER |= UART_IER_THRI; | ||
1241 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
1242 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
1243 | } | ||
1244 | |||
1245 | spin_unlock_irqrestore(&info->lock, flags); | ||
1246 | return ret; | ||
1247 | } | ||
1248 | |||
1249 | static int rs_write_room(struct tty_struct *tty) | ||
1250 | { | ||
1251 | struct esp_struct *info = tty->driver_data; | ||
1252 | int ret; | ||
1253 | unsigned long flags; | ||
1254 | |||
1255 | if (serial_paranoia_check(info, tty->name, "rs_write_room")) | ||
1256 | return 0; | ||
1257 | |||
1258 | spin_lock_irqsave(&info->lock, flags); | ||
1259 | |||
1260 | ret = ESP_XMIT_SIZE - info->xmit_cnt - 1; | ||
1261 | if (ret < 0) | ||
1262 | ret = 0; | ||
1263 | spin_unlock_irqrestore(&info->lock, flags); | ||
1264 | return ret; | ||
1265 | } | ||
1266 | |||
1267 | static int rs_chars_in_buffer(struct tty_struct *tty) | ||
1268 | { | ||
1269 | struct esp_struct *info = tty->driver_data; | ||
1270 | |||
1271 | if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) | ||
1272 | return 0; | ||
1273 | return info->xmit_cnt; | ||
1274 | } | ||
1275 | |||
1276 | static void rs_flush_buffer(struct tty_struct *tty) | ||
1277 | { | ||
1278 | struct esp_struct *info = tty->driver_data; | ||
1279 | unsigned long flags; | ||
1280 | |||
1281 | if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) | ||
1282 | return; | ||
1283 | spin_lock_irqsave(&info->lock, flags); | ||
1284 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
1285 | spin_unlock_irqrestore(&info->lock, flags); | ||
1286 | tty_wakeup(tty); | ||
1287 | } | ||
1288 | |||
1289 | /* | ||
1290 | * ------------------------------------------------------------ | ||
1291 | * rs_throttle() | ||
1292 | * | ||
1293 | * This routine is called by the upper-layer tty layer to signal that | ||
1294 | * incoming characters should be throttled. | ||
1295 | * ------------------------------------------------------------ | ||
1296 | */ | ||
1297 | static void rs_throttle(struct tty_struct *tty) | ||
1298 | { | ||
1299 | struct esp_struct *info = tty->driver_data; | ||
1300 | unsigned long flags; | ||
1301 | #ifdef SERIAL_DEBUG_THROTTLE | ||
1302 | char buf[64]; | ||
1303 | |||
1304 | printk("throttle %s: %d....\n", tty_name(tty, buf), | ||
1305 | tty_chars_in_buffer(tty)); | ||
1306 | #endif | ||
1307 | |||
1308 | if (serial_paranoia_check(info, tty->name, "rs_throttle")) | ||
1309 | return; | ||
1310 | |||
1311 | spin_lock_irqsave(&info->lock, flags); | ||
1312 | info->IER &= ~UART_IER_RDI; | ||
1313 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
1314 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
1315 | serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); | ||
1316 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
1317 | spin_unlock_irqrestore(&info->lock, flags); | ||
1318 | } | ||
1319 | |||
1320 | static void rs_unthrottle(struct tty_struct *tty) | ||
1321 | { | ||
1322 | struct esp_struct *info = tty->driver_data; | ||
1323 | unsigned long flags; | ||
1324 | #ifdef SERIAL_DEBUG_THROTTLE | ||
1325 | char buf[64]; | ||
1326 | |||
1327 | printk(KERN_DEBUG "unthrottle %s: %d....\n", tty_name(tty, buf), | ||
1328 | tty_chars_in_buffer(tty)); | ||
1329 | #endif | ||
1330 | |||
1331 | if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) | ||
1332 | return; | ||
1333 | |||
1334 | spin_lock_irqsave(&info->lock, flags); | ||
1335 | info->IER |= UART_IER_RDI; | ||
1336 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
1337 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
1338 | serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); | ||
1339 | serial_out(info, UART_ESI_CMD2, info->config.rx_timeout); | ||
1340 | spin_unlock_irqrestore(&info->lock, flags); | ||
1341 | } | ||
1342 | |||
1343 | /* | ||
1344 | * ------------------------------------------------------------ | ||
1345 | * rs_ioctl() and friends | ||
1346 | * ------------------------------------------------------------ | ||
1347 | */ | ||
1348 | |||
1349 | static int get_serial_info(struct esp_struct *info, | ||
1350 | struct serial_struct __user *retinfo) | ||
1351 | { | ||
1352 | struct serial_struct tmp; | ||
1353 | |||
1354 | lock_kernel(); | ||
1355 | memset(&tmp, 0, sizeof(tmp)); | ||
1356 | tmp.type = PORT_16550A; | ||
1357 | tmp.line = info->line; | ||
1358 | tmp.port = info->io_port; | ||
1359 | tmp.irq = info->irq; | ||
1360 | tmp.flags = info->port.flags; | ||
1361 | tmp.xmit_fifo_size = 1024; | ||
1362 | tmp.baud_base = BASE_BAUD; | ||
1363 | tmp.close_delay = info->close_delay; | ||
1364 | tmp.closing_wait = info->closing_wait; | ||
1365 | tmp.custom_divisor = info->custom_divisor; | ||
1366 | tmp.hub6 = 0; | ||
1367 | unlock_kernel(); | ||
1368 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
1369 | return -EFAULT; | ||
1370 | return 0; | ||
1371 | } | ||
1372 | |||
1373 | static int get_esp_config(struct esp_struct *info, | ||
1374 | struct hayes_esp_config __user *retinfo) | ||
1375 | { | ||
1376 | struct hayes_esp_config tmp; | ||
1377 | |||
1378 | if (!retinfo) | ||
1379 | return -EFAULT; | ||
1380 | |||
1381 | memset(&tmp, 0, sizeof(tmp)); | ||
1382 | lock_kernel(); | ||
1383 | tmp.rx_timeout = info->config.rx_timeout; | ||
1384 | tmp.rx_trigger = info->config.rx_trigger; | ||
1385 | tmp.tx_trigger = info->config.tx_trigger; | ||
1386 | tmp.flow_off = info->config.flow_off; | ||
1387 | tmp.flow_on = info->config.flow_on; | ||
1388 | tmp.pio_threshold = info->config.pio_threshold; | ||
1389 | tmp.dma_channel = (info->stat_flags & ESP_STAT_NEVER_DMA ? 0 : dma); | ||
1390 | unlock_kernel(); | ||
1391 | |||
1392 | return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0; | ||
1393 | } | ||
1394 | |||
1395 | static int set_serial_info(struct esp_struct *info, | ||
1396 | struct serial_struct __user *new_info) | ||
1397 | { | ||
1398 | struct serial_struct new_serial; | ||
1399 | struct esp_struct old_info; | ||
1400 | unsigned int change_irq; | ||
1401 | int retval = 0; | ||
1402 | struct esp_struct *current_async; | ||
1403 | |||
1404 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) | ||
1405 | return -EFAULT; | ||
1406 | old_info = *info; | ||
1407 | |||
1408 | if ((new_serial.type != PORT_16550A) || | ||
1409 | (new_serial.hub6) || | ||
1410 | (info->io_port != new_serial.port) || | ||
1411 | (new_serial.baud_base != BASE_BAUD) || | ||
1412 | (new_serial.irq > 15) || | ||
1413 | (new_serial.irq < 2) || | ||
1414 | (new_serial.irq == 6) || | ||
1415 | (new_serial.irq == 8) || | ||
1416 | (new_serial.irq == 13)) | ||
1417 | return -EINVAL; | ||
1418 | |||
1419 | change_irq = new_serial.irq != info->irq; | ||
1420 | |||
1421 | if (change_irq && (info->line % 8)) | ||
1422 | return -EINVAL; | ||
1423 | |||
1424 | if (!capable(CAP_SYS_ADMIN)) { | ||
1425 | if (change_irq || | ||
1426 | (new_serial.close_delay != info->close_delay) || | ||
1427 | ((new_serial.flags & ~ASYNC_USR_MASK) != | ||
1428 | (info->port.flags & ~ASYNC_USR_MASK))) | ||
1429 | return -EPERM; | ||
1430 | info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) | | ||
1431 | (new_serial.flags & ASYNC_USR_MASK)); | ||
1432 | info->custom_divisor = new_serial.custom_divisor; | ||
1433 | } else { | ||
1434 | if (new_serial.irq == 2) | ||
1435 | new_serial.irq = 9; | ||
1436 | |||
1437 | if (change_irq) { | ||
1438 | current_async = ports; | ||
1439 | |||
1440 | while (current_async) { | ||
1441 | if ((current_async->line >= info->line) && | ||
1442 | (current_async->line < (info->line + 8))) { | ||
1443 | if (current_async == info) { | ||
1444 | if (current_async->port.count > 1) | ||
1445 | return -EBUSY; | ||
1446 | } else if (current_async->port.count) | ||
1447 | return -EBUSY; | ||
1448 | } | ||
1449 | |||
1450 | current_async = current_async->next_port; | ||
1451 | } | ||
1452 | } | ||
1453 | |||
1454 | /* | ||
1455 | * OK, past this point, all the error checking has been done. | ||
1456 | * At this point, we start making changes..... | ||
1457 | */ | ||
1458 | |||
1459 | info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) | | ||
1460 | (new_serial.flags & ASYNC_FLAGS)); | ||
1461 | info->custom_divisor = new_serial.custom_divisor; | ||
1462 | info->close_delay = new_serial.close_delay * HZ/100; | ||
1463 | info->closing_wait = new_serial.closing_wait * HZ/100; | ||
1464 | |||
1465 | if (change_irq) { | ||
1466 | /* | ||
1467 | * We need to shutdown the serial port at the old | ||
1468 | * port/irq combination. | ||
1469 | */ | ||
1470 | shutdown(info); | ||
1471 | |||
1472 | current_async = ports; | ||
1473 | |||
1474 | while (current_async) { | ||
1475 | if ((current_async->line >= info->line) && | ||
1476 | (current_async->line < (info->line + 8))) | ||
1477 | current_async->irq = new_serial.irq; | ||
1478 | |||
1479 | current_async = current_async->next_port; | ||
1480 | } | ||
1481 | |||
1482 | serial_out(info, UART_ESI_CMD1, ESI_SET_ENH_IRQ); | ||
1483 | if (info->irq == 9) | ||
1484 | serial_out(info, UART_ESI_CMD2, 0x02); | ||
1485 | else | ||
1486 | serial_out(info, UART_ESI_CMD2, info->irq); | ||
1487 | } | ||
1488 | } | ||
1489 | |||
1490 | if (info->port.flags & ASYNC_INITIALIZED) { | ||
1491 | if (((old_info.port.flags & ASYNC_SPD_MASK) != | ||
1492 | (info->port.flags & ASYNC_SPD_MASK)) || | ||
1493 | (old_info.custom_divisor != info->custom_divisor)) { | ||
1494 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | ||
1495 | info->port.tty->alt_speed = 57600; | ||
1496 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | ||
1497 | info->port.tty->alt_speed = 115200; | ||
1498 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | ||
1499 | info->port.tty->alt_speed = 230400; | ||
1500 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | ||
1501 | info->port.tty->alt_speed = 460800; | ||
1502 | change_speed(info); | ||
1503 | } | ||
1504 | } else | ||
1505 | retval = startup(info); | ||
1506 | |||
1507 | return retval; | ||
1508 | } | ||
1509 | |||
1510 | static int set_esp_config(struct esp_struct *info, | ||
1511 | struct hayes_esp_config __user *new_info) | ||
1512 | { | ||
1513 | struct hayes_esp_config new_config; | ||
1514 | unsigned int change_dma; | ||
1515 | int retval = 0; | ||
1516 | struct esp_struct *current_async; | ||
1517 | unsigned long flags; | ||
1518 | |||
1519 | /* Perhaps a non-sysadmin user should be able to do some of these */ | ||
1520 | /* operations. I haven't decided yet. */ | ||
1521 | |||
1522 | if (!capable(CAP_SYS_ADMIN)) | ||
1523 | return -EPERM; | ||
1524 | |||
1525 | if (copy_from_user(&new_config, new_info, sizeof(new_config))) | ||
1526 | return -EFAULT; | ||
1527 | |||
1528 | if ((new_config.flow_on >= new_config.flow_off) || | ||
1529 | (new_config.rx_trigger < 1) || | ||
1530 | (new_config.tx_trigger < 1) || | ||
1531 | (new_config.flow_off < 1) || | ||
1532 | (new_config.flow_on < 1) || | ||
1533 | (new_config.rx_trigger > 1023) || | ||
1534 | (new_config.tx_trigger > 1023) || | ||
1535 | (new_config.flow_off > 1023) || | ||
1536 | (new_config.flow_on > 1023) || | ||
1537 | (new_config.pio_threshold < 0) || | ||
1538 | (new_config.pio_threshold > 1024)) | ||
1539 | return -EINVAL; | ||
1540 | |||
1541 | if ((new_config.dma_channel != 1) && (new_config.dma_channel != 3)) | ||
1542 | new_config.dma_channel = 0; | ||
1543 | |||
1544 | if (info->stat_flags & ESP_STAT_NEVER_DMA) | ||
1545 | change_dma = new_config.dma_channel; | ||
1546 | else | ||
1547 | change_dma = (new_config.dma_channel != dma); | ||
1548 | |||
1549 | if (change_dma) { | ||
1550 | if (new_config.dma_channel) { | ||
1551 | /* PIO mode to DMA mode transition OR */ | ||
1552 | /* change current DMA channel */ | ||
1553 | current_async = ports; | ||
1554 | |||
1555 | while (current_async) { | ||
1556 | if (current_async == info) { | ||
1557 | if (current_async->port.count > 1) | ||
1558 | return -EBUSY; | ||
1559 | } else if (current_async->port.count) | ||
1560 | return -EBUSY; | ||
1561 | |||
1562 | current_async = current_async->next_port; | ||
1563 | } | ||
1564 | |||
1565 | shutdown(info); | ||
1566 | dma = new_config.dma_channel; | ||
1567 | info->stat_flags &= ~ESP_STAT_NEVER_DMA; | ||
1568 | |||
1569 | /* all ports must use the same DMA channel */ | ||
1570 | |||
1571 | spin_lock_irqsave(&info->lock, flags); | ||
1572 | current_async = ports; | ||
1573 | |||
1574 | while (current_async) { | ||
1575 | esp_basic_init(current_async); | ||
1576 | current_async = current_async->next_port; | ||
1577 | } | ||
1578 | spin_unlock_irqrestore(&info->lock, flags); | ||
1579 | } else { | ||
1580 | /* DMA mode to PIO mode only */ | ||
1581 | if (info->port.count > 1) | ||
1582 | return -EBUSY; | ||
1583 | |||
1584 | shutdown(info); | ||
1585 | spin_lock_irqsave(&info->lock, flags); | ||
1586 | info->stat_flags |= ESP_STAT_NEVER_DMA; | ||
1587 | esp_basic_init(info); | ||
1588 | spin_unlock_irqrestore(&info->lock, flags); | ||
1589 | } | ||
1590 | } | ||
1591 | |||
1592 | info->config.pio_threshold = new_config.pio_threshold; | ||
1593 | |||
1594 | if ((new_config.flow_off != info->config.flow_off) || | ||
1595 | (new_config.flow_on != info->config.flow_on)) { | ||
1596 | info->config.flow_off = new_config.flow_off; | ||
1597 | info->config.flow_on = new_config.flow_on; | ||
1598 | |||
1599 | spin_lock_irqsave(&info->lock, flags); | ||
1600 | serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL); | ||
1601 | serial_out(info, UART_ESI_CMD2, new_config.flow_off >> 8); | ||
1602 | serial_out(info, UART_ESI_CMD2, new_config.flow_off); | ||
1603 | serial_out(info, UART_ESI_CMD2, new_config.flow_on >> 8); | ||
1604 | serial_out(info, UART_ESI_CMD2, new_config.flow_on); | ||
1605 | spin_unlock_irqrestore(&info->lock, flags); | ||
1606 | } | ||
1607 | |||
1608 | if ((new_config.rx_trigger != info->config.rx_trigger) || | ||
1609 | (new_config.tx_trigger != info->config.tx_trigger)) { | ||
1610 | info->config.rx_trigger = new_config.rx_trigger; | ||
1611 | info->config.tx_trigger = new_config.tx_trigger; | ||
1612 | spin_lock_irqsave(&info->lock, flags); | ||
1613 | serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER); | ||
1614 | serial_out(info, UART_ESI_CMD2, | ||
1615 | new_config.rx_trigger >> 8); | ||
1616 | serial_out(info, UART_ESI_CMD2, new_config.rx_trigger); | ||
1617 | serial_out(info, UART_ESI_CMD2, | ||
1618 | new_config.tx_trigger >> 8); | ||
1619 | serial_out(info, UART_ESI_CMD2, new_config.tx_trigger); | ||
1620 | spin_unlock_irqrestore(&info->lock, flags); | ||
1621 | } | ||
1622 | |||
1623 | if (new_config.rx_timeout != info->config.rx_timeout) { | ||
1624 | info->config.rx_timeout = new_config.rx_timeout; | ||
1625 | spin_lock_irqsave(&info->lock, flags); | ||
1626 | |||
1627 | if (info->IER & UART_IER_RDI) { | ||
1628 | serial_out(info, UART_ESI_CMD1, | ||
1629 | ESI_SET_RX_TIMEOUT); | ||
1630 | serial_out(info, UART_ESI_CMD2, | ||
1631 | new_config.rx_timeout); | ||
1632 | } | ||
1633 | |||
1634 | spin_unlock_irqrestore(&info->lock, flags); | ||
1635 | } | ||
1636 | |||
1637 | if (!(info->port.flags & ASYNC_INITIALIZED)) | ||
1638 | retval = startup(info); | ||
1639 | |||
1640 | return retval; | ||
1641 | } | ||
1642 | |||
1643 | /* | ||
1644 | * get_lsr_info - get line status register info | ||
1645 | * | ||
1646 | * Purpose: Let user call ioctl() to get info when the UART physically | ||
1647 | * is emptied. On bus types like RS485, the transmitter must | ||
1648 | * release the bus after transmitting. This must be done when | ||
1649 | * the transmit shift register is empty, not be done when the | ||
1650 | * transmit holding register is empty. This functionality | ||
1651 | * allows an RS485 driver to be written in user space. | ||
1652 | */ | ||
1653 | static int get_lsr_info(struct esp_struct *info, unsigned int __user *value) | ||
1654 | { | ||
1655 | unsigned char status; | ||
1656 | unsigned int result; | ||
1657 | unsigned long flags; | ||
1658 | |||
1659 | spin_lock_irqsave(&info->lock, flags); | ||
1660 | serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); | ||
1661 | status = serial_in(info, UART_ESI_STAT1); | ||
1662 | spin_unlock_irqrestore(&info->lock, flags); | ||
1663 | result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); | ||
1664 | return put_user(result, value); | ||
1665 | } | ||
1666 | |||
1667 | |||
1668 | static int esp_tiocmget(struct tty_struct *tty, struct file *file) | ||
1669 | { | ||
1670 | struct esp_struct *info = tty->driver_data; | ||
1671 | unsigned char control, status; | ||
1672 | unsigned long flags; | ||
1673 | |||
1674 | if (serial_paranoia_check(info, tty->name, __func__)) | ||
1675 | return -ENODEV; | ||
1676 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1677 | return -EIO; | ||
1678 | |||
1679 | control = info->MCR; | ||
1680 | |||
1681 | spin_lock_irqsave(&info->lock, flags); | ||
1682 | serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); | ||
1683 | status = serial_in(info, UART_ESI_STAT2); | ||
1684 | spin_unlock_irqrestore(&info->lock, flags); | ||
1685 | |||
1686 | return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | ||
1687 | | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | ||
1688 | | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | ||
1689 | | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ||
1690 | | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ||
1691 | | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); | ||
1692 | } | ||
1693 | |||
1694 | static int esp_tiocmset(struct tty_struct *tty, struct file *file, | ||
1695 | unsigned int set, unsigned int clear) | ||
1696 | { | ||
1697 | struct esp_struct *info = tty->driver_data; | ||
1698 | unsigned long flags; | ||
1699 | |||
1700 | if (serial_paranoia_check(info, tty->name, __func__)) | ||
1701 | return -ENODEV; | ||
1702 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1703 | return -EIO; | ||
1704 | |||
1705 | spin_lock_irqsave(&info->lock, flags); | ||
1706 | |||
1707 | if (set & TIOCM_RTS) | ||
1708 | info->MCR |= UART_MCR_RTS; | ||
1709 | if (set & TIOCM_DTR) | ||
1710 | info->MCR |= UART_MCR_DTR; | ||
1711 | |||
1712 | if (clear & TIOCM_RTS) | ||
1713 | info->MCR &= ~UART_MCR_RTS; | ||
1714 | if (clear & TIOCM_DTR) | ||
1715 | info->MCR &= ~UART_MCR_DTR; | ||
1716 | |||
1717 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
1718 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
1719 | serial_out(info, UART_ESI_CMD2, info->MCR); | ||
1720 | |||
1721 | spin_unlock_irqrestore(&info->lock, flags); | ||
1722 | return 0; | ||
1723 | } | ||
1724 | |||
1725 | /* | ||
1726 | * rs_break() --- routine which turns the break handling on or off | ||
1727 | */ | ||
1728 | static int esp_break(struct tty_struct *tty, int break_state) | ||
1729 | { | ||
1730 | struct esp_struct *info = tty->driver_data; | ||
1731 | unsigned long flags; | ||
1732 | |||
1733 | if (serial_paranoia_check(info, tty->name, "esp_break")) | ||
1734 | return -EINVAL; | ||
1735 | |||
1736 | if (break_state == -1) { | ||
1737 | spin_lock_irqsave(&info->lock, flags); | ||
1738 | serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK); | ||
1739 | serial_out(info, UART_ESI_CMD2, 0x01); | ||
1740 | spin_unlock_irqrestore(&info->lock, flags); | ||
1741 | |||
1742 | /* FIXME - new style wait needed here */ | ||
1743 | interruptible_sleep_on(&info->break_wait); | ||
1744 | } else { | ||
1745 | spin_lock_irqsave(&info->lock, flags); | ||
1746 | serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK); | ||
1747 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
1748 | spin_unlock_irqrestore(&info->lock, flags); | ||
1749 | } | ||
1750 | return 0; | ||
1751 | } | ||
1752 | |||
1753 | static int rs_ioctl(struct tty_struct *tty, struct file *file, | ||
1754 | unsigned int cmd, unsigned long arg) | ||
1755 | { | ||
1756 | struct esp_struct *info = tty->driver_data; | ||
1757 | struct async_icount cprev, cnow; /* kernel counter temps */ | ||
1758 | struct serial_icounter_struct __user *p_cuser; /* user space */ | ||
1759 | void __user *argp = (void __user *)arg; | ||
1760 | unsigned long flags; | ||
1761 | int ret; | ||
1762 | |||
1763 | if (serial_paranoia_check(info, tty->name, "rs_ioctl")) | ||
1764 | return -ENODEV; | ||
1765 | |||
1766 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | ||
1767 | (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && | ||
1768 | (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT) && | ||
1769 | (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT) && | ||
1770 | (cmd != TIOCGHAYESESP) && (cmd != TIOCSHAYESESP)) { | ||
1771 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1772 | return -EIO; | ||
1773 | } | ||
1774 | |||
1775 | switch (cmd) { | ||
1776 | case TIOCGSERIAL: | ||
1777 | return get_serial_info(info, argp); | ||
1778 | case TIOCSSERIAL: | ||
1779 | lock_kernel(); | ||
1780 | ret = set_serial_info(info, argp); | ||
1781 | unlock_kernel(); | ||
1782 | return ret; | ||
1783 | case TIOCSERGWILD: | ||
1784 | return put_user(0L, (unsigned long __user *)argp); | ||
1785 | case TIOCSERGETLSR: /* Get line status register */ | ||
1786 | return get_lsr_info(info, argp); | ||
1787 | case TIOCSERSWILD: | ||
1788 | if (!capable(CAP_SYS_ADMIN)) | ||
1789 | return -EPERM; | ||
1790 | return 0; | ||
1791 | /* | ||
1792 | * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change | ||
1793 | * - mask passed in arg for lines of interest | ||
1794 | * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) | ||
1795 | * Caller should use TIOCGICOUNT to see which one it was | ||
1796 | */ | ||
1797 | case TIOCMIWAIT: | ||
1798 | spin_lock_irqsave(&info->lock, flags); | ||
1799 | cprev = info->icount; /* note the counters on entry */ | ||
1800 | spin_unlock_irqrestore(&info->lock, flags); | ||
1801 | while (1) { | ||
1802 | /* FIXME: convert to new style wakeup */ | ||
1803 | interruptible_sleep_on(&info->port.delta_msr_wait); | ||
1804 | /* see if a signal did it */ | ||
1805 | if (signal_pending(current)) | ||
1806 | return -ERESTARTSYS; | ||
1807 | spin_lock_irqsave(&info->lock, flags); | ||
1808 | cnow = info->icount; /* atomic copy */ | ||
1809 | spin_unlock_irqrestore(&info->lock, flags); | ||
1810 | if (cnow.rng == cprev.rng && | ||
1811 | cnow.dsr == cprev.dsr && | ||
1812 | cnow.dcd == cprev.dcd && | ||
1813 | cnow.cts == cprev.cts) | ||
1814 | return -EIO; /* no change => error */ | ||
1815 | if (((arg & TIOCM_RNG) && | ||
1816 | (cnow.rng != cprev.rng)) || | ||
1817 | ((arg & TIOCM_DSR) && | ||
1818 | (cnow.dsr != cprev.dsr)) || | ||
1819 | ((arg & TIOCM_CD) && | ||
1820 | (cnow.dcd != cprev.dcd)) || | ||
1821 | ((arg & TIOCM_CTS) && | ||
1822 | (cnow.cts != cprev.cts))) { | ||
1823 | return 0; | ||
1824 | } | ||
1825 | cprev = cnow; | ||
1826 | } | ||
1827 | /* NOTREACHED */ | ||
1828 | /* | ||
1829 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
1830 | * Return: write counters to the user passed counter struct | ||
1831 | * NB: both 1->0 and 0->1 transitions are counted except for | ||
1832 | * RI where only 0->1 is counted. | ||
1833 | */ | ||
1834 | case TIOCGICOUNT: | ||
1835 | spin_lock_irqsave(&info->lock, flags); | ||
1836 | cnow = info->icount; | ||
1837 | spin_unlock_irqrestore(&info->lock, flags); | ||
1838 | p_cuser = argp; | ||
1839 | if (put_user(cnow.cts, &p_cuser->cts) || | ||
1840 | put_user(cnow.dsr, &p_cuser->dsr) || | ||
1841 | put_user(cnow.rng, &p_cuser->rng) || | ||
1842 | put_user(cnow.dcd, &p_cuser->dcd)) | ||
1843 | return -EFAULT; | ||
1844 | return 0; | ||
1845 | case TIOCGHAYESESP: | ||
1846 | return get_esp_config(info, argp); | ||
1847 | case TIOCSHAYESESP: | ||
1848 | lock_kernel(); | ||
1849 | ret = set_esp_config(info, argp); | ||
1850 | unlock_kernel(); | ||
1851 | return ret; | ||
1852 | default: | ||
1853 | return -ENOIOCTLCMD; | ||
1854 | } | ||
1855 | return 0; | ||
1856 | } | ||
1857 | |||
1858 | static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | ||
1859 | { | ||
1860 | struct esp_struct *info = tty->driver_data; | ||
1861 | unsigned long flags; | ||
1862 | |||
1863 | change_speed(info); | ||
1864 | |||
1865 | spin_lock_irqsave(&info->lock, flags); | ||
1866 | |||
1867 | /* Handle transition to B0 status */ | ||
1868 | if ((old_termios->c_cflag & CBAUD) && | ||
1869 | !(tty->termios->c_cflag & CBAUD)) { | ||
1870 | info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); | ||
1871 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
1872 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
1873 | serial_out(info, UART_ESI_CMD2, info->MCR); | ||
1874 | } | ||
1875 | |||
1876 | /* Handle transition away from B0 status */ | ||
1877 | if (!(old_termios->c_cflag & CBAUD) && | ||
1878 | (tty->termios->c_cflag & CBAUD)) { | ||
1879 | info->MCR |= (UART_MCR_DTR | UART_MCR_RTS); | ||
1880 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
1881 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
1882 | serial_out(info, UART_ESI_CMD2, info->MCR); | ||
1883 | } | ||
1884 | |||
1885 | spin_unlock_irqrestore(&info->lock, flags); | ||
1886 | |||
1887 | /* Handle turning of CRTSCTS */ | ||
1888 | if ((old_termios->c_cflag & CRTSCTS) && | ||
1889 | !(tty->termios->c_cflag & CRTSCTS)) { | ||
1890 | rs_start(tty); | ||
1891 | } | ||
1892 | } | ||
1893 | |||
1894 | /* | ||
1895 | * ------------------------------------------------------------ | ||
1896 | * rs_close() | ||
1897 | * | ||
1898 | * This routine is called when the serial port gets closed. First, we | ||
1899 | * wait for the last remaining data to be sent. Then, we unlink its | ||
1900 | * async structure from the interrupt chain if necessary, and we free | ||
1901 | * that IRQ if nothing is left in the chain. | ||
1902 | * ------------------------------------------------------------ | ||
1903 | */ | ||
1904 | static void rs_close(struct tty_struct *tty, struct file *filp) | ||
1905 | { | ||
1906 | struct esp_struct *info = tty->driver_data; | ||
1907 | unsigned long flags; | ||
1908 | |||
1909 | if (!info || serial_paranoia_check(info, tty->name, "rs_close")) | ||
1910 | return; | ||
1911 | |||
1912 | spin_lock_irqsave(&info->lock, flags); | ||
1913 | |||
1914 | if (tty_hung_up_p(filp)) { | ||
1915 | DBG_CNT("before DEC-hung"); | ||
1916 | goto out; | ||
1917 | } | ||
1918 | |||
1919 | #ifdef SERIAL_DEBUG_OPEN | ||
1920 | printk(KERN_DEBUG "rs_close ttys%d, count = %d\n", | ||
1921 | info->line, info->port.count); | ||
1922 | #endif | ||
1923 | if (tty->count == 1 && info->port.count != 1) { | ||
1924 | /* | ||
1925 | * Uh, oh. tty->count is 1, which means that the tty | ||
1926 | * structure will be freed. Info->count should always | ||
1927 | * be one in these conditions. If it's greater than | ||
1928 | * one, we've got real problems, since it means the | ||
1929 | * serial port won't be shutdown. | ||
1930 | */ | ||
1931 | printk(KERN_DEBUG "rs_close: bad serial port count; tty->count is 1, info->port.count is %d\n", info->port.count); | ||
1932 | info->port.count = 1; | ||
1933 | } | ||
1934 | if (--info->port.count < 0) { | ||
1935 | printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", | ||
1936 | info->line, info->port.count); | ||
1937 | info->port.count = 0; | ||
1938 | } | ||
1939 | if (info->port.count) { | ||
1940 | DBG_CNT("before DEC-2"); | ||
1941 | goto out; | ||
1942 | } | ||
1943 | info->port.flags |= ASYNC_CLOSING; | ||
1944 | |||
1945 | spin_unlock_irqrestore(&info->lock, flags); | ||
1946 | /* | ||
1947 | * Now we wait for the transmit buffer to clear; and we notify | ||
1948 | * the line discipline to only process XON/XOFF characters. | ||
1949 | */ | ||
1950 | tty->closing = 1; | ||
1951 | if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
1952 | tty_wait_until_sent(tty, info->closing_wait); | ||
1953 | /* | ||
1954 | * At this point we stop accepting input. To do this, we | ||
1955 | * disable the receive line status interrupts, and tell the | ||
1956 | * interrupt driver to stop checking the data ready bit in the | ||
1957 | * line status register. | ||
1958 | */ | ||
1959 | /* info->IER &= ~UART_IER_RLSI; */ | ||
1960 | info->IER &= ~UART_IER_RDI; | ||
1961 | info->read_status_mask &= ~UART_LSR_DR; | ||
1962 | if (info->port.flags & ASYNC_INITIALIZED) { | ||
1963 | |||
1964 | spin_lock_irqsave(&info->lock, flags); | ||
1965 | serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK); | ||
1966 | serial_out(info, UART_ESI_CMD2, info->IER); | ||
1967 | |||
1968 | /* disable receive timeout */ | ||
1969 | serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT); | ||
1970 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
1971 | |||
1972 | spin_unlock_irqrestore(&info->lock, flags); | ||
1973 | |||
1974 | /* | ||
1975 | * Before we drop DTR, make sure the UART transmitter | ||
1976 | * has completely drained; this is especially | ||
1977 | * important if there is a transmit FIFO! | ||
1978 | */ | ||
1979 | rs_wait_until_sent(tty, info->timeout); | ||
1980 | } | ||
1981 | shutdown(info); | ||
1982 | rs_flush_buffer(tty); | ||
1983 | tty_ldisc_flush(tty); | ||
1984 | tty->closing = 0; | ||
1985 | info->port.tty = NULL; | ||
1986 | |||
1987 | if (info->port.blocked_open) { | ||
1988 | if (info->close_delay) | ||
1989 | msleep_interruptible(jiffies_to_msecs(info->close_delay)); | ||
1990 | wake_up_interruptible(&info->port.open_wait); | ||
1991 | } | ||
1992 | info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
1993 | wake_up_interruptible(&info->port.close_wait); | ||
1994 | return; | ||
1995 | |||
1996 | out: | ||
1997 | spin_unlock_irqrestore(&info->lock, flags); | ||
1998 | } | ||
1999 | |||
2000 | static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | ||
2001 | { | ||
2002 | struct esp_struct *info = tty->driver_data; | ||
2003 | unsigned long orig_jiffies, char_time; | ||
2004 | unsigned long flags; | ||
2005 | |||
2006 | if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) | ||
2007 | return; | ||
2008 | |||
2009 | orig_jiffies = jiffies; | ||
2010 | char_time = ((info->timeout - HZ / 50) / 1024) / 5; | ||
2011 | |||
2012 | if (!char_time) | ||
2013 | char_time = 1; | ||
2014 | |||
2015 | spin_lock_irqsave(&info->lock, flags); | ||
2016 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
2017 | serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); | ||
2018 | |||
2019 | while ((serial_in(info, UART_ESI_STAT1) != 0x03) || | ||
2020 | (serial_in(info, UART_ESI_STAT2) != 0xff)) { | ||
2021 | |||
2022 | spin_unlock_irqrestore(&info->lock, flags); | ||
2023 | msleep_interruptible(jiffies_to_msecs(char_time)); | ||
2024 | |||
2025 | if (signal_pending(current)) | ||
2026 | return; | ||
2027 | |||
2028 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | ||
2029 | return; | ||
2030 | |||
2031 | spin_lock_irqsave(&info->lock, flags); | ||
2032 | serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND); | ||
2033 | serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL); | ||
2034 | } | ||
2035 | spin_unlock_irqrestore(&info->lock, flags); | ||
2036 | set_current_state(TASK_RUNNING); | ||
2037 | } | ||
2038 | |||
2039 | /* | ||
2040 | * esp_hangup() --- called by tty_hangup() when a hangup is signaled. | ||
2041 | */ | ||
2042 | static void esp_hangup(struct tty_struct *tty) | ||
2043 | { | ||
2044 | struct esp_struct *info = tty->driver_data; | ||
2045 | |||
2046 | if (serial_paranoia_check(info, tty->name, "esp_hangup")) | ||
2047 | return; | ||
2048 | |||
2049 | rs_flush_buffer(tty); | ||
2050 | shutdown(info); | ||
2051 | info->port.count = 0; | ||
2052 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
2053 | info->port.tty = NULL; | ||
2054 | wake_up_interruptible(&info->port.open_wait); | ||
2055 | } | ||
2056 | |||
2057 | static int esp_carrier_raised(struct tty_port *port) | ||
2058 | { | ||
2059 | struct esp_struct *info = container_of(port, struct esp_struct, port); | ||
2060 | serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); | ||
2061 | if (serial_in(info, UART_ESI_STAT2) & UART_MSR_DCD) | ||
2062 | return 1; | ||
2063 | return 0; | ||
2064 | } | ||
2065 | |||
2066 | /* | ||
2067 | * ------------------------------------------------------------ | ||
2068 | * esp_open() and friends | ||
2069 | * ------------------------------------------------------------ | ||
2070 | */ | ||
2071 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | ||
2072 | struct esp_struct *info) | ||
2073 | { | ||
2074 | DECLARE_WAITQUEUE(wait, current); | ||
2075 | int retval; | ||
2076 | int do_clocal = 0; | ||
2077 | unsigned long flags; | ||
2078 | int cd; | ||
2079 | struct tty_port *port = &info->port; | ||
2080 | |||
2081 | /* | ||
2082 | * If the device is in the middle of being closed, then block | ||
2083 | * until it's done, and then try again. | ||
2084 | */ | ||
2085 | if (tty_hung_up_p(filp) || | ||
2086 | (port->flags & ASYNC_CLOSING)) { | ||
2087 | if (port->flags & ASYNC_CLOSING) | ||
2088 | interruptible_sleep_on(&port->close_wait); | ||
2089 | #ifdef SERIAL_DO_RESTART | ||
2090 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
2091 | return -EAGAIN; | ||
2092 | else | ||
2093 | return -ERESTARTSYS; | ||
2094 | #else | ||
2095 | return -EAGAIN; | ||
2096 | #endif | ||
2097 | } | ||
2098 | |||
2099 | /* | ||
2100 | * If non-blocking mode is set, or the port is not enabled, | ||
2101 | * then make the check up front and then exit. | ||
2102 | */ | ||
2103 | if ((filp->f_flags & O_NONBLOCK) || | ||
2104 | (tty->flags & (1 << TTY_IO_ERROR))) { | ||
2105 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
2106 | return 0; | ||
2107 | } | ||
2108 | |||
2109 | if (tty->termios->c_cflag & CLOCAL) | ||
2110 | do_clocal = 1; | ||
2111 | |||
2112 | /* | ||
2113 | * Block waiting for the carrier detect and the line to become | ||
2114 | * free (i.e., not in use by the callout). While we are in | ||
2115 | * this loop, port->count is dropped by one, so that | ||
2116 | * rs_close() knows when to free things. We restore it upon | ||
2117 | * exit, either normal or abnormal. | ||
2118 | */ | ||
2119 | retval = 0; | ||
2120 | add_wait_queue(&port->open_wait, &wait); | ||
2121 | #ifdef SERIAL_DEBUG_OPEN | ||
2122 | printk(KERN_DEBUG "block_til_ready before block: ttys%d, count = %d\n", | ||
2123 | info->line, port->count); | ||
2124 | #endif | ||
2125 | spin_lock_irqsave(&info->lock, flags); | ||
2126 | if (!tty_hung_up_p(filp)) | ||
2127 | port->count--; | ||
2128 | port->blocked_open++; | ||
2129 | while (1) { | ||
2130 | if ((tty->termios->c_cflag & CBAUD)) { | ||
2131 | unsigned int scratch; | ||
2132 | |||
2133 | serial_out(info, UART_ESI_CMD1, ESI_READ_UART); | ||
2134 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
2135 | scratch = serial_in(info, UART_ESI_STAT1); | ||
2136 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
2137 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
2138 | serial_out(info, UART_ESI_CMD2, | ||
2139 | scratch | UART_MCR_DTR | UART_MCR_RTS); | ||
2140 | } | ||
2141 | set_current_state(TASK_INTERRUPTIBLE); | ||
2142 | if (tty_hung_up_p(filp) || | ||
2143 | !(port->flags & ASYNC_INITIALIZED)) { | ||
2144 | #ifdef SERIAL_DO_RESTART | ||
2145 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
2146 | retval = -EAGAIN; | ||
2147 | else | ||
2148 | retval = -ERESTARTSYS; | ||
2149 | #else | ||
2150 | retval = -EAGAIN; | ||
2151 | #endif | ||
2152 | break; | ||
2153 | } | ||
2154 | |||
2155 | cd = tty_port_carrier_raised(port); | ||
2156 | |||
2157 | if (!(port->flags & ASYNC_CLOSING) && | ||
2158 | (do_clocal)) | ||
2159 | break; | ||
2160 | if (signal_pending(current)) { | ||
2161 | retval = -ERESTARTSYS; | ||
2162 | break; | ||
2163 | } | ||
2164 | #ifdef SERIAL_DEBUG_OPEN | ||
2165 | printk(KERN_DEBUG "block_til_ready blocking: ttys%d, count = %d\n", | ||
2166 | info->line, port->count); | ||
2167 | #endif | ||
2168 | spin_unlock_irqrestore(&info->lock, flags); | ||
2169 | schedule(); | ||
2170 | spin_lock_irqsave(&info->lock, flags); | ||
2171 | } | ||
2172 | set_current_state(TASK_RUNNING); | ||
2173 | remove_wait_queue(&port->open_wait, &wait); | ||
2174 | if (!tty_hung_up_p(filp)) | ||
2175 | port->count++; | ||
2176 | port->blocked_open--; | ||
2177 | spin_unlock_irqrestore(&info->lock, flags); | ||
2178 | #ifdef SERIAL_DEBUG_OPEN | ||
2179 | printk(KERN_DEBUG "block_til_ready after blocking: ttys%d, count = %d\n", | ||
2180 | info->line, port->count); | ||
2181 | #endif | ||
2182 | if (retval) | ||
2183 | return retval; | ||
2184 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
2185 | return 0; | ||
2186 | } | ||
2187 | |||
2188 | /* | ||
2189 | * This routine is called whenever a serial port is opened. It | ||
2190 | * enables interrupts for a serial port, linking in its async structure into | ||
2191 | * the IRQ chain. It also performs the serial-specific | ||
2192 | * initialization for the tty structure. | ||
2193 | */ | ||
2194 | static int esp_open(struct tty_struct *tty, struct file *filp) | ||
2195 | { | ||
2196 | struct esp_struct *info; | ||
2197 | int retval, line; | ||
2198 | unsigned long flags; | ||
2199 | |||
2200 | line = tty->index; | ||
2201 | if ((line < 0) || (line >= NR_PORTS)) | ||
2202 | return -ENODEV; | ||
2203 | |||
2204 | /* find the port in the chain */ | ||
2205 | |||
2206 | info = ports; | ||
2207 | |||
2208 | while (info && (info->line != line)) | ||
2209 | info = info->next_port; | ||
2210 | |||
2211 | if (!info) { | ||
2212 | serial_paranoia_check(info, tty->name, "esp_open"); | ||
2213 | return -ENODEV; | ||
2214 | } | ||
2215 | |||
2216 | #ifdef SERIAL_DEBUG_OPEN | ||
2217 | printk(KERN_DEBUG "esp_open %s, count = %d\n", tty->name, info->port.count); | ||
2218 | #endif | ||
2219 | spin_lock_irqsave(&info->lock, flags); | ||
2220 | info->port.count++; | ||
2221 | tty->driver_data = info; | ||
2222 | info->port.tty = tty; | ||
2223 | |||
2224 | spin_unlock_irqrestore(&info->lock, flags); | ||
2225 | |||
2226 | /* | ||
2227 | * Start up serial port | ||
2228 | */ | ||
2229 | retval = startup(info); | ||
2230 | if (retval) | ||
2231 | return retval; | ||
2232 | |||
2233 | retval = block_til_ready(tty, filp, info); | ||
2234 | if (retval) { | ||
2235 | #ifdef SERIAL_DEBUG_OPEN | ||
2236 | printk(KERN_DEBUG "esp_open returning after block_til_ready with %d\n", | ||
2237 | retval); | ||
2238 | #endif | ||
2239 | return retval; | ||
2240 | } | ||
2241 | #ifdef SERIAL_DEBUG_OPEN | ||
2242 | printk(KERN_DEBUG "esp_open %s successful...", tty->name); | ||
2243 | #endif | ||
2244 | return 0; | ||
2245 | } | ||
2246 | |||
2247 | /* | ||
2248 | * --------------------------------------------------------------------- | ||
2249 | * espserial_init() and friends | ||
2250 | * | ||
2251 | * espserial_init() is called at boot-time to initialize the serial driver. | ||
2252 | * --------------------------------------------------------------------- | ||
2253 | */ | ||
2254 | |||
2255 | /* | ||
2256 | * This routine prints out the appropriate serial driver version | ||
2257 | * number, and identifies which options were configured into this | ||
2258 | * driver. | ||
2259 | */ | ||
2260 | |||
2261 | static void __init show_serial_version(void) | ||
2262 | { | ||
2263 | printk(KERN_INFO "%s version %s (DMA %u)\n", | ||
2264 | serial_name, serial_version, dma); | ||
2265 | } | ||
2266 | |||
2267 | /* | ||
2268 | * This routine is called by espserial_init() to initialize a specific serial | ||
2269 | * port. | ||
2270 | */ | ||
2271 | static int autoconfig(struct esp_struct *info) | ||
2272 | { | ||
2273 | int port_detected = 0; | ||
2274 | unsigned long flags; | ||
2275 | |||
2276 | if (!request_region(info->io_port, REGION_SIZE, "esp serial")) | ||
2277 | return -EIO; | ||
2278 | |||
2279 | spin_lock_irqsave(&info->lock, flags); | ||
2280 | /* | ||
2281 | * Check for ESP card | ||
2282 | */ | ||
2283 | |||
2284 | if (serial_in(info, UART_ESI_BASE) == 0xf3) { | ||
2285 | serial_out(info, UART_ESI_CMD1, 0x00); | ||
2286 | serial_out(info, UART_ESI_CMD1, 0x01); | ||
2287 | |||
2288 | if ((serial_in(info, UART_ESI_STAT2) & 0x70) == 0x20) { | ||
2289 | port_detected = 1; | ||
2290 | |||
2291 | if (!(info->irq)) { | ||
2292 | serial_out(info, UART_ESI_CMD1, 0x02); | ||
2293 | |||
2294 | if (serial_in(info, UART_ESI_STAT1) & 0x01) | ||
2295 | info->irq = 3; | ||
2296 | else | ||
2297 | info->irq = 4; | ||
2298 | } | ||
2299 | |||
2300 | |||
2301 | /* put card in enhanced mode */ | ||
2302 | /* this prevents access through */ | ||
2303 | /* the "old" IO ports */ | ||
2304 | esp_basic_init(info); | ||
2305 | |||
2306 | /* clear out MCR */ | ||
2307 | serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); | ||
2308 | serial_out(info, UART_ESI_CMD2, UART_MCR); | ||
2309 | serial_out(info, UART_ESI_CMD2, 0x00); | ||
2310 | } | ||
2311 | } | ||
2312 | if (!port_detected) | ||
2313 | release_region(info->io_port, REGION_SIZE); | ||
2314 | |||
2315 | spin_unlock_irqrestore(&info->lock, flags); | ||
2316 | return (port_detected); | ||
2317 | } | ||
2318 | |||
2319 | static const struct tty_operations esp_ops = { | ||
2320 | .open = esp_open, | ||
2321 | .close = rs_close, | ||
2322 | .write = rs_write, | ||
2323 | .put_char = rs_put_char, | ||
2324 | .flush_chars = rs_flush_chars, | ||
2325 | .write_room = rs_write_room, | ||
2326 | .chars_in_buffer = rs_chars_in_buffer, | ||
2327 | .flush_buffer = rs_flush_buffer, | ||
2328 | .ioctl = rs_ioctl, | ||
2329 | .throttle = rs_throttle, | ||
2330 | .unthrottle = rs_unthrottle, | ||
2331 | .set_termios = rs_set_termios, | ||
2332 | .stop = rs_stop, | ||
2333 | .start = rs_start, | ||
2334 | .hangup = esp_hangup, | ||
2335 | .break_ctl = esp_break, | ||
2336 | .wait_until_sent = rs_wait_until_sent, | ||
2337 | .tiocmget = esp_tiocmget, | ||
2338 | .tiocmset = esp_tiocmset, | ||
2339 | }; | ||
2340 | |||
2341 | static const struct tty_port_operations esp_port_ops = { | ||
2342 | .esp_carrier_raised, | ||
2343 | }; | ||
2344 | |||
2345 | /* | ||
2346 | * The serial driver boot-time initialization code! | ||
2347 | */ | ||
2348 | static int __init espserial_init(void) | ||
2349 | { | ||
2350 | int i, offset; | ||
2351 | struct esp_struct *info; | ||
2352 | struct esp_struct *last_primary = NULL; | ||
2353 | int esp[] = { 0x100, 0x140, 0x180, 0x200, 0x240, 0x280, 0x300, 0x380 }; | ||
2354 | |||
2355 | esp_driver = alloc_tty_driver(NR_PORTS); | ||
2356 | if (!esp_driver) | ||
2357 | return -ENOMEM; | ||
2358 | |||
2359 | for (i = 0; i < NR_PRIMARY; i++) { | ||
2360 | if (irq[i] != 0) { | ||
2361 | if ((irq[i] < 2) || (irq[i] > 15) || (irq[i] == 6) || | ||
2362 | (irq[i] == 8) || (irq[i] == 13)) | ||
2363 | irq[i] = 0; | ||
2364 | else if (irq[i] == 2) | ||
2365 | irq[i] = 9; | ||
2366 | } | ||
2367 | } | ||
2368 | |||
2369 | if ((dma != 1) && (dma != 3)) | ||
2370 | dma = 0; | ||
2371 | |||
2372 | if ((rx_trigger < 1) || (rx_trigger > 1023)) | ||
2373 | rx_trigger = 768; | ||
2374 | |||
2375 | if ((tx_trigger < 1) || (tx_trigger > 1023)) | ||
2376 | tx_trigger = 768; | ||
2377 | |||
2378 | if ((flow_off < 1) || (flow_off > 1023)) | ||
2379 | flow_off = 1016; | ||
2380 | |||
2381 | if ((flow_on < 1) || (flow_on > 1023)) | ||
2382 | flow_on = 944; | ||
2383 | |||
2384 | if ((rx_timeout < 0) || (rx_timeout > 255)) | ||
2385 | rx_timeout = 128; | ||
2386 | |||
2387 | if (flow_on >= flow_off) | ||
2388 | flow_on = flow_off - 1; | ||
2389 | |||
2390 | show_serial_version(); | ||
2391 | |||
2392 | /* Initialize the tty_driver structure */ | ||
2393 | |||
2394 | esp_driver->owner = THIS_MODULE; | ||
2395 | esp_driver->name = "ttyP"; | ||
2396 | esp_driver->major = ESP_IN_MAJOR; | ||
2397 | esp_driver->minor_start = 0; | ||
2398 | esp_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
2399 | esp_driver->subtype = SERIAL_TYPE_NORMAL; | ||
2400 | esp_driver->init_termios = tty_std_termios; | ||
2401 | esp_driver->init_termios.c_cflag = | ||
2402 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
2403 | esp_driver->init_termios.c_ispeed = 9600; | ||
2404 | esp_driver->init_termios.c_ospeed = 9600; | ||
2405 | esp_driver->flags = TTY_DRIVER_REAL_RAW; | ||
2406 | tty_set_operations(esp_driver, &esp_ops); | ||
2407 | if (tty_register_driver(esp_driver)) { | ||
2408 | printk(KERN_ERR "Couldn't register esp serial driver"); | ||
2409 | put_tty_driver(esp_driver); | ||
2410 | return 1; | ||
2411 | } | ||
2412 | |||
2413 | info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL); | ||
2414 | |||
2415 | if (!info) { | ||
2416 | printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); | ||
2417 | tty_unregister_driver(esp_driver); | ||
2418 | put_tty_driver(esp_driver); | ||
2419 | return 1; | ||
2420 | } | ||
2421 | |||
2422 | spin_lock_init(&info->lock); | ||
2423 | /* rx_trigger, tx_trigger are needed by autoconfig */ | ||
2424 | info->config.rx_trigger = rx_trigger; | ||
2425 | info->config.tx_trigger = tx_trigger; | ||
2426 | |||
2427 | i = 0; | ||
2428 | offset = 0; | ||
2429 | |||
2430 | do { | ||
2431 | tty_port_init(&info->port); | ||
2432 | info->port.ops = &esp_port_ops; | ||
2433 | info->io_port = esp[i] + offset; | ||
2434 | info->irq = irq[i]; | ||
2435 | info->line = (i * 8) + (offset / 8); | ||
2436 | |||
2437 | if (!autoconfig(info)) { | ||
2438 | i++; | ||
2439 | offset = 0; | ||
2440 | continue; | ||
2441 | } | ||
2442 | |||
2443 | info->custom_divisor = (divisor[i] >> (offset / 2)) & 0xf; | ||
2444 | info->port.flags = STD_COM_FLAGS; | ||
2445 | if (info->custom_divisor) | ||
2446 | info->port.flags |= ASYNC_SPD_CUST; | ||
2447 | info->magic = ESP_MAGIC; | ||
2448 | info->close_delay = 5*HZ/10; | ||
2449 | info->closing_wait = 30*HZ; | ||
2450 | info->config.rx_timeout = rx_timeout; | ||
2451 | info->config.flow_on = flow_on; | ||
2452 | info->config.flow_off = flow_off; | ||
2453 | info->config.pio_threshold = pio_threshold; | ||
2454 | info->next_port = ports; | ||
2455 | init_waitqueue_head(&info->break_wait); | ||
2456 | ports = info; | ||
2457 | printk(KERN_INFO "ttyP%d at 0x%04x (irq = %d) is an ESP ", | ||
2458 | info->line, info->io_port, info->irq); | ||
2459 | |||
2460 | if (info->line % 8) { | ||
2461 | printk("secondary port\n"); | ||
2462 | /* 8 port cards can't do DMA */ | ||
2463 | info->stat_flags |= ESP_STAT_NEVER_DMA; | ||
2464 | |||
2465 | if (last_primary) | ||
2466 | last_primary->stat_flags |= ESP_STAT_NEVER_DMA; | ||
2467 | } else { | ||
2468 | printk("primary port\n"); | ||
2469 | last_primary = info; | ||
2470 | irq[i] = info->irq; | ||
2471 | } | ||
2472 | |||
2473 | if (!dma) | ||
2474 | info->stat_flags |= ESP_STAT_NEVER_DMA; | ||
2475 | |||
2476 | info = kzalloc(sizeof(struct esp_struct), GFP_KERNEL); | ||
2477 | if (!info) { | ||
2478 | printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); | ||
2479 | /* allow use of the already detected ports */ | ||
2480 | return 0; | ||
2481 | } | ||
2482 | |||
2483 | spin_lock_init(&info->lock); | ||
2484 | /* rx_trigger, tx_trigger are needed by autoconfig */ | ||
2485 | info->config.rx_trigger = rx_trigger; | ||
2486 | info->config.tx_trigger = tx_trigger; | ||
2487 | |||
2488 | if (offset == 56) { | ||
2489 | i++; | ||
2490 | offset = 0; | ||
2491 | } else { | ||
2492 | offset += 8; | ||
2493 | } | ||
2494 | } while (i < NR_PRIMARY); | ||
2495 | |||
2496 | /* free the last port memory allocation */ | ||
2497 | kfree(info); | ||
2498 | |||
2499 | return 0; | ||
2500 | } | ||
2501 | |||
2502 | static void __exit espserial_exit(void) | ||
2503 | { | ||
2504 | int e1; | ||
2505 | struct esp_struct *temp_async; | ||
2506 | struct esp_pio_buffer *pio_buf; | ||
2507 | |||
2508 | e1 = tty_unregister_driver(esp_driver); | ||
2509 | if (e1) | ||
2510 | printk(KERN_ERR "esp: failed to unregister driver (%d)\n", e1); | ||
2511 | put_tty_driver(esp_driver); | ||
2512 | |||
2513 | while (ports) { | ||
2514 | if (ports->io_port) | ||
2515 | release_region(ports->io_port, REGION_SIZE); | ||
2516 | temp_async = ports->next_port; | ||
2517 | kfree(ports); | ||
2518 | ports = temp_async; | ||
2519 | } | ||
2520 | |||
2521 | if (dma_buffer) | ||
2522 | free_pages((unsigned long)dma_buffer, | ||
2523 | get_order(DMA_BUFFER_SZ)); | ||
2524 | |||
2525 | while (free_pio_buf) { | ||
2526 | pio_buf = free_pio_buf->next; | ||
2527 | kfree(free_pio_buf); | ||
2528 | free_pio_buf = pio_buf; | ||
2529 | } | ||
2530 | } | ||
2531 | |||
2532 | module_init(espserial_init); | ||
2533 | module_exit(espserial_exit); | ||
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 426bfdd7f3e0..300d5bd6cd06 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -793,35 +793,30 @@ static inline void isicom_setup_board(struct isi_board *bp) | |||
793 | { | 793 | { |
794 | int channel; | 794 | int channel; |
795 | struct isi_port *port; | 795 | struct isi_port *port; |
796 | unsigned long flags; | ||
797 | 796 | ||
798 | spin_lock_irqsave(&bp->card_lock, flags); | 797 | bp->count++; |
799 | if (bp->status & BOARD_ACTIVE) { | 798 | if (!(bp->status & BOARD_INIT)) { |
800 | spin_unlock_irqrestore(&bp->card_lock, flags); | 799 | port = bp->ports; |
801 | return; | 800 | for (channel = 0; channel < bp->port_count; channel++, port++) |
801 | drop_dtr_rts(port); | ||
802 | } | 802 | } |
803 | port = bp->ports; | 803 | bp->status |= BOARD_ACTIVE | BOARD_INIT; |
804 | bp->status |= BOARD_ACTIVE; | ||
805 | for (channel = 0; channel < bp->port_count; channel++, port++) | ||
806 | drop_dtr_rts(port); | ||
807 | spin_unlock_irqrestore(&bp->card_lock, flags); | ||
808 | } | 804 | } |
809 | 805 | ||
810 | static int isicom_setup_port(struct tty_struct *tty) | 806 | /* Activate and thus setup board are protected from races against shutdown |
807 | by the tty_port mutex */ | ||
808 | |||
809 | static int isicom_activate(struct tty_port *tport, struct tty_struct *tty) | ||
811 | { | 810 | { |
812 | struct isi_port *port = tty->driver_data; | 811 | struct isi_port *port = container_of(tport, struct isi_port, port); |
813 | struct isi_board *card = port->card; | 812 | struct isi_board *card = port->card; |
814 | unsigned long flags; | 813 | unsigned long flags; |
815 | 814 | ||
816 | if (port->port.flags & ASYNC_INITIALIZED) | 815 | if (tty_port_alloc_xmit_buf(tport) < 0) |
817 | return 0; | ||
818 | if (tty_port_alloc_xmit_buf(&port->port) < 0) | ||
819 | return -ENOMEM; | 816 | return -ENOMEM; |
820 | 817 | ||
821 | spin_lock_irqsave(&card->card_lock, flags); | 818 | spin_lock_irqsave(&card->card_lock, flags); |
822 | clear_bit(TTY_IO_ERROR, &tty->flags); | 819 | isicom_setup_board(card); |
823 | if (port->port.count == 1) | ||
824 | card->count++; | ||
825 | 820 | ||
826 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 821 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; |
827 | 822 | ||
@@ -832,9 +827,7 @@ static int isicom_setup_port(struct tty_struct *tty) | |||
832 | outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base); | 827 | outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base); |
833 | InterruptTheCard(card->base); | 828 | InterruptTheCard(card->base); |
834 | } | 829 | } |
835 | |||
836 | isicom_config_port(tty); | 830 | isicom_config_port(tty); |
837 | port->port.flags |= ASYNC_INITIALIZED; | ||
838 | spin_unlock_irqrestore(&card->card_lock, flags); | 831 | spin_unlock_irqrestore(&card->card_lock, flags); |
839 | 832 | ||
840 | return 0; | 833 | return 0; |
@@ -871,85 +864,37 @@ static struct tty_port *isicom_find_port(struct tty_struct *tty) | |||
871 | 864 | ||
872 | return &port->port; | 865 | return &port->port; |
873 | } | 866 | } |
874 | 867 | ||
875 | static int isicom_open(struct tty_struct *tty, struct file *filp) | 868 | static int isicom_open(struct tty_struct *tty, struct file *filp) |
876 | { | 869 | { |
877 | struct isi_port *port; | 870 | struct isi_port *port; |
878 | struct isi_board *card; | 871 | struct isi_board *card; |
879 | struct tty_port *tport; | 872 | struct tty_port *tport; |
880 | int error = 0; | ||
881 | 873 | ||
882 | tport = isicom_find_port(tty); | 874 | tport = isicom_find_port(tty); |
883 | if (tport == NULL) | 875 | if (tport == NULL) |
884 | return -ENODEV; | 876 | return -ENODEV; |
885 | port = container_of(tport, struct isi_port, port); | 877 | port = container_of(tport, struct isi_port, port); |
886 | card = &isi_card[BOARD(tty->index)]; | 878 | card = &isi_card[BOARD(tty->index)]; |
887 | isicom_setup_board(card); | ||
888 | 879 | ||
889 | /* FIXME: locking on port.count etc */ | 880 | return tty_port_open(tport, tty, filp); |
890 | port->port.count++; | ||
891 | tty->driver_data = port; | ||
892 | tty_port_tty_set(&port->port, tty); | ||
893 | /* FIXME: Locking on Initialized flag */ | ||
894 | if (!test_bit(ASYNCB_INITIALIZED, &tport->flags)) | ||
895 | error = isicom_setup_port(tty); | ||
896 | if (error == 0) | ||
897 | error = tty_port_block_til_ready(&port->port, tty, filp); | ||
898 | return error; | ||
899 | } | 881 | } |
900 | 882 | ||
901 | /* close et all */ | 883 | /* close et all */ |
902 | 884 | ||
903 | static inline void isicom_shutdown_board(struct isi_board *bp) | ||
904 | { | ||
905 | if (bp->status & BOARD_ACTIVE) | ||
906 | bp->status &= ~BOARD_ACTIVE; | ||
907 | } | ||
908 | |||
909 | /* card->lock HAS to be held */ | 885 | /* card->lock HAS to be held */ |
910 | static void isicom_shutdown_port(struct isi_port *port) | 886 | static void isicom_shutdown_port(struct isi_port *port) |
911 | { | 887 | { |
912 | struct isi_board *card = port->card; | 888 | struct isi_board *card = port->card; |
913 | struct tty_struct *tty; | ||
914 | |||
915 | tty = tty_port_tty_get(&port->port); | ||
916 | |||
917 | if (!(port->port.flags & ASYNC_INITIALIZED)) { | ||
918 | tty_kref_put(tty); | ||
919 | return; | ||
920 | } | ||
921 | |||
922 | tty_port_free_xmit_buf(&port->port); | ||
923 | port->port.flags &= ~ASYNC_INITIALIZED; | ||
924 | /* 3rd October 2000 : Vinayak P Risbud */ | ||
925 | tty_port_tty_set(&port->port, NULL); | ||
926 | |||
927 | /*Fix done by Anil .S on 30-04-2001 | ||
928 | remote login through isi port has dtr toggle problem | ||
929 | due to which the carrier drops before the password prompt | ||
930 | appears on the remote end. Now we drop the dtr only if the | ||
931 | HUPCL(Hangup on close) flag is set for the tty*/ | ||
932 | |||
933 | if (C_HUPCL(tty)) | ||
934 | /* drop dtr on this port */ | ||
935 | drop_dtr(port); | ||
936 | |||
937 | /* any other port uninits */ | ||
938 | if (tty) | ||
939 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
940 | 889 | ||
941 | if (--card->count < 0) { | 890 | if (--card->count < 0) { |
942 | pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", | 891 | pr_dbg("isicom_shutdown_port: bad board(0x%lx) count %d.\n", |
943 | card->base, card->count); | 892 | card->base, card->count); |
944 | card->count = 0; | 893 | card->count = 0; |
945 | } | 894 | } |
946 | 895 | /* last port was closed, shutdown that board too */ | |
947 | /* last port was closed, shutdown that boad too */ | 896 | if (!card->count) |
948 | if (C_HUPCL(tty)) { | 897 | card->status &= BOARD_ACTIVE; |
949 | if (!card->count) | ||
950 | isicom_shutdown_board(card); | ||
951 | } | ||
952 | tty_kref_put(tty); | ||
953 | } | 898 | } |
954 | 899 | ||
955 | static void isicom_flush_buffer(struct tty_struct *tty) | 900 | static void isicom_flush_buffer(struct tty_struct *tty) |
@@ -968,7 +913,7 @@ static void isicom_flush_buffer(struct tty_struct *tty) | |||
968 | tty_wakeup(tty); | 913 | tty_wakeup(tty); |
969 | } | 914 | } |
970 | 915 | ||
971 | static void isicom_close_port(struct tty_port *port) | 916 | static void isicom_shutdown(struct tty_port *port) |
972 | { | 917 | { |
973 | struct isi_port *ip = container_of(port, struct isi_port, port); | 918 | struct isi_port *ip = container_of(port, struct isi_port, port); |
974 | struct isi_board *card = ip->card; | 919 | struct isi_board *card = ip->card; |
@@ -977,12 +922,11 @@ static void isicom_close_port(struct tty_port *port) | |||
977 | /* indicate to the card that no more data can be received | 922 | /* indicate to the card that no more data can be received |
978 | on this port */ | 923 | on this port */ |
979 | spin_lock_irqsave(&card->card_lock, flags); | 924 | spin_lock_irqsave(&card->card_lock, flags); |
980 | if (port->flags & ASYNC_INITIALIZED) { | 925 | card->port_status &= ~(1 << ip->channel); |
981 | card->port_status &= ~(1 << ip->channel); | 926 | outw(card->port_status, card->base + 0x02); |
982 | outw(card->port_status, card->base + 0x02); | ||
983 | } | ||
984 | isicom_shutdown_port(ip); | 927 | isicom_shutdown_port(ip); |
985 | spin_unlock_irqrestore(&card->card_lock, flags); | 928 | spin_unlock_irqrestore(&card->card_lock, flags); |
929 | tty_port_free_xmit_buf(port); | ||
986 | } | 930 | } |
987 | 931 | ||
988 | static void isicom_close(struct tty_struct *tty, struct file *filp) | 932 | static void isicom_close(struct tty_struct *tty, struct file *filp) |
@@ -991,12 +935,7 @@ static void isicom_close(struct tty_struct *tty, struct file *filp) | |||
991 | struct tty_port *port = &ip->port; | 935 | struct tty_port *port = &ip->port; |
992 | if (isicom_paranoia_check(ip, tty->name, "isicom_close")) | 936 | if (isicom_paranoia_check(ip, tty->name, "isicom_close")) |
993 | return; | 937 | return; |
994 | 938 | tty_port_close(port, tty, filp); | |
995 | if (tty_port_close_start(port, tty, filp) == 0) | ||
996 | return; | ||
997 | isicom_close_port(port); | ||
998 | isicom_flush_buffer(tty); | ||
999 | tty_port_close_end(port, tty); | ||
1000 | } | 939 | } |
1001 | 940 | ||
1002 | /* write et all */ | 941 | /* write et all */ |
@@ -1326,15 +1265,9 @@ static void isicom_start(struct tty_struct *tty) | |||
1326 | static void isicom_hangup(struct tty_struct *tty) | 1265 | static void isicom_hangup(struct tty_struct *tty) |
1327 | { | 1266 | { |
1328 | struct isi_port *port = tty->driver_data; | 1267 | struct isi_port *port = tty->driver_data; |
1329 | unsigned long flags; | ||
1330 | 1268 | ||
1331 | if (isicom_paranoia_check(port, tty->name, "isicom_hangup")) | 1269 | if (isicom_paranoia_check(port, tty->name, "isicom_hangup")) |
1332 | return; | 1270 | return; |
1333 | |||
1334 | spin_lock_irqsave(&port->card->card_lock, flags); | ||
1335 | isicom_shutdown_port(port); | ||
1336 | spin_unlock_irqrestore(&port->card->card_lock, flags); | ||
1337 | |||
1338 | tty_port_hangup(&port->port); | 1271 | tty_port_hangup(&port->port); |
1339 | } | 1272 | } |
1340 | 1273 | ||
@@ -1367,6 +1300,8 @@ static const struct tty_operations isicom_ops = { | |||
1367 | static const struct tty_port_operations isicom_port_ops = { | 1300 | static const struct tty_port_operations isicom_port_ops = { |
1368 | .carrier_raised = isicom_carrier_raised, | 1301 | .carrier_raised = isicom_carrier_raised, |
1369 | .dtr_rts = isicom_dtr_rts, | 1302 | .dtr_rts = isicom_dtr_rts, |
1303 | .activate = isicom_activate, | ||
1304 | .shutdown = isicom_shutdown, | ||
1370 | }; | 1305 | }; |
1371 | 1306 | ||
1372 | static int __devinit reset_card(struct pci_dev *pdev, | 1307 | static int __devinit reset_card(struct pci_dev *pdev, |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 402838f4083e..4cd6c527ee41 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -213,7 +213,6 @@ static int stli_shared; | |||
213 | * with the slave. Most of them need to be updated atomically, so always | 213 | * with the slave. Most of them need to be updated atomically, so always |
214 | * use the bit setting operations (unless protected by cli/sti). | 214 | * use the bit setting operations (unless protected by cli/sti). |
215 | */ | 215 | */ |
216 | #define ST_INITIALIZING 1 | ||
217 | #define ST_OPENING 2 | 216 | #define ST_OPENING 2 |
218 | #define ST_CLOSING 3 | 217 | #define ST_CLOSING 3 |
219 | #define ST_CMDING 4 | 218 | #define ST_CMDING 4 |
@@ -621,7 +620,7 @@ static int stli_brdinit(struct stlibrd *brdp); | |||
621 | static int stli_startbrd(struct stlibrd *brdp); | 620 | static int stli_startbrd(struct stlibrd *brdp); |
622 | static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); | 621 | static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp); |
623 | static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); | 622 | static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp); |
624 | static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); | 623 | static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); |
625 | static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); | 624 | static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); |
626 | static void stli_poll(unsigned long arg); | 625 | static void stli_poll(unsigned long arg); |
627 | static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); | 626 | static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); |
@@ -704,7 +703,7 @@ static const struct file_operations stli_fsiomem = { | |||
704 | .owner = THIS_MODULE, | 703 | .owner = THIS_MODULE, |
705 | .read = stli_memread, | 704 | .read = stli_memread, |
706 | .write = stli_memwrite, | 705 | .write = stli_memwrite, |
707 | .ioctl = stli_memioctl, | 706 | .unlocked_ioctl = stli_memioctl, |
708 | }; | 707 | }; |
709 | 708 | ||
710 | /*****************************************************************************/ | 709 | /*****************************************************************************/ |
@@ -783,13 +782,32 @@ static int stli_parsebrd(struct stlconf *confp, char **argp) | |||
783 | 782 | ||
784 | /*****************************************************************************/ | 783 | /*****************************************************************************/ |
785 | 784 | ||
785 | /* | ||
786 | * On the first open of the device setup the port hardware, and | ||
787 | * initialize the per port data structure. Since initializing the port | ||
788 | * requires several commands to the board we will need to wait for any | ||
789 | * other open that is already initializing the port. | ||
790 | * | ||
791 | * Locking: protected by the port mutex. | ||
792 | */ | ||
793 | |||
794 | static int stli_activate(struct tty_port *port, struct tty_struct *tty) | ||
795 | { | ||
796 | struct stliport *portp = container_of(port, struct stliport, port); | ||
797 | struct stlibrd *brdp = stli_brds[portp->brdnr]; | ||
798 | int rc; | ||
799 | |||
800 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) | ||
801 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
802 | wake_up_interruptible(&portp->raw_wait); | ||
803 | return rc; | ||
804 | } | ||
805 | |||
786 | static int stli_open(struct tty_struct *tty, struct file *filp) | 806 | static int stli_open(struct tty_struct *tty, struct file *filp) |
787 | { | 807 | { |
788 | struct stlibrd *brdp; | 808 | struct stlibrd *brdp; |
789 | struct stliport *portp; | 809 | struct stliport *portp; |
790 | struct tty_port *port; | ||
791 | unsigned int minordev, brdnr, portnr; | 810 | unsigned int minordev, brdnr, portnr; |
792 | int rc; | ||
793 | 811 | ||
794 | minordev = tty->index; | 812 | minordev = tty->index; |
795 | brdnr = MINOR2BRD(minordev); | 813 | brdnr = MINOR2BRD(minordev); |
@@ -809,95 +827,56 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
809 | return -ENODEV; | 827 | return -ENODEV; |
810 | if (portp->devnr < 1) | 828 | if (portp->devnr < 1) |
811 | return -ENODEV; | 829 | return -ENODEV; |
812 | port = &portp->port; | 830 | return tty_port_open(&portp->port, tty, filp); |
813 | |||
814 | /* | ||
815 | * On the first open of the device setup the port hardware, and | ||
816 | * initialize the per port data structure. Since initializing the port | ||
817 | * requires several commands to the board we will need to wait for any | ||
818 | * other open that is already initializing the port. | ||
819 | * | ||
820 | * Review - locking | ||
821 | */ | ||
822 | tty_port_tty_set(port, tty); | ||
823 | tty->driver_data = portp; | ||
824 | port->count++; | ||
825 | |||
826 | wait_event_interruptible(portp->raw_wait, | ||
827 | !test_bit(ST_INITIALIZING, &portp->state)); | ||
828 | if (signal_pending(current)) | ||
829 | return -ERESTARTSYS; | ||
830 | |||
831 | if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { | ||
832 | set_bit(ST_INITIALIZING, &portp->state); | ||
833 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) { | ||
834 | /* Locking */ | ||
835 | port->flags |= ASYNC_INITIALIZED; | ||
836 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
837 | } | ||
838 | clear_bit(ST_INITIALIZING, &portp->state); | ||
839 | wake_up_interruptible(&portp->raw_wait); | ||
840 | if (rc < 0) | ||
841 | return rc; | ||
842 | } | ||
843 | return tty_port_block_til_ready(&portp->port, tty, filp); | ||
844 | } | 831 | } |
845 | 832 | ||
833 | |||
846 | /*****************************************************************************/ | 834 | /*****************************************************************************/ |
847 | 835 | ||
848 | static void stli_close(struct tty_struct *tty, struct file *filp) | 836 | static void stli_shutdown(struct tty_port *port) |
849 | { | 837 | { |
850 | struct stlibrd *brdp; | 838 | struct stlibrd *brdp; |
851 | struct stliport *portp; | 839 | unsigned long ftype; |
852 | struct tty_port *port; | ||
853 | unsigned long flags; | 840 | unsigned long flags; |
841 | struct stliport *portp = container_of(port, struct stliport, port); | ||
854 | 842 | ||
855 | portp = tty->driver_data; | 843 | if (portp->brdnr >= stli_nrbrds) |
856 | if (portp == NULL) | ||
857 | return; | 844 | return; |
858 | port = &portp->port; | 845 | brdp = stli_brds[portp->brdnr]; |
859 | 846 | if (brdp == NULL) | |
860 | if (tty_port_close_start(port, tty, filp) == 0) | ||
861 | return; | 847 | return; |
862 | 848 | ||
863 | /* | 849 | /* |
864 | * May want to wait for data to drain before closing. The BUSY flag | 850 | * May want to wait for data to drain before closing. The BUSY |
865 | * keeps track of whether we are still transmitting or not. It is | 851 | * flag keeps track of whether we are still transmitting or not. |
866 | * updated by messages from the slave - indicating when all chars | 852 | * It is updated by messages from the slave - indicating when all |
867 | * really have drained. | 853 | * chars really have drained. |
868 | */ | 854 | */ |
869 | spin_lock_irqsave(&stli_lock, flags); | ||
870 | if (tty == stli_txcooktty) | ||
871 | stli_flushchars(tty); | ||
872 | spin_unlock_irqrestore(&stli_lock, flags); | ||
873 | |||
874 | /* We end up doing this twice for the moment. This needs looking at | ||
875 | eventually. Note we still use portp->closing_wait as a result */ | ||
876 | if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
877 | tty_wait_until_sent(tty, portp->closing_wait); | ||
878 | 855 | ||
879 | /* FIXME: port locking here needs attending to */ | 856 | if (!test_bit(ST_CLOSING, &portp->state)) |
880 | port->flags &= ~ASYNC_INITIALIZED; | 857 | stli_rawclose(brdp, portp, 0, 0); |
881 | 858 | ||
882 | brdp = stli_brds[portp->brdnr]; | 859 | spin_lock_irqsave(&stli_lock, flags); |
883 | stli_rawclose(brdp, portp, 0, 0); | ||
884 | if (tty->termios->c_cflag & HUPCL) { | ||
885 | stli_mkasysigs(&portp->asig, 0, 0); | ||
886 | if (test_bit(ST_CMDING, &portp->state)) | ||
887 | set_bit(ST_DOSIGS, &portp->state); | ||
888 | else | ||
889 | stli_sendcmd(brdp, portp, A_SETSIGNALS, &portp->asig, | ||
890 | sizeof(asysigs_t), 0); | ||
891 | } | ||
892 | clear_bit(ST_TXBUSY, &portp->state); | 860 | clear_bit(ST_TXBUSY, &portp->state); |
893 | clear_bit(ST_RXSTOP, &portp->state); | 861 | clear_bit(ST_RXSTOP, &portp->state); |
894 | set_bit(TTY_IO_ERROR, &tty->flags); | 862 | spin_unlock_irqrestore(&stli_lock, flags); |
895 | tty_ldisc_flush(tty); | ||
896 | set_bit(ST_DOFLUSHRX, &portp->state); | ||
897 | stli_flushbuffer(tty); | ||
898 | 863 | ||
899 | tty_port_close_end(port, tty); | 864 | ftype = FLUSHTX | FLUSHRX; |
900 | tty_port_tty_set(port, NULL); | 865 | stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0); |
866 | } | ||
867 | |||
868 | static void stli_close(struct tty_struct *tty, struct file *filp) | ||
869 | { | ||
870 | struct stliport *portp = tty->driver_data; | ||
871 | unsigned long flags; | ||
872 | if (portp == NULL) | ||
873 | return; | ||
874 | spin_lock_irqsave(&stli_lock, flags); | ||
875 | /* Flush any internal buffering out first */ | ||
876 | if (tty == stli_txcooktty) | ||
877 | stli_flushchars(tty); | ||
878 | spin_unlock_irqrestore(&stli_lock, flags); | ||
879 | tty_port_close(&portp->port, tty, filp); | ||
901 | } | 880 | } |
902 | 881 | ||
903 | /*****************************************************************************/ | 882 | /*****************************************************************************/ |
@@ -1724,6 +1703,7 @@ static void stli_start(struct tty_struct *tty) | |||
1724 | 1703 | ||
1725 | /*****************************************************************************/ | 1704 | /*****************************************************************************/ |
1726 | 1705 | ||
1706 | |||
1727 | /* | 1707 | /* |
1728 | * Hangup this port. This is pretty much like closing the port, only | 1708 | * Hangup this port. This is pretty much like closing the port, only |
1729 | * a little more brutal. No waiting for data to drain. Shutdown the | 1709 | * a little more brutal. No waiting for data to drain. Shutdown the |
@@ -1733,47 +1713,8 @@ static void stli_start(struct tty_struct *tty) | |||
1733 | 1713 | ||
1734 | static void stli_hangup(struct tty_struct *tty) | 1714 | static void stli_hangup(struct tty_struct *tty) |
1735 | { | 1715 | { |
1736 | struct stliport *portp; | 1716 | struct stliport *portp = tty->driver_data; |
1737 | struct stlibrd *brdp; | 1717 | tty_port_hangup(&portp->port); |
1738 | struct tty_port *port; | ||
1739 | unsigned long flags; | ||
1740 | |||
1741 | portp = tty->driver_data; | ||
1742 | if (portp == NULL) | ||
1743 | return; | ||
1744 | if (portp->brdnr >= stli_nrbrds) | ||
1745 | return; | ||
1746 | brdp = stli_brds[portp->brdnr]; | ||
1747 | if (brdp == NULL) | ||
1748 | return; | ||
1749 | port = &portp->port; | ||
1750 | |||
1751 | spin_lock_irqsave(&port->lock, flags); | ||
1752 | port->flags &= ~ASYNC_INITIALIZED; | ||
1753 | spin_unlock_irqrestore(&port->lock, flags); | ||
1754 | |||
1755 | if (!test_bit(ST_CLOSING, &portp->state)) | ||
1756 | stli_rawclose(brdp, portp, 0, 0); | ||
1757 | |||
1758 | spin_lock_irqsave(&stli_lock, flags); | ||
1759 | if (tty->termios->c_cflag & HUPCL) { | ||
1760 | stli_mkasysigs(&portp->asig, 0, 0); | ||
1761 | if (test_bit(ST_CMDING, &portp->state)) { | ||
1762 | set_bit(ST_DOSIGS, &portp->state); | ||
1763 | set_bit(ST_DOFLUSHTX, &portp->state); | ||
1764 | set_bit(ST_DOFLUSHRX, &portp->state); | ||
1765 | } else { | ||
1766 | stli_sendcmd(brdp, portp, A_SETSIGNALSF, | ||
1767 | &portp->asig, sizeof(asysigs_t), 0); | ||
1768 | } | ||
1769 | } | ||
1770 | |||
1771 | clear_bit(ST_TXBUSY, &portp->state); | ||
1772 | clear_bit(ST_RXSTOP, &portp->state); | ||
1773 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
1774 | spin_unlock_irqrestore(&stli_lock, flags); | ||
1775 | |||
1776 | tty_port_hangup(port); | ||
1777 | } | 1718 | } |
1778 | 1719 | ||
1779 | /*****************************************************************************/ | 1720 | /*****************************************************************************/ |
@@ -4311,7 +4252,7 @@ static int stli_getbrdstruct(struct stlibrd __user *arg) | |||
4311 | * reset it, and start/stop it. | 4252 | * reset it, and start/stop it. |
4312 | */ | 4253 | */ |
4313 | 4254 | ||
4314 | static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) | 4255 | static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) |
4315 | { | 4256 | { |
4316 | struct stlibrd *brdp; | 4257 | struct stlibrd *brdp; |
4317 | int brdnr, rc, done; | 4258 | int brdnr, rc, done; |
@@ -4356,7 +4297,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un | |||
4356 | * Now handle the board specific ioctls. These all depend on the | 4297 | * Now handle the board specific ioctls. These all depend on the |
4357 | * minor number of the device they were called from. | 4298 | * minor number of the device they were called from. |
4358 | */ | 4299 | */ |
4359 | brdnr = iminor(ip); | 4300 | brdnr = iminor(fp->f_dentry->d_inode); |
4360 | if (brdnr >= STL_MAXBRDS) | 4301 | if (brdnr >= STL_MAXBRDS) |
4361 | return -ENODEV; | 4302 | return -ENODEV; |
4362 | brdp = stli_brds[brdnr]; | 4303 | brdp = stli_brds[brdnr]; |
@@ -4420,6 +4361,8 @@ static const struct tty_operations stli_ops = { | |||
4420 | static const struct tty_port_operations stli_port_ops = { | 4361 | static const struct tty_port_operations stli_port_ops = { |
4421 | .carrier_raised = stli_carrier_raised, | 4362 | .carrier_raised = stli_carrier_raised, |
4422 | .dtr_rts = stli_dtr_rts, | 4363 | .dtr_rts = stli_dtr_rts, |
4364 | .activate = stli_activate, | ||
4365 | .shutdown = stli_shutdown, | ||
4423 | }; | 4366 | }; |
4424 | 4367 | ||
4425 | /*****************************************************************************/ | 4368 | /*****************************************************************************/ |
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index dd0083bbb64a..63ee3bbc1ce4 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/tty.h> | 34 | #include <linux/tty.h> |
35 | #include <linux/tty_flip.h> | 35 | #include <linux/tty_flip.h> |
36 | #include <linux/major.h> | 36 | #include <linux/major.h> |
37 | #include <linux/smp_lock.h> | ||
38 | #include <linux/string.h> | 37 | #include <linux/string.h> |
39 | #include <linux/fcntl.h> | 38 | #include <linux/fcntl.h> |
40 | #include <linux/ptrace.h> | 39 | #include <linux/ptrace.h> |
@@ -139,7 +138,7 @@ struct moxa_port { | |||
139 | int cflag; | 138 | int cflag; |
140 | unsigned long statusflags; | 139 | unsigned long statusflags; |
141 | 140 | ||
142 | u8 DCDState; | 141 | u8 DCDState; /* Protected by the port lock */ |
143 | u8 lineCtrl; | 142 | u8 lineCtrl; |
144 | u8 lowChkFlag; | 143 | u8 lowChkFlag; |
145 | }; | 144 | }; |
@@ -151,10 +150,9 @@ struct mon_str { | |||
151 | }; | 150 | }; |
152 | 151 | ||
153 | /* statusflags */ | 152 | /* statusflags */ |
154 | #define TXSTOPPED 0x1 | 153 | #define TXSTOPPED 1 |
155 | #define LOWWAIT 0x2 | 154 | #define LOWWAIT 2 |
156 | #define EMPTYWAIT 0x4 | 155 | #define EMPTYWAIT 3 |
157 | #define THROTTLE 0x8 | ||
158 | 156 | ||
159 | #define SERIAL_DO_RESTART | 157 | #define SERIAL_DO_RESTART |
160 | 158 | ||
@@ -165,6 +163,7 @@ static struct mon_str moxaLog; | |||
165 | static unsigned int moxaFuncTout = HZ / 2; | 163 | static unsigned int moxaFuncTout = HZ / 2; |
166 | static unsigned int moxaLowWaterChk; | 164 | static unsigned int moxaLowWaterChk; |
167 | static DEFINE_MUTEX(moxa_openlock); | 165 | static DEFINE_MUTEX(moxa_openlock); |
166 | static DEFINE_SPINLOCK(moxa_lock); | ||
168 | /* Variables for insmod */ | 167 | /* Variables for insmod */ |
169 | #ifdef MODULE | 168 | #ifdef MODULE |
170 | static unsigned long baseaddr[MAX_BOARDS]; | 169 | static unsigned long baseaddr[MAX_BOARDS]; |
@@ -194,8 +193,6 @@ static int moxa_write(struct tty_struct *, const unsigned char *, int); | |||
194 | static int moxa_write_room(struct tty_struct *); | 193 | static int moxa_write_room(struct tty_struct *); |
195 | static void moxa_flush_buffer(struct tty_struct *); | 194 | static void moxa_flush_buffer(struct tty_struct *); |
196 | static int moxa_chars_in_buffer(struct tty_struct *); | 195 | static int moxa_chars_in_buffer(struct tty_struct *); |
197 | static void moxa_throttle(struct tty_struct *); | ||
198 | static void moxa_unthrottle(struct tty_struct *); | ||
199 | static void moxa_set_termios(struct tty_struct *, struct ktermios *); | 196 | static void moxa_set_termios(struct tty_struct *, struct ktermios *); |
200 | static void moxa_stop(struct tty_struct *); | 197 | static void moxa_stop(struct tty_struct *); |
201 | static void moxa_start(struct tty_struct *); | 198 | static void moxa_start(struct tty_struct *); |
@@ -205,9 +202,9 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, | |||
205 | unsigned int set, unsigned int clear); | 202 | unsigned int set, unsigned int clear); |
206 | static void moxa_poll(unsigned long); | 203 | static void moxa_poll(unsigned long); |
207 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); | 204 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); |
208 | static void moxa_setup_empty_event(struct tty_struct *); | 205 | static void moxa_shutdown(struct tty_port *); |
209 | static void moxa_shut_down(struct tty_struct *); | ||
210 | static int moxa_carrier_raised(struct tty_port *); | 206 | static int moxa_carrier_raised(struct tty_port *); |
207 | static void moxa_dtr_rts(struct tty_port *, int); | ||
211 | /* | 208 | /* |
212 | * moxa board interface functions: | 209 | * moxa board interface functions: |
213 | */ | 210 | */ |
@@ -234,6 +231,8 @@ static void MoxaSetFifo(struct moxa_port *port, int enable); | |||
234 | * I/O functions | 231 | * I/O functions |
235 | */ | 232 | */ |
236 | 233 | ||
234 | static DEFINE_SPINLOCK(moxafunc_lock); | ||
235 | |||
237 | static void moxa_wait_finish(void __iomem *ofsAddr) | 236 | static void moxa_wait_finish(void __iomem *ofsAddr) |
238 | { | 237 | { |
239 | unsigned long end = jiffies + moxaFuncTout; | 238 | unsigned long end = jiffies + moxaFuncTout; |
@@ -247,9 +246,25 @@ static void moxa_wait_finish(void __iomem *ofsAddr) | |||
247 | 246 | ||
248 | static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg) | 247 | static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg) |
249 | { | 248 | { |
249 | unsigned long flags; | ||
250 | spin_lock_irqsave(&moxafunc_lock, flags); | ||
250 | writew(arg, ofsAddr + FuncArg); | 251 | writew(arg, ofsAddr + FuncArg); |
251 | writew(cmd, ofsAddr + FuncCode); | 252 | writew(cmd, ofsAddr + FuncCode); |
252 | moxa_wait_finish(ofsAddr); | 253 | moxa_wait_finish(ofsAddr); |
254 | spin_unlock_irqrestore(&moxafunc_lock, flags); | ||
255 | } | ||
256 | |||
257 | static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg) | ||
258 | { | ||
259 | unsigned long flags; | ||
260 | u16 ret; | ||
261 | spin_lock_irqsave(&moxafunc_lock, flags); | ||
262 | writew(arg, ofsAddr + FuncArg); | ||
263 | writew(cmd, ofsAddr + FuncCode); | ||
264 | moxa_wait_finish(ofsAddr); | ||
265 | ret = readw(ofsAddr + FuncArg); | ||
266 | spin_unlock_irqrestore(&moxafunc_lock, flags); | ||
267 | return ret; | ||
253 | } | 268 | } |
254 | 269 | ||
255 | static void moxa_low_water_check(void __iomem *ofsAddr) | 270 | static void moxa_low_water_check(void __iomem *ofsAddr) |
@@ -299,22 +314,20 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
299 | struct moxa_port *p; | 314 | struct moxa_port *p; |
300 | unsigned int i, j; | 315 | unsigned int i, j; |
301 | 316 | ||
302 | mutex_lock(&moxa_openlock); | ||
303 | for (i = 0; i < MAX_BOARDS; i++) { | 317 | for (i = 0; i < MAX_BOARDS; i++) { |
304 | p = moxa_boards[i].ports; | 318 | p = moxa_boards[i].ports; |
305 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { | 319 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { |
306 | memset(&tmp, 0, sizeof(tmp)); | 320 | memset(&tmp, 0, sizeof(tmp)); |
321 | spin_lock_bh(&moxa_lock); | ||
307 | if (moxa_boards[i].ready) { | 322 | if (moxa_boards[i].ready) { |
308 | tmp.inq = MoxaPortRxQueue(p); | 323 | tmp.inq = MoxaPortRxQueue(p); |
309 | tmp.outq = MoxaPortTxQueue(p); | 324 | tmp.outq = MoxaPortTxQueue(p); |
310 | } | 325 | } |
311 | if (copy_to_user(argm, &tmp, sizeof(tmp))) { | 326 | spin_unlock_bh(&moxa_lock); |
312 | mutex_unlock(&moxa_openlock); | 327 | if (copy_to_user(argm, &tmp, sizeof(tmp))) |
313 | return -EFAULT; | 328 | return -EFAULT; |
314 | } | ||
315 | } | 329 | } |
316 | } | 330 | } |
317 | mutex_unlock(&moxa_openlock); | ||
318 | break; | 331 | break; |
319 | } case MOXA_GET_OQUEUE: | 332 | } case MOXA_GET_OQUEUE: |
320 | status = MoxaPortTxQueue(ch); | 333 | status = MoxaPortTxQueue(ch); |
@@ -330,16 +343,20 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
330 | struct moxa_port *p; | 343 | struct moxa_port *p; |
331 | unsigned int i, j; | 344 | unsigned int i, j; |
332 | 345 | ||
333 | mutex_lock(&moxa_openlock); | ||
334 | for (i = 0; i < MAX_BOARDS; i++) { | 346 | for (i = 0; i < MAX_BOARDS; i++) { |
335 | p = moxa_boards[i].ports; | 347 | p = moxa_boards[i].ports; |
336 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { | 348 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { |
337 | struct tty_struct *ttyp; | 349 | struct tty_struct *ttyp; |
338 | memset(&tmp, 0, sizeof(tmp)); | 350 | memset(&tmp, 0, sizeof(tmp)); |
339 | if (!moxa_boards[i].ready) | 351 | spin_lock_bh(&moxa_lock); |
352 | if (!moxa_boards[i].ready) { | ||
353 | spin_unlock_bh(&moxa_lock); | ||
340 | goto copy; | 354 | goto copy; |
355 | } | ||
341 | 356 | ||
342 | status = MoxaPortLineStatus(p); | 357 | status = MoxaPortLineStatus(p); |
358 | spin_unlock_bh(&moxa_lock); | ||
359 | |||
343 | if (status & 1) | 360 | if (status & 1) |
344 | tmp.cts = 1; | 361 | tmp.cts = 1; |
345 | if (status & 2) | 362 | if (status & 2) |
@@ -354,24 +371,21 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
354 | tmp.cflag = ttyp->termios->c_cflag; | 371 | tmp.cflag = ttyp->termios->c_cflag; |
355 | tty_kref_put(tty); | 372 | tty_kref_put(tty); |
356 | copy: | 373 | copy: |
357 | if (copy_to_user(argm, &tmp, sizeof(tmp))) { | 374 | if (copy_to_user(argm, &tmp, sizeof(tmp))) |
358 | mutex_unlock(&moxa_openlock); | ||
359 | return -EFAULT; | 375 | return -EFAULT; |
360 | } | ||
361 | } | 376 | } |
362 | } | 377 | } |
363 | mutex_unlock(&moxa_openlock); | ||
364 | break; | 378 | break; |
365 | } | 379 | } |
366 | case TIOCGSERIAL: | 380 | case TIOCGSERIAL: |
367 | mutex_lock(&moxa_openlock); | 381 | mutex_lock(&ch->port.mutex); |
368 | ret = moxa_get_serial_info(ch, argp); | 382 | ret = moxa_get_serial_info(ch, argp); |
369 | mutex_unlock(&moxa_openlock); | 383 | mutex_unlock(&ch->port.mutex); |
370 | break; | 384 | break; |
371 | case TIOCSSERIAL: | 385 | case TIOCSSERIAL: |
372 | mutex_lock(&moxa_openlock); | 386 | mutex_lock(&ch->port.mutex); |
373 | ret = moxa_set_serial_info(ch, argp); | 387 | ret = moxa_set_serial_info(ch, argp); |
374 | mutex_unlock(&moxa_openlock); | 388 | mutex_unlock(&ch->port.mutex); |
375 | break; | 389 | break; |
376 | default: | 390 | default: |
377 | ret = -ENOIOCTLCMD; | 391 | ret = -ENOIOCTLCMD; |
@@ -396,8 +410,6 @@ static const struct tty_operations moxa_ops = { | |||
396 | .flush_buffer = moxa_flush_buffer, | 410 | .flush_buffer = moxa_flush_buffer, |
397 | .chars_in_buffer = moxa_chars_in_buffer, | 411 | .chars_in_buffer = moxa_chars_in_buffer, |
398 | .ioctl = moxa_ioctl, | 412 | .ioctl = moxa_ioctl, |
399 | .throttle = moxa_throttle, | ||
400 | .unthrottle = moxa_unthrottle, | ||
401 | .set_termios = moxa_set_termios, | 413 | .set_termios = moxa_set_termios, |
402 | .stop = moxa_stop, | 414 | .stop = moxa_stop, |
403 | .start = moxa_start, | 415 | .start = moxa_start, |
@@ -409,11 +421,12 @@ static const struct tty_operations moxa_ops = { | |||
409 | 421 | ||
410 | static const struct tty_port_operations moxa_port_ops = { | 422 | static const struct tty_port_operations moxa_port_ops = { |
411 | .carrier_raised = moxa_carrier_raised, | 423 | .carrier_raised = moxa_carrier_raised, |
424 | .dtr_rts = moxa_dtr_rts, | ||
425 | .shutdown = moxa_shutdown, | ||
412 | }; | 426 | }; |
413 | 427 | ||
414 | static struct tty_driver *moxaDriver; | 428 | static struct tty_driver *moxaDriver; |
415 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); | 429 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); |
416 | static DEFINE_SPINLOCK(moxa_lock); | ||
417 | 430 | ||
418 | /* | 431 | /* |
419 | * HW init | 432 | * HW init |
@@ -1112,14 +1125,12 @@ static void __exit moxa_exit(void) | |||
1112 | module_init(moxa_init); | 1125 | module_init(moxa_init); |
1113 | module_exit(moxa_exit); | 1126 | module_exit(moxa_exit); |
1114 | 1127 | ||
1115 | static void moxa_close_port(struct tty_struct *tty) | 1128 | static void moxa_shutdown(struct tty_port *port) |
1116 | { | 1129 | { |
1117 | struct moxa_port *ch = tty->driver_data; | 1130 | struct moxa_port *ch = container_of(port, struct moxa_port, port); |
1118 | moxa_shut_down(tty); | 1131 | MoxaPortDisable(ch); |
1119 | MoxaPortFlushData(ch, 2); | 1132 | MoxaPortFlushData(ch, 2); |
1120 | ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1133 | clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); |
1121 | tty->driver_data = NULL; | ||
1122 | tty_port_tty_set(&ch->port, NULL); | ||
1123 | } | 1134 | } |
1124 | 1135 | ||
1125 | static int moxa_carrier_raised(struct tty_port *port) | 1136 | static int moxa_carrier_raised(struct tty_port *port) |
@@ -1127,45 +1138,19 @@ static int moxa_carrier_raised(struct tty_port *port) | |||
1127 | struct moxa_port *ch = container_of(port, struct moxa_port, port); | 1138 | struct moxa_port *ch = container_of(port, struct moxa_port, port); |
1128 | int dcd; | 1139 | int dcd; |
1129 | 1140 | ||
1130 | spin_lock_bh(&moxa_lock); | 1141 | spin_lock_irq(&port->lock); |
1131 | dcd = ch->DCDState; | 1142 | dcd = ch->DCDState; |
1132 | spin_unlock_bh(&moxa_lock); | 1143 | spin_unlock_irq(&port->lock); |
1133 | return dcd; | 1144 | return dcd; |
1134 | } | 1145 | } |
1135 | 1146 | ||
1136 | static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, | 1147 | static void moxa_dtr_rts(struct tty_port *port, int onoff) |
1137 | struct moxa_port *ch) | ||
1138 | { | 1148 | { |
1139 | struct tty_port *port = &ch->port; | 1149 | struct moxa_port *ch = container_of(port, struct moxa_port, port); |
1140 | DEFINE_WAIT(wait); | 1150 | MoxaPortLineCtrl(ch, onoff, onoff); |
1141 | int retval = 0; | ||
1142 | u8 dcd; | ||
1143 | |||
1144 | while (1) { | ||
1145 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); | ||
1146 | if (tty_hung_up_p(filp)) { | ||
1147 | #ifdef SERIAL_DO_RESTART | ||
1148 | retval = -ERESTARTSYS; | ||
1149 | #else | ||
1150 | retval = -EAGAIN; | ||
1151 | #endif | ||
1152 | break; | ||
1153 | } | ||
1154 | dcd = tty_port_carrier_raised(port); | ||
1155 | if (dcd) | ||
1156 | break; | ||
1157 | |||
1158 | if (signal_pending(current)) { | ||
1159 | retval = -ERESTARTSYS; | ||
1160 | break; | ||
1161 | } | ||
1162 | schedule(); | ||
1163 | } | ||
1164 | finish_wait(&port->open_wait, &wait); | ||
1165 | |||
1166 | return retval; | ||
1167 | } | 1151 | } |
1168 | 1152 | ||
1153 | |||
1169 | static int moxa_open(struct tty_struct *tty, struct file *filp) | 1154 | static int moxa_open(struct tty_struct *tty, struct file *filp) |
1170 | { | 1155 | { |
1171 | struct moxa_board_conf *brd; | 1156 | struct moxa_board_conf *brd; |
@@ -1194,6 +1179,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
1194 | ch->port.count++; | 1179 | ch->port.count++; |
1195 | tty->driver_data = ch; | 1180 | tty->driver_data = ch; |
1196 | tty_port_tty_set(&ch->port, tty); | 1181 | tty_port_tty_set(&ch->port, tty); |
1182 | mutex_lock(&ch->port.mutex); | ||
1197 | if (!(ch->port.flags & ASYNC_INITIALIZED)) { | 1183 | if (!(ch->port.flags & ASYNC_INITIALIZED)) { |
1198 | ch->statusflags = 0; | 1184 | ch->statusflags = 0; |
1199 | moxa_set_tty_param(tty, tty->termios); | 1185 | moxa_set_tty_param(tty, tty->termios); |
@@ -1202,58 +1188,20 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
1202 | MoxaSetFifo(ch, ch->type == PORT_16550A); | 1188 | MoxaSetFifo(ch, ch->type == PORT_16550A); |
1203 | ch->port.flags |= ASYNC_INITIALIZED; | 1189 | ch->port.flags |= ASYNC_INITIALIZED; |
1204 | } | 1190 | } |
1191 | mutex_unlock(&ch->port.mutex); | ||
1205 | mutex_unlock(&moxa_openlock); | 1192 | mutex_unlock(&moxa_openlock); |
1206 | 1193 | ||
1207 | retval = 0; | 1194 | retval = tty_port_block_til_ready(&ch->port, tty, filp); |
1208 | if (!(filp->f_flags & O_NONBLOCK) && !C_CLOCAL(tty)) | 1195 | if (retval == 0) |
1209 | retval = moxa_block_till_ready(tty, filp, ch); | 1196 | set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags); |
1210 | mutex_lock(&moxa_openlock); | ||
1211 | if (retval) { | ||
1212 | if (ch->port.count) /* 0 means already hung up... */ | ||
1213 | if (--ch->port.count == 0) | ||
1214 | moxa_close_port(tty); | ||
1215 | } else | ||
1216 | ch->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
1217 | mutex_unlock(&moxa_openlock); | ||
1218 | |||
1219 | return retval; | 1197 | return retval; |
1220 | } | 1198 | } |
1221 | 1199 | ||
1222 | static void moxa_close(struct tty_struct *tty, struct file *filp) | 1200 | static void moxa_close(struct tty_struct *tty, struct file *filp) |
1223 | { | 1201 | { |
1224 | struct moxa_port *ch; | 1202 | struct moxa_port *ch = tty->driver_data; |
1225 | int port; | ||
1226 | |||
1227 | port = tty->index; | ||
1228 | if (port == MAX_PORTS || tty_hung_up_p(filp)) | ||
1229 | return; | ||
1230 | |||
1231 | mutex_lock(&moxa_openlock); | ||
1232 | ch = tty->driver_data; | ||
1233 | if (ch == NULL) | ||
1234 | goto unlock; | ||
1235 | if (tty->count == 1 && ch->port.count != 1) { | ||
1236 | printk(KERN_WARNING "moxa_close: bad serial port count; " | ||
1237 | "tty->count is 1, ch->port.count is %d\n", ch->port.count); | ||
1238 | ch->port.count = 1; | ||
1239 | } | ||
1240 | if (--ch->port.count < 0) { | ||
1241 | printk(KERN_WARNING "moxa_close: bad serial port count, " | ||
1242 | "device=%s\n", tty->name); | ||
1243 | ch->port.count = 0; | ||
1244 | } | ||
1245 | if (ch->port.count) | ||
1246 | goto unlock; | ||
1247 | |||
1248 | ch->cflag = tty->termios->c_cflag; | 1203 | ch->cflag = tty->termios->c_cflag; |
1249 | if (ch->port.flags & ASYNC_INITIALIZED) { | 1204 | tty_port_close(&ch->port, tty, filp); |
1250 | moxa_setup_empty_event(tty); | ||
1251 | tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ | ||
1252 | } | ||
1253 | |||
1254 | moxa_close_port(tty); | ||
1255 | unlock: | ||
1256 | mutex_unlock(&moxa_openlock); | ||
1257 | } | 1205 | } |
1258 | 1206 | ||
1259 | static int moxa_write(struct tty_struct *tty, | 1207 | static int moxa_write(struct tty_struct *tty, |
@@ -1269,7 +1217,7 @@ static int moxa_write(struct tty_struct *tty, | |||
1269 | len = MoxaPortWriteData(tty, buf, count); | 1217 | len = MoxaPortWriteData(tty, buf, count); |
1270 | spin_unlock_bh(&moxa_lock); | 1218 | spin_unlock_bh(&moxa_lock); |
1271 | 1219 | ||
1272 | ch->statusflags |= LOWWAIT; | 1220 | set_bit(LOWWAIT, &ch->statusflags); |
1273 | return len; | 1221 | return len; |
1274 | } | 1222 | } |
1275 | 1223 | ||
@@ -1300,40 +1248,21 @@ static int moxa_chars_in_buffer(struct tty_struct *tty) | |||
1300 | struct moxa_port *ch = tty->driver_data; | 1248 | struct moxa_port *ch = tty->driver_data; |
1301 | int chars; | 1249 | int chars; |
1302 | 1250 | ||
1303 | /* | ||
1304 | * Sigh...I have to check if driver_data is NULL here, because | ||
1305 | * if an open() fails, the TTY subsystem eventually calls | ||
1306 | * tty_wait_until_sent(), which calls the driver's chars_in_buffer() | ||
1307 | * routine. And since the open() failed, we return 0 here. TDJ | ||
1308 | */ | ||
1309 | if (ch == NULL) | ||
1310 | return 0; | ||
1311 | lock_kernel(); | ||
1312 | chars = MoxaPortTxQueue(ch); | 1251 | chars = MoxaPortTxQueue(ch); |
1313 | if (chars) { | 1252 | if (chars) |
1314 | /* | 1253 | /* |
1315 | * Make it possible to wakeup anything waiting for output | 1254 | * Make it possible to wakeup anything waiting for output |
1316 | * in tty_ioctl.c, etc. | 1255 | * in tty_ioctl.c, etc. |
1317 | */ | 1256 | */ |
1318 | if (!(ch->statusflags & EMPTYWAIT)) | 1257 | set_bit(EMPTYWAIT, &ch->statusflags); |
1319 | moxa_setup_empty_event(tty); | ||
1320 | } | ||
1321 | unlock_kernel(); | ||
1322 | return chars; | 1258 | return chars; |
1323 | } | 1259 | } |
1324 | 1260 | ||
1325 | static int moxa_tiocmget(struct tty_struct *tty, struct file *file) | 1261 | static int moxa_tiocmget(struct tty_struct *tty, struct file *file) |
1326 | { | 1262 | { |
1327 | struct moxa_port *ch; | 1263 | struct moxa_port *ch = tty->driver_data; |
1328 | int flag = 0, dtr, rts; | 1264 | int flag = 0, dtr, rts; |
1329 | 1265 | ||
1330 | mutex_lock(&moxa_openlock); | ||
1331 | ch = tty->driver_data; | ||
1332 | if (!ch) { | ||
1333 | mutex_unlock(&moxa_openlock); | ||
1334 | return -EINVAL; | ||
1335 | } | ||
1336 | |||
1337 | MoxaPortGetLineOut(ch, &dtr, &rts); | 1266 | MoxaPortGetLineOut(ch, &dtr, &rts); |
1338 | if (dtr) | 1267 | if (dtr) |
1339 | flag |= TIOCM_DTR; | 1268 | flag |= TIOCM_DTR; |
@@ -1346,7 +1275,6 @@ static int moxa_tiocmget(struct tty_struct *tty, struct file *file) | |||
1346 | flag |= TIOCM_DSR; | 1275 | flag |= TIOCM_DSR; |
1347 | if (dtr & 4) | 1276 | if (dtr & 4) |
1348 | flag |= TIOCM_CD; | 1277 | flag |= TIOCM_CD; |
1349 | mutex_unlock(&moxa_openlock); | ||
1350 | return flag; | 1278 | return flag; |
1351 | } | 1279 | } |
1352 | 1280 | ||
@@ -1379,20 +1307,6 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, | |||
1379 | return 0; | 1307 | return 0; |
1380 | } | 1308 | } |
1381 | 1309 | ||
1382 | static void moxa_throttle(struct tty_struct *tty) | ||
1383 | { | ||
1384 | struct moxa_port *ch = tty->driver_data; | ||
1385 | |||
1386 | ch->statusflags |= THROTTLE; | ||
1387 | } | ||
1388 | |||
1389 | static void moxa_unthrottle(struct tty_struct *tty) | ||
1390 | { | ||
1391 | struct moxa_port *ch = tty->driver_data; | ||
1392 | |||
1393 | ch->statusflags &= ~THROTTLE; | ||
1394 | } | ||
1395 | |||
1396 | static void moxa_set_termios(struct tty_struct *tty, | 1310 | static void moxa_set_termios(struct tty_struct *tty, |
1397 | struct ktermios *old_termios) | 1311 | struct ktermios *old_termios) |
1398 | { | 1312 | { |
@@ -1412,7 +1326,7 @@ static void moxa_stop(struct tty_struct *tty) | |||
1412 | if (ch == NULL) | 1326 | if (ch == NULL) |
1413 | return; | 1327 | return; |
1414 | MoxaPortTxDisable(ch); | 1328 | MoxaPortTxDisable(ch); |
1415 | ch->statusflags |= TXSTOPPED; | 1329 | set_bit(TXSTOPPED, &ch->statusflags); |
1416 | } | 1330 | } |
1417 | 1331 | ||
1418 | 1332 | ||
@@ -1427,38 +1341,32 @@ static void moxa_start(struct tty_struct *tty) | |||
1427 | return; | 1341 | return; |
1428 | 1342 | ||
1429 | MoxaPortTxEnable(ch); | 1343 | MoxaPortTxEnable(ch); |
1430 | ch->statusflags &= ~TXSTOPPED; | 1344 | clear_bit(TXSTOPPED, &ch->statusflags); |
1431 | } | 1345 | } |
1432 | 1346 | ||
1433 | static void moxa_hangup(struct tty_struct *tty) | 1347 | static void moxa_hangup(struct tty_struct *tty) |
1434 | { | 1348 | { |
1435 | struct moxa_port *ch; | 1349 | struct moxa_port *ch = tty->driver_data; |
1436 | 1350 | tty_port_hangup(&ch->port); | |
1437 | mutex_lock(&moxa_openlock); | ||
1438 | ch = tty->driver_data; | ||
1439 | if (ch == NULL) { | ||
1440 | mutex_unlock(&moxa_openlock); | ||
1441 | return; | ||
1442 | } | ||
1443 | ch->port.count = 0; | ||
1444 | moxa_close_port(tty); | ||
1445 | mutex_unlock(&moxa_openlock); | ||
1446 | |||
1447 | wake_up_interruptible(&ch->port.open_wait); | ||
1448 | } | 1351 | } |
1449 | 1352 | ||
1450 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) | 1353 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) |
1451 | { | 1354 | { |
1452 | struct tty_struct *tty; | 1355 | struct tty_struct *tty; |
1356 | unsigned long flags; | ||
1453 | dcd = !!dcd; | 1357 | dcd = !!dcd; |
1454 | 1358 | ||
1359 | spin_lock_irqsave(&p->port.lock, flags); | ||
1455 | if (dcd != p->DCDState) { | 1360 | if (dcd != p->DCDState) { |
1361 | p->DCDState = dcd; | ||
1362 | spin_unlock_irqrestore(&p->port.lock, flags); | ||
1456 | tty = tty_port_tty_get(&p->port); | 1363 | tty = tty_port_tty_get(&p->port); |
1457 | if (tty && C_CLOCAL(tty) && !dcd) | 1364 | if (tty && C_CLOCAL(tty) && !dcd) |
1458 | tty_hangup(tty); | 1365 | tty_hangup(tty); |
1459 | tty_kref_put(tty); | 1366 | tty_kref_put(tty); |
1460 | } | 1367 | } |
1461 | p->DCDState = dcd; | 1368 | else |
1369 | spin_unlock_irqrestore(&p->port.lock, flags); | ||
1462 | } | 1370 | } |
1463 | 1371 | ||
1464 | static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | 1372 | static int moxa_poll_port(struct moxa_port *p, unsigned int handle, |
@@ -1470,24 +1378,24 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | |||
1470 | u16 intr; | 1378 | u16 intr; |
1471 | 1379 | ||
1472 | if (tty) { | 1380 | if (tty) { |
1473 | if ((p->statusflags & EMPTYWAIT) && | 1381 | if (test_bit(EMPTYWAIT, &p->statusflags) && |
1474 | MoxaPortTxQueue(p) == 0) { | 1382 | MoxaPortTxQueue(p) == 0) { |
1475 | p->statusflags &= ~EMPTYWAIT; | 1383 | clear_bit(EMPTYWAIT, &p->statusflags); |
1476 | tty_wakeup(tty); | 1384 | tty_wakeup(tty); |
1477 | } | 1385 | } |
1478 | if ((p->statusflags & LOWWAIT) && !tty->stopped && | 1386 | if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped && |
1479 | MoxaPortTxQueue(p) <= WAKEUP_CHARS) { | 1387 | MoxaPortTxQueue(p) <= WAKEUP_CHARS) { |
1480 | p->statusflags &= ~LOWWAIT; | 1388 | clear_bit(LOWWAIT, &p->statusflags); |
1481 | tty_wakeup(tty); | 1389 | tty_wakeup(tty); |
1482 | } | 1390 | } |
1483 | 1391 | ||
1484 | if (inited && !(p->statusflags & THROTTLE) && | 1392 | if (inited && !test_bit(TTY_THROTTLED, &tty->flags) && |
1485 | MoxaPortRxQueue(p) > 0) { /* RX */ | 1393 | MoxaPortRxQueue(p) > 0) { /* RX */ |
1486 | MoxaPortReadData(p); | 1394 | MoxaPortReadData(p); |
1487 | tty_schedule_flip(tty); | 1395 | tty_schedule_flip(tty); |
1488 | } | 1396 | } |
1489 | } else { | 1397 | } else { |
1490 | p->statusflags &= ~EMPTYWAIT; | 1398 | clear_bit(EMPTYWAIT, &p->statusflags); |
1491 | MoxaPortFlushData(p, 0); /* flush RX */ | 1399 | MoxaPortFlushData(p, 0); /* flush RX */ |
1492 | } | 1400 | } |
1493 | 1401 | ||
@@ -1588,35 +1496,6 @@ static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_term | |||
1588 | tty_encode_baud_rate(tty, baud, baud); | 1496 | tty_encode_baud_rate(tty, baud, baud); |
1589 | } | 1497 | } |
1590 | 1498 | ||
1591 | static void moxa_setup_empty_event(struct tty_struct *tty) | ||
1592 | { | ||
1593 | struct moxa_port *ch = tty->driver_data; | ||
1594 | |||
1595 | spin_lock_bh(&moxa_lock); | ||
1596 | ch->statusflags |= EMPTYWAIT; | ||
1597 | spin_unlock_bh(&moxa_lock); | ||
1598 | } | ||
1599 | |||
1600 | static void moxa_shut_down(struct tty_struct *tty) | ||
1601 | { | ||
1602 | struct moxa_port *ch = tty->driver_data; | ||
1603 | |||
1604 | if (!(ch->port.flags & ASYNC_INITIALIZED)) | ||
1605 | return; | ||
1606 | |||
1607 | MoxaPortDisable(ch); | ||
1608 | |||
1609 | /* | ||
1610 | * If we're a modem control device and HUPCL is on, drop RTS & DTR. | ||
1611 | */ | ||
1612 | if (C_HUPCL(tty)) | ||
1613 | MoxaPortLineCtrl(ch, 0, 0); | ||
1614 | |||
1615 | spin_lock_bh(&moxa_lock); | ||
1616 | ch->port.flags &= ~ASYNC_INITIALIZED; | ||
1617 | spin_unlock_bh(&moxa_lock); | ||
1618 | } | ||
1619 | |||
1620 | /***************************************************************************** | 1499 | /***************************************************************************** |
1621 | * Driver level functions: * | 1500 | * Driver level functions: * |
1622 | *****************************************************************************/ | 1501 | *****************************************************************************/ |
@@ -1918,10 +1797,12 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio, | |||
1918 | baud = MoxaPortSetBaud(port, baud); | 1797 | baud = MoxaPortSetBaud(port, baud); |
1919 | 1798 | ||
1920 | if (termio->c_iflag & (IXON | IXOFF | IXANY)) { | 1799 | if (termio->c_iflag & (IXON | IXOFF | IXANY)) { |
1800 | spin_lock_irq(&moxafunc_lock); | ||
1921 | writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); | 1801 | writeb(termio->c_cc[VSTART], ofsAddr + FuncArg); |
1922 | writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); | 1802 | writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1); |
1923 | writeb(FC_SetXonXoff, ofsAddr + FuncCode); | 1803 | writeb(FC_SetXonXoff, ofsAddr + FuncCode); |
1924 | moxa_wait_finish(ofsAddr); | 1804 | moxa_wait_finish(ofsAddr); |
1805 | spin_unlock_irq(&moxafunc_lock); | ||
1925 | 1806 | ||
1926 | } | 1807 | } |
1927 | return baud; | 1808 | return baud; |
@@ -1974,18 +1855,14 @@ static int MoxaPortLineStatus(struct moxa_port *port) | |||
1974 | int val; | 1855 | int val; |
1975 | 1856 | ||
1976 | ofsAddr = port->tableAddr; | 1857 | ofsAddr = port->tableAddr; |
1977 | if (MOXA_IS_320(port->board)) { | 1858 | if (MOXA_IS_320(port->board)) |
1978 | moxafunc(ofsAddr, FC_LineStatus, 0); | 1859 | val = moxafuncret(ofsAddr, FC_LineStatus, 0); |
1979 | val = readw(ofsAddr + FuncArg); | 1860 | else |
1980 | } else { | ||
1981 | val = readw(ofsAddr + FlagStat) >> 4; | 1861 | val = readw(ofsAddr + FlagStat) >> 4; |
1982 | } | ||
1983 | val &= 0x0B; | 1862 | val &= 0x0B; |
1984 | if (val & 8) | 1863 | if (val & 8) |
1985 | val |= 4; | 1864 | val |= 4; |
1986 | spin_lock_bh(&moxa_lock); | ||
1987 | moxa_new_dcdstate(port, val & 8); | 1865 | moxa_new_dcdstate(port, val & 8); |
1988 | spin_unlock_bh(&moxa_lock); | ||
1989 | val &= 7; | 1866 | val &= 7; |
1990 | return val; | 1867 | return val; |
1991 | } | 1868 | } |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 5e28d39b9e81..3d923065d9a2 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | #include <linux/signal.h> | 24 | #include <linux/signal.h> |
25 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
26 | #include <linux/smp_lock.h> | ||
27 | #include <linux/timer.h> | 26 | #include <linux/timer.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
29 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
@@ -856,9 +855,9 @@ static void mxser_check_modem_status(struct tty_struct *tty, | |||
856 | } | 855 | } |
857 | } | 856 | } |
858 | 857 | ||
859 | static int mxser_startup(struct tty_struct *tty) | 858 | static int mxser_activate(struct tty_port *port, struct tty_struct *tty) |
860 | { | 859 | { |
861 | struct mxser_port *info = tty->driver_data; | 860 | struct mxser_port *info = container_of(port, struct mxser_port, port); |
862 | unsigned long page; | 861 | unsigned long page; |
863 | unsigned long flags; | 862 | unsigned long flags; |
864 | 863 | ||
@@ -868,22 +867,13 @@ static int mxser_startup(struct tty_struct *tty) | |||
868 | 867 | ||
869 | spin_lock_irqsave(&info->slock, flags); | 868 | spin_lock_irqsave(&info->slock, flags); |
870 | 869 | ||
871 | if (info->port.flags & ASYNC_INITIALIZED) { | ||
872 | free_page(page); | ||
873 | spin_unlock_irqrestore(&info->slock, flags); | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | if (!info->ioaddr || !info->type) { | 870 | if (!info->ioaddr || !info->type) { |
878 | set_bit(TTY_IO_ERROR, &tty->flags); | 871 | set_bit(TTY_IO_ERROR, &tty->flags); |
879 | free_page(page); | 872 | free_page(page); |
880 | spin_unlock_irqrestore(&info->slock, flags); | 873 | spin_unlock_irqrestore(&info->slock, flags); |
881 | return 0; | 874 | return 0; |
882 | } | 875 | } |
883 | if (info->port.xmit_buf) | 876 | info->port.xmit_buf = (unsigned char *) page; |
884 | free_page(page); | ||
885 | else | ||
886 | info->port.xmit_buf = (unsigned char *) page; | ||
887 | 877 | ||
888 | /* | 878 | /* |
889 | * Clear the FIFO buffers and disable them | 879 | * Clear the FIFO buffers and disable them |
@@ -951,24 +941,19 @@ static int mxser_startup(struct tty_struct *tty) | |||
951 | * and set the speed of the serial port | 941 | * and set the speed of the serial port |
952 | */ | 942 | */ |
953 | mxser_change_speed(tty, NULL); | 943 | mxser_change_speed(tty, NULL); |
954 | info->port.flags |= ASYNC_INITIALIZED; | ||
955 | spin_unlock_irqrestore(&info->slock, flags); | 944 | spin_unlock_irqrestore(&info->slock, flags); |
956 | 945 | ||
957 | return 0; | 946 | return 0; |
958 | } | 947 | } |
959 | 948 | ||
960 | /* | 949 | /* |
961 | * This routine will shutdown a serial port; interrupts maybe disabled, and | 950 | * This routine will shutdown a serial port |
962 | * DTR is dropped if the hangup on close termio flag is on. | ||
963 | */ | 951 | */ |
964 | static void mxser_shutdown(struct tty_struct *tty) | 952 | static void mxser_shutdown_port(struct tty_port *port) |
965 | { | 953 | { |
966 | struct mxser_port *info = tty->driver_data; | 954 | struct mxser_port *info = container_of(port, struct mxser_port, port); |
967 | unsigned long flags; | 955 | unsigned long flags; |
968 | 956 | ||
969 | if (!(info->port.flags & ASYNC_INITIALIZED)) | ||
970 | return; | ||
971 | |||
972 | spin_lock_irqsave(&info->slock, flags); | 957 | spin_lock_irqsave(&info->slock, flags); |
973 | 958 | ||
974 | /* | 959 | /* |
@@ -978,7 +963,7 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
978 | wake_up_interruptible(&info->port.delta_msr_wait); | 963 | wake_up_interruptible(&info->port.delta_msr_wait); |
979 | 964 | ||
980 | /* | 965 | /* |
981 | * Free the IRQ, if necessary | 966 | * Free the xmit buffer, if necessary |
982 | */ | 967 | */ |
983 | if (info->port.xmit_buf) { | 968 | if (info->port.xmit_buf) { |
984 | free_page((unsigned long) info->port.xmit_buf); | 969 | free_page((unsigned long) info->port.xmit_buf); |
@@ -988,10 +973,6 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
988 | info->IER = 0; | 973 | info->IER = 0; |
989 | outb(0x00, info->ioaddr + UART_IER); | 974 | outb(0x00, info->ioaddr + UART_IER); |
990 | 975 | ||
991 | if (tty->termios->c_cflag & HUPCL) | ||
992 | info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); | ||
993 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
994 | |||
995 | /* clear Rx/Tx FIFO's */ | 976 | /* clear Rx/Tx FIFO's */ |
996 | if (info->board->chip_flag) | 977 | if (info->board->chip_flag) |
997 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | | 978 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | |
@@ -1004,9 +985,6 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
1004 | /* read data port to reset things */ | 985 | /* read data port to reset things */ |
1005 | (void) inb(info->ioaddr + UART_RX); | 986 | (void) inb(info->ioaddr + UART_RX); |
1006 | 987 | ||
1007 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
1008 | |||
1009 | info->port.flags &= ~ASYNC_INITIALIZED; | ||
1010 | 988 | ||
1011 | if (info->board->chip_flag) | 989 | if (info->board->chip_flag) |
1012 | SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); | 990 | SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); |
@@ -1023,8 +1001,7 @@ static void mxser_shutdown(struct tty_struct *tty) | |||
1023 | static int mxser_open(struct tty_struct *tty, struct file *filp) | 1001 | static int mxser_open(struct tty_struct *tty, struct file *filp) |
1024 | { | 1002 | { |
1025 | struct mxser_port *info; | 1003 | struct mxser_port *info; |
1026 | unsigned long flags; | 1004 | int line; |
1027 | int retval, line; | ||
1028 | 1005 | ||
1029 | line = tty->index; | 1006 | line = tty->index; |
1030 | if (line == MXSER_PORTS) | 1007 | if (line == MXSER_PORTS) |
@@ -1035,23 +1012,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
1035 | if (!info->ioaddr) | 1012 | if (!info->ioaddr) |
1036 | return -ENODEV; | 1013 | return -ENODEV; |
1037 | 1014 | ||
1038 | tty->driver_data = info; | 1015 | return tty_port_open(&info->port, tty, filp); |
1039 | tty_port_tty_set(&info->port, tty); | ||
1040 | /* | ||
1041 | * Start up serial port | ||
1042 | */ | ||
1043 | spin_lock_irqsave(&info->port.lock, flags); | ||
1044 | info->port.count++; | ||
1045 | spin_unlock_irqrestore(&info->port.lock, flags); | ||
1046 | retval = mxser_startup(tty); | ||
1047 | if (retval) | ||
1048 | return retval; | ||
1049 | |||
1050 | retval = tty_port_block_til_ready(&info->port, tty, filp); | ||
1051 | if (retval) | ||
1052 | return retval; | ||
1053 | |||
1054 | return 0; | ||
1055 | } | 1016 | } |
1056 | 1017 | ||
1057 | static void mxser_flush_buffer(struct tty_struct *tty) | 1018 | static void mxser_flush_buffer(struct tty_struct *tty) |
@@ -1075,19 +1036,11 @@ static void mxser_flush_buffer(struct tty_struct *tty) | |||
1075 | } | 1036 | } |
1076 | 1037 | ||
1077 | 1038 | ||
1078 | static void mxser_close_port(struct tty_struct *tty, struct tty_port *port) | 1039 | static void mxser_close_port(struct tty_port *port) |
1079 | { | 1040 | { |
1080 | struct mxser_port *info = container_of(port, struct mxser_port, port); | 1041 | struct mxser_port *info = container_of(port, struct mxser_port, port); |
1081 | unsigned long timeout; | 1042 | unsigned long timeout; |
1082 | /* | 1043 | /* |
1083 | * Save the termios structure, since this port may have | ||
1084 | * separate termios for callout and dialin. | ||
1085 | * | ||
1086 | * FIXME: Can this go ? | ||
1087 | */ | ||
1088 | if (port->flags & ASYNC_NORMAL_ACTIVE) | ||
1089 | info->normal_termios = *tty->termios; | ||
1090 | /* | ||
1091 | * At this point we stop accepting input. To do this, we | 1044 | * At this point we stop accepting input. To do this, we |
1092 | * disable the receive line status interrupts, and tell the | 1045 | * disable the receive line status interrupts, and tell the |
1093 | * interrupt driver to stop checking the data ready bit in the | 1046 | * interrupt driver to stop checking the data ready bit in the |
@@ -1097,22 +1050,18 @@ static void mxser_close_port(struct tty_struct *tty, struct tty_port *port) | |||
1097 | if (info->board->chip_flag) | 1050 | if (info->board->chip_flag) |
1098 | info->IER &= ~MOXA_MUST_RECV_ISR; | 1051 | info->IER &= ~MOXA_MUST_RECV_ISR; |
1099 | 1052 | ||
1100 | if (port->flags & ASYNC_INITIALIZED) { | 1053 | outb(info->IER, info->ioaddr + UART_IER); |
1101 | outb(info->IER, info->ioaddr + UART_IER); | 1054 | /* |
1102 | /* | 1055 | * Before we drop DTR, make sure the UART transmitter |
1103 | * Before we drop DTR, make sure the UART transmitter | 1056 | * has completely drained; this is especially |
1104 | * has completely drained; this is especially | 1057 | * important if there is a transmit FIFO! |
1105 | * important if there is a transmit FIFO! | 1058 | */ |
1106 | */ | 1059 | timeout = jiffies + HZ; |
1107 | timeout = jiffies + HZ; | 1060 | while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { |
1108 | while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { | 1061 | schedule_timeout_interruptible(5); |
1109 | schedule_timeout_interruptible(5); | 1062 | if (time_after(jiffies, timeout)) |
1110 | if (time_after(jiffies, timeout)) | 1063 | break; |
1111 | break; | ||
1112 | } | ||
1113 | } | 1064 | } |
1114 | mxser_shutdown(tty); | ||
1115 | |||
1116 | } | 1065 | } |
1117 | 1066 | ||
1118 | /* | 1067 | /* |
@@ -1130,8 +1079,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1130 | return; | 1079 | return; |
1131 | if (tty_port_close_start(port, tty, filp) == 0) | 1080 | if (tty_port_close_start(port, tty, filp) == 0) |
1132 | return; | 1081 | return; |
1133 | mxser_close_port(tty, port); | 1082 | mutex_lock(&port->mutex); |
1083 | mxser_close_port(port); | ||
1134 | mxser_flush_buffer(tty); | 1084 | mxser_flush_buffer(tty); |
1085 | mxser_shutdown_port(port); | ||
1086 | clear_bit(ASYNCB_INITIALIZED, &port->flags); | ||
1087 | mutex_unlock(&port->mutex); | ||
1135 | /* Right now the tty_port set is done outside of the close_end helper | 1088 | /* Right now the tty_port set is done outside of the close_end helper |
1136 | as we don't yet have everyone using refcounts */ | 1089 | as we don't yet have everyone using refcounts */ |
1137 | tty_port_close_end(port, tty); | 1090 | tty_port_close_end(port, tty); |
@@ -1275,6 +1228,7 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1275 | struct serial_struct __user *new_info) | 1228 | struct serial_struct __user *new_info) |
1276 | { | 1229 | { |
1277 | struct mxser_port *info = tty->driver_data; | 1230 | struct mxser_port *info = tty->driver_data; |
1231 | struct tty_port *port = &info->port; | ||
1278 | struct serial_struct new_serial; | 1232 | struct serial_struct new_serial; |
1279 | speed_t baud; | 1233 | speed_t baud; |
1280 | unsigned long sl_flags; | 1234 | unsigned long sl_flags; |
@@ -1290,7 +1244,7 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1290 | new_serial.port != info->ioaddr) | 1244 | new_serial.port != info->ioaddr) |
1291 | return -EINVAL; | 1245 | return -EINVAL; |
1292 | 1246 | ||
1293 | flags = info->port.flags & ASYNC_SPD_MASK; | 1247 | flags = port->flags & ASYNC_SPD_MASK; |
1294 | 1248 | ||
1295 | if (!capable(CAP_SYS_ADMIN)) { | 1249 | if (!capable(CAP_SYS_ADMIN)) { |
1296 | if ((new_serial.baud_base != info->baud_base) || | 1250 | if ((new_serial.baud_base != info->baud_base) || |
@@ -1304,16 +1258,17 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1304 | * OK, past this point, all the error checking has been done. | 1258 | * OK, past this point, all the error checking has been done. |
1305 | * At this point, we start making changes..... | 1259 | * At this point, we start making changes..... |
1306 | */ | 1260 | */ |
1307 | info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) | | 1261 | port->flags = ((port->flags & ~ASYNC_FLAGS) | |
1308 | (new_serial.flags & ASYNC_FLAGS)); | 1262 | (new_serial.flags & ASYNC_FLAGS)); |
1309 | info->port.close_delay = new_serial.close_delay * HZ / 100; | 1263 | port->close_delay = new_serial.close_delay * HZ / 100; |
1310 | info->port.closing_wait = new_serial.closing_wait * HZ / 100; | 1264 | port->closing_wait = new_serial.closing_wait * HZ / 100; |
1311 | tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) | 1265 | tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
1312 | ? 1 : 0; | 1266 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && |
1313 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && | ||
1314 | (new_serial.baud_base != info->baud_base || | 1267 | (new_serial.baud_base != info->baud_base || |
1315 | new_serial.custom_divisor != | 1268 | new_serial.custom_divisor != |
1316 | info->custom_divisor)) { | 1269 | info->custom_divisor)) { |
1270 | if (new_serial.custom_divisor == 0) | ||
1271 | return -EINVAL; | ||
1317 | baud = new_serial.baud_base / new_serial.custom_divisor; | 1272 | baud = new_serial.baud_base / new_serial.custom_divisor; |
1318 | tty_encode_baud_rate(tty, baud, baud); | 1273 | tty_encode_baud_rate(tty, baud, baud); |
1319 | } | 1274 | } |
@@ -1323,15 +1278,17 @@ static int mxser_set_serial_info(struct tty_struct *tty, | |||
1323 | 1278 | ||
1324 | process_txrx_fifo(info); | 1279 | process_txrx_fifo(info); |
1325 | 1280 | ||
1326 | if (info->port.flags & ASYNC_INITIALIZED) { | 1281 | if (test_bit(ASYNCB_INITIALIZED, &port->flags)) { |
1327 | if (flags != (info->port.flags & ASYNC_SPD_MASK)) { | 1282 | if (flags != (port->flags & ASYNC_SPD_MASK)) { |
1328 | spin_lock_irqsave(&info->slock, sl_flags); | 1283 | spin_lock_irqsave(&info->slock, sl_flags); |
1329 | mxser_change_speed(tty, NULL); | 1284 | mxser_change_speed(tty, NULL); |
1330 | spin_unlock_irqrestore(&info->slock, sl_flags); | 1285 | spin_unlock_irqrestore(&info->slock, sl_flags); |
1331 | } | 1286 | } |
1332 | } else | 1287 | } else { |
1333 | retval = mxser_startup(tty); | 1288 | retval = mxser_activate(port, tty); |
1334 | 1289 | if (retval == 0) | |
1290 | set_bit(ASYNCB_INITIALIZED, &port->flags); | ||
1291 | } | ||
1335 | return retval; | 1292 | return retval; |
1336 | } | 1293 | } |
1337 | 1294 | ||
@@ -1520,7 +1477,8 @@ static int __init mxser_read_register(int port, unsigned short *regs) | |||
1520 | 1477 | ||
1521 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | 1478 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) |
1522 | { | 1479 | { |
1523 | struct mxser_port *port; | 1480 | struct mxser_port *ip; |
1481 | struct tty_port *port; | ||
1524 | struct tty_struct *tty; | 1482 | struct tty_struct *tty; |
1525 | int result, status; | 1483 | int result, status; |
1526 | unsigned int i, j; | 1484 | unsigned int i, j; |
@@ -1536,38 +1494,39 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1536 | 1494 | ||
1537 | case MOXA_CHKPORTENABLE: | 1495 | case MOXA_CHKPORTENABLE: |
1538 | result = 0; | 1496 | result = 0; |
1539 | lock_kernel(); | ||
1540 | for (i = 0; i < MXSER_BOARDS; i++) | 1497 | for (i = 0; i < MXSER_BOARDS; i++) |
1541 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) | 1498 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) |
1542 | if (mxser_boards[i].ports[j].ioaddr) | 1499 | if (mxser_boards[i].ports[j].ioaddr) |
1543 | result |= (1 << i); | 1500 | result |= (1 << i); |
1544 | unlock_kernel(); | ||
1545 | return put_user(result, (unsigned long __user *)argp); | 1501 | return put_user(result, (unsigned long __user *)argp); |
1546 | case MOXA_GETDATACOUNT: | 1502 | case MOXA_GETDATACOUNT: |
1547 | lock_kernel(); | 1503 | /* The receive side is locked by port->slock but it isn't |
1504 | clear that an exact snapshot is worth copying here */ | ||
1548 | if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) | 1505 | if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) |
1549 | ret = -EFAULT; | 1506 | ret = -EFAULT; |
1550 | unlock_kernel(); | ||
1551 | return ret; | 1507 | return ret; |
1552 | case MOXA_GETMSTATUS: { | 1508 | case MOXA_GETMSTATUS: { |
1553 | struct mxser_mstatus ms, __user *msu = argp; | 1509 | struct mxser_mstatus ms, __user *msu = argp; |
1554 | lock_kernel(); | ||
1555 | for (i = 0; i < MXSER_BOARDS; i++) | 1510 | for (i = 0; i < MXSER_BOARDS; i++) |
1556 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | 1511 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { |
1557 | port = &mxser_boards[i].ports[j]; | 1512 | ip = &mxser_boards[i].ports[j]; |
1513 | port = &ip->port; | ||
1558 | memset(&ms, 0, sizeof(ms)); | 1514 | memset(&ms, 0, sizeof(ms)); |
1559 | 1515 | ||
1560 | if (!port->ioaddr) | 1516 | mutex_lock(&port->mutex); |
1517 | if (!ip->ioaddr) | ||
1561 | goto copy; | 1518 | goto copy; |
1562 | 1519 | ||
1563 | tty = tty_port_tty_get(&port->port); | 1520 | tty = tty_port_tty_get(port); |
1564 | 1521 | ||
1565 | if (!tty || !tty->termios) | 1522 | if (!tty || !tty->termios) |
1566 | ms.cflag = port->normal_termios.c_cflag; | 1523 | ms.cflag = ip->normal_termios.c_cflag; |
1567 | else | 1524 | else |
1568 | ms.cflag = tty->termios->c_cflag; | 1525 | ms.cflag = tty->termios->c_cflag; |
1569 | tty_kref_put(tty); | 1526 | tty_kref_put(tty); |
1570 | status = inb(port->ioaddr + UART_MSR); | 1527 | spin_lock_irq(&ip->slock); |
1528 | status = inb(ip->ioaddr + UART_MSR); | ||
1529 | spin_unlock_irq(&ip->slock); | ||
1571 | if (status & UART_MSR_DCD) | 1530 | if (status & UART_MSR_DCD) |
1572 | ms.dcd = 1; | 1531 | ms.dcd = 1; |
1573 | if (status & UART_MSR_DSR) | 1532 | if (status & UART_MSR_DSR) |
@@ -1575,13 +1534,11 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1575 | if (status & UART_MSR_CTS) | 1534 | if (status & UART_MSR_CTS) |
1576 | ms.cts = 1; | 1535 | ms.cts = 1; |
1577 | copy: | 1536 | copy: |
1578 | if (copy_to_user(msu, &ms, sizeof(ms))) { | 1537 | mutex_unlock(&port->mutex); |
1579 | unlock_kernel(); | 1538 | if (copy_to_user(msu, &ms, sizeof(ms))) |
1580 | return -EFAULT; | 1539 | return -EFAULT; |
1581 | } | ||
1582 | msu++; | 1540 | msu++; |
1583 | } | 1541 | } |
1584 | unlock_kernel(); | ||
1585 | return 0; | 1542 | return 0; |
1586 | } | 1543 | } |
1587 | case MOXA_ASPP_MON_EXT: { | 1544 | case MOXA_ASPP_MON_EXT: { |
@@ -1593,41 +1550,48 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1593 | if (!me) | 1550 | if (!me) |
1594 | return -ENOMEM; | 1551 | return -ENOMEM; |
1595 | 1552 | ||
1596 | lock_kernel(); | ||
1597 | for (i = 0, p = 0; i < MXSER_BOARDS; i++) { | 1553 | for (i = 0, p = 0; i < MXSER_BOARDS; i++) { |
1598 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { | 1554 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { |
1599 | if (p >= ARRAY_SIZE(me->rx_cnt)) { | 1555 | if (p >= ARRAY_SIZE(me->rx_cnt)) { |
1600 | i = MXSER_BOARDS; | 1556 | i = MXSER_BOARDS; |
1601 | break; | 1557 | break; |
1602 | } | 1558 | } |
1603 | port = &mxser_boards[i].ports[j]; | 1559 | ip = &mxser_boards[i].ports[j]; |
1604 | if (!port->ioaddr) | 1560 | port = &ip->port; |
1561 | |||
1562 | mutex_lock(&port->mutex); | ||
1563 | if (!ip->ioaddr) { | ||
1564 | mutex_unlock(&port->mutex); | ||
1605 | continue; | 1565 | continue; |
1566 | } | ||
1606 | 1567 | ||
1607 | status = mxser_get_msr(port->ioaddr, 0, p); | 1568 | spin_lock_irq(&ip->slock); |
1569 | status = mxser_get_msr(ip->ioaddr, 0, p); | ||
1608 | 1570 | ||
1609 | if (status & UART_MSR_TERI) | 1571 | if (status & UART_MSR_TERI) |
1610 | port->icount.rng++; | 1572 | ip->icount.rng++; |
1611 | if (status & UART_MSR_DDSR) | 1573 | if (status & UART_MSR_DDSR) |
1612 | port->icount.dsr++; | 1574 | ip->icount.dsr++; |
1613 | if (status & UART_MSR_DDCD) | 1575 | if (status & UART_MSR_DDCD) |
1614 | port->icount.dcd++; | 1576 | ip->icount.dcd++; |
1615 | if (status & UART_MSR_DCTS) | 1577 | if (status & UART_MSR_DCTS) |
1616 | port->icount.cts++; | 1578 | ip->icount.cts++; |
1617 | 1579 | ||
1618 | port->mon_data.modem_status = status; | 1580 | ip->mon_data.modem_status = status; |
1619 | me->rx_cnt[p] = port->mon_data.rxcnt; | 1581 | me->rx_cnt[p] = ip->mon_data.rxcnt; |
1620 | me->tx_cnt[p] = port->mon_data.txcnt; | 1582 | me->tx_cnt[p] = ip->mon_data.txcnt; |
1621 | me->up_rxcnt[p] = port->mon_data.up_rxcnt; | 1583 | me->up_rxcnt[p] = ip->mon_data.up_rxcnt; |
1622 | me->up_txcnt[p] = port->mon_data.up_txcnt; | 1584 | me->up_txcnt[p] = ip->mon_data.up_txcnt; |
1623 | me->modem_status[p] = | 1585 | me->modem_status[p] = |
1624 | port->mon_data.modem_status; | 1586 | ip->mon_data.modem_status; |
1625 | tty = tty_port_tty_get(&port->port); | 1587 | spin_unlock_irq(&ip->slock); |
1588 | |||
1589 | tty = tty_port_tty_get(&ip->port); | ||
1626 | 1590 | ||
1627 | if (!tty || !tty->termios) { | 1591 | if (!tty || !tty->termios) { |
1628 | cflag = port->normal_termios.c_cflag; | 1592 | cflag = ip->normal_termios.c_cflag; |
1629 | iflag = port->normal_termios.c_iflag; | 1593 | iflag = ip->normal_termios.c_iflag; |
1630 | me->baudrate[p] = tty_termios_baud_rate(&port->normal_termios); | 1594 | me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios); |
1631 | } else { | 1595 | } else { |
1632 | cflag = tty->termios->c_cflag; | 1596 | cflag = tty->termios->c_cflag; |
1633 | iflag = tty->termios->c_iflag; | 1597 | iflag = tty->termios->c_iflag; |
@@ -1646,16 +1610,15 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1646 | if (iflag & (IXON | IXOFF)) | 1610 | if (iflag & (IXON | IXOFF)) |
1647 | me->flowctrl[p] |= 0x0C; | 1611 | me->flowctrl[p] |= 0x0C; |
1648 | 1612 | ||
1649 | if (port->type == PORT_16550A) | 1613 | if (ip->type == PORT_16550A) |
1650 | me->fifo[p] = 1; | 1614 | me->fifo[p] = 1; |
1651 | 1615 | ||
1652 | opmode = inb(port->opmode_ioaddr) >> | 1616 | opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2); |
1653 | ((p % 4) * 2); | ||
1654 | opmode &= OP_MODE_MASK; | 1617 | opmode &= OP_MODE_MASK; |
1655 | me->iftype[p] = opmode; | 1618 | me->iftype[p] = opmode; |
1619 | mutex_unlock(&port->mutex); | ||
1656 | } | 1620 | } |
1657 | } | 1621 | } |
1658 | unlock_kernel(); | ||
1659 | if (copy_to_user(argp, me, sizeof(*me))) | 1622 | if (copy_to_user(argp, me, sizeof(*me))) |
1660 | ret = -EFAULT; | 1623 | ret = -EFAULT; |
1661 | kfree(me); | 1624 | kfree(me); |
@@ -1692,6 +1655,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1692 | unsigned int cmd, unsigned long arg) | 1655 | unsigned int cmd, unsigned long arg) |
1693 | { | 1656 | { |
1694 | struct mxser_port *info = tty->driver_data; | 1657 | struct mxser_port *info = tty->driver_data; |
1658 | struct tty_port *port = &info->port; | ||
1695 | struct async_icount cnow; | 1659 | struct async_icount cnow; |
1696 | unsigned long flags; | 1660 | unsigned long flags; |
1697 | void __user *argp = (void __user *)arg; | 1661 | void __user *argp = (void __user *)arg; |
@@ -1716,20 +1680,20 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1716 | opmode != RS422_MODE && | 1680 | opmode != RS422_MODE && |
1717 | opmode != RS485_4WIRE_MODE) | 1681 | opmode != RS485_4WIRE_MODE) |
1718 | return -EFAULT; | 1682 | return -EFAULT; |
1719 | lock_kernel(); | ||
1720 | mask = ModeMask[p]; | 1683 | mask = ModeMask[p]; |
1721 | shiftbit = p * 2; | 1684 | shiftbit = p * 2; |
1685 | spin_lock_irq(&info->slock); | ||
1722 | val = inb(info->opmode_ioaddr); | 1686 | val = inb(info->opmode_ioaddr); |
1723 | val &= mask; | 1687 | val &= mask; |
1724 | val |= (opmode << shiftbit); | 1688 | val |= (opmode << shiftbit); |
1725 | outb(val, info->opmode_ioaddr); | 1689 | outb(val, info->opmode_ioaddr); |
1726 | unlock_kernel(); | 1690 | spin_unlock_irq(&info->slock); |
1727 | } else { | 1691 | } else { |
1728 | lock_kernel(); | ||
1729 | shiftbit = p * 2; | 1692 | shiftbit = p * 2; |
1693 | spin_lock_irq(&info->slock); | ||
1730 | opmode = inb(info->opmode_ioaddr) >> shiftbit; | 1694 | opmode = inb(info->opmode_ioaddr) >> shiftbit; |
1695 | spin_unlock_irq(&info->slock); | ||
1731 | opmode &= OP_MODE_MASK; | 1696 | opmode &= OP_MODE_MASK; |
1732 | unlock_kernel(); | ||
1733 | if (put_user(opmode, (int __user *)argp)) | 1697 | if (put_user(opmode, (int __user *)argp)) |
1734 | return -EFAULT; | 1698 | return -EFAULT; |
1735 | } | 1699 | } |
@@ -1742,14 +1706,14 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1742 | 1706 | ||
1743 | switch (cmd) { | 1707 | switch (cmd) { |
1744 | case TIOCGSERIAL: | 1708 | case TIOCGSERIAL: |
1745 | lock_kernel(); | 1709 | mutex_lock(&port->mutex); |
1746 | retval = mxser_get_serial_info(tty, argp); | 1710 | retval = mxser_get_serial_info(tty, argp); |
1747 | unlock_kernel(); | 1711 | mutex_unlock(&port->mutex); |
1748 | return retval; | 1712 | return retval; |
1749 | case TIOCSSERIAL: | 1713 | case TIOCSSERIAL: |
1750 | lock_kernel(); | 1714 | mutex_lock(&port->mutex); |
1751 | retval = mxser_set_serial_info(tty, argp); | 1715 | retval = mxser_set_serial_info(tty, argp); |
1752 | unlock_kernel(); | 1716 | mutex_unlock(&port->mutex); |
1753 | return retval; | 1717 | return retval; |
1754 | case TIOCSERGETLSR: /* Get line status register */ | 1718 | case TIOCSERGETLSR: /* Get line status register */ |
1755 | return mxser_get_lsr_info(info, argp); | 1719 | return mxser_get_lsr_info(info, argp); |
@@ -1795,31 +1759,33 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1795 | case MOXA_HighSpeedOn: | 1759 | case MOXA_HighSpeedOn: |
1796 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); | 1760 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); |
1797 | case MOXA_SDS_RSTICOUNTER: | 1761 | case MOXA_SDS_RSTICOUNTER: |
1798 | lock_kernel(); | 1762 | spin_lock_irq(&info->slock); |
1799 | info->mon_data.rxcnt = 0; | 1763 | info->mon_data.rxcnt = 0; |
1800 | info->mon_data.txcnt = 0; | 1764 | info->mon_data.txcnt = 0; |
1801 | unlock_kernel(); | 1765 | spin_unlock_irq(&info->slock); |
1802 | return 0; | 1766 | return 0; |
1803 | 1767 | ||
1804 | case MOXA_ASPP_OQUEUE:{ | 1768 | case MOXA_ASPP_OQUEUE:{ |
1805 | int len, lsr; | 1769 | int len, lsr; |
1806 | 1770 | ||
1807 | lock_kernel(); | ||
1808 | len = mxser_chars_in_buffer(tty); | 1771 | len = mxser_chars_in_buffer(tty); |
1772 | spin_lock(&info->slock); | ||
1809 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; | 1773 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE; |
1774 | spin_unlock_irq(&info->slock); | ||
1810 | len += (lsr ? 0 : 1); | 1775 | len += (lsr ? 0 : 1); |
1811 | unlock_kernel(); | ||
1812 | 1776 | ||
1813 | return put_user(len, (int __user *)argp); | 1777 | return put_user(len, (int __user *)argp); |
1814 | } | 1778 | } |
1815 | case MOXA_ASPP_MON: { | 1779 | case MOXA_ASPP_MON: { |
1816 | int mcr, status; | 1780 | int mcr, status; |
1817 | 1781 | ||
1818 | lock_kernel(); | 1782 | spin_lock(&info->slock); |
1819 | status = mxser_get_msr(info->ioaddr, 1, tty->index); | 1783 | status = mxser_get_msr(info->ioaddr, 1, tty->index); |
1820 | mxser_check_modem_status(tty, info, status); | 1784 | mxser_check_modem_status(tty, info, status); |
1821 | 1785 | ||
1822 | mcr = inb(info->ioaddr + UART_MCR); | 1786 | mcr = inb(info->ioaddr + UART_MCR); |
1787 | spin_unlock(&info->slock); | ||
1788 | |||
1823 | if (mcr & MOXA_MUST_MCR_XON_FLAG) | 1789 | if (mcr & MOXA_MUST_MCR_XON_FLAG) |
1824 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; | 1790 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; |
1825 | else | 1791 | else |
@@ -1834,7 +1800,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1834 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; | 1800 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; |
1835 | else | 1801 | else |
1836 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; | 1802 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; |
1837 | unlock_kernel(); | 1803 | |
1838 | if (copy_to_user(argp, &info->mon_data, | 1804 | if (copy_to_user(argp, &info->mon_data, |
1839 | sizeof(struct mxser_mon))) | 1805 | sizeof(struct mxser_mon))) |
1840 | return -EFAULT; | 1806 | return -EFAULT; |
@@ -1993,6 +1959,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1993 | { | 1959 | { |
1994 | struct mxser_port *info = tty->driver_data; | 1960 | struct mxser_port *info = tty->driver_data; |
1995 | unsigned long orig_jiffies, char_time; | 1961 | unsigned long orig_jiffies, char_time; |
1962 | unsigned long flags; | ||
1996 | int lsr; | 1963 | int lsr; |
1997 | 1964 | ||
1998 | if (info->type == PORT_UNKNOWN) | 1965 | if (info->type == PORT_UNKNOWN) |
@@ -2032,19 +1999,21 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
2032 | timeout, char_time); | 1999 | timeout, char_time); |
2033 | printk("jiff=%lu...", jiffies); | 2000 | printk("jiff=%lu...", jiffies); |
2034 | #endif | 2001 | #endif |
2035 | lock_kernel(); | 2002 | spin_lock_irqsave(&info->slock, flags); |
2036 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { | 2003 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { |
2037 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 2004 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
2038 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); | 2005 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); |
2039 | #endif | 2006 | #endif |
2007 | spin_unlock_irqrestore(&info->slock, flags); | ||
2040 | schedule_timeout_interruptible(char_time); | 2008 | schedule_timeout_interruptible(char_time); |
2009 | spin_lock_irqsave(&info->slock, flags); | ||
2041 | if (signal_pending(current)) | 2010 | if (signal_pending(current)) |
2042 | break; | 2011 | break; |
2043 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | 2012 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) |
2044 | break; | 2013 | break; |
2045 | } | 2014 | } |
2015 | spin_unlock_irqrestore(&info->slock, flags); | ||
2046 | set_current_state(TASK_RUNNING); | 2016 | set_current_state(TASK_RUNNING); |
2047 | unlock_kernel(); | ||
2048 | 2017 | ||
2049 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 2018 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
2050 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | 2019 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); |
@@ -2059,7 +2028,6 @@ static void mxser_hangup(struct tty_struct *tty) | |||
2059 | struct mxser_port *info = tty->driver_data; | 2028 | struct mxser_port *info = tty->driver_data; |
2060 | 2029 | ||
2061 | mxser_flush_buffer(tty); | 2030 | mxser_flush_buffer(tty); |
2062 | mxser_shutdown(tty); | ||
2063 | tty_port_hangup(&info->port); | 2031 | tty_port_hangup(&info->port); |
2064 | } | 2032 | } |
2065 | 2033 | ||
@@ -2363,6 +2331,8 @@ static const struct tty_operations mxser_ops = { | |||
2363 | struct tty_port_operations mxser_port_ops = { | 2331 | struct tty_port_operations mxser_port_ops = { |
2364 | .carrier_raised = mxser_carrier_raised, | 2332 | .carrier_raised = mxser_carrier_raised, |
2365 | .dtr_rts = mxser_dtr_rts, | 2333 | .dtr_rts = mxser_dtr_rts, |
2334 | .activate = mxser_activate, | ||
2335 | .shutdown = mxser_shutdown_port, | ||
2366 | }; | 2336 | }; |
2367 | 2337 | ||
2368 | /* | 2338 | /* |
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 674b3ab3587d..2bb7874a6899 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c | |||
@@ -603,7 +603,7 @@ void ipwireless_tty_free(struct ipw_tty *tty) | |||
603 | } | 603 | } |
604 | } | 604 | } |
605 | 605 | ||
606 | static struct tty_operations tty_ops = { | 606 | static const struct tty_operations tty_ops = { |
607 | .open = ipw_open, | 607 | .open = ipw_open, |
608 | .close = ipw_close, | 608 | .close = ipw_close, |
609 | .hangup = ipw_hangup, | 609 | .hangup = ipw_hangup, |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index d86c0bc05c1c..385c44b3034f 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -659,7 +659,7 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
659 | if (!retval) | 659 | if (!retval) |
660 | return 0; | 660 | return 0; |
661 | out1: | 661 | out1: |
662 | tty_release_dev(filp); | 662 | tty_release(inode, filp); |
663 | return retval; | 663 | return retval; |
664 | out: | 664 | out: |
665 | devpts_kill_index(inode, index); | 665 | devpts_kill_index(inode, index); |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 3cfa22d469e0..0a8d1e56c993 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -793,26 +793,21 @@ static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp, | |||
793 | } | 793 | } |
794 | 794 | ||
795 | /* Must be called with interrupts enabled */ | 795 | /* Must be called with interrupts enabled */ |
796 | static int rc_setup_port(struct tty_struct *tty, struct riscom_board *bp, | 796 | static int rc_activate_port(struct tty_port *port, struct tty_struct *tty) |
797 | struct riscom_port *port) | ||
798 | { | 797 | { |
798 | struct riscom_port *rp = container_of(port, struct riscom_port, port); | ||
799 | struct riscom_board *bp = port_Board(rp); | ||
799 | unsigned long flags; | 800 | unsigned long flags; |
800 | 801 | ||
801 | if (port->port.flags & ASYNC_INITIALIZED) | 802 | if (tty_port_alloc_xmit_buf(port) < 0) |
802 | return 0; | ||
803 | |||
804 | if (tty_port_alloc_xmit_buf(&port->port) < 0) | ||
805 | return -ENOMEM; | 803 | return -ENOMEM; |
806 | 804 | ||
807 | spin_lock_irqsave(&riscom_lock, flags); | 805 | spin_lock_irqsave(&riscom_lock, flags); |
808 | 806 | ||
809 | clear_bit(TTY_IO_ERROR, &tty->flags); | 807 | clear_bit(TTY_IO_ERROR, &tty->flags); |
810 | if (port->port.count == 1) | 808 | bp->count++; |
811 | bp->count++; | 809 | rp->xmit_cnt = rp->xmit_head = rp->xmit_tail = 0; |
812 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 810 | rc_change_speed(tty, bp, rp); |
813 | rc_change_speed(tty, bp, port); | ||
814 | port->port.flags |= ASYNC_INITIALIZED; | ||
815 | |||
816 | spin_unlock_irqrestore(&riscom_lock, flags); | 811 | spin_unlock_irqrestore(&riscom_lock, flags); |
817 | return 0; | 812 | return 0; |
818 | } | 813 | } |
@@ -821,9 +816,6 @@ static int rc_setup_port(struct tty_struct *tty, struct riscom_board *bp, | |||
821 | static void rc_shutdown_port(struct tty_struct *tty, | 816 | static void rc_shutdown_port(struct tty_struct *tty, |
822 | struct riscom_board *bp, struct riscom_port *port) | 817 | struct riscom_board *bp, struct riscom_port *port) |
823 | { | 818 | { |
824 | if (!(port->port.flags & ASYNC_INITIALIZED)) | ||
825 | return; | ||
826 | |||
827 | #ifdef RC_REPORT_OVERRUN | 819 | #ifdef RC_REPORT_OVERRUN |
828 | printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n", | 820 | printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n", |
829 | board_No(bp), port_No(port), port->overrun); | 821 | board_No(bp), port_No(port), port->overrun); |
@@ -840,11 +832,6 @@ static void rc_shutdown_port(struct tty_struct *tty, | |||
840 | } | 832 | } |
841 | #endif | 833 | #endif |
842 | tty_port_free_xmit_buf(&port->port); | 834 | tty_port_free_xmit_buf(&port->port); |
843 | if (C_HUPCL(tty)) { | ||
844 | /* Drop DTR */ | ||
845 | bp->DTR |= (1u << port_No(port)); | ||
846 | rc_out(bp, RC_DTR, bp->DTR); | ||
847 | } | ||
848 | 835 | ||
849 | /* Select port */ | 836 | /* Select port */ |
850 | rc_out(bp, CD180_CAR, port_No(port)); | 837 | rc_out(bp, CD180_CAR, port_No(port)); |
@@ -856,7 +843,6 @@ static void rc_shutdown_port(struct tty_struct *tty, | |||
856 | rc_out(bp, CD180_IER, port->IER); | 843 | rc_out(bp, CD180_IER, port->IER); |
857 | 844 | ||
858 | set_bit(TTY_IO_ERROR, &tty->flags); | 845 | set_bit(TTY_IO_ERROR, &tty->flags); |
859 | port->port.flags &= ~ASYNC_INITIALIZED; | ||
860 | 846 | ||
861 | if (--bp->count < 0) { | 847 | if (--bp->count < 0) { |
862 | printk(KERN_INFO "rc%d: rc_shutdown_port: " | 848 | printk(KERN_INFO "rc%d: rc_shutdown_port: " |
@@ -889,6 +875,20 @@ static int carrier_raised(struct tty_port *port) | |||
889 | return CD; | 875 | return CD; |
890 | } | 876 | } |
891 | 877 | ||
878 | static void dtr_rts(struct tty_port *port, int onoff) | ||
879 | { | ||
880 | struct riscom_port *p = container_of(port, struct riscom_port, port); | ||
881 | struct riscom_board *bp = port_Board(p); | ||
882 | unsigned long flags; | ||
883 | |||
884 | spin_lock_irqsave(&riscom_lock, flags); | ||
885 | bp->DTR &= ~(1u << port_No(p)); | ||
886 | if (onoff == 0) | ||
887 | bp->DTR |= (1u << port_No(p)); | ||
888 | rc_out(bp, RC_DTR, bp->DTR); | ||
889 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
890 | } | ||
891 | |||
892 | static int rc_open(struct tty_struct *tty, struct file *filp) | 892 | static int rc_open(struct tty_struct *tty, struct file *filp) |
893 | { | 893 | { |
894 | int board; | 894 | int board; |
@@ -909,14 +909,7 @@ static int rc_open(struct tty_struct *tty, struct file *filp) | |||
909 | if (error) | 909 | if (error) |
910 | return error; | 910 | return error; |
911 | 911 | ||
912 | port->port.count++; | 912 | return tty_port_open(&port->port, tty, filp); |
913 | tty->driver_data = port; | ||
914 | tty_port_tty_set(&port->port, tty); | ||
915 | |||
916 | error = rc_setup_port(tty, bp, port); | ||
917 | if (error == 0) | ||
918 | error = tty_port_block_til_ready(&port->port, tty, filp); | ||
919 | return error; | ||
920 | } | 913 | } |
921 | 914 | ||
922 | static void rc_flush_buffer(struct tty_struct *tty) | 915 | static void rc_flush_buffer(struct tty_struct *tty) |
@@ -950,24 +943,23 @@ static void rc_close_port(struct tty_port *port) | |||
950 | 943 | ||
951 | spin_lock_irqsave(&riscom_lock, flags); | 944 | spin_lock_irqsave(&riscom_lock, flags); |
952 | rp->IER &= ~IER_RXD; | 945 | rp->IER &= ~IER_RXD; |
953 | if (port->flags & ASYNC_INITIALIZED) { | 946 | |
954 | rp->IER &= ~IER_TXRDY; | 947 | rp->IER &= ~IER_TXRDY; |
955 | rp->IER |= IER_TXEMPTY; | 948 | rp->IER |= IER_TXEMPTY; |
956 | rc_out(bp, CD180_CAR, port_No(rp)); | 949 | rc_out(bp, CD180_CAR, port_No(rp)); |
957 | rc_out(bp, CD180_IER, rp->IER); | 950 | rc_out(bp, CD180_IER, rp->IER); |
958 | /* | 951 | /* |
959 | * Before we drop DTR, make sure the UART transmitter | 952 | * Before we drop DTR, make sure the UART transmitter |
960 | * has completely drained; this is especially | 953 | * has completely drained; this is especially |
961 | * important if there is a transmit FIFO! | 954 | * important if there is a transmit FIFO! |
962 | */ | 955 | */ |
963 | timeout = jiffies + HZ; | 956 | timeout = jiffies + HZ; |
964 | while (rp->IER & IER_TXEMPTY) { | 957 | while (rp->IER & IER_TXEMPTY) { |
965 | spin_unlock_irqrestore(&riscom_lock, flags); | 958 | spin_unlock_irqrestore(&riscom_lock, flags); |
966 | msleep_interruptible(jiffies_to_msecs(rp->timeout)); | 959 | msleep_interruptible(jiffies_to_msecs(rp->timeout)); |
967 | spin_lock_irqsave(&riscom_lock, flags); | 960 | spin_lock_irqsave(&riscom_lock, flags); |
968 | if (time_after(jiffies, timeout)) | 961 | if (time_after(jiffies, timeout)) |
969 | break; | 962 | break; |
970 | } | ||
971 | } | 963 | } |
972 | rc_shutdown_port(port->tty, bp, rp); | 964 | rc_shutdown_port(port->tty, bp, rp); |
973 | spin_unlock_irqrestore(&riscom_lock, flags); | 965 | spin_unlock_irqrestore(&riscom_lock, flags); |
@@ -1354,7 +1346,6 @@ static void rc_hangup(struct tty_struct *tty) | |||
1354 | if (rc_paranoia_check(port, tty->name, "rc_hangup")) | 1346 | if (rc_paranoia_check(port, tty->name, "rc_hangup")) |
1355 | return; | 1347 | return; |
1356 | 1348 | ||
1357 | rc_shutdown_port(tty, port_Board(port), port); | ||
1358 | tty_port_hangup(&port->port); | 1349 | tty_port_hangup(&port->port); |
1359 | } | 1350 | } |
1360 | 1351 | ||
@@ -1401,7 +1392,9 @@ static const struct tty_operations riscom_ops = { | |||
1401 | 1392 | ||
1402 | static const struct tty_port_operations riscom_port_ops = { | 1393 | static const struct tty_port_operations riscom_port_ops = { |
1403 | .carrier_raised = carrier_raised, | 1394 | .carrier_raised = carrier_raised, |
1395 | .dtr_rts = dtr_rts, | ||
1404 | .shutdown = rc_close_port, | 1396 | .shutdown = rc_close_port, |
1397 | .activate = rc_activate_port, | ||
1405 | }; | 1398 | }; |
1406 | 1399 | ||
1407 | 1400 | ||
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index db6dcfa35ba0..0e511d61f544 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -407,7 +407,7 @@ static unsigned int stl_baudrates[] = { | |||
407 | * Declare all those functions in this driver! | 407 | * Declare all those functions in this driver! |
408 | */ | 408 | */ |
409 | 409 | ||
410 | static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); | 410 | static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); |
411 | static int stl_brdinit(struct stlbrd *brdp); | 411 | static int stl_brdinit(struct stlbrd *brdp); |
412 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); | 412 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); |
413 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); | 413 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); |
@@ -607,7 +607,7 @@ static unsigned int sc26198_baudtable[] = { | |||
607 | */ | 607 | */ |
608 | static const struct file_operations stl_fsiomem = { | 608 | static const struct file_operations stl_fsiomem = { |
609 | .owner = THIS_MODULE, | 609 | .owner = THIS_MODULE, |
610 | .ioctl = stl_memioctl, | 610 | .unlocked_ioctl = stl_memioctl, |
611 | }; | 611 | }; |
612 | 612 | ||
613 | static struct class *stallion_class; | 613 | static struct class *stallion_class; |
@@ -702,6 +702,24 @@ static struct stlbrd *stl_allocbrd(void) | |||
702 | 702 | ||
703 | /*****************************************************************************/ | 703 | /*****************************************************************************/ |
704 | 704 | ||
705 | static int stl_activate(struct tty_port *port, struct tty_struct *tty) | ||
706 | { | ||
707 | struct stlport *portp = container_of(port, struct stlport, port); | ||
708 | if (!portp->tx.buf) { | ||
709 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); | ||
710 | if (!portp->tx.buf) | ||
711 | return -ENOMEM; | ||
712 | portp->tx.head = portp->tx.buf; | ||
713 | portp->tx.tail = portp->tx.buf; | ||
714 | } | ||
715 | stl_setport(portp, tty->termios); | ||
716 | portp->sigs = stl_getsignals(portp); | ||
717 | stl_setsignals(portp, 1, 1); | ||
718 | stl_enablerxtx(portp, 1, 1); | ||
719 | stl_startrxtx(portp, 1, 0); | ||
720 | return 0; | ||
721 | } | ||
722 | |||
705 | static int stl_open(struct tty_struct *tty, struct file *filp) | 723 | static int stl_open(struct tty_struct *tty, struct file *filp) |
706 | { | 724 | { |
707 | struct stlport *portp; | 725 | struct stlport *portp; |
@@ -737,32 +755,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
737 | if (portp == NULL) | 755 | if (portp == NULL) |
738 | return -ENODEV; | 756 | return -ENODEV; |
739 | port = &portp->port; | 757 | port = &portp->port; |
758 | return tty_port_open(&portp->port, tty, filp); | ||
740 | 759 | ||
741 | /* | ||
742 | * On the first open of the device setup the port hardware, and | ||
743 | * initialize the per port data structure. | ||
744 | */ | ||
745 | tty_port_tty_set(port, tty); | ||
746 | tty->driver_data = portp; | ||
747 | port->count++; | ||
748 | |||
749 | if ((port->flags & ASYNC_INITIALIZED) == 0) { | ||
750 | if (!portp->tx.buf) { | ||
751 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); | ||
752 | if (!portp->tx.buf) | ||
753 | return -ENOMEM; | ||
754 | portp->tx.head = portp->tx.buf; | ||
755 | portp->tx.tail = portp->tx.buf; | ||
756 | } | ||
757 | stl_setport(portp, tty->termios); | ||
758 | portp->sigs = stl_getsignals(portp); | ||
759 | stl_setsignals(portp, 1, 1); | ||
760 | stl_enablerxtx(portp, 1, 1); | ||
761 | stl_startrxtx(portp, 1, 0); | ||
762 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
763 | port->flags |= ASYNC_INITIALIZED; | ||
764 | } | ||
765 | return tty_port_block_til_ready(port, tty, filp); | ||
766 | } | 760 | } |
767 | 761 | ||
768 | /*****************************************************************************/ | 762 | /*****************************************************************************/ |
@@ -826,38 +820,12 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
826 | 820 | ||
827 | /*****************************************************************************/ | 821 | /*****************************************************************************/ |
828 | 822 | ||
829 | static void stl_close(struct tty_struct *tty, struct file *filp) | 823 | static void stl_shutdown(struct tty_port *port) |
830 | { | 824 | { |
831 | struct stlport *portp; | 825 | struct stlport *portp = container_of(port, struct stlport, port); |
832 | struct tty_port *port; | ||
833 | unsigned long flags; | ||
834 | |||
835 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); | ||
836 | |||
837 | portp = tty->driver_data; | ||
838 | BUG_ON(portp == NULL); | ||
839 | |||
840 | port = &portp->port; | ||
841 | |||
842 | if (tty_port_close_start(port, tty, filp) == 0) | ||
843 | return; | ||
844 | /* | ||
845 | * May want to wait for any data to drain before closing. The BUSY | ||
846 | * flag keeps track of whether we are still sending or not - it is | ||
847 | * very accurate for the cd1400, not quite so for the sc26198. | ||
848 | * (The sc26198 has no "end-of-data" interrupt only empty FIFO) | ||
849 | */ | ||
850 | stl_waituntilsent(tty, (HZ / 2)); | ||
851 | |||
852 | spin_lock_irqsave(&port->lock, flags); | ||
853 | portp->port.flags &= ~ASYNC_INITIALIZED; | ||
854 | spin_unlock_irqrestore(&port->lock, flags); | ||
855 | |||
856 | stl_disableintrs(portp); | 826 | stl_disableintrs(portp); |
857 | if (tty->termios->c_cflag & HUPCL) | ||
858 | stl_setsignals(portp, 0, 0); | ||
859 | stl_enablerxtx(portp, 0, 0); | 827 | stl_enablerxtx(portp, 0, 0); |
860 | stl_flushbuffer(tty); | 828 | stl_flush(portp); |
861 | portp->istate = 0; | 829 | portp->istate = 0; |
862 | if (portp->tx.buf != NULL) { | 830 | if (portp->tx.buf != NULL) { |
863 | kfree(portp->tx.buf); | 831 | kfree(portp->tx.buf); |
@@ -865,9 +833,16 @@ static void stl_close(struct tty_struct *tty, struct file *filp) | |||
865 | portp->tx.head = NULL; | 833 | portp->tx.head = NULL; |
866 | portp->tx.tail = NULL; | 834 | portp->tx.tail = NULL; |
867 | } | 835 | } |
836 | } | ||
837 | |||
838 | static void stl_close(struct tty_struct *tty, struct file *filp) | ||
839 | { | ||
840 | struct stlport*portp; | ||
841 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); | ||
868 | 842 | ||
869 | tty_port_close_end(port, tty); | 843 | portp = tty->driver_data; |
870 | tty_port_tty_set(port, NULL); | 844 | BUG_ON(portp == NULL); |
845 | tty_port_close(&portp->port, tty, filp); | ||
871 | } | 846 | } |
872 | 847 | ||
873 | /*****************************************************************************/ | 848 | /*****************************************************************************/ |
@@ -1314,35 +1289,12 @@ static void stl_stop(struct tty_struct *tty) | |||
1314 | 1289 | ||
1315 | static void stl_hangup(struct tty_struct *tty) | 1290 | static void stl_hangup(struct tty_struct *tty) |
1316 | { | 1291 | { |
1317 | struct stlport *portp; | 1292 | struct stlport *portp = tty->driver_data; |
1318 | struct tty_port *port; | ||
1319 | unsigned long flags; | ||
1320 | |||
1321 | pr_debug("stl_hangup(tty=%p)\n", tty); | 1293 | pr_debug("stl_hangup(tty=%p)\n", tty); |
1322 | 1294 | ||
1323 | portp = tty->driver_data; | ||
1324 | if (portp == NULL) | 1295 | if (portp == NULL) |
1325 | return; | 1296 | return; |
1326 | port = &portp->port; | 1297 | tty_port_hangup(&portp->port); |
1327 | |||
1328 | spin_lock_irqsave(&port->lock, flags); | ||
1329 | port->flags &= ~ASYNC_INITIALIZED; | ||
1330 | spin_unlock_irqrestore(&port->lock, flags); | ||
1331 | |||
1332 | stl_disableintrs(portp); | ||
1333 | if (tty->termios->c_cflag & HUPCL) | ||
1334 | stl_setsignals(portp, 0, 0); | ||
1335 | stl_enablerxtx(portp, 0, 0); | ||
1336 | stl_flushbuffer(tty); | ||
1337 | portp->istate = 0; | ||
1338 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
1339 | if (portp->tx.buf != NULL) { | ||
1340 | kfree(portp->tx.buf); | ||
1341 | portp->tx.buf = NULL; | ||
1342 | portp->tx.head = NULL; | ||
1343 | portp->tx.tail = NULL; | ||
1344 | } | ||
1345 | tty_port_hangup(port); | ||
1346 | } | 1298 | } |
1347 | 1299 | ||
1348 | /*****************************************************************************/ | 1300 | /*****************************************************************************/ |
@@ -2486,18 +2438,19 @@ static int stl_getbrdstruct(struct stlbrd __user *arg) | |||
2486 | * collection. | 2438 | * collection. |
2487 | */ | 2439 | */ |
2488 | 2440 | ||
2489 | static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) | 2441 | static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) |
2490 | { | 2442 | { |
2491 | int brdnr, rc; | 2443 | int brdnr, rc; |
2492 | void __user *argp = (void __user *)arg; | 2444 | void __user *argp = (void __user *)arg; |
2493 | 2445 | ||
2494 | pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg); | 2446 | pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg); |
2495 | 2447 | ||
2496 | brdnr = iminor(ip); | 2448 | brdnr = iminor(fp->f_dentry->d_inode); |
2497 | if (brdnr >= STL_MAXBRDS) | 2449 | if (brdnr >= STL_MAXBRDS) |
2498 | return -ENODEV; | 2450 | return -ENODEV; |
2499 | rc = 0; | 2451 | rc = 0; |
2500 | 2452 | ||
2453 | lock_kernel(); | ||
2501 | switch (cmd) { | 2454 | switch (cmd) { |
2502 | case COM_GETPORTSTATS: | 2455 | case COM_GETPORTSTATS: |
2503 | rc = stl_getportstats(NULL, NULL, argp); | 2456 | rc = stl_getportstats(NULL, NULL, argp); |
@@ -2518,7 +2471,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns | |||
2518 | rc = -ENOIOCTLCMD; | 2471 | rc = -ENOIOCTLCMD; |
2519 | break; | 2472 | break; |
2520 | } | 2473 | } |
2521 | 2474 | unlock_kernel(); | |
2522 | return rc; | 2475 | return rc; |
2523 | } | 2476 | } |
2524 | 2477 | ||
@@ -2549,6 +2502,8 @@ static const struct tty_operations stl_ops = { | |||
2549 | static const struct tty_port_operations stl_port_ops = { | 2502 | static const struct tty_port_operations stl_port_ops = { |
2550 | .carrier_raised = stl_carrier_raised, | 2503 | .carrier_raised = stl_carrier_raised, |
2551 | .dtr_rts = stl_dtr_rts, | 2504 | .dtr_rts = stl_dtr_rts, |
2505 | .activate = stl_activate, | ||
2506 | .shutdown = stl_shutdown, | ||
2552 | }; | 2507 | }; |
2553 | 2508 | ||
2554 | /*****************************************************************************/ | 2509 | /*****************************************************************************/ |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 59499ee0fe6a..684f0e0b175e 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -142,7 +142,6 @@ ssize_t redirected_tty_write(struct file *, const char __user *, | |||
142 | size_t, loff_t *); | 142 | size_t, loff_t *); |
143 | static unsigned int tty_poll(struct file *, poll_table *); | 143 | static unsigned int tty_poll(struct file *, poll_table *); |
144 | static int tty_open(struct inode *, struct file *); | 144 | static int tty_open(struct inode *, struct file *); |
145 | static int tty_release(struct inode *, struct file *); | ||
146 | long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 145 | long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
147 | #ifdef CONFIG_COMPAT | 146 | #ifdef CONFIG_COMPAT |
148 | static long tty_compat_ioctl(struct file *file, unsigned int cmd, | 147 | static long tty_compat_ioctl(struct file *file, unsigned int cmd, |
@@ -506,8 +505,6 @@ static void do_tty_hangup(struct work_struct *work) | |||
506 | if (!tty) | 505 | if (!tty) |
507 | return; | 506 | return; |
508 | 507 | ||
509 | /* inuse_filps is protected by the single kernel lock */ | ||
510 | lock_kernel(); | ||
511 | 508 | ||
512 | spin_lock(&redirect_lock); | 509 | spin_lock(&redirect_lock); |
513 | if (redirect && redirect->private_data == tty) { | 510 | if (redirect && redirect->private_data == tty) { |
@@ -516,7 +513,11 @@ static void do_tty_hangup(struct work_struct *work) | |||
516 | } | 513 | } |
517 | spin_unlock(&redirect_lock); | 514 | spin_unlock(&redirect_lock); |
518 | 515 | ||
516 | /* inuse_filps is protected by the single kernel lock */ | ||
517 | lock_kernel(); | ||
519 | check_tty_count(tty, "do_tty_hangup"); | 518 | check_tty_count(tty, "do_tty_hangup"); |
519 | unlock_kernel(); | ||
520 | |||
520 | file_list_lock(); | 521 | file_list_lock(); |
521 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ | 522 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ |
522 | list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { | 523 | list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { |
@@ -530,6 +531,7 @@ static void do_tty_hangup(struct work_struct *work) | |||
530 | } | 531 | } |
531 | file_list_unlock(); | 532 | file_list_unlock(); |
532 | 533 | ||
534 | lock_kernel(); | ||
533 | tty_ldisc_hangup(tty); | 535 | tty_ldisc_hangup(tty); |
534 | 536 | ||
535 | read_lock(&tasklist_lock); | 537 | read_lock(&tasklist_lock); |
@@ -708,6 +710,8 @@ void disassociate_ctty(int on_exit) | |||
708 | struct tty_struct *tty; | 710 | struct tty_struct *tty; |
709 | struct pid *tty_pgrp = NULL; | 711 | struct pid *tty_pgrp = NULL; |
710 | 712 | ||
713 | if (!current->signal->leader) | ||
714 | return; | ||
711 | 715 | ||
712 | tty = get_current_tty(); | 716 | tty = get_current_tty(); |
713 | if (tty) { | 717 | if (tty) { |
@@ -773,8 +777,7 @@ void no_tty(void) | |||
773 | { | 777 | { |
774 | struct task_struct *tsk = current; | 778 | struct task_struct *tsk = current; |
775 | lock_kernel(); | 779 | lock_kernel(); |
776 | if (tsk->signal->leader) | 780 | disassociate_ctty(0); |
777 | disassociate_ctty(0); | ||
778 | unlock_kernel(); | 781 | unlock_kernel(); |
779 | proc_clear_tty(tsk); | 782 | proc_clear_tty(tsk); |
780 | } | 783 | } |
@@ -1017,14 +1020,16 @@ out: | |||
1017 | 1020 | ||
1018 | void tty_write_message(struct tty_struct *tty, char *msg) | 1021 | void tty_write_message(struct tty_struct *tty, char *msg) |
1019 | { | 1022 | { |
1020 | lock_kernel(); | ||
1021 | if (tty) { | 1023 | if (tty) { |
1022 | mutex_lock(&tty->atomic_write_lock); | 1024 | mutex_lock(&tty->atomic_write_lock); |
1023 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) | 1025 | lock_kernel(); |
1026 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { | ||
1027 | unlock_kernel(); | ||
1024 | tty->ops->write(tty, msg, strlen(msg)); | 1028 | tty->ops->write(tty, msg, strlen(msg)); |
1029 | } else | ||
1030 | unlock_kernel(); | ||
1025 | tty_write_unlock(tty); | 1031 | tty_write_unlock(tty); |
1026 | } | 1032 | } |
1027 | unlock_kernel(); | ||
1028 | return; | 1033 | return; |
1029 | } | 1034 | } |
1030 | 1035 | ||
@@ -1202,14 +1207,21 @@ static int tty_driver_install_tty(struct tty_driver *driver, | |||
1202 | struct tty_struct *tty) | 1207 | struct tty_struct *tty) |
1203 | { | 1208 | { |
1204 | int idx = tty->index; | 1209 | int idx = tty->index; |
1210 | int ret; | ||
1205 | 1211 | ||
1206 | if (driver->ops->install) | 1212 | if (driver->ops->install) { |
1207 | return driver->ops->install(driver, tty); | 1213 | lock_kernel(); |
1214 | ret = driver->ops->install(driver, tty); | ||
1215 | unlock_kernel(); | ||
1216 | return ret; | ||
1217 | } | ||
1208 | 1218 | ||
1209 | if (tty_init_termios(tty) == 0) { | 1219 | if (tty_init_termios(tty) == 0) { |
1220 | lock_kernel(); | ||
1210 | tty_driver_kref_get(driver); | 1221 | tty_driver_kref_get(driver); |
1211 | tty->count++; | 1222 | tty->count++; |
1212 | driver->ttys[idx] = tty; | 1223 | driver->ttys[idx] = tty; |
1224 | unlock_kernel(); | ||
1213 | return 0; | 1225 | return 0; |
1214 | } | 1226 | } |
1215 | return -ENOMEM; | 1227 | return -ENOMEM; |
@@ -1302,10 +1314,14 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
1302 | struct tty_struct *tty; | 1314 | struct tty_struct *tty; |
1303 | int retval; | 1315 | int retval; |
1304 | 1316 | ||
1317 | lock_kernel(); | ||
1305 | /* Check if pty master is being opened multiple times */ | 1318 | /* Check if pty master is being opened multiple times */ |
1306 | if (driver->subtype == PTY_TYPE_MASTER && | 1319 | if (driver->subtype == PTY_TYPE_MASTER && |
1307 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) | 1320 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { |
1321 | unlock_kernel(); | ||
1308 | return ERR_PTR(-EIO); | 1322 | return ERR_PTR(-EIO); |
1323 | } | ||
1324 | unlock_kernel(); | ||
1309 | 1325 | ||
1310 | /* | 1326 | /* |
1311 | * First time open is complex, especially for PTY devices. | 1327 | * First time open is complex, especially for PTY devices. |
@@ -1335,7 +1351,6 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
1335 | * If we fail here just call release_tty to clean up. No need | 1351 | * If we fail here just call release_tty to clean up. No need |
1336 | * to decrement the use counts, as release_tty doesn't care. | 1352 | * to decrement the use counts, as release_tty doesn't care. |
1337 | */ | 1353 | */ |
1338 | |||
1339 | retval = tty_ldisc_setup(tty, tty->link); | 1354 | retval = tty_ldisc_setup(tty, tty->link); |
1340 | if (retval) | 1355 | if (retval) |
1341 | goto release_mem_out; | 1356 | goto release_mem_out; |
@@ -1350,7 +1365,9 @@ release_mem_out: | |||
1350 | if (printk_ratelimit()) | 1365 | if (printk_ratelimit()) |
1351 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " | 1366 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " |
1352 | "clearing slot %d\n", idx); | 1367 | "clearing slot %d\n", idx); |
1368 | lock_kernel(); | ||
1353 | release_tty(tty, idx); | 1369 | release_tty(tty, idx); |
1370 | unlock_kernel(); | ||
1354 | return ERR_PTR(retval); | 1371 | return ERR_PTR(retval); |
1355 | } | 1372 | } |
1356 | 1373 | ||
@@ -1464,7 +1481,17 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
1464 | tty_kref_put(tty); | 1481 | tty_kref_put(tty); |
1465 | } | 1482 | } |
1466 | 1483 | ||
1467 | /* | 1484 | /** |
1485 | * tty_release - vfs callback for close | ||
1486 | * @inode: inode of tty | ||
1487 | * @filp: file pointer for handle to tty | ||
1488 | * | ||
1489 | * Called the last time each file handle is closed that references | ||
1490 | * this tty. There may however be several such references. | ||
1491 | * | ||
1492 | * Locking: | ||
1493 | * Takes bkl. See tty_release_dev | ||
1494 | * | ||
1468 | * Even releasing the tty structures is a tricky business.. We have | 1495 | * Even releasing the tty structures is a tricky business.. We have |
1469 | * to be very careful that the structures are all released at the | 1496 | * to be very careful that the structures are all released at the |
1470 | * same time, as interrupts might otherwise get the wrong pointers. | 1497 | * same time, as interrupts might otherwise get the wrong pointers. |
@@ -1472,20 +1499,20 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
1472 | * WSH 09/09/97: rewritten to avoid some nasty race conditions that could | 1499 | * WSH 09/09/97: rewritten to avoid some nasty race conditions that could |
1473 | * lead to double frees or releasing memory still in use. | 1500 | * lead to double frees or releasing memory still in use. |
1474 | */ | 1501 | */ |
1475 | void tty_release_dev(struct file *filp) | 1502 | |
1503 | int tty_release(struct inode *inode, struct file *filp) | ||
1476 | { | 1504 | { |
1477 | struct tty_struct *tty, *o_tty; | 1505 | struct tty_struct *tty, *o_tty; |
1478 | int pty_master, tty_closing, o_tty_closing, do_sleep; | 1506 | int pty_master, tty_closing, o_tty_closing, do_sleep; |
1479 | int devpts; | 1507 | int devpts; |
1480 | int idx; | 1508 | int idx; |
1481 | char buf[64]; | 1509 | char buf[64]; |
1482 | struct inode *inode; | ||
1483 | 1510 | ||
1484 | inode = filp->f_path.dentry->d_inode; | ||
1485 | tty = (struct tty_struct *)filp->private_data; | 1511 | tty = (struct tty_struct *)filp->private_data; |
1486 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) | 1512 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) |
1487 | return; | 1513 | return 0; |
1488 | 1514 | ||
1515 | lock_kernel(); | ||
1489 | check_tty_count(tty, "tty_release_dev"); | 1516 | check_tty_count(tty, "tty_release_dev"); |
1490 | 1517 | ||
1491 | tty_fasync(-1, filp, 0); | 1518 | tty_fasync(-1, filp, 0); |
@@ -1500,19 +1527,22 @@ void tty_release_dev(struct file *filp) | |||
1500 | if (idx < 0 || idx >= tty->driver->num) { | 1527 | if (idx < 0 || idx >= tty->driver->num) { |
1501 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " | 1528 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " |
1502 | "free (%s)\n", tty->name); | 1529 | "free (%s)\n", tty->name); |
1503 | return; | 1530 | unlock_kernel(); |
1531 | return 0; | ||
1504 | } | 1532 | } |
1505 | if (!devpts) { | 1533 | if (!devpts) { |
1506 | if (tty != tty->driver->ttys[idx]) { | 1534 | if (tty != tty->driver->ttys[idx]) { |
1535 | unlock_kernel(); | ||
1507 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " | 1536 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " |
1508 | "for (%s)\n", idx, tty->name); | 1537 | "for (%s)\n", idx, tty->name); |
1509 | return; | 1538 | return 0; |
1510 | } | 1539 | } |
1511 | if (tty->termios != tty->driver->termios[idx]) { | 1540 | if (tty->termios != tty->driver->termios[idx]) { |
1541 | unlock_kernel(); | ||
1512 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " | 1542 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " |
1513 | "for (%s)\n", | 1543 | "for (%s)\n", |
1514 | idx, tty->name); | 1544 | idx, tty->name); |
1515 | return; | 1545 | return 0; |
1516 | } | 1546 | } |
1517 | } | 1547 | } |
1518 | #endif | 1548 | #endif |
@@ -1526,26 +1556,30 @@ void tty_release_dev(struct file *filp) | |||
1526 | if (tty->driver->other && | 1556 | if (tty->driver->other && |
1527 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | 1557 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { |
1528 | if (o_tty != tty->driver->other->ttys[idx]) { | 1558 | if (o_tty != tty->driver->other->ttys[idx]) { |
1559 | unlock_kernel(); | ||
1529 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " | 1560 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " |
1530 | "not o_tty for (%s)\n", | 1561 | "not o_tty for (%s)\n", |
1531 | idx, tty->name); | 1562 | idx, tty->name); |
1532 | return; | 1563 | return 0 ; |
1533 | } | 1564 | } |
1534 | if (o_tty->termios != tty->driver->other->termios[idx]) { | 1565 | if (o_tty->termios != tty->driver->other->termios[idx]) { |
1566 | unlock_kernel(); | ||
1535 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " | 1567 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " |
1536 | "not o_termios for (%s)\n", | 1568 | "not o_termios for (%s)\n", |
1537 | idx, tty->name); | 1569 | idx, tty->name); |
1538 | return; | 1570 | return 0; |
1539 | } | 1571 | } |
1540 | if (o_tty->link != tty) { | 1572 | if (o_tty->link != tty) { |
1573 | unlock_kernel(); | ||
1541 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); | 1574 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); |
1542 | return; | 1575 | return 0; |
1543 | } | 1576 | } |
1544 | } | 1577 | } |
1545 | #endif | 1578 | #endif |
1546 | if (tty->ops->close) | 1579 | if (tty->ops->close) |
1547 | tty->ops->close(tty, filp); | 1580 | tty->ops->close(tty, filp); |
1548 | 1581 | ||
1582 | unlock_kernel(); | ||
1549 | /* | 1583 | /* |
1550 | * Sanity check: if tty->count is going to zero, there shouldn't be | 1584 | * Sanity check: if tty->count is going to zero, there shouldn't be |
1551 | * any waiters on tty->read_wait or tty->write_wait. We test the | 1585 | * any waiters on tty->read_wait or tty->write_wait. We test the |
@@ -1568,6 +1602,7 @@ void tty_release_dev(struct file *filp) | |||
1568 | opens on /dev/tty */ | 1602 | opens on /dev/tty */ |
1569 | 1603 | ||
1570 | mutex_lock(&tty_mutex); | 1604 | mutex_lock(&tty_mutex); |
1605 | lock_kernel(); | ||
1571 | tty_closing = tty->count <= 1; | 1606 | tty_closing = tty->count <= 1; |
1572 | o_tty_closing = o_tty && | 1607 | o_tty_closing = o_tty && |
1573 | (o_tty->count <= (pty_master ? 1 : 0)); | 1608 | (o_tty->count <= (pty_master ? 1 : 0)); |
@@ -1598,6 +1633,7 @@ void tty_release_dev(struct file *filp) | |||
1598 | 1633 | ||
1599 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " | 1634 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " |
1600 | "active!\n", tty_name(tty, buf)); | 1635 | "active!\n", tty_name(tty, buf)); |
1636 | unlock_kernel(); | ||
1601 | mutex_unlock(&tty_mutex); | 1637 | mutex_unlock(&tty_mutex); |
1602 | schedule(); | 1638 | schedule(); |
1603 | } | 1639 | } |
@@ -1661,8 +1697,10 @@ void tty_release_dev(struct file *filp) | |||
1661 | mutex_unlock(&tty_mutex); | 1697 | mutex_unlock(&tty_mutex); |
1662 | 1698 | ||
1663 | /* check whether both sides are closing ... */ | 1699 | /* check whether both sides are closing ... */ |
1664 | if (!tty_closing || (o_tty && !o_tty_closing)) | 1700 | if (!tty_closing || (o_tty && !o_tty_closing)) { |
1665 | return; | 1701 | unlock_kernel(); |
1702 | return 0; | ||
1703 | } | ||
1666 | 1704 | ||
1667 | #ifdef TTY_DEBUG_HANGUP | 1705 | #ifdef TTY_DEBUG_HANGUP |
1668 | printk(KERN_DEBUG "freeing tty structure..."); | 1706 | printk(KERN_DEBUG "freeing tty structure..."); |
@@ -1680,10 +1718,12 @@ void tty_release_dev(struct file *filp) | |||
1680 | /* Make this pty number available for reallocation */ | 1718 | /* Make this pty number available for reallocation */ |
1681 | if (devpts) | 1719 | if (devpts) |
1682 | devpts_kill_index(inode, idx); | 1720 | devpts_kill_index(inode, idx); |
1721 | unlock_kernel(); | ||
1722 | return 0; | ||
1683 | } | 1723 | } |
1684 | 1724 | ||
1685 | /** | 1725 | /** |
1686 | * __tty_open - open a tty device | 1726 | * tty_open - open a tty device |
1687 | * @inode: inode of device file | 1727 | * @inode: inode of device file |
1688 | * @filp: file pointer to tty | 1728 | * @filp: file pointer to tty |
1689 | * | 1729 | * |
@@ -1703,7 +1743,7 @@ void tty_release_dev(struct file *filp) | |||
1703 | * ->siglock protects ->signal/->sighand | 1743 | * ->siglock protects ->signal/->sighand |
1704 | */ | 1744 | */ |
1705 | 1745 | ||
1706 | static int __tty_open(struct inode *inode, struct file *filp) | 1746 | static int tty_open(struct inode *inode, struct file *filp) |
1707 | { | 1747 | { |
1708 | struct tty_struct *tty = NULL; | 1748 | struct tty_struct *tty = NULL; |
1709 | int noctty, retval; | 1749 | int noctty, retval; |
@@ -1720,10 +1760,12 @@ retry_open: | |||
1720 | retval = 0; | 1760 | retval = 0; |
1721 | 1761 | ||
1722 | mutex_lock(&tty_mutex); | 1762 | mutex_lock(&tty_mutex); |
1763 | lock_kernel(); | ||
1723 | 1764 | ||
1724 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { | 1765 | if (device == MKDEV(TTYAUX_MAJOR, 0)) { |
1725 | tty = get_current_tty(); | 1766 | tty = get_current_tty(); |
1726 | if (!tty) { | 1767 | if (!tty) { |
1768 | unlock_kernel(); | ||
1727 | mutex_unlock(&tty_mutex); | 1769 | mutex_unlock(&tty_mutex); |
1728 | return -ENXIO; | 1770 | return -ENXIO; |
1729 | } | 1771 | } |
@@ -1755,12 +1797,14 @@ retry_open: | |||
1755 | goto got_driver; | 1797 | goto got_driver; |
1756 | } | 1798 | } |
1757 | } | 1799 | } |
1800 | unlock_kernel(); | ||
1758 | mutex_unlock(&tty_mutex); | 1801 | mutex_unlock(&tty_mutex); |
1759 | return -ENODEV; | 1802 | return -ENODEV; |
1760 | } | 1803 | } |
1761 | 1804 | ||
1762 | driver = get_tty_driver(device, &index); | 1805 | driver = get_tty_driver(device, &index); |
1763 | if (!driver) { | 1806 | if (!driver) { |
1807 | unlock_kernel(); | ||
1764 | mutex_unlock(&tty_mutex); | 1808 | mutex_unlock(&tty_mutex); |
1765 | return -ENODEV; | 1809 | return -ENODEV; |
1766 | } | 1810 | } |
@@ -1770,6 +1814,7 @@ got_driver: | |||
1770 | tty = tty_driver_lookup_tty(driver, inode, index); | 1814 | tty = tty_driver_lookup_tty(driver, inode, index); |
1771 | 1815 | ||
1772 | if (IS_ERR(tty)) { | 1816 | if (IS_ERR(tty)) { |
1817 | unlock_kernel(); | ||
1773 | mutex_unlock(&tty_mutex); | 1818 | mutex_unlock(&tty_mutex); |
1774 | return PTR_ERR(tty); | 1819 | return PTR_ERR(tty); |
1775 | } | 1820 | } |
@@ -1784,8 +1829,10 @@ got_driver: | |||
1784 | 1829 | ||
1785 | mutex_unlock(&tty_mutex); | 1830 | mutex_unlock(&tty_mutex); |
1786 | tty_driver_kref_put(driver); | 1831 | tty_driver_kref_put(driver); |
1787 | if (IS_ERR(tty)) | 1832 | if (IS_ERR(tty)) { |
1833 | unlock_kernel(); | ||
1788 | return PTR_ERR(tty); | 1834 | return PTR_ERR(tty); |
1835 | } | ||
1789 | 1836 | ||
1790 | filp->private_data = tty; | 1837 | filp->private_data = tty; |
1791 | file_move(filp, &tty->tty_files); | 1838 | file_move(filp, &tty->tty_files); |
@@ -1813,11 +1860,15 @@ got_driver: | |||
1813 | printk(KERN_DEBUG "error %d in opening %s...", retval, | 1860 | printk(KERN_DEBUG "error %d in opening %s...", retval, |
1814 | tty->name); | 1861 | tty->name); |
1815 | #endif | 1862 | #endif |
1816 | tty_release_dev(filp); | 1863 | tty_release(inode, filp); |
1817 | if (retval != -ERESTARTSYS) | 1864 | if (retval != -ERESTARTSYS) { |
1865 | unlock_kernel(); | ||
1818 | return retval; | 1866 | return retval; |
1819 | if (signal_pending(current)) | 1867 | } |
1868 | if (signal_pending(current)) { | ||
1869 | unlock_kernel(); | ||
1820 | return retval; | 1870 | return retval; |
1871 | } | ||
1821 | schedule(); | 1872 | schedule(); |
1822 | /* | 1873 | /* |
1823 | * Need to reset f_op in case a hangup happened. | 1874 | * Need to reset f_op in case a hangup happened. |
@@ -1826,8 +1877,11 @@ got_driver: | |||
1826 | filp->f_op = &tty_fops; | 1877 | filp->f_op = &tty_fops; |
1827 | goto retry_open; | 1878 | goto retry_open; |
1828 | } | 1879 | } |
1880 | unlock_kernel(); | ||
1881 | |||
1829 | 1882 | ||
1830 | mutex_lock(&tty_mutex); | 1883 | mutex_lock(&tty_mutex); |
1884 | lock_kernel(); | ||
1831 | spin_lock_irq(¤t->sighand->siglock); | 1885 | spin_lock_irq(¤t->sighand->siglock); |
1832 | if (!noctty && | 1886 | if (!noctty && |
1833 | current->signal->leader && | 1887 | current->signal->leader && |
@@ -1835,43 +1889,12 @@ got_driver: | |||
1835 | tty->session == NULL) | 1889 | tty->session == NULL) |
1836 | __proc_set_tty(current, tty); | 1890 | __proc_set_tty(current, tty); |
1837 | spin_unlock_irq(¤t->sighand->siglock); | 1891 | spin_unlock_irq(¤t->sighand->siglock); |
1892 | unlock_kernel(); | ||
1838 | mutex_unlock(&tty_mutex); | 1893 | mutex_unlock(&tty_mutex); |
1839 | return 0; | 1894 | return 0; |
1840 | } | 1895 | } |
1841 | 1896 | ||
1842 | /* BKL pushdown: scary code avoidance wrapper */ | ||
1843 | static int tty_open(struct inode *inode, struct file *filp) | ||
1844 | { | ||
1845 | int ret; | ||
1846 | |||
1847 | lock_kernel(); | ||
1848 | ret = __tty_open(inode, filp); | ||
1849 | unlock_kernel(); | ||
1850 | return ret; | ||
1851 | } | ||
1852 | |||
1853 | |||
1854 | |||
1855 | |||
1856 | /** | ||
1857 | * tty_release - vfs callback for close | ||
1858 | * @inode: inode of tty | ||
1859 | * @filp: file pointer for handle to tty | ||
1860 | * | ||
1861 | * Called the last time each file handle is closed that references | ||
1862 | * this tty. There may however be several such references. | ||
1863 | * | ||
1864 | * Locking: | ||
1865 | * Takes bkl. See tty_release_dev | ||
1866 | */ | ||
1867 | 1897 | ||
1868 | static int tty_release(struct inode *inode, struct file *filp) | ||
1869 | { | ||
1870 | lock_kernel(); | ||
1871 | tty_release_dev(filp); | ||
1872 | unlock_kernel(); | ||
1873 | return 0; | ||
1874 | } | ||
1875 | 1898 | ||
1876 | /** | 1899 | /** |
1877 | * tty_poll - check tty status | 1900 | * tty_poll - check tty status |
@@ -2317,9 +2340,7 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) | |||
2317 | if (get_user(ldisc, p)) | 2340 | if (get_user(ldisc, p)) |
2318 | return -EFAULT; | 2341 | return -EFAULT; |
2319 | 2342 | ||
2320 | lock_kernel(); | ||
2321 | ret = tty_set_ldisc(tty, ldisc); | 2343 | ret = tty_set_ldisc(tty, ldisc); |
2322 | unlock_kernel(); | ||
2323 | 2344 | ||
2324 | return ret; | 2345 | return ret; |
2325 | } | 2346 | } |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index feb55075819b..3f653f7d849f 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/vt_kern.h> | 34 | #include <linux/vt_kern.h> |
35 | #include <linux/selection.h> | 35 | #include <linux/selection.h> |
36 | 36 | ||
37 | #include <linux/smp_lock.h> /* For the moment */ | ||
38 | |||
37 | #include <linux/kmod.h> | 39 | #include <linux/kmod.h> |
38 | #include <linux/nsproxy.h> | 40 | #include <linux/nsproxy.h> |
39 | 41 | ||
@@ -443,8 +445,14 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
443 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | 445 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) |
444 | { | 446 | { |
445 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); | 447 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); |
446 | if (ld->ops->open) | 448 | if (ld->ops->open) { |
447 | return ld->ops->open(tty); | 449 | int ret; |
450 | /* BKL here locks verus a hangup event */ | ||
451 | lock_kernel(); | ||
452 | ret = ld->ops->open(tty); | ||
453 | unlock_kernel(); | ||
454 | return ret; | ||
455 | } | ||
448 | return 0; | 456 | return 0; |
449 | } | 457 | } |
450 | 458 | ||
@@ -545,6 +553,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
545 | if (IS_ERR(new_ldisc)) | 553 | if (IS_ERR(new_ldisc)) |
546 | return PTR_ERR(new_ldisc); | 554 | return PTR_ERR(new_ldisc); |
547 | 555 | ||
556 | lock_kernel(); | ||
548 | /* | 557 | /* |
549 | * We need to look at the tty locking here for pty/tty pairs | 558 | * We need to look at the tty locking here for pty/tty pairs |
550 | * when both sides try to change in parallel. | 559 | * when both sides try to change in parallel. |
@@ -558,10 +567,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
558 | */ | 567 | */ |
559 | 568 | ||
560 | if (tty->ldisc->ops->num == ldisc) { | 569 | if (tty->ldisc->ops->num == ldisc) { |
570 | unlock_kernel(); | ||
561 | tty_ldisc_put(new_ldisc); | 571 | tty_ldisc_put(new_ldisc); |
562 | return 0; | 572 | return 0; |
563 | } | 573 | } |
564 | 574 | ||
575 | unlock_kernel(); | ||
565 | /* | 576 | /* |
566 | * Problem: What do we do if this blocks ? | 577 | * Problem: What do we do if this blocks ? |
567 | * We could deadlock here | 578 | * We could deadlock here |
@@ -582,6 +593,9 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
582 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | 593 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); |
583 | mutex_lock(&tty->ldisc_mutex); | 594 | mutex_lock(&tty->ldisc_mutex); |
584 | } | 595 | } |
596 | |||
597 | lock_kernel(); | ||
598 | |||
585 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | 599 | set_bit(TTY_LDISC_CHANGING, &tty->flags); |
586 | 600 | ||
587 | /* | 601 | /* |
@@ -592,6 +606,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
592 | tty->receive_room = 0; | 606 | tty->receive_room = 0; |
593 | 607 | ||
594 | o_ldisc = tty->ldisc; | 608 | o_ldisc = tty->ldisc; |
609 | |||
610 | unlock_kernel(); | ||
595 | /* | 611 | /* |
596 | * Make sure we don't change while someone holds a | 612 | * Make sure we don't change while someone holds a |
597 | * reference to the line discipline. The TTY_LDISC bit | 613 | * reference to the line discipline. The TTY_LDISC bit |
@@ -617,12 +633,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
617 | flush_scheduled_work(); | 633 | flush_scheduled_work(); |
618 | 634 | ||
619 | mutex_lock(&tty->ldisc_mutex); | 635 | mutex_lock(&tty->ldisc_mutex); |
636 | lock_kernel(); | ||
620 | if (test_bit(TTY_HUPPED, &tty->flags)) { | 637 | if (test_bit(TTY_HUPPED, &tty->flags)) { |
621 | /* We were raced by the hangup method. It will have stomped | 638 | /* We were raced by the hangup method. It will have stomped |
622 | the ldisc data and closed the ldisc down */ | 639 | the ldisc data and closed the ldisc down */ |
623 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | 640 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); |
624 | mutex_unlock(&tty->ldisc_mutex); | 641 | mutex_unlock(&tty->ldisc_mutex); |
625 | tty_ldisc_put(new_ldisc); | 642 | tty_ldisc_put(new_ldisc); |
643 | unlock_kernel(); | ||
626 | return -EIO; | 644 | return -EIO; |
627 | } | 645 | } |
628 | 646 | ||
@@ -664,6 +682,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) | |||
664 | if (o_work) | 682 | if (o_work) |
665 | schedule_delayed_work(&o_tty->buf.work, 1); | 683 | schedule_delayed_work(&o_tty->buf.work, 1); |
666 | mutex_unlock(&tty->ldisc_mutex); | 684 | mutex_unlock(&tty->ldisc_mutex); |
685 | unlock_kernel(); | ||
667 | return retval; | 686 | return retval; |
668 | } | 687 | } |
669 | 688 | ||
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index c63f3d33914a..be492dd66437 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
@@ -25,19 +25,21 @@ void tty_port_init(struct tty_port *port) | |||
25 | init_waitqueue_head(&port->close_wait); | 25 | init_waitqueue_head(&port->close_wait); |
26 | init_waitqueue_head(&port->delta_msr_wait); | 26 | init_waitqueue_head(&port->delta_msr_wait); |
27 | mutex_init(&port->mutex); | 27 | mutex_init(&port->mutex); |
28 | mutex_init(&port->buf_mutex); | ||
28 | spin_lock_init(&port->lock); | 29 | spin_lock_init(&port->lock); |
29 | port->close_delay = (50 * HZ) / 100; | 30 | port->close_delay = (50 * HZ) / 100; |
30 | port->closing_wait = (3000 * HZ) / 100; | 31 | port->closing_wait = (3000 * HZ) / 100; |
32 | kref_init(&port->kref); | ||
31 | } | 33 | } |
32 | EXPORT_SYMBOL(tty_port_init); | 34 | EXPORT_SYMBOL(tty_port_init); |
33 | 35 | ||
34 | int tty_port_alloc_xmit_buf(struct tty_port *port) | 36 | int tty_port_alloc_xmit_buf(struct tty_port *port) |
35 | { | 37 | { |
36 | /* We may sleep in get_zeroed_page() */ | 38 | /* We may sleep in get_zeroed_page() */ |
37 | mutex_lock(&port->mutex); | 39 | mutex_lock(&port->buf_mutex); |
38 | if (port->xmit_buf == NULL) | 40 | if (port->xmit_buf == NULL) |
39 | port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); | 41 | port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); |
40 | mutex_unlock(&port->mutex); | 42 | mutex_unlock(&port->buf_mutex); |
41 | if (port->xmit_buf == NULL) | 43 | if (port->xmit_buf == NULL) |
42 | return -ENOMEM; | 44 | return -ENOMEM; |
43 | return 0; | 45 | return 0; |
@@ -46,15 +48,32 @@ EXPORT_SYMBOL(tty_port_alloc_xmit_buf); | |||
46 | 48 | ||
47 | void tty_port_free_xmit_buf(struct tty_port *port) | 49 | void tty_port_free_xmit_buf(struct tty_port *port) |
48 | { | 50 | { |
49 | mutex_lock(&port->mutex); | 51 | mutex_lock(&port->buf_mutex); |
50 | if (port->xmit_buf != NULL) { | 52 | if (port->xmit_buf != NULL) { |
51 | free_page((unsigned long)port->xmit_buf); | 53 | free_page((unsigned long)port->xmit_buf); |
52 | port->xmit_buf = NULL; | 54 | port->xmit_buf = NULL; |
53 | } | 55 | } |
54 | mutex_unlock(&port->mutex); | 56 | mutex_unlock(&port->buf_mutex); |
55 | } | 57 | } |
56 | EXPORT_SYMBOL(tty_port_free_xmit_buf); | 58 | EXPORT_SYMBOL(tty_port_free_xmit_buf); |
57 | 59 | ||
60 | static void tty_port_destructor(struct kref *kref) | ||
61 | { | ||
62 | struct tty_port *port = container_of(kref, struct tty_port, kref); | ||
63 | if (port->xmit_buf) | ||
64 | free_page((unsigned long)port->xmit_buf); | ||
65 | if (port->ops->destruct) | ||
66 | port->ops->destruct(port); | ||
67 | else | ||
68 | kfree(port); | ||
69 | } | ||
70 | |||
71 | void tty_port_put(struct tty_port *port) | ||
72 | { | ||
73 | if (port) | ||
74 | kref_put(&port->kref, tty_port_destructor); | ||
75 | } | ||
76 | EXPORT_SYMBOL(tty_port_put); | ||
58 | 77 | ||
59 | /** | 78 | /** |
60 | * tty_port_tty_get - get a tty reference | 79 | * tty_port_tty_get - get a tty reference |
@@ -99,10 +118,11 @@ EXPORT_SYMBOL(tty_port_tty_set); | |||
99 | 118 | ||
100 | static void tty_port_shutdown(struct tty_port *port) | 119 | static void tty_port_shutdown(struct tty_port *port) |
101 | { | 120 | { |
121 | mutex_lock(&port->mutex); | ||
102 | if (port->ops->shutdown && | 122 | if (port->ops->shutdown && |
103 | test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) | 123 | test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) |
104 | port->ops->shutdown(port); | 124 | port->ops->shutdown(port); |
105 | 125 | mutex_unlock(&port->mutex); | |
106 | } | 126 | } |
107 | 127 | ||
108 | /** | 128 | /** |
@@ -120,8 +140,10 @@ void tty_port_hangup(struct tty_port *port) | |||
120 | spin_lock_irqsave(&port->lock, flags); | 140 | spin_lock_irqsave(&port->lock, flags); |
121 | port->count = 0; | 141 | port->count = 0; |
122 | port->flags &= ~ASYNC_NORMAL_ACTIVE; | 142 | port->flags &= ~ASYNC_NORMAL_ACTIVE; |
123 | if (port->tty) | 143 | if (port->tty) { |
144 | set_bit(TTY_IO_ERROR, &port->tty->flags); | ||
124 | tty_kref_put(port->tty); | 145 | tty_kref_put(port->tty); |
146 | } | ||
125 | port->tty = NULL; | 147 | port->tty = NULL; |
126 | spin_unlock_irqrestore(&port->lock, flags); | 148 | spin_unlock_irqrestore(&port->lock, flags); |
127 | wake_up_interruptible(&port->open_wait); | 149 | wake_up_interruptible(&port->open_wait); |
@@ -198,7 +220,7 @@ EXPORT_SYMBOL(tty_port_lower_dtr_rts); | |||
198 | * management of these lines. Note that the dtr/rts raise is done each | 220 | * management of these lines. Note that the dtr/rts raise is done each |
199 | * iteration as a hangup may have previously dropped them while we wait. | 221 | * iteration as a hangup may have previously dropped them while we wait. |
200 | */ | 222 | */ |
201 | 223 | ||
202 | int tty_port_block_til_ready(struct tty_port *port, | 224 | int tty_port_block_til_ready(struct tty_port *port, |
203 | struct tty_struct *tty, struct file *filp) | 225 | struct tty_struct *tty, struct file *filp) |
204 | { | 226 | { |
@@ -253,7 +275,8 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
253 | tty_port_raise_dtr_rts(port); | 275 | tty_port_raise_dtr_rts(port); |
254 | 276 | ||
255 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); | 277 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); |
256 | /* Check for a hangup or uninitialised port. Return accordingly */ | 278 | /* Check for a hangup or uninitialised port. |
279 | Return accordingly */ | ||
257 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { | 280 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { |
258 | if (port->flags & ASYNC_HUP_NOTIFY) | 281 | if (port->flags & ASYNC_HUP_NOTIFY) |
259 | retval = -EAGAIN; | 282 | retval = -EAGAIN; |
@@ -285,11 +308,11 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
285 | port->flags |= ASYNC_NORMAL_ACTIVE; | 308 | port->flags |= ASYNC_NORMAL_ACTIVE; |
286 | spin_unlock_irqrestore(&port->lock, flags); | 309 | spin_unlock_irqrestore(&port->lock, flags); |
287 | return retval; | 310 | return retval; |
288 | |||
289 | } | 311 | } |
290 | EXPORT_SYMBOL(tty_port_block_til_ready); | 312 | EXPORT_SYMBOL(tty_port_block_til_ready); |
291 | 313 | ||
292 | int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp) | 314 | int tty_port_close_start(struct tty_port *port, |
315 | struct tty_struct *tty, struct file *filp) | ||
293 | { | 316 | { |
294 | unsigned long flags; | 317 | unsigned long flags; |
295 | 318 | ||
@@ -299,7 +322,7 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f | |||
299 | return 0; | 322 | return 0; |
300 | } | 323 | } |
301 | 324 | ||
302 | if( tty->count == 1 && port->count != 1) { | 325 | if (tty->count == 1 && port->count != 1) { |
303 | printk(KERN_WARNING | 326 | printk(KERN_WARNING |
304 | "tty_port_close_start: tty->count = 1 port count = %d.\n", | 327 | "tty_port_close_start: tty->count = 1 port count = %d.\n", |
305 | port->count); | 328 | port->count); |
@@ -331,12 +354,20 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f | |||
331 | long timeout; | 354 | long timeout; |
332 | 355 | ||
333 | if (bps > 1200) | 356 | if (bps > 1200) |
334 | timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps, | 357 | timeout = max_t(long, |
335 | HZ / 10); | 358 | (HZ * 10 * port->drain_delay) / bps, HZ / 10); |
336 | else | 359 | else |
337 | timeout = 2 * HZ; | 360 | timeout = 2 * HZ; |
338 | schedule_timeout_interruptible(timeout); | 361 | schedule_timeout_interruptible(timeout); |
339 | } | 362 | } |
363 | /* Flush the ldisc buffering */ | ||
364 | tty_ldisc_flush(tty); | ||
365 | |||
366 | /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to | ||
367 | hang up the line */ | ||
368 | if (tty->termios->c_cflag & HUPCL) | ||
369 | tty_port_lower_dtr_rts(port); | ||
370 | |||
340 | /* Don't call port->drop for the last reference. Callers will want | 371 | /* Don't call port->drop for the last reference. Callers will want |
341 | to drop the last active reference in ->shutdown() or the tty | 372 | to drop the last active reference in ->shutdown() or the tty |
342 | shutdown path */ | 373 | shutdown path */ |
@@ -348,11 +379,6 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) | |||
348 | { | 379 | { |
349 | unsigned long flags; | 380 | unsigned long flags; |
350 | 381 | ||
351 | tty_ldisc_flush(tty); | ||
352 | |||
353 | if (tty->termios->c_cflag & HUPCL) | ||
354 | tty_port_lower_dtr_rts(port); | ||
355 | |||
356 | spin_lock_irqsave(&port->lock, flags); | 382 | spin_lock_irqsave(&port->lock, flags); |
357 | tty->closing = 0; | 383 | tty->closing = 0; |
358 | 384 | ||
@@ -377,7 +403,42 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty, | |||
377 | if (tty_port_close_start(port, tty, filp) == 0) | 403 | if (tty_port_close_start(port, tty, filp) == 0) |
378 | return; | 404 | return; |
379 | tty_port_shutdown(port); | 405 | tty_port_shutdown(port); |
406 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
380 | tty_port_close_end(port, tty); | 407 | tty_port_close_end(port, tty); |
381 | tty_port_tty_set(port, NULL); | 408 | tty_port_tty_set(port, NULL); |
382 | } | 409 | } |
383 | EXPORT_SYMBOL(tty_port_close); | 410 | EXPORT_SYMBOL(tty_port_close); |
411 | |||
412 | int tty_port_open(struct tty_port *port, struct tty_struct *tty, | ||
413 | struct file *filp) | ||
414 | { | ||
415 | spin_lock_irq(&port->lock); | ||
416 | if (!tty_hung_up_p(filp)) | ||
417 | ++port->count; | ||
418 | spin_unlock_irq(&port->lock); | ||
419 | tty_port_tty_set(port, tty); | ||
420 | |||
421 | /* | ||
422 | * Do the device-specific open only if the hardware isn't | ||
423 | * already initialized. Serialize open and shutdown using the | ||
424 | * port mutex. | ||
425 | */ | ||
426 | |||
427 | mutex_lock(&port->mutex); | ||
428 | |||
429 | if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) { | ||
430 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
431 | if (port->ops->activate) { | ||
432 | int retval = port->ops->activate(port, tty); | ||
433 | if (retval) { | ||
434 | mutex_unlock(&port->mutex); | ||
435 | return retval; | ||
436 | } | ||
437 | } | ||
438 | set_bit(ASYNCB_INITIALIZED, &port->flags); | ||
439 | } | ||
440 | mutex_unlock(&port->mutex); | ||
441 | return tty_port_block_til_ready(port, tty, filp); | ||
442 | } | ||
443 | |||
444 | EXPORT_SYMBOL(tty_port_open); | ||
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index b8e7c5ae981e..f53755533e7e 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/sched.h> | ||
32 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
33 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
34 | #include <linux/serial_reg.h> | 35 | #include <linux/serial_reg.h> |
@@ -73,11 +74,10 @@ struct uart_icount { | |||
73 | }; | 74 | }; |
74 | 75 | ||
75 | struct sdio_uart_port { | 76 | struct sdio_uart_port { |
77 | struct tty_port port; | ||
76 | struct kref kref; | 78 | struct kref kref; |
77 | struct tty_struct *tty; | 79 | struct tty_struct *tty; |
78 | unsigned int index; | 80 | unsigned int index; |
79 | unsigned int opened; | ||
80 | struct mutex open_lock; | ||
81 | struct sdio_func *func; | 81 | struct sdio_func *func; |
82 | struct mutex func_lock; | 82 | struct mutex func_lock; |
83 | struct task_struct *in_sdio_uart_irq; | 83 | struct task_struct *in_sdio_uart_irq; |
@@ -87,6 +87,7 @@ struct sdio_uart_port { | |||
87 | struct uart_icount icount; | 87 | struct uart_icount icount; |
88 | unsigned int uartclk; | 88 | unsigned int uartclk; |
89 | unsigned int mctrl; | 89 | unsigned int mctrl; |
90 | unsigned int rx_mctrl; | ||
90 | unsigned int read_status_mask; | 91 | unsigned int read_status_mask; |
91 | unsigned int ignore_status_mask; | 92 | unsigned int ignore_status_mask; |
92 | unsigned char x_char; | 93 | unsigned char x_char; |
@@ -102,7 +103,6 @@ static int sdio_uart_add_port(struct sdio_uart_port *port) | |||
102 | int index, ret = -EBUSY; | 103 | int index, ret = -EBUSY; |
103 | 104 | ||
104 | kref_init(&port->kref); | 105 | kref_init(&port->kref); |
105 | mutex_init(&port->open_lock); | ||
106 | mutex_init(&port->func_lock); | 106 | mutex_init(&port->func_lock); |
107 | spin_lock_init(&port->write_lock); | 107 | spin_lock_init(&port->write_lock); |
108 | 108 | ||
@@ -151,6 +151,7 @@ static void sdio_uart_port_put(struct sdio_uart_port *port) | |||
151 | static void sdio_uart_port_remove(struct sdio_uart_port *port) | 151 | static void sdio_uart_port_remove(struct sdio_uart_port *port) |
152 | { | 152 | { |
153 | struct sdio_func *func; | 153 | struct sdio_func *func; |
154 | struct tty_struct *tty; | ||
154 | 155 | ||
155 | BUG_ON(sdio_uart_table[port->index] != port); | 156 | BUG_ON(sdio_uart_table[port->index] != port); |
156 | 157 | ||
@@ -165,15 +166,19 @@ static void sdio_uart_port_remove(struct sdio_uart_port *port) | |||
165 | * give up on that port ASAP. | 166 | * give up on that port ASAP. |
166 | * Beware: the lock ordering is critical. | 167 | * Beware: the lock ordering is critical. |
167 | */ | 168 | */ |
168 | mutex_lock(&port->open_lock); | 169 | mutex_lock(&port->port.mutex); |
169 | mutex_lock(&port->func_lock); | 170 | mutex_lock(&port->func_lock); |
170 | func = port->func; | 171 | func = port->func; |
171 | sdio_claim_host(func); | 172 | sdio_claim_host(func); |
172 | port->func = NULL; | 173 | port->func = NULL; |
173 | mutex_unlock(&port->func_lock); | 174 | mutex_unlock(&port->func_lock); |
174 | if (port->opened) | 175 | tty = tty_port_tty_get(&port->port); |
175 | tty_hangup(port->tty); | 176 | /* tty_hangup is async so is this safe as is ?? */ |
176 | mutex_unlock(&port->open_lock); | 177 | if (tty) { |
178 | tty_hangup(tty); | ||
179 | tty_kref_put(tty); | ||
180 | } | ||
181 | mutex_unlock(&port->port.mutex); | ||
177 | sdio_release_irq(func); | 182 | sdio_release_irq(func); |
178 | sdio_disable_func(func); | 183 | sdio_disable_func(func); |
179 | sdio_release_host(func); | 184 | sdio_release_host(func); |
@@ -217,6 +222,8 @@ static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port) | |||
217 | unsigned char status; | 222 | unsigned char status; |
218 | unsigned int ret; | 223 | unsigned int ret; |
219 | 224 | ||
225 | /* FIXME: What stops this losing the delta bits and breaking | ||
226 | sdio_uart_check_modem_status ? */ | ||
220 | status = sdio_in(port, UART_MSR); | 227 | status = sdio_in(port, UART_MSR); |
221 | 228 | ||
222 | ret = 0; | 229 | ret = 0; |
@@ -391,7 +398,7 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port) | |||
391 | static void sdio_uart_receive_chars(struct sdio_uart_port *port, | 398 | static void sdio_uart_receive_chars(struct sdio_uart_port *port, |
392 | unsigned int *status) | 399 | unsigned int *status) |
393 | { | 400 | { |
394 | struct tty_struct *tty = port->tty; | 401 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
395 | unsigned int ch, flag; | 402 | unsigned int ch, flag; |
396 | int max_count = 256; | 403 | int max_count = 256; |
397 | 404 | ||
@@ -428,24 +435,30 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port, | |||
428 | } | 435 | } |
429 | 436 | ||
430 | if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0) | 437 | if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0) |
431 | tty_insert_flip_char(tty, ch, flag); | 438 | if (tty) |
439 | tty_insert_flip_char(tty, ch, flag); | ||
432 | 440 | ||
433 | /* | 441 | /* |
434 | * Overrun is special. Since it's reported immediately, | 442 | * Overrun is special. Since it's reported immediately, |
435 | * it doesn't affect the current character. | 443 | * it doesn't affect the current character. |
436 | */ | 444 | */ |
437 | if (*status & ~port->ignore_status_mask & UART_LSR_OE) | 445 | if (*status & ~port->ignore_status_mask & UART_LSR_OE) |
438 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 446 | if (tty) |
447 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
439 | 448 | ||
440 | *status = sdio_in(port, UART_LSR); | 449 | *status = sdio_in(port, UART_LSR); |
441 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); | 450 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); |
442 | tty_flip_buffer_push(tty); | 451 | if (tty) { |
452 | tty_flip_buffer_push(tty); | ||
453 | tty_kref_put(tty); | ||
454 | } | ||
443 | } | 455 | } |
444 | 456 | ||
445 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | 457 | static void sdio_uart_transmit_chars(struct sdio_uart_port *port) |
446 | { | 458 | { |
447 | struct circ_buf *xmit = &port->xmit; | 459 | struct circ_buf *xmit = &port->xmit; |
448 | int count; | 460 | int count; |
461 | struct tty_struct *tty; | ||
449 | 462 | ||
450 | if (port->x_char) { | 463 | if (port->x_char) { |
451 | sdio_out(port, UART_TX, port->x_char); | 464 | sdio_out(port, UART_TX, port->x_char); |
@@ -453,8 +466,13 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | |||
453 | port->x_char = 0; | 466 | port->x_char = 0; |
454 | return; | 467 | return; |
455 | } | 468 | } |
456 | if (circ_empty(xmit) || port->tty->stopped || port->tty->hw_stopped) { | 469 | |
470 | tty = tty_port_tty_get(&port->port); | ||
471 | |||
472 | if (tty == NULL || circ_empty(xmit) || | ||
473 | tty->stopped || tty->hw_stopped) { | ||
457 | sdio_uart_stop_tx(port); | 474 | sdio_uart_stop_tx(port); |
475 | tty_kref_put(tty); | ||
458 | return; | 476 | return; |
459 | } | 477 | } |
460 | 478 | ||
@@ -468,15 +486,17 @@ static void sdio_uart_transmit_chars(struct sdio_uart_port *port) | |||
468 | } while (--count > 0); | 486 | } while (--count > 0); |
469 | 487 | ||
470 | if (circ_chars_pending(xmit) < WAKEUP_CHARS) | 488 | if (circ_chars_pending(xmit) < WAKEUP_CHARS) |
471 | tty_wakeup(port->tty); | 489 | tty_wakeup(tty); |
472 | 490 | ||
473 | if (circ_empty(xmit)) | 491 | if (circ_empty(xmit)) |
474 | sdio_uart_stop_tx(port); | 492 | sdio_uart_stop_tx(port); |
493 | tty_kref_put(tty); | ||
475 | } | 494 | } |
476 | 495 | ||
477 | static void sdio_uart_check_modem_status(struct sdio_uart_port *port) | 496 | static void sdio_uart_check_modem_status(struct sdio_uart_port *port) |
478 | { | 497 | { |
479 | int status; | 498 | int status; |
499 | struct tty_struct *tty; | ||
480 | 500 | ||
481 | status = sdio_in(port, UART_MSR); | 501 | status = sdio_in(port, UART_MSR); |
482 | 502 | ||
@@ -487,25 +507,39 @@ static void sdio_uart_check_modem_status(struct sdio_uart_port *port) | |||
487 | port->icount.rng++; | 507 | port->icount.rng++; |
488 | if (status & UART_MSR_DDSR) | 508 | if (status & UART_MSR_DDSR) |
489 | port->icount.dsr++; | 509 | port->icount.dsr++; |
490 | if (status & UART_MSR_DDCD) | 510 | if (status & UART_MSR_DDCD) { |
491 | port->icount.dcd++; | 511 | port->icount.dcd++; |
512 | /* DCD raise - wake for open */ | ||
513 | if (status & UART_MSR_DCD) | ||
514 | wake_up_interruptible(&port->port.open_wait); | ||
515 | else { | ||
516 | /* DCD drop - hang up if tty attached */ | ||
517 | tty = tty_port_tty_get(&port->port); | ||
518 | if (tty) { | ||
519 | tty_hangup(tty); | ||
520 | tty_kref_put(tty); | ||
521 | } | ||
522 | } | ||
523 | } | ||
492 | if (status & UART_MSR_DCTS) { | 524 | if (status & UART_MSR_DCTS) { |
493 | port->icount.cts++; | 525 | port->icount.cts++; |
494 | if (port->tty->termios->c_cflag & CRTSCTS) { | 526 | tty = tty_port_tty_get(&port->port); |
527 | if (tty && (tty->termios->c_cflag & CRTSCTS)) { | ||
495 | int cts = (status & UART_MSR_CTS); | 528 | int cts = (status & UART_MSR_CTS); |
496 | if (port->tty->hw_stopped) { | 529 | if (tty->hw_stopped) { |
497 | if (cts) { | 530 | if (cts) { |
498 | port->tty->hw_stopped = 0; | 531 | tty->hw_stopped = 0; |
499 | sdio_uart_start_tx(port); | 532 | sdio_uart_start_tx(port); |
500 | tty_wakeup(port->tty); | 533 | tty_wakeup(tty); |
501 | } | 534 | } |
502 | } else { | 535 | } else { |
503 | if (!cts) { | 536 | if (!cts) { |
504 | port->tty->hw_stopped = 1; | 537 | tty->hw_stopped = 1; |
505 | sdio_uart_stop_tx(port); | 538 | sdio_uart_stop_tx(port); |
506 | } | 539 | } |
507 | } | 540 | } |
508 | } | 541 | } |
542 | tty_kref_put(tty); | ||
509 | } | 543 | } |
510 | } | 544 | } |
511 | 545 | ||
@@ -542,8 +576,62 @@ static void sdio_uart_irq(struct sdio_func *func) | |||
542 | port->in_sdio_uart_irq = NULL; | 576 | port->in_sdio_uart_irq = NULL; |
543 | } | 577 | } |
544 | 578 | ||
545 | static int sdio_uart_startup(struct sdio_uart_port *port) | 579 | static int uart_carrier_raised(struct tty_port *tport) |
580 | { | ||
581 | struct sdio_uart_port *port = | ||
582 | container_of(tport, struct sdio_uart_port, port); | ||
583 | unsigned int ret = sdio_uart_claim_func(port); | ||
584 | if (ret) /* Missing hardware shoudn't block for carrier */ | ||
585 | return 1; | ||
586 | ret = sdio_uart_get_mctrl(port); | ||
587 | sdio_uart_release_func(port); | ||
588 | if (ret & TIOCM_CAR) | ||
589 | return 1; | ||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | /** | ||
594 | * uart_dtr_rts - port helper to set uart signals | ||
595 | * @tport: tty port to be updated | ||
596 | * @onoff: set to turn on DTR/RTS | ||
597 | * | ||
598 | * Called by the tty port helpers when the modem signals need to be | ||
599 | * adjusted during an open, close and hangup. | ||
600 | */ | ||
601 | |||
602 | static void uart_dtr_rts(struct tty_port *tport, int onoff) | ||
603 | { | ||
604 | struct sdio_uart_port *port = | ||
605 | container_of(tport, struct sdio_uart_port, port); | ||
606 | int ret = sdio_uart_claim_func(port); | ||
607 | if (ret) | ||
608 | return; | ||
609 | if (onoff == 0) | ||
610 | sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
611 | else | ||
612 | sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
613 | sdio_uart_release_func(port); | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * sdio_uart_activate - start up hardware | ||
618 | * @tport: tty port to activate | ||
619 | * @tty: tty bound to this port | ||
620 | * | ||
621 | * Activate a tty port. The port locking guarantees us this will be | ||
622 | * run exactly once per set of opens, and if successful will see the | ||
623 | * shutdown method run exactly once to match. Start up and shutdown are | ||
624 | * protected from each other by the internal locking and will not run | ||
625 | * at the same time even during a hangup event. | ||
626 | * | ||
627 | * If we successfully start up the port we take an extra kref as we | ||
628 | * will keep it around until shutdown when the kref is dropped. | ||
629 | */ | ||
630 | |||
631 | static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty) | ||
546 | { | 632 | { |
633 | struct sdio_uart_port *port = | ||
634 | container_of(tport, struct sdio_uart_port, port); | ||
547 | unsigned long page; | 635 | unsigned long page; |
548 | int ret; | 636 | int ret; |
549 | 637 | ||
@@ -551,7 +639,7 @@ static int sdio_uart_startup(struct sdio_uart_port *port) | |||
551 | * Set the TTY IO error marker - we will only clear this | 639 | * Set the TTY IO error marker - we will only clear this |
552 | * once we have successfully opened the port. | 640 | * once we have successfully opened the port. |
553 | */ | 641 | */ |
554 | set_bit(TTY_IO_ERROR, &port->tty->flags); | 642 | set_bit(TTY_IO_ERROR, &tty->flags); |
555 | 643 | ||
556 | /* Initialise and allocate the transmit buffer. */ | 644 | /* Initialise and allocate the transmit buffer. */ |
557 | page = __get_free_page(GFP_KERNEL); | 645 | page = __get_free_page(GFP_KERNEL); |
@@ -592,19 +680,19 @@ static int sdio_uart_startup(struct sdio_uart_port *port) | |||
592 | */ | 680 | */ |
593 | sdio_out(port, UART_LCR, UART_LCR_WLEN8); | 681 | sdio_out(port, UART_LCR, UART_LCR_WLEN8); |
594 | 682 | ||
595 | port->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE; | 683 | port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE; |
596 | port->mctrl = TIOCM_OUT2; | 684 | port->mctrl = TIOCM_OUT2; |
597 | 685 | ||
598 | sdio_uart_change_speed(port, port->tty->termios, NULL); | 686 | sdio_uart_change_speed(port, tty->termios, NULL); |
599 | 687 | ||
600 | if (port->tty->termios->c_cflag & CBAUD) | 688 | if (tty->termios->c_cflag & CBAUD) |
601 | sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); | 689 | sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); |
602 | 690 | ||
603 | if (port->tty->termios->c_cflag & CRTSCTS) | 691 | if (tty->termios->c_cflag & CRTSCTS) |
604 | if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) | 692 | if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) |
605 | port->tty->hw_stopped = 1; | 693 | tty->hw_stopped = 1; |
606 | 694 | ||
607 | clear_bit(TTY_IO_ERROR, &port->tty->flags); | 695 | clear_bit(TTY_IO_ERROR, &tty->flags); |
608 | 696 | ||
609 | /* Kick the IRQ handler once while we're still holding the host lock */ | 697 | /* Kick the IRQ handler once while we're still holding the host lock */ |
610 | sdio_uart_irq(port->func); | 698 | sdio_uart_irq(port->func); |
@@ -621,8 +709,20 @@ err1: | |||
621 | return ret; | 709 | return ret; |
622 | } | 710 | } |
623 | 711 | ||
624 | static void sdio_uart_shutdown(struct sdio_uart_port *port) | 712 | /** |
713 | * sdio_uart_shutdown - stop hardware | ||
714 | * @tport: tty port to shut down | ||
715 | * | ||
716 | * Deactivate a tty port. The port locking guarantees us this will be | ||
717 | * run only if a successful matching activate already ran. The two are | ||
718 | * protected from each other by the internal locking and will not run | ||
719 | * at the same time even during a hangup event. | ||
720 | */ | ||
721 | |||
722 | static void sdio_uart_shutdown(struct tty_port *tport) | ||
625 | { | 723 | { |
724 | struct sdio_uart_port *port = | ||
725 | container_of(tport, struct sdio_uart_port, port); | ||
626 | int ret; | 726 | int ret; |
627 | 727 | ||
628 | ret = sdio_uart_claim_func(port); | 728 | ret = sdio_uart_claim_func(port); |
@@ -631,12 +731,6 @@ static void sdio_uart_shutdown(struct sdio_uart_port *port) | |||
631 | 731 | ||
632 | sdio_uart_stop_rx(port); | 732 | sdio_uart_stop_rx(port); |
633 | 733 | ||
634 | /* TODO: wait here for TX FIFO to drain */ | ||
635 | |||
636 | /* Turn off DTR and RTS early. */ | ||
637 | if (port->tty->termios->c_cflag & HUPCL) | ||
638 | sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
639 | |||
640 | /* Disable interrupts from this port */ | 734 | /* Disable interrupts from this port */ |
641 | sdio_release_irq(port->func); | 735 | sdio_release_irq(port->func); |
642 | port->ier = 0; | 736 | port->ier = 0; |
@@ -661,77 +755,70 @@ skip: | |||
661 | free_page((unsigned long)port->xmit.buf); | 755 | free_page((unsigned long)port->xmit.buf); |
662 | } | 756 | } |
663 | 757 | ||
664 | static int sdio_uart_open(struct tty_struct *tty, struct file *filp) | 758 | /** |
759 | * sdio_uart_install - install method | ||
760 | * @driver: the driver in use (sdio_uart in our case) | ||
761 | * @tty: the tty being bound | ||
762 | * | ||
763 | * Look up and bind the tty and the driver together. Initialize | ||
764 | * any needed private data (in our case the termios) | ||
765 | */ | ||
766 | |||
767 | static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty) | ||
665 | { | 768 | { |
666 | struct sdio_uart_port *port; | 769 | int idx = tty->index; |
667 | int ret; | 770 | struct sdio_uart_port *port = sdio_uart_port_get(idx); |
771 | int ret = tty_init_termios(tty); | ||
772 | |||
773 | if (ret == 0) { | ||
774 | tty_driver_kref_get(driver); | ||
775 | tty->count++; | ||
776 | /* This is the ref sdio_uart_port get provided */ | ||
777 | tty->driver_data = port; | ||
778 | driver->ttys[idx] = tty; | ||
779 | } else | ||
780 | sdio_uart_port_put(port); | ||
781 | return ret; | ||
782 | } | ||
668 | 783 | ||
669 | port = sdio_uart_port_get(tty->index); | 784 | /** |
670 | if (!port) | 785 | * sdio_uart_cleanup - called on the last tty kref drop |
671 | return -ENODEV; | 786 | * @tty: the tty being destroyed |
787 | * | ||
788 | * Called asynchronously when the last reference to the tty is dropped. | ||
789 | * We cannot destroy the tty->driver_data port kref until this point | ||
790 | */ | ||
672 | 791 | ||
673 | mutex_lock(&port->open_lock); | 792 | static void sdio_uart_cleanup(struct tty_struct *tty) |
793 | { | ||
794 | struct sdio_uart_port *port = tty->driver_data; | ||
795 | tty->driver_data = NULL; /* Bug trap */ | ||
796 | sdio_uart_port_put(port); | ||
797 | } | ||
674 | 798 | ||
675 | /* | 799 | /* |
676 | * Make sure not to mess up with a dead port | 800 | * Open/close/hangup is now entirely boilerplate |
677 | * which has not been closed yet. | 801 | */ |
678 | */ | ||
679 | if (tty->driver_data && tty->driver_data != port) { | ||
680 | mutex_unlock(&port->open_lock); | ||
681 | sdio_uart_port_put(port); | ||
682 | return -EBUSY; | ||
683 | } | ||
684 | 802 | ||
685 | if (!port->opened) { | 803 | static int sdio_uart_open(struct tty_struct *tty, struct file *filp) |
686 | tty->driver_data = port; | 804 | { |
687 | port->tty = tty; | 805 | struct sdio_uart_port *port = tty->driver_data; |
688 | ret = sdio_uart_startup(port); | 806 | return tty_port_open(&port->port, tty, filp); |
689 | if (ret) { | ||
690 | tty->driver_data = NULL; | ||
691 | port->tty = NULL; | ||
692 | mutex_unlock(&port->open_lock); | ||
693 | sdio_uart_port_put(port); | ||
694 | return ret; | ||
695 | } | ||
696 | } | ||
697 | port->opened++; | ||
698 | mutex_unlock(&port->open_lock); | ||
699 | return 0; | ||
700 | } | 807 | } |
701 | 808 | ||
702 | static void sdio_uart_close(struct tty_struct *tty, struct file * filp) | 809 | static void sdio_uart_close(struct tty_struct *tty, struct file * filp) |
703 | { | 810 | { |
704 | struct sdio_uart_port *port = tty->driver_data; | 811 | struct sdio_uart_port *port = tty->driver_data; |
812 | tty_port_close(&port->port, tty, filp); | ||
813 | } | ||
705 | 814 | ||
706 | if (!port) | 815 | static void sdio_uart_hangup(struct tty_struct *tty) |
707 | return; | 816 | { |
708 | 817 | struct sdio_uart_port *port = tty->driver_data; | |
709 | mutex_lock(&port->open_lock); | 818 | tty_port_hangup(&port->port); |
710 | BUG_ON(!port->opened); | ||
711 | |||
712 | /* | ||
713 | * This is messy. The tty layer calls us even when open() | ||
714 | * returned an error. Ignore this close request if tty->count | ||
715 | * is larger than port->count. | ||
716 | */ | ||
717 | if (tty->count > port->opened) { | ||
718 | mutex_unlock(&port->open_lock); | ||
719 | return; | ||
720 | } | ||
721 | |||
722 | if (--port->opened == 0) { | ||
723 | tty->closing = 1; | ||
724 | sdio_uart_shutdown(port); | ||
725 | tty_ldisc_flush(tty); | ||
726 | port->tty = NULL; | ||
727 | tty->driver_data = NULL; | ||
728 | tty->closing = 0; | ||
729 | } | ||
730 | mutex_unlock(&port->open_lock); | ||
731 | sdio_uart_port_put(port); | ||
732 | } | 819 | } |
733 | 820 | ||
734 | static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf, | 821 | static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf, |
735 | int count) | 822 | int count) |
736 | { | 823 | { |
737 | struct sdio_uart_port *port = tty->driver_data; | 824 | struct sdio_uart_port *port = tty->driver_data; |
@@ -756,7 +843,7 @@ static int sdio_uart_write(struct tty_struct * tty, const unsigned char *buf, | |||
756 | } | 843 | } |
757 | spin_unlock(&port->write_lock); | 844 | spin_unlock(&port->write_lock); |
758 | 845 | ||
759 | if ( !(port->ier & UART_IER_THRI)) { | 846 | if (!(port->ier & UART_IER_THRI)) { |
760 | int err = sdio_uart_claim_func(port); | 847 | int err = sdio_uart_claim_func(port); |
761 | if (!err) { | 848 | if (!err) { |
762 | sdio_uart_start_tx(port); | 849 | sdio_uart_start_tx(port); |
@@ -843,17 +930,12 @@ static void sdio_uart_unthrottle(struct tty_struct *tty) | |||
843 | sdio_uart_release_func(port); | 930 | sdio_uart_release_func(port); |
844 | } | 931 | } |
845 | 932 | ||
846 | static void sdio_uart_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | 933 | static void sdio_uart_set_termios(struct tty_struct *tty, |
934 | struct ktermios *old_termios) | ||
847 | { | 935 | { |
848 | struct sdio_uart_port *port = tty->driver_data; | 936 | struct sdio_uart_port *port = tty->driver_data; |
849 | unsigned int cflag = tty->termios->c_cflag; | 937 | unsigned int cflag = tty->termios->c_cflag; |
850 | 938 | ||
851 | #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
852 | |||
853 | if ((cflag ^ old_termios->c_cflag) == 0 && | ||
854 | RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) | ||
855 | return; | ||
856 | |||
857 | if (sdio_uart_claim_func(port) != 0) | 939 | if (sdio_uart_claim_func(port) != 0) |
858 | return; | 940 | return; |
859 | 941 | ||
@@ -928,7 +1010,7 @@ static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file, | |||
928 | int result; | 1010 | int result; |
929 | 1011 | ||
930 | result = sdio_uart_claim_func(port); | 1012 | result = sdio_uart_claim_func(port); |
931 | if(!result) { | 1013 | if (!result) { |
932 | sdio_uart_update_mctrl(port, set, clear); | 1014 | sdio_uart_update_mctrl(port, set, clear); |
933 | sdio_uart_release_func(port); | 1015 | sdio_uart_release_func(port); |
934 | } | 1016 | } |
@@ -946,7 +1028,7 @@ static int sdio_uart_proc_show(struct seq_file *m, void *v) | |||
946 | struct sdio_uart_port *port = sdio_uart_port_get(i); | 1028 | struct sdio_uart_port *port = sdio_uart_port_get(i); |
947 | if (port) { | 1029 | if (port) { |
948 | seq_printf(m, "%d: uart:SDIO", i); | 1030 | seq_printf(m, "%d: uart:SDIO", i); |
949 | if(capable(CAP_SYS_ADMIN)) { | 1031 | if (capable(CAP_SYS_ADMIN)) { |
950 | seq_printf(m, " tx:%d rx:%d", | 1032 | seq_printf(m, " tx:%d rx:%d", |
951 | port->icount.tx, port->icount.rx); | 1033 | port->icount.tx, port->icount.rx); |
952 | if (port->icount.frame) | 1034 | if (port->icount.frame) |
@@ -994,6 +1076,13 @@ static const struct file_operations sdio_uart_proc_fops = { | |||
994 | .release = single_release, | 1076 | .release = single_release, |
995 | }; | 1077 | }; |
996 | 1078 | ||
1079 | static const struct tty_port_operations sdio_uart_port_ops = { | ||
1080 | .dtr_rts = uart_dtr_rts, | ||
1081 | .carrier_raised = uart_carrier_raised, | ||
1082 | .shutdown = sdio_uart_shutdown, | ||
1083 | .activate = sdio_uart_activate, | ||
1084 | }; | ||
1085 | |||
997 | static const struct tty_operations sdio_uart_ops = { | 1086 | static const struct tty_operations sdio_uart_ops = { |
998 | .open = sdio_uart_open, | 1087 | .open = sdio_uart_open, |
999 | .close = sdio_uart_close, | 1088 | .close = sdio_uart_close, |
@@ -1004,9 +1093,12 @@ static const struct tty_operations sdio_uart_ops = { | |||
1004 | .throttle = sdio_uart_throttle, | 1093 | .throttle = sdio_uart_throttle, |
1005 | .unthrottle = sdio_uart_unthrottle, | 1094 | .unthrottle = sdio_uart_unthrottle, |
1006 | .set_termios = sdio_uart_set_termios, | 1095 | .set_termios = sdio_uart_set_termios, |
1096 | .hangup = sdio_uart_hangup, | ||
1007 | .break_ctl = sdio_uart_break_ctl, | 1097 | .break_ctl = sdio_uart_break_ctl, |
1008 | .tiocmget = sdio_uart_tiocmget, | 1098 | .tiocmget = sdio_uart_tiocmget, |
1009 | .tiocmset = sdio_uart_tiocmset, | 1099 | .tiocmset = sdio_uart_tiocmset, |
1100 | .install = sdio_uart_install, | ||
1101 | .cleanup = sdio_uart_cleanup, | ||
1010 | .proc_fops = &sdio_uart_proc_fops, | 1102 | .proc_fops = &sdio_uart_proc_fops, |
1011 | }; | 1103 | }; |
1012 | 1104 | ||
@@ -1043,7 +1135,7 @@ static int sdio_uart_probe(struct sdio_func *func, | |||
1043 | } | 1135 | } |
1044 | if (!tpl) { | 1136 | if (!tpl) { |
1045 | printk(KERN_WARNING | 1137 | printk(KERN_WARNING |
1046 | "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n", | 1138 | "%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n", |
1047 | sdio_func_id(func)); | 1139 | sdio_func_id(func)); |
1048 | kfree(port); | 1140 | kfree(port); |
1049 | return -EINVAL; | 1141 | return -EINVAL; |
@@ -1068,13 +1160,16 @@ static int sdio_uart_probe(struct sdio_func *func, | |||
1068 | 1160 | ||
1069 | port->func = func; | 1161 | port->func = func; |
1070 | sdio_set_drvdata(func, port); | 1162 | sdio_set_drvdata(func, port); |
1163 | tty_port_init(&port->port); | ||
1164 | port->port.ops = &sdio_uart_port_ops; | ||
1071 | 1165 | ||
1072 | ret = sdio_uart_add_port(port); | 1166 | ret = sdio_uart_add_port(port); |
1073 | if (ret) { | 1167 | if (ret) { |
1074 | kfree(port); | 1168 | kfree(port); |
1075 | } else { | 1169 | } else { |
1076 | struct device *dev; | 1170 | struct device *dev; |
1077 | dev = tty_register_device(sdio_uart_tty_driver, port->index, &func->dev); | 1171 | dev = tty_register_device(sdio_uart_tty_driver, |
1172 | port->index, &func->dev); | ||
1078 | if (IS_ERR(dev)) { | 1173 | if (IS_ERR(dev)) { |
1079 | sdio_uart_port_remove(port); | 1174 | sdio_uart_port_remove(port); |
1080 | ret = PTR_ERR(dev); | 1175 | ret = PTR_ERR(dev); |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 737b4c960971..c3e37c8e7e26 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -1339,14 +1339,12 @@ static void serial8250_start_tx(struct uart_port *port) | |||
1339 | serial_out(up, UART_IER, up->ier); | 1339 | serial_out(up, UART_IER, up->ier); |
1340 | 1340 | ||
1341 | if (up->bugs & UART_BUG_TXEN) { | 1341 | if (up->bugs & UART_BUG_TXEN) { |
1342 | unsigned char lsr, iir; | 1342 | unsigned char lsr; |
1343 | lsr = serial_in(up, UART_LSR); | 1343 | lsr = serial_in(up, UART_LSR); |
1344 | up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; | 1344 | up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS; |
1345 | iir = serial_in(up, UART_IIR) & 0x0f; | ||
1346 | if ((up->port.type == PORT_RM9000) ? | 1345 | if ((up->port.type == PORT_RM9000) ? |
1347 | (lsr & UART_LSR_THRE && | 1346 | (lsr & UART_LSR_THRE) : |
1348 | (iir == UART_IIR_NO_INT || iir == UART_IIR_THRI)) : | 1347 | (lsr & UART_LSR_TEMT)) |
1349 | (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)) | ||
1350 | transmit_chars(up); | 1348 | transmit_chars(up); |
1351 | } | 1349 | } |
1352 | } | 1350 | } |
@@ -2646,7 +2644,7 @@ static void __init serial8250_isa_init_ports(void) | |||
2646 | { | 2644 | { |
2647 | struct uart_8250_port *up; | 2645 | struct uart_8250_port *up; |
2648 | static int first = 1; | 2646 | static int first = 1; |
2649 | int i; | 2647 | int i, irqflag = 0; |
2650 | 2648 | ||
2651 | if (!first) | 2649 | if (!first) |
2652 | return; | 2650 | return; |
@@ -2670,6 +2668,9 @@ static void __init serial8250_isa_init_ports(void) | |||
2670 | up->port.ops = &serial8250_pops; | 2668 | up->port.ops = &serial8250_pops; |
2671 | } | 2669 | } |
2672 | 2670 | ||
2671 | if (share_irqs) | ||
2672 | irqflag = IRQF_SHARED; | ||
2673 | |||
2673 | for (i = 0, up = serial8250_ports; | 2674 | for (i = 0, up = serial8250_ports; |
2674 | i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; | 2675 | i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; |
2675 | i++, up++) { | 2676 | i++, up++) { |
@@ -2683,8 +2684,7 @@ static void __init serial8250_isa_init_ports(void) | |||
2683 | up->port.iotype = old_serial_port[i].io_type; | 2684 | up->port.iotype = old_serial_port[i].io_type; |
2684 | up->port.regshift = old_serial_port[i].iomem_reg_shift; | 2685 | up->port.regshift = old_serial_port[i].iomem_reg_shift; |
2685 | set_io_from_upio(&up->port); | 2686 | set_io_from_upio(&up->port); |
2686 | if (share_irqs) | 2687 | up->port.irqflags |= irqflag; |
2687 | up->port.irqflags |= IRQF_SHARED; | ||
2688 | } | 2688 | } |
2689 | } | 2689 | } |
2690 | 2690 | ||
@@ -2940,10 +2940,13 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
2940 | { | 2940 | { |
2941 | struct plat_serial8250_port *p = dev->dev.platform_data; | 2941 | struct plat_serial8250_port *p = dev->dev.platform_data; |
2942 | struct uart_port port; | 2942 | struct uart_port port; |
2943 | int ret, i; | 2943 | int ret, i, irqflag = 0; |
2944 | 2944 | ||
2945 | memset(&port, 0, sizeof(struct uart_port)); | 2945 | memset(&port, 0, sizeof(struct uart_port)); |
2946 | 2946 | ||
2947 | if (share_irqs) | ||
2948 | irqflag = IRQF_SHARED; | ||
2949 | |||
2947 | for (i = 0; p && p->flags != 0; p++, i++) { | 2950 | for (i = 0; p && p->flags != 0; p++, i++) { |
2948 | port.iobase = p->iobase; | 2951 | port.iobase = p->iobase; |
2949 | port.membase = p->membase; | 2952 | port.membase = p->membase; |
@@ -2960,8 +2963,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) | |||
2960 | port.serial_in = p->serial_in; | 2963 | port.serial_in = p->serial_in; |
2961 | port.serial_out = p->serial_out; | 2964 | port.serial_out = p->serial_out; |
2962 | port.dev = &dev->dev; | 2965 | port.dev = &dev->dev; |
2963 | if (share_irqs) | 2966 | port.irqflags |= irqflag; |
2964 | port.irqflags |= IRQF_SHARED; | ||
2965 | ret = serial8250_register_port(&port); | 2967 | ret = serial8250_register_port(&port); |
2966 | if (ret < 0) { | 2968 | if (ret < 0) { |
2967 | dev_err(&dev->dev, "unable to register port at index %d " | 2969 | dev_err(&dev->dev, "unable to register port at index %d " |
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index 4e5f3bde0461..38a509c684cd 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h | |||
@@ -138,7 +138,6 @@ struct jsm_board | |||
138 | u32 nasync; /* Number of ports on card */ | 138 | u32 nasync; /* Number of ports on card */ |
139 | 139 | ||
140 | u32 irq; /* Interrupt request number */ | 140 | u32 irq; /* Interrupt request number */ |
141 | u64 intr_count; /* Count of interrupts */ | ||
142 | 141 | ||
143 | u64 membase; /* Start of base memory of the card */ | 142 | u64 membase; /* Start of base memory of the card */ |
144 | u64 membase_end; /* End of base memory of the card */ | 143 | u64 membase_end; /* End of base memory of the card */ |
@@ -206,8 +205,6 @@ struct jsm_channel { | |||
206 | 205 | ||
207 | u64 ch_close_delay; /* How long we should drop RTS/DTR for */ | 206 | u64 ch_close_delay; /* How long we should drop RTS/DTR for */ |
208 | 207 | ||
209 | u64 ch_cpstime; /* Time for CPS calculations */ | ||
210 | |||
211 | tcflag_t ch_c_iflag; /* channel iflags */ | 208 | tcflag_t ch_c_iflag; /* channel iflags */ |
212 | tcflag_t ch_c_cflag; /* channel cflags */ | 209 | tcflag_t ch_c_cflag; /* channel cflags */ |
213 | tcflag_t ch_c_oflag; /* channel oflags */ | 210 | tcflag_t ch_c_oflag; /* channel oflags */ |
@@ -215,11 +212,6 @@ struct jsm_channel { | |||
215 | u8 ch_stopc; /* Stop character */ | 212 | u8 ch_stopc; /* Stop character */ |
216 | u8 ch_startc; /* Start character */ | 213 | u8 ch_startc; /* Start character */ |
217 | 214 | ||
218 | u32 ch_old_baud; /* Cache of the current baud */ | ||
219 | u32 ch_custom_speed;/* Custom baud, if set */ | ||
220 | |||
221 | u32 ch_wopen; /* Waiting for open process cnt */ | ||
222 | |||
223 | u8 ch_mostat; /* FEP output modem status */ | 215 | u8 ch_mostat; /* FEP output modem status */ |
224 | u8 ch_mistat; /* FEP input modem status */ | 216 | u8 ch_mistat; /* FEP input modem status */ |
225 | 217 | ||
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c index b3604aa322a4..108c3e0471fd 100644 --- a/drivers/serial/jsm/jsm_driver.c +++ b/drivers/serial/jsm/jsm_driver.c | |||
@@ -48,6 +48,17 @@ struct uart_driver jsm_uart_driver = { | |||
48 | .nr = NR_PORTS, | 48 | .nr = NR_PORTS, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, | ||
52 | pci_channel_state_t state); | ||
53 | static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev); | ||
54 | static void jsm_io_resume(struct pci_dev *pdev); | ||
55 | |||
56 | static struct pci_error_handlers jsm_err_handler = { | ||
57 | .error_detected = jsm_io_error_detected, | ||
58 | .slot_reset = jsm_io_slot_reset, | ||
59 | .resume = jsm_io_resume, | ||
60 | }; | ||
61 | |||
51 | int jsm_debug; | 62 | int jsm_debug; |
52 | module_param(jsm_debug, int, 0); | 63 | module_param(jsm_debug, int, 0); |
53 | MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); | 64 | MODULE_PARM_DESC(jsm_debug, "Driver debugging level"); |
@@ -123,7 +134,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device | |||
123 | } | 134 | } |
124 | 135 | ||
125 | rc = request_irq(brd->irq, brd->bd_ops->intr, | 136 | rc = request_irq(brd->irq, brd->bd_ops->intr, |
126 | IRQF_DISABLED|IRQF_SHARED, "JSM", brd); | 137 | IRQF_SHARED, "JSM", brd); |
127 | if (rc) { | 138 | if (rc) { |
128 | printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); | 139 | printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); |
129 | goto out_iounmap; | 140 | goto out_iounmap; |
@@ -164,6 +175,7 @@ static int __devinit jsm_probe_one(struct pci_dev *pdev, const struct pci_device | |||
164 | } | 175 | } |
165 | 176 | ||
166 | pci_set_drvdata(pdev, brd); | 177 | pci_set_drvdata(pdev, brd); |
178 | pci_save_state(pdev); | ||
167 | 179 | ||
168 | return 0; | 180 | return 0; |
169 | out_free_irq: | 181 | out_free_irq: |
@@ -222,8 +234,42 @@ static struct pci_driver jsm_driver = { | |||
222 | .id_table = jsm_pci_tbl, | 234 | .id_table = jsm_pci_tbl, |
223 | .probe = jsm_probe_one, | 235 | .probe = jsm_probe_one, |
224 | .remove = __devexit_p(jsm_remove_one), | 236 | .remove = __devexit_p(jsm_remove_one), |
237 | .err_handler = &jsm_err_handler, | ||
225 | }; | 238 | }; |
226 | 239 | ||
240 | static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, | ||
241 | pci_channel_state_t state) | ||
242 | { | ||
243 | struct jsm_board *brd = pci_get_drvdata(pdev); | ||
244 | |||
245 | jsm_remove_uart_port(brd); | ||
246 | |||
247 | return PCI_ERS_RESULT_NEED_RESET; | ||
248 | } | ||
249 | |||
250 | static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev) | ||
251 | { | ||
252 | int rc; | ||
253 | |||
254 | rc = pci_enable_device(pdev); | ||
255 | |||
256 | if (rc) | ||
257 | return PCI_ERS_RESULT_DISCONNECT; | ||
258 | |||
259 | pci_set_master(pdev); | ||
260 | |||
261 | return PCI_ERS_RESULT_RECOVERED; | ||
262 | } | ||
263 | |||
264 | static void jsm_io_resume(struct pci_dev *pdev) | ||
265 | { | ||
266 | struct jsm_board *brd = pci_get_drvdata(pdev); | ||
267 | |||
268 | pci_restore_state(pdev); | ||
269 | |||
270 | jsm_uart_port_init(brd); | ||
271 | } | ||
272 | |||
227 | static int __init jsm_init_module(void) | 273 | static int __init jsm_init_module(void) |
228 | { | 274 | { |
229 | int rc; | 275 | int rc; |
diff --git a/drivers/serial/jsm/jsm_neo.c b/drivers/serial/jsm/jsm_neo.c index b4b124e4828f..7960d9633c15 100644 --- a/drivers/serial/jsm/jsm_neo.c +++ b/drivers/serial/jsm/jsm_neo.c | |||
@@ -954,13 +954,8 @@ static void neo_param(struct jsm_channel *ch) | |||
954 | ch->ch_flags |= (CH_BAUD0); | 954 | ch->ch_flags |= (CH_BAUD0); |
955 | ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); | 955 | ch->ch_mostat &= ~(UART_MCR_RTS | UART_MCR_DTR); |
956 | neo_assert_modem_signals(ch); | 956 | neo_assert_modem_signals(ch); |
957 | ch->ch_old_baud = 0; | ||
958 | return; | 957 | return; |
959 | 958 | ||
960 | } else if (ch->ch_custom_speed) { | ||
961 | baud = ch->ch_custom_speed; | ||
962 | if (ch->ch_flags & CH_BAUD0) | ||
963 | ch->ch_flags &= ~(CH_BAUD0); | ||
964 | } else { | 959 | } else { |
965 | int i; | 960 | int i; |
966 | unsigned int cflag; | 961 | unsigned int cflag; |
@@ -1045,7 +1040,6 @@ static void neo_param(struct jsm_channel *ch) | |||
1045 | quot = ch->ch_bd->bd_dividend / baud; | 1040 | quot = ch->ch_bd->bd_dividend / baud; |
1046 | 1041 | ||
1047 | if (quot != 0) { | 1042 | if (quot != 0) { |
1048 | ch->ch_old_baud = baud; | ||
1049 | writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr); | 1043 | writeb(UART_LCR_DLAB, &ch->ch_neo_uart->lcr); |
1050 | writeb((quot & 0xff), &ch->ch_neo_uart->txrx); | 1044 | writeb((quot & 0xff), &ch->ch_neo_uart->txrx); |
1051 | writeb((quot >> 8), &ch->ch_neo_uart->ier); | 1045 | writeb((quot >> 8), &ch->ch_neo_uart->ier); |
@@ -1123,8 +1117,6 @@ static irqreturn_t neo_intr(int irq, void *voidbrd) | |||
1123 | unsigned long lock_flags2; | 1117 | unsigned long lock_flags2; |
1124 | int outofloop_count = 0; | 1118 | int outofloop_count = 0; |
1125 | 1119 | ||
1126 | brd->intr_count++; | ||
1127 | |||
1128 | /* Lock out the slow poller from running on this board. */ | 1120 | /* Lock out the slow poller from running on this board. */ |
1129 | spin_lock_irqsave(&brd->bd_intr_lock, lock_flags); | 1121 | spin_lock_irqsave(&brd->bd_intr_lock, lock_flags); |
1130 | 1122 | ||
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 7439c0373620..cd95e215550d 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
@@ -296,8 +296,6 @@ static void jsm_tty_close(struct uart_port *port) | |||
296 | bd->bd_ops->assert_modem_signals(channel); | 296 | bd->bd_ops->assert_modem_signals(channel); |
297 | } | 297 | } |
298 | 298 | ||
299 | channel->ch_old_baud = 0; | ||
300 | |||
301 | /* Turn off UART interrupts for this port */ | 299 | /* Turn off UART interrupts for this port */ |
302 | channel->ch_bd->bd_ops->uart_off(channel); | 300 | channel->ch_bd->bd_ops->uart_off(channel); |
303 | 301 | ||
@@ -432,7 +430,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd) | |||
432 | return 0; | 430 | return 0; |
433 | } | 431 | } |
434 | 432 | ||
435 | int __devinit jsm_uart_port_init(struct jsm_board *brd) | 433 | int jsm_uart_port_init(struct jsm_board *brd) |
436 | { | 434 | { |
437 | int i; | 435 | int i; |
438 | unsigned int line; | 436 | unsigned int line; |
@@ -472,7 +470,7 @@ int __devinit jsm_uart_port_init(struct jsm_board *brd) | |||
472 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) | 470 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) |
473 | printk(KERN_INFO "jsm: add device failed\n"); | 471 | printk(KERN_INFO "jsm: add device failed\n"); |
474 | else | 472 | else |
475 | printk(KERN_INFO "Added device \n"); | 473 | printk(KERN_INFO "jsm: Port %d added\n", i); |
476 | } | 474 | } |
477 | 475 | ||
478 | jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n"); | 476 | jsm_printk(INIT, INFO, &brd->pci_dev, "finish\n"); |
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index b8629d74f6a2..4a821046baae 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c | |||
@@ -438,6 +438,7 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, | |||
438 | unsigned char cval, fcr = 0; | 438 | unsigned char cval, fcr = 0; |
439 | unsigned long flags; | 439 | unsigned long flags; |
440 | unsigned int baud, quot; | 440 | unsigned int baud, quot; |
441 | unsigned int dll; | ||
441 | 442 | ||
442 | switch (termios->c_cflag & CSIZE) { | 443 | switch (termios->c_cflag & CSIZE) { |
443 | case CS5: | 444 | case CS5: |
@@ -534,10 +535,18 @@ serial_pxa_set_termios(struct uart_port *port, struct ktermios *termios, | |||
534 | else | 535 | else |
535 | up->mcr &= ~UART_MCR_AFE; | 536 | up->mcr &= ~UART_MCR_AFE; |
536 | 537 | ||
537 | serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ | 538 | serial_out(up, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ |
538 | serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ | 539 | serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ |
540 | |||
541 | /* | ||
542 | * work around Errata #75 according to Intel(R) PXA27x Processor Family | ||
543 | * Specification Update (Nov 2005) | ||
544 | */ | ||
545 | dll = serial_in(up, UART_DLL); | ||
546 | WARN_ON(dll != (quot & 0xff)); | ||
547 | |||
539 | serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ | 548 | serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ |
540 | serial_out(up, UART_LCR, cval); /* reset DLAB */ | 549 | serial_out(up, UART_LCR, cval); /* reset DLAB */ |
541 | up->lcr = cval; /* Save LCR */ | 550 | up->lcr = cval; /* Save LCR */ |
542 | serial_pxa_set_mctrl(&up->port, up->port.mctrl); | 551 | serial_pxa_set_mctrl(&up->port, up->port.mctrl); |
543 | serial_out(up, UART_FCR, fcr); | 552 | serial_out(up, UART_FCR, fcr); |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index dcc72444e8e7..047530b285bb 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -342,11 +342,11 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios, | |||
342 | 342 | ||
343 | if (flags == UPF_SPD_HI) | 343 | if (flags == UPF_SPD_HI) |
344 | altbaud = 57600; | 344 | altbaud = 57600; |
345 | if (flags == UPF_SPD_VHI) | 345 | else if (flags == UPF_SPD_VHI) |
346 | altbaud = 115200; | 346 | altbaud = 115200; |
347 | if (flags == UPF_SPD_SHI) | 347 | else if (flags == UPF_SPD_SHI) |
348 | altbaud = 230400; | 348 | altbaud = 230400; |
349 | if (flags == UPF_SPD_WARP) | 349 | else if (flags == UPF_SPD_WARP) |
350 | altbaud = 460800; | 350 | altbaud = 460800; |
351 | 351 | ||
352 | for (try = 0; try < 2; try++) { | 352 | for (try = 0; try < 2; try++) { |
@@ -1217,9 +1217,8 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1217 | /* Handle transition to B0 status */ | 1217 | /* Handle transition to B0 status */ |
1218 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) | 1218 | if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) |
1219 | uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR); | 1219 | uart_clear_mctrl(state->uart_port, TIOCM_RTS | TIOCM_DTR); |
1220 | |||
1221 | /* Handle transition away from B0 status */ | 1220 | /* Handle transition away from B0 status */ |
1222 | if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { | 1221 | else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { |
1223 | unsigned int mask = TIOCM_DTR; | 1222 | unsigned int mask = TIOCM_DTR; |
1224 | if (!(cflag & CRTSCTS) || | 1223 | if (!(cflag & CRTSCTS) || |
1225 | !test_bit(TTY_THROTTLED, &tty->flags)) | 1224 | !test_bit(TTY_THROTTLED, &tty->flags)) |
@@ -1234,9 +1233,8 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1234 | __uart_start(tty); | 1233 | __uart_start(tty); |
1235 | spin_unlock_irqrestore(&state->uart_port->lock, flags); | 1234 | spin_unlock_irqrestore(&state->uart_port->lock, flags); |
1236 | } | 1235 | } |
1237 | |||
1238 | /* Handle turning on CRTSCTS */ | 1236 | /* Handle turning on CRTSCTS */ |
1239 | if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { | 1237 | else if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) { |
1240 | spin_lock_irqsave(&state->uart_port->lock, flags); | 1238 | spin_lock_irqsave(&state->uart_port->lock, flags); |
1241 | if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) { | 1239 | if (!(state->uart_port->ops->get_mctrl(state->uart_port) & TIOCM_CTS)) { |
1242 | tty->hw_stopped = 1; | 1240 | tty->hw_stopped = 1; |
@@ -2344,7 +2342,7 @@ static const struct tty_operations uart_ops = { | |||
2344 | */ | 2342 | */ |
2345 | int uart_register_driver(struct uart_driver *drv) | 2343 | int uart_register_driver(struct uart_driver *drv) |
2346 | { | 2344 | { |
2347 | struct tty_driver *normal = NULL; | 2345 | struct tty_driver *normal; |
2348 | int i, retval; | 2346 | int i, retval; |
2349 | 2347 | ||
2350 | BUG_ON(drv->state); | 2348 | BUG_ON(drv->state); |
@@ -2354,13 +2352,12 @@ int uart_register_driver(struct uart_driver *drv) | |||
2354 | * we have a large number of ports to handle. | 2352 | * we have a large number of ports to handle. |
2355 | */ | 2353 | */ |
2356 | drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); | 2354 | drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); |
2357 | retval = -ENOMEM; | ||
2358 | if (!drv->state) | 2355 | if (!drv->state) |
2359 | goto out; | 2356 | goto out; |
2360 | 2357 | ||
2361 | normal = alloc_tty_driver(drv->nr); | 2358 | normal = alloc_tty_driver(drv->nr); |
2362 | if (!normal) | 2359 | if (!normal) |
2363 | goto out; | 2360 | goto out_kfree; |
2364 | 2361 | ||
2365 | drv->tty_driver = normal; | 2362 | drv->tty_driver = normal; |
2366 | 2363 | ||
@@ -2393,12 +2390,14 @@ int uart_register_driver(struct uart_driver *drv) | |||
2393 | } | 2390 | } |
2394 | 2391 | ||
2395 | retval = tty_register_driver(normal); | 2392 | retval = tty_register_driver(normal); |
2396 | out: | 2393 | if (retval >= 0) |
2397 | if (retval < 0) { | 2394 | return retval; |
2398 | put_tty_driver(normal); | 2395 | |
2399 | kfree(drv->state); | 2396 | put_tty_driver(normal); |
2400 | } | 2397 | out_kfree: |
2401 | return retval; | 2398 | kfree(drv->state); |
2399 | out: | ||
2400 | return -ENOMEM; | ||
2402 | } | 2401 | } |
2403 | 2402 | ||
2404 | /** | 2403 | /** |
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 80f59b6350cb..4cdb975caa89 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c | |||
@@ -501,12 +501,13 @@ static int opticon_resume(struct usb_interface *intf) | |||
501 | struct usb_serial_port *port = serial->port[0]; | 501 | struct usb_serial_port *port = serial->port[0]; |
502 | int result; | 502 | int result; |
503 | 503 | ||
504 | mutex_lock(&port->mutex); | 504 | mutex_lock(&port->port.mutex); |
505 | if (port->port.count) | 505 | /* This is protected by the port mutex against close/open */ |
506 | if (test_bit(ASYNCB_INITIALIZED, &port->port.flags)) | ||
506 | result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); | 507 | result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); |
507 | else | 508 | else |
508 | result = 0; | 509 | result = 0; |
509 | mutex_unlock(&port->mutex); | 510 | mutex_unlock(&port->port.mutex); |
510 | return result; | 511 | return result; |
511 | } | 512 | } |
512 | 513 | ||
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index bd3fa7ff15b1..4543f359be75 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -247,96 +247,66 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | |||
247 | return retval; | 247 | return retval; |
248 | } | 248 | } |
249 | 249 | ||
250 | static int serial_open(struct tty_struct *tty, struct file *filp) | 250 | static int serial_activate(struct tty_port *tport, struct tty_struct *tty) |
251 | { | 251 | { |
252 | struct usb_serial_port *port = tty->driver_data; | 252 | struct usb_serial_port *port = |
253 | container_of(tport, struct usb_serial_port, port); | ||
253 | struct usb_serial *serial = port->serial; | 254 | struct usb_serial *serial = port->serial; |
254 | int retval; | 255 | int retval; |
255 | 256 | ||
256 | dbg("%s - port %d", __func__, port->number); | 257 | mutex_lock(&serial->disc_mutex); |
257 | 258 | if (serial->disconnected) | |
258 | spin_lock_irq(&port->port.lock); | 259 | retval = -ENODEV; |
259 | if (!tty_hung_up_p(filp)) | 260 | else |
260 | ++port->port.count; | 261 | retval = port->serial->type->open(tty, port); |
261 | spin_unlock_irq(&port->port.lock); | 262 | mutex_unlock(&serial->disc_mutex); |
262 | tty_port_tty_set(&port->port, tty); | 263 | return retval; |
264 | } | ||
263 | 265 | ||
264 | /* Do the device-specific open only if the hardware isn't | 266 | static int serial_open(struct tty_struct *tty, struct file *filp) |
265 | * already initialized. | 267 | { |
266 | */ | 268 | struct usb_serial_port *port = tty->driver_data; |
267 | if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) { | ||
268 | if (mutex_lock_interruptible(&port->mutex)) | ||
269 | return -ERESTARTSYS; | ||
270 | mutex_lock(&serial->disc_mutex); | ||
271 | if (serial->disconnected) | ||
272 | retval = -ENODEV; | ||
273 | else | ||
274 | retval = port->serial->type->open(tty, port); | ||
275 | mutex_unlock(&serial->disc_mutex); | ||
276 | mutex_unlock(&port->mutex); | ||
277 | if (retval) | ||
278 | return retval; | ||
279 | set_bit(ASYNCB_INITIALIZED, &port->port.flags); | ||
280 | } | ||
281 | 269 | ||
282 | /* Now do the correct tty layer semantics */ | 270 | dbg("%s - port %d", __func__, port->number); |
283 | retval = tty_port_block_til_ready(&port->port, tty, filp); | 271 | return tty_port_open(&port->port, tty, filp); |
284 | return retval; | ||
285 | } | 272 | } |
286 | 273 | ||
287 | /** | 274 | /** |
288 | * serial_down - shut down hardware | 275 | * serial_down - shut down hardware |
289 | * @port: port to shut down | 276 | * @tport: tty port to shut down |
290 | * | 277 | * |
291 | * Shut down a USB serial port unless it is the console. We never | 278 | * Shut down a USB serial port unless it is the console. We never |
292 | * shut down the console hardware as it will always be in use. | 279 | * shut down the console hardware as it will always be in use. Serialized |
280 | * against activate by the tport mutex and kept to matching open/close pairs | ||
281 | * of calls by the ASYNCB_INITIALIZED flag. | ||
293 | */ | 282 | */ |
294 | static void serial_down(struct usb_serial_port *port) | 283 | static void serial_down(struct tty_port *tport) |
295 | { | 284 | { |
285 | struct usb_serial_port *port = | ||
286 | container_of(tport, struct usb_serial_port, port); | ||
296 | struct usb_serial_driver *drv = port->serial->type; | 287 | struct usb_serial_driver *drv = port->serial->type; |
297 | |||
298 | /* | 288 | /* |
299 | * The console is magical. Do not hang up the console hardware | 289 | * The console is magical. Do not hang up the console hardware |
300 | * or there will be tears. | 290 | * or there will be tears. |
301 | */ | 291 | */ |
302 | if (port->console) | 292 | if (port->console) |
303 | return; | 293 | return; |
304 | |||
305 | /* Don't call the close method if the hardware hasn't been | ||
306 | * initialized. | ||
307 | */ | ||
308 | if (!test_and_clear_bit(ASYNCB_INITIALIZED, &port->port.flags)) | ||
309 | return; | ||
310 | |||
311 | mutex_lock(&port->mutex); | ||
312 | if (drv->close) | 294 | if (drv->close) |
313 | drv->close(port); | 295 | drv->close(port); |
314 | mutex_unlock(&port->mutex); | ||
315 | } | 296 | } |
316 | 297 | ||
317 | static void serial_hangup(struct tty_struct *tty) | 298 | static void serial_hangup(struct tty_struct *tty) |
318 | { | 299 | { |
319 | struct usb_serial_port *port = tty->driver_data; | 300 | struct usb_serial_port *port = tty->driver_data; |
320 | |||
321 | dbg("%s - port %d", __func__, port->number); | 301 | dbg("%s - port %d", __func__, port->number); |
322 | |||
323 | serial_down(port); | ||
324 | tty_port_hangup(&port->port); | 302 | tty_port_hangup(&port->port); |
325 | } | 303 | } |
326 | 304 | ||
327 | static void serial_close(struct tty_struct *tty, struct file *filp) | 305 | static void serial_close(struct tty_struct *tty, struct file *filp) |
328 | { | 306 | { |
329 | struct usb_serial_port *port = tty->driver_data; | 307 | struct usb_serial_port *port = tty->driver_data; |
330 | |||
331 | dbg("%s - port %d", __func__, port->number); | 308 | dbg("%s - port %d", __func__, port->number); |
332 | 309 | tty_port_close(&port->port, tty, filp); | |
333 | if (tty_hung_up_p(filp)) | ||
334 | return; | ||
335 | if (tty_port_close_start(&port->port, tty, filp) == 0) | ||
336 | return; | ||
337 | serial_down(port); | ||
338 | tty_port_close_end(&port->port, tty); | ||
339 | tty_port_tty_set(&port->port, NULL); | ||
340 | } | 310 | } |
341 | 311 | ||
342 | /** | 312 | /** |
@@ -725,6 +695,8 @@ static void serial_dtr_rts(struct tty_port *port, int on) | |||
725 | static const struct tty_port_operations serial_port_ops = { | 695 | static const struct tty_port_operations serial_port_ops = { |
726 | .carrier_raised = serial_carrier_raised, | 696 | .carrier_raised = serial_carrier_raised, |
727 | .dtr_rts = serial_dtr_rts, | 697 | .dtr_rts = serial_dtr_rts, |
698 | .activate = serial_activate, | ||
699 | .shutdown = serial_down, | ||
728 | }; | 700 | }; |
729 | 701 | ||
730 | int usb_serial_probe(struct usb_interface *interface, | 702 | int usb_serial_probe(struct usb_interface *interface, |
@@ -923,7 +895,8 @@ int usb_serial_probe(struct usb_interface *interface, | |||
923 | port->port.ops = &serial_port_ops; | 895 | port->port.ops = &serial_port_ops; |
924 | port->serial = serial; | 896 | port->serial = serial; |
925 | spin_lock_init(&port->lock); | 897 | spin_lock_init(&port->lock); |
926 | mutex_init(&port->mutex); | 898 | /* Keep this for private driver use for the moment but |
899 | should probably go away */ | ||
927 | INIT_WORK(&port->work, usb_serial_port_work); | 900 | INIT_WORK(&port->work, usb_serial_port_work); |
928 | serial->port[i] = port; | 901 | serial->port[i] = port; |
929 | port->dev.parent = &interface->dev; | 902 | port->dev.parent = &interface->dev; |
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index d5f8c96964be..8882ecc0f1bf 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c | |||
@@ -517,11 +517,23 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) | |||
517 | 517 | ||
518 | struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number) | 518 | struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number) |
519 | { | 519 | { |
520 | struct dentry *dentry; | ||
521 | struct tty_struct *tty; | ||
522 | |||
520 | BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); | 523 | BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); |
521 | 524 | ||
525 | /* Ensure dentry has not been deleted by devpts_pty_kill() */ | ||
526 | dentry = d_find_alias(pts_inode); | ||
527 | if (!dentry) | ||
528 | return NULL; | ||
529 | |||
530 | tty = NULL; | ||
522 | if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) | 531 | if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) |
523 | return (struct tty_struct *)pts_inode->i_private; | 532 | tty = (struct tty_struct *)pts_inode->i_private; |
524 | return NULL; | 533 | |
534 | dput(dentry); | ||
535 | |||
536 | return tty; | ||
525 | } | 537 | } |
526 | 538 | ||
527 | void devpts_pty_kill(struct tty_struct *tty) | 539 | void devpts_pty_kill(struct tty_struct *tty) |
diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 5a5385749e16..f72914db2a11 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild | |||
@@ -214,7 +214,6 @@ unifdef-y += futex.h | |||
214 | unifdef-y += fs.h | 214 | unifdef-y += fs.h |
215 | unifdef-y += gameport.h | 215 | unifdef-y += gameport.h |
216 | unifdef-y += generic_serial.h | 216 | unifdef-y += generic_serial.h |
217 | unifdef-y += hayesesp.h | ||
218 | unifdef-y += hdlcdrv.h | 217 | unifdef-y += hdlcdrv.h |
219 | unifdef-y += hdlc.h | 218 | unifdef-y += hdlc.h |
220 | unifdef-y += hdreg.h | 219 | unifdef-y += hdreg.h |
diff --git a/include/linux/hayesesp.h b/include/linux/hayesesp.h deleted file mode 100644 index 92b08cfe4a75..000000000000 --- a/include/linux/hayesesp.h +++ /dev/null | |||
@@ -1,114 +0,0 @@ | |||
1 | #ifndef HAYESESP_H | ||
2 | #define HAYESESP_H | ||
3 | |||
4 | struct hayes_esp_config { | ||
5 | short flow_on; | ||
6 | short flow_off; | ||
7 | short rx_trigger; | ||
8 | short tx_trigger; | ||
9 | short pio_threshold; | ||
10 | unsigned char rx_timeout; | ||
11 | char dma_channel; | ||
12 | }; | ||
13 | |||
14 | #ifdef __KERNEL__ | ||
15 | |||
16 | #define ESP_DMA_CHANNEL 0 | ||
17 | #define ESP_RX_TRIGGER 768 | ||
18 | #define ESP_TX_TRIGGER 768 | ||
19 | #define ESP_FLOW_OFF 1016 | ||
20 | #define ESP_FLOW_ON 944 | ||
21 | #define ESP_RX_TMOUT 128 | ||
22 | #define ESP_PIO_THRESHOLD 32 | ||
23 | |||
24 | #define ESP_IN_MAJOR 57 /* major dev # for dial in */ | ||
25 | #define ESP_OUT_MAJOR 58 /* major dev # for dial out */ | ||
26 | #define ESPC_SCALE 3 | ||
27 | #define UART_ESI_BASE 0x00 | ||
28 | #define UART_ESI_SID 0x01 | ||
29 | #define UART_ESI_RX 0x02 | ||
30 | #define UART_ESI_TX 0x02 | ||
31 | #define UART_ESI_CMD1 0x04 | ||
32 | #define UART_ESI_CMD2 0x05 | ||
33 | #define UART_ESI_STAT1 0x04 | ||
34 | #define UART_ESI_STAT2 0x05 | ||
35 | #define UART_ESI_RWS 0x07 | ||
36 | |||
37 | #define UART_IER_DMA_TMOUT 0x80 | ||
38 | #define UART_IER_DMA_TC 0x08 | ||
39 | |||
40 | #define ESI_SET_IRQ 0x04 | ||
41 | #define ESI_SET_DMA_TMOUT 0x05 | ||
42 | #define ESI_SET_SRV_MASK 0x06 | ||
43 | #define ESI_SET_ERR_MASK 0x07 | ||
44 | #define ESI_SET_FLOW_CNTL 0x08 | ||
45 | #define ESI_SET_FLOW_CHARS 0x09 | ||
46 | #define ESI_SET_FLOW_LVL 0x0a | ||
47 | #define ESI_SET_TRIGGER 0x0b | ||
48 | #define ESI_SET_RX_TIMEOUT 0x0c | ||
49 | #define ESI_SET_FLOW_TMOUT 0x0d | ||
50 | #define ESI_WRITE_UART 0x0e | ||
51 | #define ESI_READ_UART 0x0f | ||
52 | #define ESI_SET_MODE 0x10 | ||
53 | #define ESI_GET_ERR_STAT 0x12 | ||
54 | #define ESI_GET_UART_STAT 0x13 | ||
55 | #define ESI_GET_RX_AVAIL 0x14 | ||
56 | #define ESI_GET_TX_AVAIL 0x15 | ||
57 | #define ESI_START_DMA_RX 0x16 | ||
58 | #define ESI_START_DMA_TX 0x17 | ||
59 | #define ESI_ISSUE_BREAK 0x1a | ||
60 | #define ESI_FLUSH_RX 0x1b | ||
61 | #define ESI_FLUSH_TX 0x1c | ||
62 | #define ESI_SET_BAUD 0x1d | ||
63 | #define ESI_SET_ENH_IRQ 0x1f | ||
64 | #define ESI_SET_REINTR 0x20 | ||
65 | #define ESI_SET_PRESCALAR 0x23 | ||
66 | #define ESI_NO_COMMAND 0xff | ||
67 | |||
68 | #define ESP_STAT_RX_TIMEOUT 0x01 | ||
69 | #define ESP_STAT_DMA_RX 0x02 | ||
70 | #define ESP_STAT_DMA_TX 0x04 | ||
71 | #define ESP_STAT_NEVER_DMA 0x08 | ||
72 | #define ESP_STAT_USE_PIO 0x10 | ||
73 | |||
74 | #define ESP_MAGIC 0x53ee | ||
75 | #define ESP_XMIT_SIZE 4096 | ||
76 | |||
77 | struct esp_struct { | ||
78 | int magic; | ||
79 | struct tty_port port; | ||
80 | spinlock_t lock; | ||
81 | int io_port; | ||
82 | int irq; | ||
83 | int read_status_mask; | ||
84 | int ignore_status_mask; | ||
85 | int timeout; | ||
86 | int stat_flags; | ||
87 | int custom_divisor; | ||
88 | int close_delay; | ||
89 | unsigned short closing_wait; | ||
90 | unsigned short closing_wait2; | ||
91 | int IER; /* Interrupt Enable Register */ | ||
92 | int MCR; /* Modem control register */ | ||
93 | unsigned long last_active; | ||
94 | int line; | ||
95 | unsigned char *xmit_buf; | ||
96 | int xmit_head; | ||
97 | int xmit_tail; | ||
98 | int xmit_cnt; | ||
99 | wait_queue_head_t break_wait; | ||
100 | struct async_icount icount; /* kernel counters for the 4 input interrupts */ | ||
101 | struct hayes_esp_config config; /* port configuration */ | ||
102 | struct esp_struct *next_port; /* For the linked list */ | ||
103 | }; | ||
104 | |||
105 | struct esp_pio_buffer { | ||
106 | unsigned char data[1024]; | ||
107 | struct esp_pio_buffer *next; | ||
108 | }; | ||
109 | |||
110 | #endif /* __KERNEL__ */ | ||
111 | |||
112 | |||
113 | #endif /* ESP_H */ | ||
114 | |||
diff --git a/include/linux/isicom.h b/include/linux/isicom.h index bbd42197298f..b92e05650639 100644 --- a/include/linux/isicom.h +++ b/include/linux/isicom.h | |||
@@ -67,6 +67,7 @@ | |||
67 | 67 | ||
68 | #define FIRMWARE_LOADED 0x0001 | 68 | #define FIRMWARE_LOADED 0x0001 |
69 | #define BOARD_ACTIVE 0x0002 | 69 | #define BOARD_ACTIVE 0x0002 |
70 | #define BOARD_INIT 0x0004 | ||
70 | 71 | ||
71 | /* isi_port status bitmap */ | 72 | /* isi_port status bitmap */ |
72 | 73 | ||
diff --git a/include/linux/tty.h b/include/linux/tty.h index f0f43d08d8b8..405a9035fe40 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -190,9 +190,17 @@ struct tty_port_operations { | |||
190 | /* Control the DTR line */ | 190 | /* Control the DTR line */ |
191 | void (*dtr_rts)(struct tty_port *port, int raise); | 191 | void (*dtr_rts)(struct tty_port *port, int raise); |
192 | /* Called when the last close completes or a hangup finishes | 192 | /* Called when the last close completes or a hangup finishes |
193 | IFF the port was initialized. Do not use to free resources */ | 193 | IFF the port was initialized. Do not use to free resources. Called |
194 | under the port mutex to serialize against activate/shutdowns */ | ||
194 | void (*shutdown)(struct tty_port *port); | 195 | void (*shutdown)(struct tty_port *port); |
195 | void (*drop)(struct tty_port *port); | 196 | void (*drop)(struct tty_port *port); |
197 | /* Called under the port mutex from tty_port_open, serialized using | ||
198 | the port mutex */ | ||
199 | /* FIXME: long term getting the tty argument *out* of this would be | ||
200 | good for consoles */ | ||
201 | int (*activate)(struct tty_port *port, struct tty_struct *tty); | ||
202 | /* Called on the final put of a port */ | ||
203 | void (*destruct)(struct tty_port *port); | ||
196 | }; | 204 | }; |
197 | 205 | ||
198 | struct tty_port { | 206 | struct tty_port { |
@@ -206,12 +214,14 @@ struct tty_port { | |||
206 | wait_queue_head_t delta_msr_wait; /* Modem status change */ | 214 | wait_queue_head_t delta_msr_wait; /* Modem status change */ |
207 | unsigned long flags; /* TTY flags ASY_*/ | 215 | unsigned long flags; /* TTY flags ASY_*/ |
208 | struct mutex mutex; /* Locking */ | 216 | struct mutex mutex; /* Locking */ |
217 | struct mutex buf_mutex; /* Buffer alloc lock */ | ||
209 | unsigned char *xmit_buf; /* Optional buffer */ | 218 | unsigned char *xmit_buf; /* Optional buffer */ |
210 | unsigned int close_delay; /* Close port delay */ | 219 | unsigned int close_delay; /* Close port delay */ |
211 | unsigned int closing_wait; /* Delay for output */ | 220 | unsigned int closing_wait; /* Delay for output */ |
212 | int drain_delay; /* Set to zero if no pure time | 221 | int drain_delay; /* Set to zero if no pure time |
213 | based drain is needed else | 222 | based drain is needed else |
214 | set to size of fifo */ | 223 | set to size of fifo */ |
224 | struct kref kref; /* Ref counter */ | ||
215 | }; | 225 | }; |
216 | 226 | ||
217 | /* | 227 | /* |
@@ -439,7 +449,7 @@ extern void initialize_tty_struct(struct tty_struct *tty, | |||
439 | struct tty_driver *driver, int idx); | 449 | struct tty_driver *driver, int idx); |
440 | extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | 450 | extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, |
441 | int first_ok); | 451 | int first_ok); |
442 | extern void tty_release_dev(struct file *filp); | 452 | extern int tty_release(struct inode *inode, struct file *filp); |
443 | extern int tty_init_termios(struct tty_struct *tty); | 453 | extern int tty_init_termios(struct tty_struct *tty); |
444 | 454 | ||
445 | extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty); | 455 | extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty); |
@@ -454,6 +464,15 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay); | |||
454 | extern void tty_port_init(struct tty_port *port); | 464 | extern void tty_port_init(struct tty_port *port); |
455 | extern int tty_port_alloc_xmit_buf(struct tty_port *port); | 465 | extern int tty_port_alloc_xmit_buf(struct tty_port *port); |
456 | extern void tty_port_free_xmit_buf(struct tty_port *port); | 466 | extern void tty_port_free_xmit_buf(struct tty_port *port); |
467 | extern void tty_port_put(struct tty_port *port); | ||
468 | |||
469 | extern inline struct tty_port *tty_port_get(struct tty_port *port) | ||
470 | { | ||
471 | if (port) | ||
472 | kref_get(&port->kref); | ||
473 | return port; | ||
474 | } | ||
475 | |||
457 | extern struct tty_struct *tty_port_tty_get(struct tty_port *port); | 476 | extern struct tty_struct *tty_port_tty_get(struct tty_port *port); |
458 | extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); | 477 | extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); |
459 | extern int tty_port_carrier_raised(struct tty_port *port); | 478 | extern int tty_port_carrier_raised(struct tty_port *port); |
@@ -467,6 +486,8 @@ extern int tty_port_close_start(struct tty_port *port, | |||
467 | extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty); | 486 | extern void tty_port_close_end(struct tty_port *port, struct tty_struct *tty); |
468 | extern void tty_port_close(struct tty_port *port, | 487 | extern void tty_port_close(struct tty_port *port, |
469 | struct tty_struct *tty, struct file *filp); | 488 | struct tty_struct *tty, struct file *filp); |
489 | extern int tty_port_open(struct tty_port *port, | ||
490 | struct tty_struct *tty, struct file *filp); | ||
470 | extern inline int tty_port_users(struct tty_port *port) | 491 | extern inline int tty_port_users(struct tty_port *port) |
471 | { | 492 | { |
472 | return port->count + port->blocked_open; | 493 | return port->count + port->blocked_open; |
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index ce911ebf91e8..acf6e457c04b 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h | |||
@@ -39,8 +39,6 @@ enum port_dev_state { | |||
39 | * @serial: pointer back to the struct usb_serial owner of this port. | 39 | * @serial: pointer back to the struct usb_serial owner of this port. |
40 | * @port: pointer to the corresponding tty_port for this port. | 40 | * @port: pointer to the corresponding tty_port for this port. |
41 | * @lock: spinlock to grab when updating portions of this structure. | 41 | * @lock: spinlock to grab when updating portions of this structure. |
42 | * @mutex: mutex used to synchronize serial_open() and serial_close() | ||
43 | * access for this port. | ||
44 | * @number: the number of the port (the minor number). | 42 | * @number: the number of the port (the minor number). |
45 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. | 43 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. |
46 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. | 44 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. |
@@ -77,7 +75,6 @@ struct usb_serial_port { | |||
77 | struct usb_serial *serial; | 75 | struct usb_serial *serial; |
78 | struct tty_port port; | 76 | struct tty_port port; |
79 | spinlock_t lock; | 77 | spinlock_t lock; |
80 | struct mutex mutex; | ||
81 | unsigned char number; | 78 | unsigned char number; |
82 | 79 | ||
83 | unsigned char *interrupt_in_buffer; | 80 | unsigned char *interrupt_in_buffer; |
diff --git a/kernel/exit.c b/kernel/exit.c index 1143012951e9..6f50ef55a6f3 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -971,7 +971,7 @@ NORET_TYPE void do_exit(long code) | |||
971 | exit_thread(); | 971 | exit_thread(); |
972 | cgroup_exit(tsk, 1); | 972 | cgroup_exit(tsk, 1); |
973 | 973 | ||
974 | if (group_dead && tsk->signal->leader) | 974 | if (group_dead) |
975 | disassociate_ctty(1); | 975 | disassociate_ctty(1); |
976 | 976 | ||
977 | module_put(task_thread_info(tsk)->exec_domain->module); | 977 | module_put(task_thread_info(tsk)->exec_domain->module); |