diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/Kconfig | 13 | ||||
-rw-r--r-- | drivers/char/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/bfin_jtag_comm.c | 365 | ||||
-rw-r--r-- | drivers/char/cyclades.c | 290 | ||||
-rw-r--r-- | drivers/char/epca.c | 17 | ||||
-rw-r--r-- | drivers/char/ip2/i2lib.c | 4 | ||||
-rw-r--r-- | drivers/char/ip2/ip2main.c | 4 | ||||
-rw-r--r-- | drivers/char/isicom.c | 19 | ||||
-rw-r--r-- | drivers/char/istallion.c | 8 | ||||
-rw-r--r-- | drivers/char/moxa.c | 5 | ||||
-rw-r--r-- | drivers/char/mxser.c | 12 | ||||
-rw-r--r-- | drivers/char/n_hdlc.c | 4 | ||||
-rw-r--r-- | drivers/char/n_tty.c | 29 | ||||
-rw-r--r-- | drivers/char/pcmcia/synclink_cs.c | 11 | ||||
-rw-r--r-- | drivers/char/pty.c | 11 | ||||
-rw-r--r-- | drivers/char/raw.c | 2 | ||||
-rw-r--r-- | drivers/char/rocket.c | 19 | ||||
-rw-r--r-- | drivers/char/selection.c | 2 | ||||
-rw-r--r-- | drivers/char/stallion.c | 6 | ||||
-rw-r--r-- | drivers/char/synclink.c | 9 | ||||
-rw-r--r-- | drivers/char/synclink_gt.c | 86 | ||||
-rw-r--r-- | drivers/char/synclinkmp.c | 9 | ||||
-rw-r--r-- | drivers/char/tty_audit.c | 10 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 122 | ||||
-rw-r--r-- | drivers/char/tty_ioctl.c | 88 | ||||
-rw-r--r-- | drivers/char/tty_ldisc.c | 549 | ||||
-rw-r--r-- | drivers/char/tty_port.c | 47 | ||||
-rw-r--r-- | drivers/char/vt.c | 8 |
28 files changed, 1164 insertions, 586 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 735bbe2be51a..02ecfd5fa61c 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -97,6 +97,19 @@ config DEVKMEM | |||
97 | kind of kernel debugging operations. | 97 | kind of kernel debugging operations. |
98 | When in doubt, say "N". | 98 | When in doubt, say "N". |
99 | 99 | ||
100 | config BFIN_JTAG_COMM | ||
101 | tristate "Blackfin JTAG Communication" | ||
102 | depends on BLACKFIN | ||
103 | help | ||
104 | Add support for emulating a TTY device over the Blackfin JTAG. | ||
105 | |||
106 | To compile this driver as a module, choose M here: the | ||
107 | module will be called bfin_jtag_comm. | ||
108 | |||
109 | config BFIN_JTAG_COMM_CONSOLE | ||
110 | bool "Console on Blackfin JTAG" | ||
111 | depends on BFIN_JTAG_COMM=y | ||
112 | |||
100 | config SERIAL_NONSTANDARD | 113 | config SERIAL_NONSTANDARD |
101 | bool "Non-standard serial port support" | 114 | bool "Non-standard serial port support" |
102 | depends on HAS_IOMEM | 115 | depends on HAS_IOMEM |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 9caf5b5ad1c0..189efcff08ce 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_LEGACY_PTYS) += pty.o | |||
13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o | 13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o |
14 | obj-y += misc.o | 14 | obj-y += misc.o |
15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o | 15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o |
16 | obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o | ||
16 | obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o | 17 | obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o |
17 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o | 18 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o |
18 | obj-$(CONFIG_AUDIT) += tty_audit.o | 19 | obj-$(CONFIG_AUDIT) += tty_audit.o |
diff --git a/drivers/char/bfin_jtag_comm.c b/drivers/char/bfin_jtag_comm.c new file mode 100644 index 000000000000..44c113d56045 --- /dev/null +++ b/drivers/char/bfin_jtag_comm.c | |||
@@ -0,0 +1,365 @@ | |||
1 | /* | ||
2 | * TTY over Blackfin JTAG Communication | ||
3 | * | ||
4 | * Copyright 2008-2009 Analog Devices Inc. | ||
5 | * | ||
6 | * Enter bugs at http://blackfin.uclinux.org/ | ||
7 | * | ||
8 | * Licensed under the GPL-2 or later. | ||
9 | */ | ||
10 | |||
11 | #include <linux/circ_buf.h> | ||
12 | #include <linux/console.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/kthread.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/mutex.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/tty.h> | ||
21 | #include <linux/tty_driver.h> | ||
22 | #include <linux/tty_flip.h> | ||
23 | #include <asm/atomic.h> | ||
24 | |||
25 | /* See the Debug/Emulation chapter in the HRM */ | ||
26 | #define EMUDOF 0x00000001 /* EMUDAT_OUT full & valid */ | ||
27 | #define EMUDIF 0x00000002 /* EMUDAT_IN full & valid */ | ||
28 | #define EMUDOOVF 0x00000004 /* EMUDAT_OUT overflow */ | ||
29 | #define EMUDIOVF 0x00000008 /* EMUDAT_IN overflow */ | ||
30 | |||
31 | #define DRV_NAME "bfin-jtag-comm" | ||
32 | #define DEV_NAME "ttyBFJC" | ||
33 | |||
34 | #define pr_init(fmt, args...) ({ static const __initdata char __fmt[] = fmt; printk(__fmt, ## args); }) | ||
35 | #define debug(fmt, args...) pr_debug(DRV_NAME ": " fmt, ## args) | ||
36 | |||
37 | static inline uint32_t bfin_write_emudat(uint32_t emudat) | ||
38 | { | ||
39 | __asm__ __volatile__("emudat = %0;" : : "d"(emudat)); | ||
40 | return emudat; | ||
41 | } | ||
42 | |||
43 | static inline uint32_t bfin_read_emudat(void) | ||
44 | { | ||
45 | uint32_t emudat; | ||
46 | __asm__ __volatile__("%0 = emudat;" : "=d"(emudat)); | ||
47 | return emudat; | ||
48 | } | ||
49 | |||
50 | static inline uint32_t bfin_write_emudat_chars(char a, char b, char c, char d) | ||
51 | { | ||
52 | return bfin_write_emudat((a << 0) | (b << 8) | (c << 16) | (d << 24)); | ||
53 | } | ||
54 | |||
55 | #define CIRC_SIZE 2048 /* see comment in tty_io.c:do_tty_write() */ | ||
56 | #define CIRC_MASK (CIRC_SIZE - 1) | ||
57 | #define circ_empty(circ) ((circ)->head == (circ)->tail) | ||
58 | #define circ_free(circ) CIRC_SPACE((circ)->head, (circ)->tail, CIRC_SIZE) | ||
59 | #define circ_cnt(circ) CIRC_CNT((circ)->head, (circ)->tail, CIRC_SIZE) | ||
60 | #define circ_byte(circ, idx) ((circ)->buf[(idx) & CIRC_MASK]) | ||
61 | |||
62 | static struct tty_driver *bfin_jc_driver; | ||
63 | static struct task_struct *bfin_jc_kthread; | ||
64 | static struct tty_struct * volatile bfin_jc_tty; | ||
65 | static unsigned long bfin_jc_count; | ||
66 | static DEFINE_MUTEX(bfin_jc_tty_mutex); | ||
67 | static volatile struct circ_buf bfin_jc_write_buf; | ||
68 | |||
69 | static int | ||
70 | bfin_jc_emudat_manager(void *arg) | ||
71 | { | ||
72 | uint32_t inbound_len = 0, outbound_len = 0; | ||
73 | |||
74 | while (!kthread_should_stop()) { | ||
75 | /* no one left to give data to, so sleep */ | ||
76 | if (bfin_jc_tty == NULL && circ_empty(&bfin_jc_write_buf)) { | ||
77 | debug("waiting for readers\n"); | ||
78 | __set_current_state(TASK_UNINTERRUPTIBLE); | ||
79 | schedule(); | ||
80 | __set_current_state(TASK_RUNNING); | ||
81 | } | ||
82 | |||
83 | /* no data available, so just chill */ | ||
84 | if (!(bfin_read_DBGSTAT() & EMUDIF) && circ_empty(&bfin_jc_write_buf)) { | ||
85 | debug("waiting for data (in_len = %i) (circ: %i %i)\n", | ||
86 | inbound_len, bfin_jc_write_buf.tail, bfin_jc_write_buf.head); | ||
87 | if (inbound_len) | ||
88 | schedule(); | ||
89 | else | ||
90 | schedule_timeout_interruptible(HZ); | ||
91 | continue; | ||
92 | } | ||
93 | |||
94 | /* if incoming data is ready, eat it */ | ||
95 | if (bfin_read_DBGSTAT() & EMUDIF) { | ||
96 | struct tty_struct *tty; | ||
97 | mutex_lock(&bfin_jc_tty_mutex); | ||
98 | tty = (struct tty_struct *)bfin_jc_tty; | ||
99 | if (tty != NULL) { | ||
100 | uint32_t emudat = bfin_read_emudat(); | ||
101 | if (inbound_len == 0) { | ||
102 | debug("incoming length: 0x%08x\n", emudat); | ||
103 | inbound_len = emudat; | ||
104 | } else { | ||
105 | size_t num_chars = (4 <= inbound_len ? 4 : inbound_len); | ||
106 | debug(" incoming data: 0x%08x (pushing %zu)\n", emudat, num_chars); | ||
107 | inbound_len -= num_chars; | ||
108 | tty_insert_flip_string(tty, (unsigned char *)&emudat, num_chars); | ||
109 | tty_flip_buffer_push(tty); | ||
110 | } | ||
111 | } | ||
112 | mutex_unlock(&bfin_jc_tty_mutex); | ||
113 | } | ||
114 | |||
115 | /* if outgoing data is ready, post it */ | ||
116 | if (!(bfin_read_DBGSTAT() & EMUDOF) && !circ_empty(&bfin_jc_write_buf)) { | ||
117 | if (outbound_len == 0) { | ||
118 | outbound_len = circ_cnt(&bfin_jc_write_buf); | ||
119 | bfin_write_emudat(outbound_len); | ||
120 | debug("outgoing length: 0x%08x\n", outbound_len); | ||
121 | } else { | ||
122 | struct tty_struct *tty; | ||
123 | int tail = bfin_jc_write_buf.tail; | ||
124 | size_t ate = (4 <= outbound_len ? 4 : outbound_len); | ||
125 | uint32_t emudat = | ||
126 | bfin_write_emudat_chars( | ||
127 | circ_byte(&bfin_jc_write_buf, tail + 0), | ||
128 | circ_byte(&bfin_jc_write_buf, tail + 1), | ||
129 | circ_byte(&bfin_jc_write_buf, tail + 2), | ||
130 | circ_byte(&bfin_jc_write_buf, tail + 3) | ||
131 | ); | ||
132 | bfin_jc_write_buf.tail += ate; | ||
133 | outbound_len -= ate; | ||
134 | mutex_lock(&bfin_jc_tty_mutex); | ||
135 | tty = (struct tty_struct *)bfin_jc_tty; | ||
136 | if (tty) | ||
137 | tty_wakeup(tty); | ||
138 | mutex_unlock(&bfin_jc_tty_mutex); | ||
139 | debug(" outgoing data: 0x%08x (pushing %zu)\n", emudat, ate); | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | |||
144 | __set_current_state(TASK_RUNNING); | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int | ||
149 | bfin_jc_open(struct tty_struct *tty, struct file *filp) | ||
150 | { | ||
151 | mutex_lock(&bfin_jc_tty_mutex); | ||
152 | debug("open %lu\n", bfin_jc_count); | ||
153 | ++bfin_jc_count; | ||
154 | bfin_jc_tty = tty; | ||
155 | wake_up_process(bfin_jc_kthread); | ||
156 | mutex_unlock(&bfin_jc_tty_mutex); | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static void | ||
161 | bfin_jc_close(struct tty_struct *tty, struct file *filp) | ||
162 | { | ||
163 | mutex_lock(&bfin_jc_tty_mutex); | ||
164 | debug("close %lu\n", bfin_jc_count); | ||
165 | if (--bfin_jc_count == 0) | ||
166 | bfin_jc_tty = NULL; | ||
167 | wake_up_process(bfin_jc_kthread); | ||
168 | mutex_unlock(&bfin_jc_tty_mutex); | ||
169 | } | ||
170 | |||
171 | /* XXX: we dont handle the put_char() case where we must handle count = 1 */ | ||
172 | static int | ||
173 | bfin_jc_circ_write(const unsigned char *buf, int count) | ||
174 | { | ||
175 | int i; | ||
176 | count = min(count, circ_free(&bfin_jc_write_buf)); | ||
177 | debug("going to write chunk of %i bytes\n", count); | ||
178 | for (i = 0; i < count; ++i) | ||
179 | circ_byte(&bfin_jc_write_buf, bfin_jc_write_buf.head + i) = buf[i]; | ||
180 | bfin_jc_write_buf.head += i; | ||
181 | return i; | ||
182 | } | ||
183 | |||
184 | #ifndef CONFIG_BFIN_JTAG_COMM_CONSOLE | ||
185 | # define acquire_console_sem() | ||
186 | # define release_console_sem() | ||
187 | #endif | ||
188 | static int | ||
189 | bfin_jc_write(struct tty_struct *tty, const unsigned char *buf, int count) | ||
190 | { | ||
191 | int i; | ||
192 | acquire_console_sem(); | ||
193 | i = bfin_jc_circ_write(buf, count); | ||
194 | release_console_sem(); | ||
195 | wake_up_process(bfin_jc_kthread); | ||
196 | return i; | ||
197 | } | ||
198 | |||
199 | static void | ||
200 | bfin_jc_flush_chars(struct tty_struct *tty) | ||
201 | { | ||
202 | wake_up_process(bfin_jc_kthread); | ||
203 | } | ||
204 | |||
205 | static int | ||
206 | bfin_jc_write_room(struct tty_struct *tty) | ||
207 | { | ||
208 | return circ_free(&bfin_jc_write_buf); | ||
209 | } | ||
210 | |||
211 | static int | ||
212 | bfin_jc_chars_in_buffer(struct tty_struct *tty) | ||
213 | { | ||
214 | return circ_cnt(&bfin_jc_write_buf); | ||
215 | } | ||
216 | |||
217 | static void | ||
218 | bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout) | ||
219 | { | ||
220 | unsigned long expire = jiffies + timeout; | ||
221 | while (!circ_empty(&bfin_jc_write_buf)) { | ||
222 | if (signal_pending(current)) | ||
223 | break; | ||
224 | if (time_after(jiffies, expire)) | ||
225 | break; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | static struct tty_operations bfin_jc_ops = { | ||
230 | .open = bfin_jc_open, | ||
231 | .close = bfin_jc_close, | ||
232 | .write = bfin_jc_write, | ||
233 | /*.put_char = bfin_jc_put_char,*/ | ||
234 | .flush_chars = bfin_jc_flush_chars, | ||
235 | .write_room = bfin_jc_write_room, | ||
236 | .chars_in_buffer = bfin_jc_chars_in_buffer, | ||
237 | .wait_until_sent = bfin_jc_wait_until_sent, | ||
238 | }; | ||
239 | |||
240 | static int __init bfin_jc_init(void) | ||
241 | { | ||
242 | int ret; | ||
243 | |||
244 | bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME); | ||
245 | if (IS_ERR(bfin_jc_kthread)) | ||
246 | return PTR_ERR(bfin_jc_kthread); | ||
247 | |||
248 | ret = -ENOMEM; | ||
249 | |||
250 | bfin_jc_write_buf.head = bfin_jc_write_buf.tail = 0; | ||
251 | bfin_jc_write_buf.buf = kmalloc(CIRC_SIZE, GFP_KERNEL); | ||
252 | if (!bfin_jc_write_buf.buf) | ||
253 | goto err; | ||
254 | |||
255 | bfin_jc_driver = alloc_tty_driver(1); | ||
256 | if (!bfin_jc_driver) | ||
257 | goto err; | ||
258 | |||
259 | bfin_jc_driver->owner = THIS_MODULE; | ||
260 | bfin_jc_driver->driver_name = DRV_NAME; | ||
261 | bfin_jc_driver->name = DEV_NAME; | ||
262 | bfin_jc_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
263 | bfin_jc_driver->subtype = SERIAL_TYPE_NORMAL; | ||
264 | bfin_jc_driver->init_termios = tty_std_termios; | ||
265 | tty_set_operations(bfin_jc_driver, &bfin_jc_ops); | ||
266 | |||
267 | ret = tty_register_driver(bfin_jc_driver); | ||
268 | if (ret) | ||
269 | goto err; | ||
270 | |||
271 | pr_init(KERN_INFO DRV_NAME ": initialized\n"); | ||
272 | |||
273 | return 0; | ||
274 | |||
275 | err: | ||
276 | put_tty_driver(bfin_jc_driver); | ||
277 | kfree(bfin_jc_write_buf.buf); | ||
278 | kthread_stop(bfin_jc_kthread); | ||
279 | return ret; | ||
280 | } | ||
281 | module_init(bfin_jc_init); | ||
282 | |||
283 | static void __exit bfin_jc_exit(void) | ||
284 | { | ||
285 | kthread_stop(bfin_jc_kthread); | ||
286 | kfree(bfin_jc_write_buf.buf); | ||
287 | tty_unregister_driver(bfin_jc_driver); | ||
288 | put_tty_driver(bfin_jc_driver); | ||
289 | } | ||
290 | module_exit(bfin_jc_exit); | ||
291 | |||
292 | #if defined(CONFIG_BFIN_JTAG_COMM_CONSOLE) || defined(CONFIG_EARLY_PRINTK) | ||
293 | static void | ||
294 | bfin_jc_straight_buffer_write(const char *buf, unsigned count) | ||
295 | { | ||
296 | unsigned ate = 0; | ||
297 | while (bfin_read_DBGSTAT() & EMUDOF) | ||
298 | continue; | ||
299 | bfin_write_emudat(count); | ||
300 | while (ate < count) { | ||
301 | while (bfin_read_DBGSTAT() & EMUDOF) | ||
302 | continue; | ||
303 | bfin_write_emudat_chars(buf[ate], buf[ate+1], buf[ate+2], buf[ate+3]); | ||
304 | ate += 4; | ||
305 | } | ||
306 | } | ||
307 | #endif | ||
308 | |||
309 | #ifdef CONFIG_BFIN_JTAG_COMM_CONSOLE | ||
310 | static void | ||
311 | bfin_jc_console_write(struct console *co, const char *buf, unsigned count) | ||
312 | { | ||
313 | if (bfin_jc_kthread == NULL) | ||
314 | bfin_jc_straight_buffer_write(buf, count); | ||
315 | else | ||
316 | bfin_jc_circ_write(buf, count); | ||
317 | } | ||
318 | |||
319 | static struct tty_driver * | ||
320 | bfin_jc_console_device(struct console *co, int *index) | ||
321 | { | ||
322 | *index = co->index; | ||
323 | return bfin_jc_driver; | ||
324 | } | ||
325 | |||
326 | static struct console bfin_jc_console = { | ||
327 | .name = DEV_NAME, | ||
328 | .write = bfin_jc_console_write, | ||
329 | .device = bfin_jc_console_device, | ||
330 | .flags = CON_ANYTIME | CON_PRINTBUFFER, | ||
331 | .index = -1, | ||
332 | }; | ||
333 | |||
334 | static int __init bfin_jc_console_init(void) | ||
335 | { | ||
336 | register_console(&bfin_jc_console); | ||
337 | return 0; | ||
338 | } | ||
339 | console_initcall(bfin_jc_console_init); | ||
340 | #endif | ||
341 | |||
342 | #ifdef CONFIG_EARLY_PRINTK | ||
343 | static void __init | ||
344 | bfin_jc_early_write(struct console *co, const char *buf, unsigned int count) | ||
345 | { | ||
346 | bfin_jc_straight_buffer_write(buf, count); | ||
347 | } | ||
348 | |||
349 | static struct __initdata console bfin_jc_early_console = { | ||
350 | .name = "early_BFJC", | ||
351 | .write = bfin_jc_early_write, | ||
352 | .flags = CON_ANYTIME | CON_PRINTBUFFER, | ||
353 | .index = -1, | ||
354 | }; | ||
355 | |||
356 | struct console * __init | ||
357 | bfin_jc_early_init(unsigned int port, unsigned int cflag) | ||
358 | { | ||
359 | return &bfin_jc_early_console; | ||
360 | } | ||
361 | #endif | ||
362 | |||
363 | MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); | ||
364 | MODULE_DESCRIPTION("TTY over Blackfin JTAG Communication"); | ||
365 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 1fdb9f657d8f..f3366d3f06cf 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -604,7 +604,6 @@ | |||
604 | 604 | ||
605 | #define NR_PORTS 256 | 605 | #define NR_PORTS 256 |
606 | 606 | ||
607 | #define ZE_V1_NPORTS 64 | ||
608 | #define ZO_V1 0 | 607 | #define ZO_V1 0 |
609 | #define ZO_V2 1 | 608 | #define ZO_V2 1 |
610 | #define ZE_V1 2 | 609 | #define ZE_V1 2 |
@@ -663,18 +662,6 @@ | |||
663 | static void cy_throttle(struct tty_struct *tty); | 662 | static void cy_throttle(struct tty_struct *tty); |
664 | static void cy_send_xchar(struct tty_struct *tty, char ch); | 663 | static void cy_send_xchar(struct tty_struct *tty, char ch); |
665 | 664 | ||
666 | #define IS_CYC_Z(card) ((card).num_chips == (unsigned int)-1) | ||
667 | |||
668 | #define Z_FPGA_CHECK(card) \ | ||
669 | ((readl(&((struct RUNTIME_9060 __iomem *) \ | ||
670 | ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0) | ||
671 | |||
672 | #define ISZLOADED(card) (((ZO_V1 == readl(&((struct RUNTIME_9060 __iomem *) \ | ||
673 | ((card).ctl_addr))->mail_box_0)) || \ | ||
674 | Z_FPGA_CHECK(card)) && \ | ||
675 | (ZFIRM_ID == readl(&((struct FIRM_ID __iomem *) \ | ||
676 | ((card).base_addr+ID_ADDRESS))->signature))) | ||
677 | |||
678 | #ifndef SERIAL_XMIT_SIZE | 665 | #ifndef SERIAL_XMIT_SIZE |
679 | #define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096)) | 666 | #define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096)) |
680 | #endif | 667 | #endif |
@@ -687,8 +674,6 @@ static void cy_send_xchar(struct tty_struct *tty, char ch); | |||
687 | #define DRIVER_VERSION 0x02010203 | 674 | #define DRIVER_VERSION 0x02010203 |
688 | #define RAM_SIZE 0x80000 | 675 | #define RAM_SIZE 0x80000 |
689 | 676 | ||
690 | #define Z_FPGA_LOADED(X) ((readl(&(X)->init_ctrl) & (1<<17)) != 0) | ||
691 | |||
692 | enum zblock_type { | 677 | enum zblock_type { |
693 | ZBLOCK_PRG = 0, | 678 | ZBLOCK_PRG = 0, |
694 | ZBLOCK_FPGA = 1 | 679 | ZBLOCK_FPGA = 1 |
@@ -883,6 +868,29 @@ static void cyz_rx_restart(unsigned long); | |||
883 | static struct timer_list cyz_rx_full_timer[NR_PORTS]; | 868 | static struct timer_list cyz_rx_full_timer[NR_PORTS]; |
884 | #endif /* CONFIG_CYZ_INTR */ | 869 | #endif /* CONFIG_CYZ_INTR */ |
885 | 870 | ||
871 | static inline bool cy_is_Z(struct cyclades_card *card) | ||
872 | { | ||
873 | return card->num_chips == (unsigned int)-1; | ||
874 | } | ||
875 | |||
876 | static inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr) | ||
877 | { | ||
878 | return readl(&ctl_addr->init_ctrl) & (1 << 17); | ||
879 | } | ||
880 | |||
881 | static inline bool cyz_fpga_loaded(struct cyclades_card *card) | ||
882 | { | ||
883 | return __cyz_fpga_loaded(card->ctl_addr.p9060); | ||
884 | } | ||
885 | |||
886 | static inline bool cyz_is_loaded(struct cyclades_card *card) | ||
887 | { | ||
888 | struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS; | ||
889 | |||
890 | return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) && | ||
891 | readl(&fw_id->signature) == ZFIRM_ID; | ||
892 | } | ||
893 | |||
886 | static inline int serial_paranoia_check(struct cyclades_port *info, | 894 | static inline int serial_paranoia_check(struct cyclades_port *info, |
887 | char *name, const char *routine) | 895 | char *name, const char *routine) |
888 | { | 896 | { |
@@ -1395,19 +1403,15 @@ cyz_fetch_msg(struct cyclades_card *cinfo, | |||
1395 | unsigned long loc_doorbell; | 1403 | unsigned long loc_doorbell; |
1396 | 1404 | ||
1397 | firm_id = cinfo->base_addr + ID_ADDRESS; | 1405 | firm_id = cinfo->base_addr + ID_ADDRESS; |
1398 | if (!ISZLOADED(*cinfo)) | ||
1399 | return -1; | ||
1400 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 1406 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
1401 | board_ctrl = &zfw_ctrl->board_ctrl; | 1407 | board_ctrl = &zfw_ctrl->board_ctrl; |
1402 | 1408 | ||
1403 | loc_doorbell = readl(&((struct RUNTIME_9060 __iomem *) | 1409 | loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell); |
1404 | (cinfo->ctl_addr))->loc_doorbell); | ||
1405 | if (loc_doorbell) { | 1410 | if (loc_doorbell) { |
1406 | *cmd = (char)(0xff & loc_doorbell); | 1411 | *cmd = (char)(0xff & loc_doorbell); |
1407 | *channel = readl(&board_ctrl->fwcmd_channel); | 1412 | *channel = readl(&board_ctrl->fwcmd_channel); |
1408 | *param = (__u32) readl(&board_ctrl->fwcmd_param); | 1413 | *param = (__u32) readl(&board_ctrl->fwcmd_param); |
1409 | cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> | 1414 | cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff); |
1410 | loc_doorbell, 0xffffffff); | ||
1411 | return 1; | 1415 | return 1; |
1412 | } | 1416 | } |
1413 | return 0; | 1417 | return 0; |
@@ -1424,15 +1428,14 @@ cyz_issue_cmd(struct cyclades_card *cinfo, | |||
1424 | unsigned int index; | 1428 | unsigned int index; |
1425 | 1429 | ||
1426 | firm_id = cinfo->base_addr + ID_ADDRESS; | 1430 | firm_id = cinfo->base_addr + ID_ADDRESS; |
1427 | if (!ISZLOADED(*cinfo)) | 1431 | if (!cyz_is_loaded(cinfo)) |
1428 | return -1; | 1432 | return -1; |
1429 | 1433 | ||
1430 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 1434 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
1431 | board_ctrl = &zfw_ctrl->board_ctrl; | 1435 | board_ctrl = &zfw_ctrl->board_ctrl; |
1432 | 1436 | ||
1433 | index = 0; | 1437 | index = 0; |
1434 | pci_doorbell = | 1438 | pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell; |
1435 | &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell; | ||
1436 | while ((readl(pci_doorbell) & 0xff) != 0) { | 1439 | while ((readl(pci_doorbell) & 0xff) != 0) { |
1437 | if (index++ == 1000) | 1440 | if (index++ == 1000) |
1438 | return (int)(readl(pci_doorbell) & 0xff); | 1441 | return (int)(readl(pci_doorbell) & 0xff); |
@@ -1624,10 +1627,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) | |||
1624 | static struct BOARD_CTRL __iomem *board_ctrl; | 1627 | static struct BOARD_CTRL __iomem *board_ctrl; |
1625 | static struct CH_CTRL __iomem *ch_ctrl; | 1628 | static struct CH_CTRL __iomem *ch_ctrl; |
1626 | static struct BUF_CTRL __iomem *buf_ctrl; | 1629 | static struct BUF_CTRL __iomem *buf_ctrl; |
1627 | __u32 channel; | 1630 | __u32 channel, param, fw_ver; |
1628 | __u8 cmd; | 1631 | __u8 cmd; |
1629 | __u32 param; | ||
1630 | __u32 hw_ver, fw_ver; | ||
1631 | int special_count; | 1632 | int special_count; |
1632 | int delta_count; | 1633 | int delta_count; |
1633 | 1634 | ||
@@ -1635,8 +1636,6 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) | |||
1635 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 1636 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
1636 | board_ctrl = &zfw_ctrl->board_ctrl; | 1637 | board_ctrl = &zfw_ctrl->board_ctrl; |
1637 | fw_ver = readl(&board_ctrl->fw_version); | 1638 | fw_ver = readl(&board_ctrl->fw_version); |
1638 | hw_ver = readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> | ||
1639 | mail_box_0); | ||
1640 | 1639 | ||
1641 | while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { | 1640 | while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { |
1642 | special_count = 0; | 1641 | special_count = 0; |
@@ -1737,15 +1736,7 @@ static irqreturn_t cyz_interrupt(int irq, void *dev_id) | |||
1737 | { | 1736 | { |
1738 | struct cyclades_card *cinfo = dev_id; | 1737 | struct cyclades_card *cinfo = dev_id; |
1739 | 1738 | ||
1740 | if (unlikely(cinfo == NULL)) { | 1739 | if (unlikely(!cyz_is_loaded(cinfo))) { |
1741 | #ifdef CY_DEBUG_INTERRUPTS | ||
1742 | printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n", | ||
1743 | irq); | ||
1744 | #endif | ||
1745 | return IRQ_NONE; /* spurious interrupt */ | ||
1746 | } | ||
1747 | |||
1748 | if (unlikely(!ISZLOADED(*cinfo))) { | ||
1749 | #ifdef CY_DEBUG_INTERRUPTS | 1740 | #ifdef CY_DEBUG_INTERRUPTS |
1750 | printk(KERN_DEBUG "cyz_interrupt: board not yet loaded " | 1741 | printk(KERN_DEBUG "cyz_interrupt: board not yet loaded " |
1751 | "(IRQ%d).\n", irq); | 1742 | "(IRQ%d).\n", irq); |
@@ -1785,7 +1776,6 @@ static void cyz_poll(unsigned long arg) | |||
1785 | struct tty_struct *tty; | 1776 | struct tty_struct *tty; |
1786 | struct FIRM_ID __iomem *firm_id; | 1777 | struct FIRM_ID __iomem *firm_id; |
1787 | struct ZFW_CTRL __iomem *zfw_ctrl; | 1778 | struct ZFW_CTRL __iomem *zfw_ctrl; |
1788 | struct BOARD_CTRL __iomem *board_ctrl; | ||
1789 | struct BUF_CTRL __iomem *buf_ctrl; | 1779 | struct BUF_CTRL __iomem *buf_ctrl; |
1790 | unsigned long expires = jiffies + HZ; | 1780 | unsigned long expires = jiffies + HZ; |
1791 | unsigned int port, card; | 1781 | unsigned int port, card; |
@@ -1793,19 +1783,17 @@ static void cyz_poll(unsigned long arg) | |||
1793 | for (card = 0; card < NR_CARDS; card++) { | 1783 | for (card = 0; card < NR_CARDS; card++) { |
1794 | cinfo = &cy_card[card]; | 1784 | cinfo = &cy_card[card]; |
1795 | 1785 | ||
1796 | if (!IS_CYC_Z(*cinfo)) | 1786 | if (!cy_is_Z(cinfo)) |
1797 | continue; | 1787 | continue; |
1798 | if (!ISZLOADED(*cinfo)) | 1788 | if (!cyz_is_loaded(cinfo)) |
1799 | continue; | 1789 | continue; |
1800 | 1790 | ||
1801 | firm_id = cinfo->base_addr + ID_ADDRESS; | 1791 | firm_id = cinfo->base_addr + ID_ADDRESS; |
1802 | zfw_ctrl = cinfo->base_addr + | 1792 | zfw_ctrl = cinfo->base_addr + |
1803 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 1793 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
1804 | board_ctrl = &(zfw_ctrl->board_ctrl); | ||
1805 | 1794 | ||
1806 | /* Skip first polling cycle to avoid racing conditions with the FW */ | 1795 | /* Skip first polling cycle to avoid racing conditions with the FW */ |
1807 | if (!cinfo->intr_enabled) { | 1796 | if (!cinfo->intr_enabled) { |
1808 | cinfo->nports = (int)readl(&board_ctrl->n_channel); | ||
1809 | cinfo->intr_enabled = 1; | 1797 | cinfo->intr_enabled = 1; |
1810 | continue; | 1798 | continue; |
1811 | } | 1799 | } |
@@ -1874,7 +1862,7 @@ static int startup(struct cyclades_port *info) | |||
1874 | 1862 | ||
1875 | set_line_char(info); | 1863 | set_line_char(info); |
1876 | 1864 | ||
1877 | if (!IS_CYC_Z(*card)) { | 1865 | if (!cy_is_Z(card)) { |
1878 | chip = channel >> 2; | 1866 | chip = channel >> 2; |
1879 | channel &= 0x03; | 1867 | channel &= 0x03; |
1880 | index = card->bus_index; | 1868 | index = card->bus_index; |
@@ -1931,7 +1919,7 @@ static int startup(struct cyclades_port *info) | |||
1931 | base_addr = card->base_addr; | 1919 | base_addr = card->base_addr; |
1932 | 1920 | ||
1933 | firm_id = base_addr + ID_ADDRESS; | 1921 | firm_id = base_addr + ID_ADDRESS; |
1934 | if (!ISZLOADED(*card)) | 1922 | if (!cyz_is_loaded(card)) |
1935 | return -ENODEV; | 1923 | return -ENODEV; |
1936 | 1924 | ||
1937 | zfw_ctrl = card->base_addr + | 1925 | zfw_ctrl = card->base_addr + |
@@ -2026,7 +2014,7 @@ static void start_xmit(struct cyclades_port *info) | |||
2026 | 2014 | ||
2027 | card = info->card; | 2015 | card = info->card; |
2028 | channel = info->line - card->first_line; | 2016 | channel = info->line - card->first_line; |
2029 | if (!IS_CYC_Z(*card)) { | 2017 | if (!cy_is_Z(card)) { |
2030 | chip = channel >> 2; | 2018 | chip = channel >> 2; |
2031 | channel &= 0x03; | 2019 | channel &= 0x03; |
2032 | index = card->bus_index; | 2020 | index = card->bus_index; |
@@ -2070,7 +2058,7 @@ static void shutdown(struct cyclades_port *info) | |||
2070 | 2058 | ||
2071 | card = info->card; | 2059 | card = info->card; |
2072 | channel = info->line - card->first_line; | 2060 | channel = info->line - card->first_line; |
2073 | if (!IS_CYC_Z(*card)) { | 2061 | if (!cy_is_Z(card)) { |
2074 | chip = channel >> 2; | 2062 | chip = channel >> 2; |
2075 | channel &= 0x03; | 2063 | channel &= 0x03; |
2076 | index = card->bus_index; | 2064 | index = card->bus_index; |
@@ -2126,7 +2114,7 @@ static void shutdown(struct cyclades_port *info) | |||
2126 | #endif | 2114 | #endif |
2127 | 2115 | ||
2128 | firm_id = base_addr + ID_ADDRESS; | 2116 | firm_id = base_addr + ID_ADDRESS; |
2129 | if (!ISZLOADED(*card)) | 2117 | if (!cyz_is_loaded(card)) |
2130 | return; | 2118 | return; |
2131 | 2119 | ||
2132 | zfw_ctrl = card->base_addr + | 2120 | zfw_ctrl = card->base_addr + |
@@ -2233,7 +2221,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2233 | #endif | 2221 | #endif |
2234 | info->port.blocked_open++; | 2222 | info->port.blocked_open++; |
2235 | 2223 | ||
2236 | if (!IS_CYC_Z(*cinfo)) { | 2224 | if (!cy_is_Z(cinfo)) { |
2237 | chip = channel >> 2; | 2225 | chip = channel >> 2; |
2238 | channel &= 0x03; | 2226 | channel &= 0x03; |
2239 | index = cinfo->bus_index; | 2227 | index = cinfo->bus_index; |
@@ -2296,7 +2284,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
2296 | 2284 | ||
2297 | base_addr = cinfo->base_addr; | 2285 | base_addr = cinfo->base_addr; |
2298 | firm_id = base_addr + ID_ADDRESS; | 2286 | firm_id = base_addr + ID_ADDRESS; |
2299 | if (!ISZLOADED(*cinfo)) { | 2287 | if (!cyz_is_loaded(cinfo)) { |
2300 | __set_current_state(TASK_RUNNING); | 2288 | __set_current_state(TASK_RUNNING); |
2301 | remove_wait_queue(&info->port.open_wait, &wait); | 2289 | remove_wait_queue(&info->port.open_wait, &wait); |
2302 | return -EINVAL; | 2290 | return -EINVAL; |
@@ -2397,16 +2385,14 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2397 | treat it as absent from the system. This | 2385 | treat it as absent from the system. This |
2398 | will make the user pay attention. | 2386 | will make the user pay attention. |
2399 | */ | 2387 | */ |
2400 | if (IS_CYC_Z(*info->card)) { | 2388 | if (cy_is_Z(info->card)) { |
2401 | struct cyclades_card *cinfo = info->card; | 2389 | struct cyclades_card *cinfo = info->card; |
2402 | struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; | 2390 | struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; |
2403 | 2391 | ||
2404 | if (!ISZLOADED(*cinfo)) { | 2392 | if (!cyz_is_loaded(cinfo)) { |
2405 | if (((ZE_V1 == readl(&((struct RUNTIME_9060 __iomem *) | 2393 | if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) && |
2406 | (cinfo->ctl_addr))->mail_box_0)) && | 2394 | readl(&firm_id->signature) == |
2407 | Z_FPGA_CHECK(*cinfo)) && | 2395 | ZFIRM_HLT) { |
2408 | (ZFIRM_HLT == readl( | ||
2409 | &firm_id->signature))) { | ||
2410 | printk(KERN_ERR "cyc:Cyclades-Z Error: you " | 2396 | printk(KERN_ERR "cyc:Cyclades-Z Error: you " |
2411 | "need an external power supply for " | 2397 | "need an external power supply for " |
2412 | "this number of ports.\nFirmware " | 2398 | "this number of ports.\nFirmware " |
@@ -2423,18 +2409,13 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2423 | interrupts should be enabled as soon as the first open | 2409 | interrupts should be enabled as soon as the first open |
2424 | happens to one of its ports. */ | 2410 | happens to one of its ports. */ |
2425 | if (!cinfo->intr_enabled) { | 2411 | if (!cinfo->intr_enabled) { |
2426 | struct ZFW_CTRL __iomem *zfw_ctrl; | 2412 | u16 intr; |
2427 | struct BOARD_CTRL __iomem *board_ctrl; | ||
2428 | |||
2429 | zfw_ctrl = cinfo->base_addr + | ||
2430 | (readl(&firm_id->zfwctrl_addr) & | ||
2431 | 0xfffff); | ||
2432 | |||
2433 | board_ctrl = &zfw_ctrl->board_ctrl; | ||
2434 | 2413 | ||
2435 | /* Enable interrupts on the PLX chip */ | 2414 | /* Enable interrupts on the PLX chip */ |
2436 | cy_writew(cinfo->ctl_addr + 0x68, | 2415 | intr = readw(&cinfo->ctl_addr.p9060-> |
2437 | readw(cinfo->ctl_addr + 0x68) | 0x0900); | 2416 | intr_ctrl_stat) | 0x0900; |
2417 | cy_writew(&cinfo->ctl_addr.p9060-> | ||
2418 | intr_ctrl_stat, intr); | ||
2438 | /* Enable interrupts on the FW */ | 2419 | /* Enable interrupts on the FW */ |
2439 | retval = cyz_issue_cmd(cinfo, 0, | 2420 | retval = cyz_issue_cmd(cinfo, 0, |
2440 | C_CM_IRQ_ENBL, 0L); | 2421 | C_CM_IRQ_ENBL, 0L); |
@@ -2442,8 +2423,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
2442 | printk(KERN_ERR "cyc:IRQ enable retval " | 2423 | printk(KERN_ERR "cyc:IRQ enable retval " |
2443 | "was %x\n", retval); | 2424 | "was %x\n", retval); |
2444 | } | 2425 | } |
2445 | cinfo->nports = | ||
2446 | (int)readl(&board_ctrl->n_channel); | ||
2447 | cinfo->intr_enabled = 1; | 2426 | cinfo->intr_enabled = 1; |
2448 | } | 2427 | } |
2449 | } | 2428 | } |
@@ -2556,7 +2535,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
2556 | #endif | 2535 | #endif |
2557 | card = info->card; | 2536 | card = info->card; |
2558 | channel = (info->line) - (card->first_line); | 2537 | channel = (info->line) - (card->first_line); |
2559 | if (!IS_CYC_Z(*card)) { | 2538 | if (!cy_is_Z(card)) { |
2560 | chip = channel >> 2; | 2539 | chip = channel >> 2; |
2561 | channel &= 0x03; | 2540 | channel &= 0x03; |
2562 | index = card->bus_index; | 2541 | index = card->bus_index; |
@@ -2601,7 +2580,7 @@ static void cy_flush_buffer(struct tty_struct *tty) | |||
2601 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 2580 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
2602 | spin_unlock_irqrestore(&card->card_lock, flags); | 2581 | spin_unlock_irqrestore(&card->card_lock, flags); |
2603 | 2582 | ||
2604 | if (IS_CYC_Z(*card)) { /* If it is a Z card, flush the on-board | 2583 | if (cy_is_Z(card)) { /* If it is a Z card, flush the on-board |
2605 | buffers as well */ | 2584 | buffers as well */ |
2606 | spin_lock_irqsave(&card->card_lock, flags); | 2585 | spin_lock_irqsave(&card->card_lock, flags); |
2607 | retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L); | 2586 | retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L); |
@@ -2682,7 +2661,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp) | |||
2682 | 2661 | ||
2683 | spin_lock_irqsave(&card->card_lock, flags); | 2662 | spin_lock_irqsave(&card->card_lock, flags); |
2684 | 2663 | ||
2685 | if (!IS_CYC_Z(*card)) { | 2664 | if (!cy_is_Z(card)) { |
2686 | int channel = info->line - card->first_line; | 2665 | int channel = info->line - card->first_line; |
2687 | int index = card->bus_index; | 2666 | int index = card->bus_index; |
2688 | void __iomem *base_addr = card->base_addr + | 2667 | void __iomem *base_addr = card->base_addr + |
@@ -2902,7 +2881,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty) | |||
2902 | channel = (info->line) - (card->first_line); | 2881 | channel = (info->line) - (card->first_line); |
2903 | 2882 | ||
2904 | #ifdef Z_EXT_CHARS_IN_BUFFER | 2883 | #ifdef Z_EXT_CHARS_IN_BUFFER |
2905 | if (!IS_CYC_Z(cy_card[card])) { | 2884 | if (!cy_is_Z(card)) { |
2906 | #endif /* Z_EXT_CHARS_IN_BUFFER */ | 2885 | #endif /* Z_EXT_CHARS_IN_BUFFER */ |
2907 | #ifdef CY_DEBUG_IO | 2886 | #ifdef CY_DEBUG_IO |
2908 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", | 2887 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", |
@@ -2984,7 +2963,6 @@ static void set_line_char(struct cyclades_port *info) | |||
2984 | void __iomem *base_addr; | 2963 | void __iomem *base_addr; |
2985 | int chip, channel, index; | 2964 | int chip, channel, index; |
2986 | unsigned cflag, iflag; | 2965 | unsigned cflag, iflag; |
2987 | unsigned short chip_number; | ||
2988 | int baud, baud_rate = 0; | 2966 | int baud, baud_rate = 0; |
2989 | int i; | 2967 | int i; |
2990 | 2968 | ||
@@ -3013,9 +2991,8 @@ static void set_line_char(struct cyclades_port *info) | |||
3013 | 2991 | ||
3014 | card = info->card; | 2992 | card = info->card; |
3015 | channel = info->line - card->first_line; | 2993 | channel = info->line - card->first_line; |
3016 | chip_number = channel / 4; | ||
3017 | 2994 | ||
3018 | if (!IS_CYC_Z(*card)) { | 2995 | if (!cy_is_Z(card)) { |
3019 | 2996 | ||
3020 | index = card->bus_index; | 2997 | index = card->bus_index; |
3021 | 2998 | ||
@@ -3233,21 +3210,17 @@ static void set_line_char(struct cyclades_port *info) | |||
3233 | } else { | 3210 | } else { |
3234 | struct FIRM_ID __iomem *firm_id; | 3211 | struct FIRM_ID __iomem *firm_id; |
3235 | struct ZFW_CTRL __iomem *zfw_ctrl; | 3212 | struct ZFW_CTRL __iomem *zfw_ctrl; |
3236 | struct BOARD_CTRL __iomem *board_ctrl; | ||
3237 | struct CH_CTRL __iomem *ch_ctrl; | 3213 | struct CH_CTRL __iomem *ch_ctrl; |
3238 | struct BUF_CTRL __iomem *buf_ctrl; | ||
3239 | __u32 sw_flow; | 3214 | __u32 sw_flow; |
3240 | int retval; | 3215 | int retval; |
3241 | 3216 | ||
3242 | firm_id = card->base_addr + ID_ADDRESS; | 3217 | firm_id = card->base_addr + ID_ADDRESS; |
3243 | if (!ISZLOADED(*card)) | 3218 | if (!cyz_is_loaded(card)) |
3244 | return; | 3219 | return; |
3245 | 3220 | ||
3246 | zfw_ctrl = card->base_addr + | 3221 | zfw_ctrl = card->base_addr + |
3247 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 3222 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
3248 | board_ctrl = &zfw_ctrl->board_ctrl; | ||
3249 | ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); | 3223 | ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); |
3250 | buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; | ||
3251 | 3224 | ||
3252 | /* baud rate */ | 3225 | /* baud rate */ |
3253 | baud = tty_get_baud_rate(info->port.tty); | 3226 | baud = tty_get_baud_rate(info->port.tty); |
@@ -3457,7 +3430,7 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) | |||
3457 | 3430 | ||
3458 | card = info->card; | 3431 | card = info->card; |
3459 | channel = (info->line) - (card->first_line); | 3432 | channel = (info->line) - (card->first_line); |
3460 | if (!IS_CYC_Z(*card)) { | 3433 | if (!cy_is_Z(card)) { |
3461 | chip = channel >> 2; | 3434 | chip = channel >> 2; |
3462 | channel &= 0x03; | 3435 | channel &= 0x03; |
3463 | index = card->bus_index; | 3436 | index = card->bus_index; |
@@ -3497,7 +3470,7 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
3497 | 3470 | ||
3498 | card = info->card; | 3471 | card = info->card; |
3499 | channel = info->line - card->first_line; | 3472 | channel = info->line - card->first_line; |
3500 | if (!IS_CYC_Z(*card)) { | 3473 | if (!cy_is_Z(card)) { |
3501 | chip = channel >> 2; | 3474 | chip = channel >> 2; |
3502 | channel &= 0x03; | 3475 | channel &= 0x03; |
3503 | index = card->bus_index; | 3476 | index = card->bus_index; |
@@ -3523,7 +3496,7 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
3523 | } else { | 3496 | } else { |
3524 | base_addr = card->base_addr; | 3497 | base_addr = card->base_addr; |
3525 | firm_id = card->base_addr + ID_ADDRESS; | 3498 | firm_id = card->base_addr + ID_ADDRESS; |
3526 | if (ISZLOADED(*card)) { | 3499 | if (cyz_is_loaded(card)) { |
3527 | zfw_ctrl = card->base_addr + | 3500 | zfw_ctrl = card->base_addr + |
3528 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 3501 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
3529 | board_ctrl = &zfw_ctrl->board_ctrl; | 3502 | board_ctrl = &zfw_ctrl->board_ctrl; |
@@ -3566,7 +3539,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
3566 | 3539 | ||
3567 | card = info->card; | 3540 | card = info->card; |
3568 | channel = (info->line) - (card->first_line); | 3541 | channel = (info->line) - (card->first_line); |
3569 | if (!IS_CYC_Z(*card)) { | 3542 | if (!cy_is_Z(card)) { |
3570 | chip = channel >> 2; | 3543 | chip = channel >> 2; |
3571 | channel &= 0x03; | 3544 | channel &= 0x03; |
3572 | index = card->bus_index; | 3545 | index = card->bus_index; |
@@ -3641,7 +3614,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
3641 | base_addr = card->base_addr; | 3614 | base_addr = card->base_addr; |
3642 | 3615 | ||
3643 | firm_id = card->base_addr + ID_ADDRESS; | 3616 | firm_id = card->base_addr + ID_ADDRESS; |
3644 | if (ISZLOADED(*card)) { | 3617 | if (cyz_is_loaded(card)) { |
3645 | zfw_ctrl = card->base_addr + | 3618 | zfw_ctrl = card->base_addr + |
3646 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 3619 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
3647 | board_ctrl = &zfw_ctrl->board_ctrl; | 3620 | board_ctrl = &zfw_ctrl->board_ctrl; |
@@ -3713,7 +3686,7 @@ static int cy_break(struct tty_struct *tty, int break_state) | |||
3713 | card = info->card; | 3686 | card = info->card; |
3714 | 3687 | ||
3715 | spin_lock_irqsave(&card->card_lock, flags); | 3688 | spin_lock_irqsave(&card->card_lock, flags); |
3716 | if (!IS_CYC_Z(*card)) { | 3689 | if (!cy_is_Z(card)) { |
3717 | /* Let the transmit ISR take care of this (since it | 3690 | /* Let the transmit ISR take care of this (since it |
3718 | requires stuffing characters into the output stream). | 3691 | requires stuffing characters into the output stream). |
3719 | */ | 3692 | */ |
@@ -3782,7 +3755,7 @@ static int set_threshold(struct cyclades_port *info, unsigned long value) | |||
3782 | 3755 | ||
3783 | card = info->card; | 3756 | card = info->card; |
3784 | channel = info->line - card->first_line; | 3757 | channel = info->line - card->first_line; |
3785 | if (!IS_CYC_Z(*card)) { | 3758 | if (!cy_is_Z(card)) { |
3786 | chip = channel >> 2; | 3759 | chip = channel >> 2; |
3787 | channel &= 0x03; | 3760 | channel &= 0x03; |
3788 | index = card->bus_index; | 3761 | index = card->bus_index; |
@@ -3810,7 +3783,7 @@ static int get_threshold(struct cyclades_port *info, | |||
3810 | 3783 | ||
3811 | card = info->card; | 3784 | card = info->card; |
3812 | channel = info->line - card->first_line; | 3785 | channel = info->line - card->first_line; |
3813 | if (!IS_CYC_Z(*card)) { | 3786 | if (!cy_is_Z(card)) { |
3814 | chip = channel >> 2; | 3787 | chip = channel >> 2; |
3815 | channel &= 0x03; | 3788 | channel &= 0x03; |
3816 | index = card->bus_index; | 3789 | index = card->bus_index; |
@@ -3844,7 +3817,7 @@ static int set_timeout(struct cyclades_port *info, unsigned long value) | |||
3844 | 3817 | ||
3845 | card = info->card; | 3818 | card = info->card; |
3846 | channel = info->line - card->first_line; | 3819 | channel = info->line - card->first_line; |
3847 | if (!IS_CYC_Z(*card)) { | 3820 | if (!cy_is_Z(card)) { |
3848 | chip = channel >> 2; | 3821 | chip = channel >> 2; |
3849 | channel &= 0x03; | 3822 | channel &= 0x03; |
3850 | index = card->bus_index; | 3823 | index = card->bus_index; |
@@ -3867,7 +3840,7 @@ static int get_timeout(struct cyclades_port *info, | |||
3867 | 3840 | ||
3868 | card = info->card; | 3841 | card = info->card; |
3869 | channel = info->line - card->first_line; | 3842 | channel = info->line - card->first_line; |
3870 | if (!IS_CYC_Z(*card)) { | 3843 | if (!cy_is_Z(card)) { |
3871 | chip = channel >> 2; | 3844 | chip = channel >> 2; |
3872 | channel &= 0x03; | 3845 | channel &= 0x03; |
3873 | index = card->bus_index; | 3846 | index = card->bus_index; |
@@ -4121,7 +4094,7 @@ static void cy_send_xchar(struct tty_struct *tty, char ch) | |||
4121 | card = info->card; | 4094 | card = info->card; |
4122 | channel = info->line - card->first_line; | 4095 | channel = info->line - card->first_line; |
4123 | 4096 | ||
4124 | if (IS_CYC_Z(*card)) { | 4097 | if (cy_is_Z(card)) { |
4125 | if (ch == STOP_CHAR(tty)) | 4098 | if (ch == STOP_CHAR(tty)) |
4126 | cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L); | 4099 | cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L); |
4127 | else if (ch == START_CHAR(tty)) | 4100 | else if (ch == START_CHAR(tty)) |
@@ -4154,7 +4127,7 @@ static void cy_throttle(struct tty_struct *tty) | |||
4154 | card = info->card; | 4127 | card = info->card; |
4155 | 4128 | ||
4156 | if (I_IXOFF(tty)) { | 4129 | if (I_IXOFF(tty)) { |
4157 | if (!IS_CYC_Z(*card)) | 4130 | if (!cy_is_Z(card)) |
4158 | cy_send_xchar(tty, STOP_CHAR(tty)); | 4131 | cy_send_xchar(tty, STOP_CHAR(tty)); |
4159 | else | 4132 | else |
4160 | info->throttle = 1; | 4133 | info->throttle = 1; |
@@ -4162,7 +4135,7 @@ static void cy_throttle(struct tty_struct *tty) | |||
4162 | 4135 | ||
4163 | if (tty->termios->c_cflag & CRTSCTS) { | 4136 | if (tty->termios->c_cflag & CRTSCTS) { |
4164 | channel = info->line - card->first_line; | 4137 | channel = info->line - card->first_line; |
4165 | if (!IS_CYC_Z(*card)) { | 4138 | if (!cy_is_Z(card)) { |
4166 | chip = channel >> 2; | 4139 | chip = channel >> 2; |
4167 | channel &= 0x03; | 4140 | channel &= 0x03; |
4168 | index = card->bus_index; | 4141 | index = card->bus_index; |
@@ -4219,7 +4192,7 @@ static void cy_unthrottle(struct tty_struct *tty) | |||
4219 | if (tty->termios->c_cflag & CRTSCTS) { | 4192 | if (tty->termios->c_cflag & CRTSCTS) { |
4220 | card = info->card; | 4193 | card = info->card; |
4221 | channel = info->line - card->first_line; | 4194 | channel = info->line - card->first_line; |
4222 | if (!IS_CYC_Z(*card)) { | 4195 | if (!cy_is_Z(card)) { |
4223 | chip = channel >> 2; | 4196 | chip = channel >> 2; |
4224 | channel &= 0x03; | 4197 | channel &= 0x03; |
4225 | index = card->bus_index; | 4198 | index = card->bus_index; |
@@ -4263,7 +4236,7 @@ static void cy_stop(struct tty_struct *tty) | |||
4263 | 4236 | ||
4264 | cinfo = info->card; | 4237 | cinfo = info->card; |
4265 | channel = info->line - cinfo->first_line; | 4238 | channel = info->line - cinfo->first_line; |
4266 | if (!IS_CYC_Z(*cinfo)) { | 4239 | if (!cy_is_Z(cinfo)) { |
4267 | index = cinfo->bus_index; | 4240 | index = cinfo->bus_index; |
4268 | chip = channel >> 2; | 4241 | chip = channel >> 2; |
4269 | channel &= 0x03; | 4242 | channel &= 0x03; |
@@ -4296,7 +4269,7 @@ static void cy_start(struct tty_struct *tty) | |||
4296 | cinfo = info->card; | 4269 | cinfo = info->card; |
4297 | channel = info->line - cinfo->first_line; | 4270 | channel = info->line - cinfo->first_line; |
4298 | index = cinfo->bus_index; | 4271 | index = cinfo->bus_index; |
4299 | if (!IS_CYC_Z(*cinfo)) { | 4272 | if (!cy_is_Z(cinfo)) { |
4300 | chip = channel >> 2; | 4273 | chip = channel >> 2; |
4301 | channel &= 0x03; | 4274 | channel &= 0x03; |
4302 | base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); | 4275 | base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); |
@@ -4347,33 +4320,20 @@ static void cy_hangup(struct tty_struct *tty) | |||
4347 | static int __devinit cy_init_card(struct cyclades_card *cinfo) | 4320 | static int __devinit cy_init_card(struct cyclades_card *cinfo) |
4348 | { | 4321 | { |
4349 | struct cyclades_port *info; | 4322 | struct cyclades_port *info; |
4350 | u32 uninitialized_var(mailbox); | 4323 | unsigned int port; |
4351 | unsigned int nports, port; | ||
4352 | unsigned short chip_number; | 4324 | unsigned short chip_number; |
4353 | int uninitialized_var(index); | ||
4354 | 4325 | ||
4355 | spin_lock_init(&cinfo->card_lock); | 4326 | spin_lock_init(&cinfo->card_lock); |
4327 | cinfo->intr_enabled = 0; | ||
4356 | 4328 | ||
4357 | if (IS_CYC_Z(*cinfo)) { /* Cyclades-Z */ | 4329 | cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports), |
4358 | mailbox = readl(&((struct RUNTIME_9060 __iomem *) | 4330 | GFP_KERNEL); |
4359 | cinfo->ctl_addr)->mail_box_0); | ||
4360 | nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; | ||
4361 | cinfo->intr_enabled = 0; | ||
4362 | cinfo->nports = 0; /* Will be correctly set later, after | ||
4363 | Z FW is loaded */ | ||
4364 | } else { | ||
4365 | index = cinfo->bus_index; | ||
4366 | nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; | ||
4367 | } | ||
4368 | |||
4369 | cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL); | ||
4370 | if (cinfo->ports == NULL) { | 4331 | if (cinfo->ports == NULL) { |
4371 | printk(KERN_ERR "Cyclades: cannot allocate ports\n"); | 4332 | printk(KERN_ERR "Cyclades: cannot allocate ports\n"); |
4372 | cinfo->nports = 0; | ||
4373 | return -ENOMEM; | 4333 | return -ENOMEM; |
4374 | } | 4334 | } |
4375 | 4335 | ||
4376 | for (port = cinfo->first_line; port < cinfo->first_line + nports; | 4336 | for (port = cinfo->first_line; port < cinfo->first_line + cinfo->nports; |
4377 | port++) { | 4337 | port++) { |
4378 | info = &cinfo->ports[port - cinfo->first_line]; | 4338 | info = &cinfo->ports[port - cinfo->first_line]; |
4379 | tty_port_init(&info->port); | 4339 | tty_port_init(&info->port); |
@@ -4387,9 +4347,9 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) | |||
4387 | init_completion(&info->shutdown_wait); | 4347 | init_completion(&info->shutdown_wait); |
4388 | init_waitqueue_head(&info->delta_msr_wait); | 4348 | init_waitqueue_head(&info->delta_msr_wait); |
4389 | 4349 | ||
4390 | if (IS_CYC_Z(*cinfo)) { | 4350 | if (cy_is_Z(cinfo)) { |
4391 | info->type = PORT_STARTECH; | 4351 | info->type = PORT_STARTECH; |
4392 | if (mailbox == ZO_V1) | 4352 | if (cinfo->hw_ver == ZO_V1) |
4393 | info->xmit_fifo_size = CYZ_FIFO_SIZE; | 4353 | info->xmit_fifo_size = CYZ_FIFO_SIZE; |
4394 | else | 4354 | else |
4395 | info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; | 4355 | info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; |
@@ -4398,6 +4358,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) | |||
4398 | cyz_rx_restart, (unsigned long)info); | 4358 | cyz_rx_restart, (unsigned long)info); |
4399 | #endif | 4359 | #endif |
4400 | } else { | 4360 | } else { |
4361 | int index = cinfo->bus_index; | ||
4401 | info->type = PORT_CIRRUS; | 4362 | info->type = PORT_CIRRUS; |
4402 | info->xmit_fifo_size = CyMAX_CHAR_FIFO; | 4363 | info->xmit_fifo_size = CyMAX_CHAR_FIFO; |
4403 | info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; | 4364 | info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; |
@@ -4430,7 +4391,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) | |||
4430 | } | 4391 | } |
4431 | 4392 | ||
4432 | #ifndef CONFIG_CYZ_INTR | 4393 | #ifndef CONFIG_CYZ_INTR |
4433 | if (IS_CYC_Z(*cinfo) && !timer_pending(&cyz_timerlist)) { | 4394 | if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) { |
4434 | mod_timer(&cyz_timerlist, jiffies + 1); | 4395 | mod_timer(&cyz_timerlist, jiffies + 1); |
4435 | #ifdef CY_PCI_DEBUG | 4396 | #ifdef CY_PCI_DEBUG |
4436 | printk(KERN_DEBUG "Cyclades-Z polling initialized\n"); | 4397 | printk(KERN_DEBUG "Cyclades-Z polling initialized\n"); |
@@ -4621,11 +4582,12 @@ static int __init cy_detect_isa(void) | |||
4621 | 4582 | ||
4622 | /* set cy_card */ | 4583 | /* set cy_card */ |
4623 | cy_card[j].base_addr = cy_isa_address; | 4584 | cy_card[j].base_addr = cy_isa_address; |
4624 | cy_card[j].ctl_addr = NULL; | 4585 | cy_card[j].ctl_addr.p9050 = NULL; |
4625 | cy_card[j].irq = (int)cy_isa_irq; | 4586 | cy_card[j].irq = (int)cy_isa_irq; |
4626 | cy_card[j].bus_index = 0; | 4587 | cy_card[j].bus_index = 0; |
4627 | cy_card[j].first_line = cy_next_channel; | 4588 | cy_card[j].first_line = cy_next_channel; |
4628 | cy_card[j].num_chips = cy_isa_nchan / 4; | 4589 | cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP; |
4590 | cy_card[j].nports = cy_isa_nchan; | ||
4629 | if (cy_init_card(&cy_card[j])) { | 4591 | if (cy_init_card(&cy_card[j])) { |
4630 | cy_card[j].base_addr = NULL; | 4592 | cy_card[j].base_addr = NULL; |
4631 | free_irq(cy_isa_irq, &cy_card[j]); | 4593 | free_irq(cy_isa_irq, &cy_card[j]); |
@@ -4781,7 +4743,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
4781 | struct CUSTOM_REG __iomem *cust = base_addr; | 4743 | struct CUSTOM_REG __iomem *cust = base_addr; |
4782 | struct ZFW_CTRL __iomem *pt_zfwctrl; | 4744 | struct ZFW_CTRL __iomem *pt_zfwctrl; |
4783 | void __iomem *tmp; | 4745 | void __iomem *tmp; |
4784 | u32 mailbox, status; | 4746 | u32 mailbox, status, nchan; |
4785 | unsigned int i; | 4747 | unsigned int i; |
4786 | int retval; | 4748 | int retval; |
4787 | 4749 | ||
@@ -4793,7 +4755,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
4793 | 4755 | ||
4794 | /* Check whether the firmware is already loaded and running. If | 4756 | /* Check whether the firmware is already loaded and running. If |
4795 | positive, skip this board */ | 4757 | positive, skip this board */ |
4796 | if (Z_FPGA_LOADED(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) { | 4758 | if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) { |
4797 | u32 cntval = readl(base_addr + 0x190); | 4759 | u32 cntval = readl(base_addr + 0x190); |
4798 | 4760 | ||
4799 | udelay(100); | 4761 | udelay(100); |
@@ -4812,7 +4774,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
4812 | 4774 | ||
4813 | mailbox = readl(&ctl_addr->mail_box_0); | 4775 | mailbox = readl(&ctl_addr->mail_box_0); |
4814 | 4776 | ||
4815 | if (mailbox == 0 || Z_FPGA_LOADED(ctl_addr)) { | 4777 | if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) { |
4816 | /* stops CPU and set window to beginning of RAM */ | 4778 | /* stops CPU and set window to beginning of RAM */ |
4817 | cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); | 4779 | cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); |
4818 | cy_writel(&cust->cpu_stop, 0); | 4780 | cy_writel(&cust->cpu_stop, 0); |
@@ -4828,7 +4790,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
4828 | base_addr); | 4790 | base_addr); |
4829 | if (retval) | 4791 | if (retval) |
4830 | goto err_rel; | 4792 | goto err_rel; |
4831 | if (!Z_FPGA_LOADED(ctl_addr)) { | 4793 | if (!__cyz_fpga_loaded(ctl_addr)) { |
4832 | dev_err(&pdev->dev, "fw upload successful, but fw is " | 4794 | dev_err(&pdev->dev, "fw upload successful, but fw is " |
4833 | "not loaded\n"); | 4795 | "not loaded\n"); |
4834 | goto err_rel; | 4796 | goto err_rel; |
@@ -4887,7 +4849,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
4887 | "system before loading the new FW to the " | 4849 | "system before loading the new FW to the " |
4888 | "Cyclades-Z.\n"); | 4850 | "Cyclades-Z.\n"); |
4889 | 4851 | ||
4890 | if (Z_FPGA_LOADED(ctl_addr)) | 4852 | if (__cyz_fpga_loaded(ctl_addr)) |
4891 | plx_init(pdev, irq, ctl_addr); | 4853 | plx_init(pdev, irq, ctl_addr); |
4892 | 4854 | ||
4893 | retval = -EIO; | 4855 | retval = -EIO; |
@@ -4902,16 +4864,16 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
4902 | base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr), | 4864 | base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr), |
4903 | base_addr + readl(&fid->zfwctrl_addr)); | 4865 | base_addr + readl(&fid->zfwctrl_addr)); |
4904 | 4866 | ||
4867 | nchan = readl(&pt_zfwctrl->board_ctrl.n_channel); | ||
4905 | dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n", | 4868 | dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n", |
4906 | readl(&pt_zfwctrl->board_ctrl.fw_version), | 4869 | readl(&pt_zfwctrl->board_ctrl.fw_version), nchan); |
4907 | readl(&pt_zfwctrl->board_ctrl.n_channel)); | ||
4908 | 4870 | ||
4909 | if (readl(&pt_zfwctrl->board_ctrl.n_channel) == 0) { | 4871 | if (nchan == 0) { |
4910 | dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please " | 4872 | dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please " |
4911 | "check the connection between the Z host card and the " | 4873 | "check the connection between the Z host card and the " |
4912 | "serial expanders.\n"); | 4874 | "serial expanders.\n"); |
4913 | 4875 | ||
4914 | if (Z_FPGA_LOADED(ctl_addr)) | 4876 | if (__cyz_fpga_loaded(ctl_addr)) |
4915 | plx_init(pdev, irq, ctl_addr); | 4877 | plx_init(pdev, irq, ctl_addr); |
4916 | 4878 | ||
4917 | dev_info(&pdev->dev, "Null number of ports detected. Board " | 4879 | dev_info(&pdev->dev, "Null number of ports detected. Board " |
@@ -4932,9 +4894,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
4932 | cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | | 4894 | cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | |
4933 | 0x00030800UL); | 4895 | 0x00030800UL); |
4934 | 4896 | ||
4935 | plx_init(pdev, irq, ctl_addr); | 4897 | return nchan; |
4936 | |||
4937 | return 0; | ||
4938 | err_rel: | 4898 | err_rel: |
4939 | release_firmware(fw); | 4899 | release_firmware(fw); |
4940 | err: | 4900 | err: |
@@ -4946,7 +4906,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
4946 | { | 4906 | { |
4947 | void __iomem *addr0 = NULL, *addr2 = NULL; | 4907 | void __iomem *addr0 = NULL, *addr2 = NULL; |
4948 | char *card_name = NULL; | 4908 | char *card_name = NULL; |
4949 | u32 mailbox; | 4909 | u32 uninitialized_var(mailbox); |
4950 | unsigned int device_id, nchan = 0, card_no, i; | 4910 | unsigned int device_id, nchan = 0, card_no, i; |
4951 | unsigned char plx_ver; | 4911 | unsigned char plx_ver; |
4952 | int retval, irq; | 4912 | int retval, irq; |
@@ -5023,11 +4983,12 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
5023 | } | 4983 | } |
5024 | 4984 | ||
5025 | /* Disable interrupts on the PLX before resetting it */ | 4985 | /* Disable interrupts on the PLX before resetting it */ |
5026 | cy_writew(addr0 + 0x68, readw(addr0 + 0x68) & ~0x0900); | 4986 | cy_writew(&ctl_addr->intr_ctrl_stat, |
4987 | readw(&ctl_addr->intr_ctrl_stat) & ~0x0900); | ||
5027 | 4988 | ||
5028 | plx_init(pdev, irq, addr0); | 4989 | plx_init(pdev, irq, addr0); |
5029 | 4990 | ||
5030 | mailbox = (u32)readl(&ctl_addr->mail_box_0); | 4991 | mailbox = readl(&ctl_addr->mail_box_0); |
5031 | 4992 | ||
5032 | addr2 = ioremap_nocache(pci_resource_start(pdev, 2), | 4993 | addr2 = ioremap_nocache(pci_resource_start(pdev, 2), |
5033 | mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin); | 4994 | mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin); |
@@ -5038,12 +4999,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
5038 | 4999 | ||
5039 | if (mailbox == ZE_V1) { | 5000 | if (mailbox == ZE_V1) { |
5040 | card_name = "Cyclades-Ze"; | 5001 | card_name = "Cyclades-Ze"; |
5041 | |||
5042 | readl(&ctl_addr->mail_box_0); | ||
5043 | nchan = ZE_V1_NPORTS; | ||
5044 | } else { | 5002 | } else { |
5045 | card_name = "Cyclades-8Zo"; | 5003 | card_name = "Cyclades-8Zo"; |
5046 | |||
5047 | #ifdef CY_PCI_DEBUG | 5004 | #ifdef CY_PCI_DEBUG |
5048 | if (mailbox == ZO_V1) { | 5005 | if (mailbox == ZO_V1) { |
5049 | cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); | 5006 | cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); |
@@ -5065,15 +5022,12 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
5065 | */ | 5022 | */ |
5066 | if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) | 5023 | if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) |
5067 | cy_writel(addr2 + ID_ADDRESS, 0L); | 5024 | cy_writel(addr2 + ID_ADDRESS, 0L); |
5068 | |||
5069 | retval = cyz_load_fw(pdev, addr2, addr0, irq); | ||
5070 | if (retval) | ||
5071 | goto err_unmap; | ||
5072 | /* This must be a Cyclades-8Zo/PCI. The extendable | ||
5073 | version will have a different device_id and will | ||
5074 | be allocated its maximum number of ports. */ | ||
5075 | nchan = 8; | ||
5076 | } | 5025 | } |
5026 | |||
5027 | retval = cyz_load_fw(pdev, addr2, addr0, irq); | ||
5028 | if (retval <= 0) | ||
5029 | goto err_unmap; | ||
5030 | nchan = retval; | ||
5077 | } | 5031 | } |
5078 | 5032 | ||
5079 | if ((cy_next_channel + nchan) > NR_PORTS) { | 5033 | if ((cy_next_channel + nchan) > NR_PORTS) { |
@@ -5103,8 +5057,10 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
5103 | dev_err(&pdev->dev, "could not allocate IRQ\n"); | 5057 | dev_err(&pdev->dev, "could not allocate IRQ\n"); |
5104 | goto err_unmap; | 5058 | goto err_unmap; |
5105 | } | 5059 | } |
5106 | cy_card[card_no].num_chips = nchan / 4; | 5060 | cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP; |
5107 | } else { | 5061 | } else { |
5062 | cy_card[card_no].hw_ver = mailbox; | ||
5063 | cy_card[card_no].num_chips = (unsigned int)-1; | ||
5108 | #ifdef CONFIG_CYZ_INTR | 5064 | #ifdef CONFIG_CYZ_INTR |
5109 | /* allocate IRQ only if board has an IRQ */ | 5065 | /* allocate IRQ only if board has an IRQ */ |
5110 | if (irq != 0 && irq != 255) { | 5066 | if (irq != 0 && irq != 255) { |
@@ -5117,15 +5073,15 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
5117 | } | 5073 | } |
5118 | } | 5074 | } |
5119 | #endif /* CONFIG_CYZ_INTR */ | 5075 | #endif /* CONFIG_CYZ_INTR */ |
5120 | cy_card[card_no].num_chips = (unsigned int)-1; | ||
5121 | } | 5076 | } |
5122 | 5077 | ||
5123 | /* set cy_card */ | 5078 | /* set cy_card */ |
5124 | cy_card[card_no].base_addr = addr2; | 5079 | cy_card[card_no].base_addr = addr2; |
5125 | cy_card[card_no].ctl_addr = addr0; | 5080 | cy_card[card_no].ctl_addr.p9050 = addr0; |
5126 | cy_card[card_no].irq = irq; | 5081 | cy_card[card_no].irq = irq; |
5127 | cy_card[card_no].bus_index = 1; | 5082 | cy_card[card_no].bus_index = 1; |
5128 | cy_card[card_no].first_line = cy_next_channel; | 5083 | cy_card[card_no].first_line = cy_next_channel; |
5084 | cy_card[card_no].nports = nchan; | ||
5129 | retval = cy_init_card(&cy_card[card_no]); | 5085 | retval = cy_init_card(&cy_card[card_no]); |
5130 | if (retval) | 5086 | if (retval) |
5131 | goto err_null; | 5087 | goto err_null; |
@@ -5138,17 +5094,20 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
5138 | plx_ver = readb(addr2 + CyPLX_VER) & 0x0f; | 5094 | plx_ver = readb(addr2 + CyPLX_VER) & 0x0f; |
5139 | switch (plx_ver) { | 5095 | switch (plx_ver) { |
5140 | case PLX_9050: | 5096 | case PLX_9050: |
5141 | |||
5142 | cy_writeb(addr0 + 0x4c, 0x43); | 5097 | cy_writeb(addr0 + 0x4c, 0x43); |
5143 | break; | 5098 | break; |
5144 | 5099 | ||
5145 | case PLX_9060: | 5100 | case PLX_9060: |
5146 | case PLX_9080: | 5101 | case PLX_9080: |
5147 | default: /* Old boards, use PLX_9060 */ | 5102 | default: /* Old boards, use PLX_9060 */ |
5148 | plx_init(pdev, irq, addr0); | 5103 | { |
5149 | cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900); | 5104 | struct RUNTIME_9060 __iomem *ctl_addr = addr0; |
5105 | plx_init(pdev, irq, ctl_addr); | ||
5106 | cy_writew(&ctl_addr->intr_ctrl_stat, | ||
5107 | readw(&ctl_addr->intr_ctrl_stat) | 0x0900); | ||
5150 | break; | 5108 | break; |
5151 | } | 5109 | } |
5110 | } | ||
5152 | } | 5111 | } |
5153 | 5112 | ||
5154 | dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from " | 5113 | dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from " |
@@ -5179,22 +5138,23 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev) | |||
5179 | unsigned int i; | 5138 | unsigned int i; |
5180 | 5139 | ||
5181 | /* non-Z with old PLX */ | 5140 | /* non-Z with old PLX */ |
5182 | if (!IS_CYC_Z(*cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == | 5141 | if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == |
5183 | PLX_9050) | 5142 | PLX_9050) |
5184 | cy_writeb(cinfo->ctl_addr + 0x4c, 0); | 5143 | cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0); |
5185 | else | 5144 | else |
5186 | #ifndef CONFIG_CYZ_INTR | 5145 | #ifndef CONFIG_CYZ_INTR |
5187 | if (!IS_CYC_Z(*cinfo)) | 5146 | if (!cy_is_Z(cinfo)) |
5188 | #endif | 5147 | #endif |
5189 | cy_writew(cinfo->ctl_addr + 0x68, | 5148 | cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat, |
5190 | readw(cinfo->ctl_addr + 0x68) & ~0x0900); | 5149 | readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) & |
5150 | ~0x0900); | ||
5191 | 5151 | ||
5192 | iounmap(cinfo->base_addr); | 5152 | iounmap(cinfo->base_addr); |
5193 | if (cinfo->ctl_addr) | 5153 | if (cinfo->ctl_addr.p9050) |
5194 | iounmap(cinfo->ctl_addr); | 5154 | iounmap(cinfo->ctl_addr.p9050); |
5195 | if (cinfo->irq | 5155 | if (cinfo->irq |
5196 | #ifndef CONFIG_CYZ_INTR | 5156 | #ifndef CONFIG_CYZ_INTR |
5197 | && !IS_CYC_Z(*cinfo) | 5157 | && !cy_is_Z(cinfo) |
5198 | #endif /* CONFIG_CYZ_INTR */ | 5158 | #endif /* CONFIG_CYZ_INTR */ |
5199 | ) | 5159 | ) |
5200 | free_irq(cinfo->irq, cinfo); | 5160 | free_irq(cinfo->irq, cinfo); |
@@ -5240,7 +5200,7 @@ static int cyclades_proc_show(struct seq_file *m, void *v) | |||
5240 | (cur_jifs - info->idle_stats.recv_idle)/ | 5200 | (cur_jifs - info->idle_stats.recv_idle)/ |
5241 | HZ, info->idle_stats.overruns, | 5201 | HZ, info->idle_stats.overruns, |
5242 | /* FIXME: double check locking */ | 5202 | /* FIXME: double check locking */ |
5243 | (long)info->port.tty->ldisc.ops->num); | 5203 | (long)info->port.tty->ldisc->ops->num); |
5244 | else | 5204 | else |
5245 | seq_printf(m, "%3d %8lu %10lu %8lu " | 5205 | seq_printf(m, "%3d %8lu %10lu %8lu " |
5246 | "%10lu %8lu %9lu %6ld\n", | 5206 | "%10lu %8lu %9lu %6ld\n", |
@@ -5386,11 +5346,11 @@ static void __exit cy_cleanup_module(void) | |||
5386 | /* clear interrupt */ | 5346 | /* clear interrupt */ |
5387 | cy_writeb(card->base_addr + Cy_ClrIntr, 0); | 5347 | cy_writeb(card->base_addr + Cy_ClrIntr, 0); |
5388 | iounmap(card->base_addr); | 5348 | iounmap(card->base_addr); |
5389 | if (card->ctl_addr) | 5349 | if (card->ctl_addr.p9050) |
5390 | iounmap(card->ctl_addr); | 5350 | iounmap(card->ctl_addr.p9050); |
5391 | if (card->irq | 5351 | if (card->irq |
5392 | #ifndef CONFIG_CYZ_INTR | 5352 | #ifndef CONFIG_CYZ_INTR |
5393 | && !IS_CYC_Z(*card) | 5353 | && !cy_is_Z(card) |
5394 | #endif /* CONFIG_CYZ_INTR */ | 5354 | #endif /* CONFIG_CYZ_INTR */ |
5395 | ) | 5355 | ) |
5396 | free_irq(card->irq, card); | 5356 | free_irq(card->irq, card); |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index af7c13ca9493..abef1f7d84fe 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -745,7 +745,7 @@ static int epca_carrier_raised(struct tty_port *port) | |||
745 | return 0; | 745 | return 0; |
746 | } | 746 | } |
747 | 747 | ||
748 | static void epca_raise_dtr_rts(struct tty_port *port) | 748 | static void epca_dtr_rts(struct tty_port *port, int onoff) |
749 | { | 749 | { |
750 | } | 750 | } |
751 | 751 | ||
@@ -925,7 +925,7 @@ static const struct tty_operations pc_ops = { | |||
925 | 925 | ||
926 | static const struct tty_port_operations epca_port_ops = { | 926 | static const struct tty_port_operations epca_port_ops = { |
927 | .carrier_raised = epca_carrier_raised, | 927 | .carrier_raised = epca_carrier_raised, |
928 | .raise_dtr_rts = epca_raise_dtr_rts, | 928 | .dtr_rts = epca_dtr_rts, |
929 | }; | 929 | }; |
930 | 930 | ||
931 | static int info_open(struct tty_struct *tty, struct file *filp) | 931 | static int info_open(struct tty_struct *tty, struct file *filp) |
@@ -1518,7 +1518,7 @@ static void doevent(int crd) | |||
1518 | if (event & MODEMCHG_IND) { | 1518 | if (event & MODEMCHG_IND) { |
1519 | /* A modem signal change has been indicated */ | 1519 | /* A modem signal change has been indicated */ |
1520 | ch->imodem = mstat; | 1520 | ch->imodem = mstat; |
1521 | if (test_bit(ASYNC_CHECK_CD, &ch->port.flags)) { | 1521 | if (test_bit(ASYNCB_CHECK_CD, &ch->port.flags)) { |
1522 | /* We are now receiving dcd */ | 1522 | /* We are now receiving dcd */ |
1523 | if (mstat & ch->dcd) | 1523 | if (mstat & ch->dcd) |
1524 | wake_up_interruptible(&ch->port.open_wait); | 1524 | wake_up_interruptible(&ch->port.open_wait); |
@@ -1765,9 +1765,9 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) | |||
1765 | * that the driver will wait on carrier detect. | 1765 | * that the driver will wait on carrier detect. |
1766 | */ | 1766 | */ |
1767 | if (ts->c_cflag & CLOCAL) | 1767 | if (ts->c_cflag & CLOCAL) |
1768 | clear_bit(ASYNC_CHECK_CD, &ch->port.flags); | 1768 | clear_bit(ASYNCB_CHECK_CD, &ch->port.flags); |
1769 | else | 1769 | else |
1770 | set_bit(ASYNC_CHECK_CD, &ch->port.flags); | 1770 | set_bit(ASYNCB_CHECK_CD, &ch->port.flags); |
1771 | mval = ch->m_dtr | ch->m_rts; | 1771 | mval = ch->m_dtr | ch->m_rts; |
1772 | } /* End CBAUD not detected */ | 1772 | } /* End CBAUD not detected */ |
1773 | iflag = termios2digi_i(ch, ts->c_iflag); | 1773 | iflag = termios2digi_i(ch, ts->c_iflag); |
@@ -2114,8 +2114,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
2114 | tty_wait_until_sent(tty, 0); | 2114 | tty_wait_until_sent(tty, 0); |
2115 | } else { | 2115 | } else { |
2116 | /* ldisc lock already held in ioctl */ | 2116 | /* ldisc lock already held in ioctl */ |
2117 | if (tty->ldisc.ops->flush_buffer) | 2117 | if (tty->ldisc->ops->flush_buffer) |
2118 | tty->ldisc.ops->flush_buffer(tty); | 2118 | tty->ldisc->ops->flush_buffer(tty); |
2119 | } | 2119 | } |
2120 | unlock_kernel(); | 2120 | unlock_kernel(); |
2121 | /* Fall Thru */ | 2121 | /* Fall Thru */ |
@@ -2244,7 +2244,8 @@ static void do_softint(struct work_struct *work) | |||
2244 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { | 2244 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { |
2245 | tty_hangup(tty); | 2245 | tty_hangup(tty); |
2246 | wake_up_interruptible(&ch->port.open_wait); | 2246 | wake_up_interruptible(&ch->port.open_wait); |
2247 | clear_bit(ASYNC_NORMAL_ACTIVE, &ch->port.flags); | 2247 | clear_bit(ASYNCB_NORMAL_ACTIVE, |
2248 | &ch->port.flags); | ||
2248 | } | 2249 | } |
2249 | } | 2250 | } |
2250 | tty_kref_put(tty); | 2251 | tty_kref_put(tty); |
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c index 0061e18aff60..0d10b89218ed 100644 --- a/drivers/char/ip2/i2lib.c +++ b/drivers/char/ip2/i2lib.c | |||
@@ -868,11 +868,11 @@ i2Input(i2ChanStrPtr pCh) | |||
868 | amountToMove = count; | 868 | amountToMove = count; |
869 | } | 869 | } |
870 | // Move the first block | 870 | // Move the first block |
871 | pCh->pTTY->ldisc.ops->receive_buf( pCh->pTTY, | 871 | pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, |
872 | &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); | 872 | &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); |
873 | // If we needed to wrap, do the second data move | 873 | // If we needed to wrap, do the second data move |
874 | if (count > amountToMove) { | 874 | if (count > amountToMove) { |
875 | pCh->pTTY->ldisc.ops->receive_buf( pCh->pTTY, | 875 | pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, |
876 | pCh->Ibuf, NULL, count - amountToMove ); | 876 | pCh->Ibuf, NULL, count - amountToMove ); |
877 | } | 877 | } |
878 | // Bump and wrap the stripIndex all at once by the amount of data read. This | 878 | // Bump and wrap the stripIndex all at once by the amount of data read. This |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index afd9247cf082..517271c762e6 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -1315,8 +1315,8 @@ static inline void isig(int sig, struct tty_struct *tty, int flush) | |||
1315 | if (tty->pgrp) | 1315 | if (tty->pgrp) |
1316 | kill_pgrp(tty->pgrp, sig, 1); | 1316 | kill_pgrp(tty->pgrp, sig, 1); |
1317 | if (flush || !L_NOFLSH(tty)) { | 1317 | if (flush || !L_NOFLSH(tty)) { |
1318 | if ( tty->ldisc.ops->flush_buffer ) | 1318 | if ( tty->ldisc->ops->flush_buffer ) |
1319 | tty->ldisc.ops->flush_buffer(tty); | 1319 | tty->ldisc->ops->flush_buffer(tty); |
1320 | i2InputFlush( tty->driver_data ); | 1320 | i2InputFlush( tty->driver_data ); |
1321 | } | 1321 | } |
1322 | } | 1322 | } |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index a59eac584d16..4d745a89504f 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -329,7 +329,7 @@ static inline void drop_rts(struct isi_port *port) | |||
329 | 329 | ||
330 | /* card->lock MUST NOT be held */ | 330 | /* card->lock MUST NOT be held */ |
331 | 331 | ||
332 | static void isicom_raise_dtr_rts(struct tty_port *port) | 332 | static void isicom_dtr_rts(struct tty_port *port, int on) |
333 | { | 333 | { |
334 | struct isi_port *ip = container_of(port, struct isi_port, port); | 334 | struct isi_port *ip = container_of(port, struct isi_port, port); |
335 | struct isi_board *card = ip->card; | 335 | struct isi_board *card = ip->card; |
@@ -339,10 +339,17 @@ static void isicom_raise_dtr_rts(struct tty_port *port) | |||
339 | if (!lock_card(card)) | 339 | if (!lock_card(card)) |
340 | return; | 340 | return; |
341 | 341 | ||
342 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | 342 | if (on) { |
343 | outw(0x0f04, base); | 343 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); |
344 | InterruptTheCard(base); | 344 | outw(0x0f04, base); |
345 | ip->status |= (ISI_DTR | ISI_RTS); | 345 | InterruptTheCard(base); |
346 | ip->status |= (ISI_DTR | ISI_RTS); | ||
347 | } else { | ||
348 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | ||
349 | outw(0x0C04, base); | ||
350 | InterruptTheCard(base); | ||
351 | ip->status &= ~(ISI_DTR | ISI_RTS); | ||
352 | } | ||
346 | unlock_card(card); | 353 | unlock_card(card); |
347 | } | 354 | } |
348 | 355 | ||
@@ -1339,7 +1346,7 @@ static const struct tty_operations isicom_ops = { | |||
1339 | 1346 | ||
1340 | static const struct tty_port_operations isicom_port_ops = { | 1347 | static const struct tty_port_operations isicom_port_ops = { |
1341 | .carrier_raised = isicom_carrier_raised, | 1348 | .carrier_raised = isicom_carrier_raised, |
1342 | .raise_dtr_rts = isicom_raise_dtr_rts, | 1349 | .dtr_rts = isicom_dtr_rts, |
1343 | }; | 1350 | }; |
1344 | 1351 | ||
1345 | static int __devinit reset_card(struct pci_dev *pdev, | 1352 | static int __devinit reset_card(struct pci_dev *pdev, |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index fff19f7e29d2..e18800c400b1 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -1140,14 +1140,14 @@ static int stli_carrier_raised(struct tty_port *port) | |||
1140 | return (portp->sigs & TIOCM_CD) ? 1 : 0; | 1140 | return (portp->sigs & TIOCM_CD) ? 1 : 0; |
1141 | } | 1141 | } |
1142 | 1142 | ||
1143 | static void stli_raise_dtr_rts(struct tty_port *port) | 1143 | static void stli_dtr_rts(struct tty_port *port, int on) |
1144 | { | 1144 | { |
1145 | struct stliport *portp = container_of(port, struct stliport, port); | 1145 | struct stliport *portp = container_of(port, struct stliport, port); |
1146 | struct stlibrd *brdp = stli_brds[portp->brdnr]; | 1146 | struct stlibrd *brdp = stli_brds[portp->brdnr]; |
1147 | stli_mkasysigs(&portp->asig, 1, 1); | 1147 | stli_mkasysigs(&portp->asig, on, on); |
1148 | if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, | 1148 | if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, |
1149 | sizeof(asysigs_t), 0) < 0) | 1149 | sizeof(asysigs_t), 0) < 0) |
1150 | printk(KERN_WARNING "istallion: dtr raise failed.\n"); | 1150 | printk(KERN_WARNING "istallion: dtr set failed.\n"); |
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | 1153 | ||
@@ -4417,7 +4417,7 @@ static const struct tty_operations stli_ops = { | |||
4417 | 4417 | ||
4418 | static const struct tty_port_operations stli_port_ops = { | 4418 | static const struct tty_port_operations stli_port_ops = { |
4419 | .carrier_raised = stli_carrier_raised, | 4419 | .carrier_raised = stli_carrier_raised, |
4420 | .raise_dtr_rts = stli_raise_dtr_rts, | 4420 | .dtr_rts = stli_dtr_rts, |
4421 | }; | 4421 | }; |
4422 | 4422 | ||
4423 | /*****************************************************************************/ | 4423 | /*****************************************************************************/ |
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 4a4cab73d0be..65b6ff2442c6 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -1184,6 +1184,11 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
1184 | return -ENODEV; | 1184 | return -ENODEV; |
1185 | } | 1185 | } |
1186 | 1186 | ||
1187 | if (port % MAX_PORTS_PER_BOARD >= brd->numPorts) { | ||
1188 | mutex_unlock(&moxa_openlock); | ||
1189 | return -ENODEV; | ||
1190 | } | ||
1191 | |||
1187 | ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; | 1192 | ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; |
1188 | ch->port.count++; | 1193 | ch->port.count++; |
1189 | tty->driver_data = ch; | 1194 | tty->driver_data = ch; |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 13f8871e5b21..9533f43a30bb 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -547,14 +547,18 @@ static int mxser_carrier_raised(struct tty_port *port) | |||
547 | return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0; | 547 | return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0; |
548 | } | 548 | } |
549 | 549 | ||
550 | static void mxser_raise_dtr_rts(struct tty_port *port) | 550 | static void mxser_dtr_rts(struct tty_port *port, int on) |
551 | { | 551 | { |
552 | struct mxser_port *mp = container_of(port, struct mxser_port, port); | 552 | struct mxser_port *mp = container_of(port, struct mxser_port, port); |
553 | unsigned long flags; | 553 | unsigned long flags; |
554 | 554 | ||
555 | spin_lock_irqsave(&mp->slock, flags); | 555 | spin_lock_irqsave(&mp->slock, flags); |
556 | outb(inb(mp->ioaddr + UART_MCR) | | 556 | if (on) |
557 | UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR); | 557 | outb(inb(mp->ioaddr + UART_MCR) | |
558 | UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR); | ||
559 | else | ||
560 | outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS), | ||
561 | mp->ioaddr + UART_MCR); | ||
558 | spin_unlock_irqrestore(&mp->slock, flags); | 562 | spin_unlock_irqrestore(&mp->slock, flags); |
559 | } | 563 | } |
560 | 564 | ||
@@ -2356,7 +2360,7 @@ static const struct tty_operations mxser_ops = { | |||
2356 | 2360 | ||
2357 | struct tty_port_operations mxser_port_ops = { | 2361 | struct tty_port_operations mxser_port_ops = { |
2358 | .carrier_raised = mxser_carrier_raised, | 2362 | .carrier_raised = mxser_carrier_raised, |
2359 | .raise_dtr_rts = mxser_raise_dtr_rts, | 2363 | .dtr_rts = mxser_dtr_rts, |
2360 | }; | 2364 | }; |
2361 | 2365 | ||
2362 | /* | 2366 | /* |
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index bacb3e2872ae..461ece591a5b 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
@@ -342,8 +342,8 @@ static int n_hdlc_tty_open (struct tty_struct *tty) | |||
342 | #endif | 342 | #endif |
343 | 343 | ||
344 | /* Flush any pending characters in the driver and discipline. */ | 344 | /* Flush any pending characters in the driver and discipline. */ |
345 | if (tty->ldisc.ops->flush_buffer) | 345 | if (tty->ldisc->ops->flush_buffer) |
346 | tty->ldisc.ops->flush_buffer(tty); | 346 | tty->ldisc->ops->flush_buffer(tty); |
347 | 347 | ||
348 | tty_driver_flush_buffer(tty); | 348 | tty_driver_flush_buffer(tty); |
349 | 349 | ||
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index f6f0e4ec2b51..94a5d5020abc 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -73,24 +73,6 @@ | |||
73 | #define ECHO_OP_SET_CANON_COL 0x81 | 73 | #define ECHO_OP_SET_CANON_COL 0x81 |
74 | #define ECHO_OP_ERASE_TAB 0x82 | 74 | #define ECHO_OP_ERASE_TAB 0x82 |
75 | 75 | ||
76 | static inline unsigned char *alloc_buf(void) | ||
77 | { | ||
78 | gfp_t prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; | ||
79 | |||
80 | if (PAGE_SIZE != N_TTY_BUF_SIZE) | ||
81 | return kmalloc(N_TTY_BUF_SIZE, prio); | ||
82 | else | ||
83 | return (unsigned char *)__get_free_page(prio); | ||
84 | } | ||
85 | |||
86 | static inline void free_buf(unsigned char *buf) | ||
87 | { | ||
88 | if (PAGE_SIZE != N_TTY_BUF_SIZE) | ||
89 | kfree(buf); | ||
90 | else | ||
91 | free_page((unsigned long) buf); | ||
92 | } | ||
93 | |||
94 | static inline int tty_put_user(struct tty_struct *tty, unsigned char x, | 76 | static inline int tty_put_user(struct tty_struct *tty, unsigned char x, |
95 | unsigned char __user *ptr) | 77 | unsigned char __user *ptr) |
96 | { | 78 | { |
@@ -1558,11 +1540,11 @@ static void n_tty_close(struct tty_struct *tty) | |||
1558 | { | 1540 | { |
1559 | n_tty_flush_buffer(tty); | 1541 | n_tty_flush_buffer(tty); |
1560 | if (tty->read_buf) { | 1542 | if (tty->read_buf) { |
1561 | free_buf(tty->read_buf); | 1543 | kfree(tty->read_buf); |
1562 | tty->read_buf = NULL; | 1544 | tty->read_buf = NULL; |
1563 | } | 1545 | } |
1564 | if (tty->echo_buf) { | 1546 | if (tty->echo_buf) { |
1565 | free_buf(tty->echo_buf); | 1547 | kfree(tty->echo_buf); |
1566 | tty->echo_buf = NULL; | 1548 | tty->echo_buf = NULL; |
1567 | } | 1549 | } |
1568 | } | 1550 | } |
@@ -1584,17 +1566,16 @@ static int n_tty_open(struct tty_struct *tty) | |||
1584 | 1566 | ||
1585 | /* These are ugly. Currently a malloc failure here can panic */ | 1567 | /* These are ugly. Currently a malloc failure here can panic */ |
1586 | if (!tty->read_buf) { | 1568 | if (!tty->read_buf) { |
1587 | tty->read_buf = alloc_buf(); | 1569 | tty->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL); |
1588 | if (!tty->read_buf) | 1570 | if (!tty->read_buf) |
1589 | return -ENOMEM; | 1571 | return -ENOMEM; |
1590 | } | 1572 | } |
1591 | if (!tty->echo_buf) { | 1573 | if (!tty->echo_buf) { |
1592 | tty->echo_buf = alloc_buf(); | 1574 | tty->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL); |
1575 | |||
1593 | if (!tty->echo_buf) | 1576 | if (!tty->echo_buf) |
1594 | return -ENOMEM; | 1577 | return -ENOMEM; |
1595 | } | 1578 | } |
1596 | memset(tty->read_buf, 0, N_TTY_BUF_SIZE); | ||
1597 | memset(tty->echo_buf, 0, N_TTY_BUF_SIZE); | ||
1598 | reset_buffer_flags(tty); | 1579 | reset_buffer_flags(tty); |
1599 | tty->column = 0; | 1580 | tty->column = 0; |
1600 | n_tty_set_termios(tty, NULL); | 1581 | n_tty_set_termios(tty, NULL); |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 19d79fc54461..77b364889224 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -383,7 +383,7 @@ static void async_mode(MGSLPC_INFO *info); | |||
383 | static void tx_timeout(unsigned long context); | 383 | static void tx_timeout(unsigned long context); |
384 | 384 | ||
385 | static int carrier_raised(struct tty_port *port); | 385 | static int carrier_raised(struct tty_port *port); |
386 | static void raise_dtr_rts(struct tty_port *port); | 386 | static void dtr_rts(struct tty_port *port, int onoff); |
387 | 387 | ||
388 | #if SYNCLINK_GENERIC_HDLC | 388 | #if SYNCLINK_GENERIC_HDLC |
389 | #define dev_to_port(D) (dev_to_hdlc(D)->priv) | 389 | #define dev_to_port(D) (dev_to_hdlc(D)->priv) |
@@ -513,7 +513,7 @@ static void ldisc_receive_buf(struct tty_struct *tty, | |||
513 | 513 | ||
514 | static const struct tty_port_operations mgslpc_port_ops = { | 514 | static const struct tty_port_operations mgslpc_port_ops = { |
515 | .carrier_raised = carrier_raised, | 515 | .carrier_raised = carrier_raised, |
516 | .raise_dtr_rts = raise_dtr_rts | 516 | .dtr_rts = dtr_rts |
517 | }; | 517 | }; |
518 | 518 | ||
519 | static int mgslpc_probe(struct pcmcia_device *link) | 519 | static int mgslpc_probe(struct pcmcia_device *link) |
@@ -2528,13 +2528,16 @@ static int carrier_raised(struct tty_port *port) | |||
2528 | return 0; | 2528 | return 0; |
2529 | } | 2529 | } |
2530 | 2530 | ||
2531 | static void raise_dtr_rts(struct tty_port *port) | 2531 | static void dtr_rts(struct tty_port *port, int onoff) |
2532 | { | 2532 | { |
2533 | MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port); | 2533 | MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port); |
2534 | unsigned long flags; | 2534 | unsigned long flags; |
2535 | 2535 | ||
2536 | spin_lock_irqsave(&info->lock,flags); | 2536 | spin_lock_irqsave(&info->lock,flags); |
2537 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | 2537 | if (onoff) |
2538 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
2539 | else | ||
2540 | info->serial_signals &= ~SerialSignal_RTS + SerialSignal_DTR; | ||
2538 | set_signals(info); | 2541 | set_signals(info); |
2539 | spin_unlock_irqrestore(&info->lock,flags); | 2542 | spin_unlock_irqrestore(&info->lock,flags); |
2540 | } | 2543 | } |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 31038a0052a2..5acd29e6e043 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -30,7 +30,6 @@ | |||
30 | 30 | ||
31 | #include <asm/system.h> | 31 | #include <asm/system.h> |
32 | 32 | ||
33 | /* These are global because they are accessed in tty_io.c */ | ||
34 | #ifdef CONFIG_UNIX98_PTYS | 33 | #ifdef CONFIG_UNIX98_PTYS |
35 | static struct tty_driver *ptm_driver; | 34 | static struct tty_driver *ptm_driver; |
36 | static struct tty_driver *pts_driver; | 35 | static struct tty_driver *pts_driver; |
@@ -111,7 +110,7 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf, | |||
111 | c = to->receive_room; | 110 | c = to->receive_room; |
112 | if (c > count) | 111 | if (c > count) |
113 | c = count; | 112 | c = count; |
114 | to->ldisc.ops->receive_buf(to, buf, NULL, c); | 113 | to->ldisc->ops->receive_buf(to, buf, NULL, c); |
115 | 114 | ||
116 | return c; | 115 | return c; |
117 | } | 116 | } |
@@ -149,11 +148,11 @@ static int pty_chars_in_buffer(struct tty_struct *tty) | |||
149 | int count; | 148 | int count; |
150 | 149 | ||
151 | /* We should get the line discipline lock for "tty->link" */ | 150 | /* We should get the line discipline lock for "tty->link" */ |
152 | if (!to || !to->ldisc.ops->chars_in_buffer) | 151 | if (!to || !to->ldisc->ops->chars_in_buffer) |
153 | return 0; | 152 | return 0; |
154 | 153 | ||
155 | /* The ldisc must report 0 if no characters available to be read */ | 154 | /* The ldisc must report 0 if no characters available to be read */ |
156 | count = to->ldisc.ops->chars_in_buffer(to); | 155 | count = to->ldisc->ops->chars_in_buffer(to); |
157 | 156 | ||
158 | if (tty->driver->subtype == PTY_TYPE_SLAVE) | 157 | if (tty->driver->subtype == PTY_TYPE_SLAVE) |
159 | return count; | 158 | return count; |
@@ -187,8 +186,8 @@ static void pty_flush_buffer(struct tty_struct *tty) | |||
187 | if (!to) | 186 | if (!to) |
188 | return; | 187 | return; |
189 | 188 | ||
190 | if (to->ldisc.ops->flush_buffer) | 189 | if (to->ldisc->ops->flush_buffer) |
191 | to->ldisc.ops->flush_buffer(to); | 190 | to->ldisc->ops->flush_buffer(to); |
192 | 191 | ||
193 | if (to->packet) { | 192 | if (to->packet) { |
194 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 193 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 20d90e6a6e50..db32f0e4c7dd 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c | |||
@@ -71,7 +71,7 @@ static int raw_open(struct inode *inode, struct file *filp) | |||
71 | err = bd_claim(bdev, raw_open); | 71 | err = bd_claim(bdev, raw_open); |
72 | if (err) | 72 | if (err) |
73 | goto out1; | 73 | goto out1; |
74 | err = set_blocksize(bdev, bdev_hardsect_size(bdev)); | 74 | err = set_blocksize(bdev, bdev_logical_block_size(bdev)); |
75 | if (err) | 75 | if (err) |
76 | goto out2; | 76 | goto out2; |
77 | filp->f_flags |= O_DIRECT; | 77 | filp->f_flags |= O_DIRECT; |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index f59fc5cea067..63d5b628477a 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -872,11 +872,16 @@ static int carrier_raised(struct tty_port *port) | |||
872 | return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0; | 872 | return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0; |
873 | } | 873 | } |
874 | 874 | ||
875 | static void raise_dtr_rts(struct tty_port *port) | 875 | static void dtr_rts(struct tty_port *port, int on) |
876 | { | 876 | { |
877 | struct r_port *info = container_of(port, struct r_port, port); | 877 | struct r_port *info = container_of(port, struct r_port, port); |
878 | sSetDTR(&info->channel); | 878 | if (on) { |
879 | sSetRTS(&info->channel); | 879 | sSetDTR(&info->channel); |
880 | sSetRTS(&info->channel); | ||
881 | } else { | ||
882 | sClrDTR(&info->channel); | ||
883 | sClrRTS(&info->channel); | ||
884 | } | ||
880 | } | 885 | } |
881 | 886 | ||
882 | /* | 887 | /* |
@@ -934,7 +939,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
934 | /* | 939 | /* |
935 | * Info->count is now 1; so it's safe to sleep now. | 940 | * Info->count is now 1; so it's safe to sleep now. |
936 | */ | 941 | */ |
937 | if (!test_bit(ASYNC_INITIALIZED, &port->flags)) { | 942 | if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) { |
938 | cp = &info->channel; | 943 | cp = &info->channel; |
939 | sSetRxTrigger(cp, TRIG_1); | 944 | sSetRxTrigger(cp, TRIG_1); |
940 | if (sGetChanStatus(cp) & CD_ACT) | 945 | if (sGetChanStatus(cp) & CD_ACT) |
@@ -958,7 +963,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
958 | sEnRxFIFO(cp); | 963 | sEnRxFIFO(cp); |
959 | sEnTransmit(cp); | 964 | sEnTransmit(cp); |
960 | 965 | ||
961 | set_bit(ASYNC_INITIALIZED, &info->port.flags); | 966 | set_bit(ASYNCB_INITIALIZED, &info->port.flags); |
962 | 967 | ||
963 | /* | 968 | /* |
964 | * Set up the tty->alt_speed kludge | 969 | * Set up the tty->alt_speed kludge |
@@ -1641,7 +1646,7 @@ static int rp_write(struct tty_struct *tty, | |||
1641 | /* Write remaining data into the port's xmit_buf */ | 1646 | /* Write remaining data into the port's xmit_buf */ |
1642 | while (1) { | 1647 | while (1) { |
1643 | /* Hung up ? */ | 1648 | /* Hung up ? */ |
1644 | if (!test_bit(ASYNC_NORMAL_ACTIVE, &info->port.flags)) | 1649 | if (!test_bit(ASYNCB_NORMAL_ACTIVE, &info->port.flags)) |
1645 | goto end; | 1650 | goto end; |
1646 | c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1); | 1651 | c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1); |
1647 | c = min(c, XMIT_BUF_SIZE - info->xmit_head); | 1652 | c = min(c, XMIT_BUF_SIZE - info->xmit_head); |
@@ -2250,7 +2255,7 @@ static const struct tty_operations rocket_ops = { | |||
2250 | 2255 | ||
2251 | static const struct tty_port_operations rocket_port_ops = { | 2256 | static const struct tty_port_operations rocket_port_ops = { |
2252 | .carrier_raised = carrier_raised, | 2257 | .carrier_raised = carrier_raised, |
2253 | .raise_dtr_rts = raise_dtr_rts, | 2258 | .dtr_rts = dtr_rts, |
2254 | }; | 2259 | }; |
2255 | 2260 | ||
2256 | /* | 2261 | /* |
diff --git a/drivers/char/selection.c b/drivers/char/selection.c index cb8ca5698963..f97b9e848064 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c | |||
@@ -327,7 +327,7 @@ int paste_selection(struct tty_struct *tty) | |||
327 | } | 327 | } |
328 | count = sel_buffer_lth - pasted; | 328 | count = sel_buffer_lth - pasted; |
329 | count = min(count, tty->receive_room); | 329 | count = min(count, tty->receive_room); |
330 | tty->ldisc.ops->receive_buf(tty, sel_buffer + pasted, | 330 | tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted, |
331 | NULL, count); | 331 | NULL, count); |
332 | pasted += count; | 332 | pasted += count; |
333 | } | 333 | } |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 2ad813a801dc..53e504f41b20 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -772,11 +772,11 @@ static int stl_carrier_raised(struct tty_port *port) | |||
772 | return (portp->sigs & TIOCM_CD) ? 1 : 0; | 772 | return (portp->sigs & TIOCM_CD) ? 1 : 0; |
773 | } | 773 | } |
774 | 774 | ||
775 | static void stl_raise_dtr_rts(struct tty_port *port) | 775 | static void stl_dtr_rts(struct tty_port *port, int on) |
776 | { | 776 | { |
777 | struct stlport *portp = container_of(port, struct stlport, port); | 777 | struct stlport *portp = container_of(port, struct stlport, port); |
778 | /* Takes brd_lock internally */ | 778 | /* Takes brd_lock internally */ |
779 | stl_setsignals(portp, 1, 1); | 779 | stl_setsignals(portp, on, on); |
780 | } | 780 | } |
781 | 781 | ||
782 | /*****************************************************************************/ | 782 | /*****************************************************************************/ |
@@ -2547,7 +2547,7 @@ static const struct tty_operations stl_ops = { | |||
2547 | 2547 | ||
2548 | static const struct tty_port_operations stl_port_ops = { | 2548 | static const struct tty_port_operations stl_port_ops = { |
2549 | .carrier_raised = stl_carrier_raised, | 2549 | .carrier_raised = stl_carrier_raised, |
2550 | .raise_dtr_rts = stl_raise_dtr_rts, | 2550 | .dtr_rts = stl_dtr_rts, |
2551 | }; | 2551 | }; |
2552 | 2552 | ||
2553 | /*****************************************************************************/ | 2553 | /*****************************************************************************/ |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index afd0b26ca056..afded3a2379c 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -3247,13 +3247,16 @@ static int carrier_raised(struct tty_port *port) | |||
3247 | return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; | 3247 | return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; |
3248 | } | 3248 | } |
3249 | 3249 | ||
3250 | static void raise_dtr_rts(struct tty_port *port) | 3250 | static void dtr_rts(struct tty_port *port, int on) |
3251 | { | 3251 | { |
3252 | struct mgsl_struct *info = container_of(port, struct mgsl_struct, port); | 3252 | struct mgsl_struct *info = container_of(port, struct mgsl_struct, port); |
3253 | unsigned long flags; | 3253 | unsigned long flags; |
3254 | 3254 | ||
3255 | spin_lock_irqsave(&info->irq_spinlock,flags); | 3255 | spin_lock_irqsave(&info->irq_spinlock,flags); |
3256 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | 3256 | if (on) |
3257 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3258 | else | ||
3259 | info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); | ||
3257 | usc_set_serial_signals(info); | 3260 | usc_set_serial_signals(info); |
3258 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | 3261 | spin_unlock_irqrestore(&info->irq_spinlock,flags); |
3259 | } | 3262 | } |
@@ -4258,7 +4261,7 @@ static void mgsl_add_device( struct mgsl_struct *info ) | |||
4258 | 4261 | ||
4259 | static const struct tty_port_operations mgsl_port_ops = { | 4262 | static const struct tty_port_operations mgsl_port_ops = { |
4260 | .carrier_raised = carrier_raised, | 4263 | .carrier_raised = carrier_raised, |
4261 | .raise_dtr_rts = raise_dtr_rts, | 4264 | .dtr_rts = dtr_rts, |
4262 | }; | 4265 | }; |
4263 | 4266 | ||
4264 | 4267 | ||
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 5e256494686a..1386625fc4ca 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -214,6 +214,7 @@ struct slgt_desc | |||
214 | #define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b)) | 214 | #define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b)) |
215 | #define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b)) | 215 | #define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b)) |
216 | #define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0)) | 216 | #define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0)) |
217 | #define set_desc_status(a, b) (a).status = cpu_to_le16((unsigned short)(b)) | ||
217 | #define desc_count(a) (le16_to_cpu((a).count)) | 218 | #define desc_count(a) (le16_to_cpu((a).count)) |
218 | #define desc_status(a) (le16_to_cpu((a).status)) | 219 | #define desc_status(a) (le16_to_cpu((a).status)) |
219 | #define desc_complete(a) (le16_to_cpu((a).status) & BIT15) | 220 | #define desc_complete(a) (le16_to_cpu((a).status) & BIT15) |
@@ -297,6 +298,7 @@ struct slgt_info { | |||
297 | u32 max_frame_size; /* as set by device config */ | 298 | u32 max_frame_size; /* as set by device config */ |
298 | 299 | ||
299 | unsigned int rbuf_fill_level; | 300 | unsigned int rbuf_fill_level; |
301 | unsigned int rx_pio; | ||
300 | unsigned int if_mode; | 302 | unsigned int if_mode; |
301 | unsigned int base_clock; | 303 | unsigned int base_clock; |
302 | 304 | ||
@@ -331,6 +333,8 @@ struct slgt_info { | |||
331 | struct slgt_desc *rbufs; | 333 | struct slgt_desc *rbufs; |
332 | unsigned int rbuf_current; | 334 | unsigned int rbuf_current; |
333 | unsigned int rbuf_index; | 335 | unsigned int rbuf_index; |
336 | unsigned int rbuf_fill_index; | ||
337 | unsigned short rbuf_fill_count; | ||
334 | 338 | ||
335 | unsigned int tbuf_count; | 339 | unsigned int tbuf_count; |
336 | struct slgt_desc *tbufs; | 340 | struct slgt_desc *tbufs; |
@@ -2110,6 +2114,40 @@ static void ri_change(struct slgt_info *info, unsigned short status) | |||
2110 | info->pending_bh |= BH_STATUS; | 2114 | info->pending_bh |= BH_STATUS; |
2111 | } | 2115 | } |
2112 | 2116 | ||
2117 | static void isr_rxdata(struct slgt_info *info) | ||
2118 | { | ||
2119 | unsigned int count = info->rbuf_fill_count; | ||
2120 | unsigned int i = info->rbuf_fill_index; | ||
2121 | unsigned short reg; | ||
2122 | |||
2123 | while (rd_reg16(info, SSR) & IRQ_RXDATA) { | ||
2124 | reg = rd_reg16(info, RDR); | ||
2125 | DBGISR(("isr_rxdata %s RDR=%04X\n", info->device_name, reg)); | ||
2126 | if (desc_complete(info->rbufs[i])) { | ||
2127 | /* all buffers full */ | ||
2128 | rx_stop(info); | ||
2129 | info->rx_restart = 1; | ||
2130 | continue; | ||
2131 | } | ||
2132 | info->rbufs[i].buf[count++] = (unsigned char)reg; | ||
2133 | /* async mode saves status byte to buffer for each data byte */ | ||
2134 | if (info->params.mode == MGSL_MODE_ASYNC) | ||
2135 | info->rbufs[i].buf[count++] = (unsigned char)(reg >> 8); | ||
2136 | if (count == info->rbuf_fill_level || (reg & BIT10)) { | ||
2137 | /* buffer full or end of frame */ | ||
2138 | set_desc_count(info->rbufs[i], count); | ||
2139 | set_desc_status(info->rbufs[i], BIT15 | (reg >> 8)); | ||
2140 | info->rbuf_fill_count = count = 0; | ||
2141 | if (++i == info->rbuf_count) | ||
2142 | i = 0; | ||
2143 | info->pending_bh |= BH_RECEIVE; | ||
2144 | } | ||
2145 | } | ||
2146 | |||
2147 | info->rbuf_fill_index = i; | ||
2148 | info->rbuf_fill_count = count; | ||
2149 | } | ||
2150 | |||
2113 | static void isr_serial(struct slgt_info *info) | 2151 | static void isr_serial(struct slgt_info *info) |
2114 | { | 2152 | { |
2115 | unsigned short status = rd_reg16(info, SSR); | 2153 | unsigned short status = rd_reg16(info, SSR); |
@@ -2125,6 +2163,8 @@ static void isr_serial(struct slgt_info *info) | |||
2125 | if (info->tx_count) | 2163 | if (info->tx_count) |
2126 | isr_txeom(info, status); | 2164 | isr_txeom(info, status); |
2127 | } | 2165 | } |
2166 | if (info->rx_pio && (status & IRQ_RXDATA)) | ||
2167 | isr_rxdata(info); | ||
2128 | if ((status & IRQ_RXBREAK) && (status & RXBREAK)) { | 2168 | if ((status & IRQ_RXBREAK) && (status & RXBREAK)) { |
2129 | info->icount.brk++; | 2169 | info->icount.brk++; |
2130 | /* process break detection if tty control allows */ | 2170 | /* process break detection if tty control allows */ |
@@ -2141,7 +2181,8 @@ static void isr_serial(struct slgt_info *info) | |||
2141 | } else { | 2181 | } else { |
2142 | if (status & (IRQ_TXIDLE + IRQ_TXUNDER)) | 2182 | if (status & (IRQ_TXIDLE + IRQ_TXUNDER)) |
2143 | isr_txeom(info, status); | 2183 | isr_txeom(info, status); |
2144 | 2184 | if (info->rx_pio && (status & IRQ_RXDATA)) | |
2185 | isr_rxdata(info); | ||
2145 | if (status & IRQ_RXIDLE) { | 2186 | if (status & IRQ_RXIDLE) { |
2146 | if (status & RXIDLE) | 2187 | if (status & RXIDLE) |
2147 | info->icount.rxidle++; | 2188 | info->icount.rxidle++; |
@@ -2642,6 +2683,10 @@ static int rx_enable(struct slgt_info *info, int enable) | |||
2642 | return -EINVAL; | 2683 | return -EINVAL; |
2643 | } | 2684 | } |
2644 | info->rbuf_fill_level = rbuf_fill_level; | 2685 | info->rbuf_fill_level = rbuf_fill_level; |
2686 | if (rbuf_fill_level < 128) | ||
2687 | info->rx_pio = 1; /* PIO mode */ | ||
2688 | else | ||
2689 | info->rx_pio = 0; /* DMA mode */ | ||
2645 | rx_stop(info); /* restart receiver to use new fill level */ | 2690 | rx_stop(info); /* restart receiver to use new fill level */ |
2646 | } | 2691 | } |
2647 | 2692 | ||
@@ -3099,13 +3144,16 @@ static int carrier_raised(struct tty_port *port) | |||
3099 | return (info->signals & SerialSignal_DCD) ? 1 : 0; | 3144 | return (info->signals & SerialSignal_DCD) ? 1 : 0; |
3100 | } | 3145 | } |
3101 | 3146 | ||
3102 | static void raise_dtr_rts(struct tty_port *port) | 3147 | static void dtr_rts(struct tty_port *port, int on) |
3103 | { | 3148 | { |
3104 | unsigned long flags; | 3149 | unsigned long flags; |
3105 | struct slgt_info *info = container_of(port, struct slgt_info, port); | 3150 | struct slgt_info *info = container_of(port, struct slgt_info, port); |
3106 | 3151 | ||
3107 | spin_lock_irqsave(&info->lock,flags); | 3152 | spin_lock_irqsave(&info->lock,flags); |
3108 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | 3153 | if (on) |
3154 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3155 | else | ||
3156 | info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); | ||
3109 | set_signals(info); | 3157 | set_signals(info); |
3110 | spin_unlock_irqrestore(&info->lock,flags); | 3158 | spin_unlock_irqrestore(&info->lock,flags); |
3111 | } | 3159 | } |
@@ -3419,7 +3467,7 @@ static void add_device(struct slgt_info *info) | |||
3419 | 3467 | ||
3420 | static const struct tty_port_operations slgt_port_ops = { | 3468 | static const struct tty_port_operations slgt_port_ops = { |
3421 | .carrier_raised = carrier_raised, | 3469 | .carrier_raised = carrier_raised, |
3422 | .raise_dtr_rts = raise_dtr_rts, | 3470 | .dtr_rts = dtr_rts, |
3423 | }; | 3471 | }; |
3424 | 3472 | ||
3425 | /* | 3473 | /* |
@@ -3841,15 +3889,27 @@ static void rx_start(struct slgt_info *info) | |||
3841 | rdma_reset(info); | 3889 | rdma_reset(info); |
3842 | reset_rbufs(info); | 3890 | reset_rbufs(info); |
3843 | 3891 | ||
3844 | /* set 1st descriptor address */ | 3892 | if (info->rx_pio) { |
3845 | wr_reg32(info, RDDAR, info->rbufs[0].pdesc); | 3893 | /* rx request when rx FIFO not empty */ |
3846 | 3894 | wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) & ~BIT14)); | |
3847 | if (info->params.mode != MGSL_MODE_ASYNC) { | 3895 | slgt_irq_on(info, IRQ_RXDATA); |
3848 | /* enable rx DMA and DMA interrupt */ | 3896 | if (info->params.mode == MGSL_MODE_ASYNC) { |
3849 | wr_reg32(info, RDCSR, (BIT2 + BIT0)); | 3897 | /* enable saving of rx status */ |
3898 | wr_reg32(info, RDCSR, BIT6); | ||
3899 | } | ||
3850 | } else { | 3900 | } else { |
3851 | /* enable saving of rx status, rx DMA and DMA interrupt */ | 3901 | /* rx request when rx FIFO half full */ |
3852 | wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0)); | 3902 | wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT14)); |
3903 | /* set 1st descriptor address */ | ||
3904 | wr_reg32(info, RDDAR, info->rbufs[0].pdesc); | ||
3905 | |||
3906 | if (info->params.mode != MGSL_MODE_ASYNC) { | ||
3907 | /* enable rx DMA and DMA interrupt */ | ||
3908 | wr_reg32(info, RDCSR, (BIT2 + BIT0)); | ||
3909 | } else { | ||
3910 | /* enable saving of rx status, rx DMA and DMA interrupt */ | ||
3911 | wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0)); | ||
3912 | } | ||
3853 | } | 3913 | } |
3854 | 3914 | ||
3855 | slgt_irq_on(info, IRQ_RXOVER); | 3915 | slgt_irq_on(info, IRQ_RXOVER); |
@@ -4467,6 +4527,8 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last | |||
4467 | static void reset_rbufs(struct slgt_info *info) | 4527 | static void reset_rbufs(struct slgt_info *info) |
4468 | { | 4528 | { |
4469 | free_rbufs(info, 0, info->rbuf_count - 1); | 4529 | free_rbufs(info, 0, info->rbuf_count - 1); |
4530 | info->rbuf_fill_index = 0; | ||
4531 | info->rbuf_fill_count = 0; | ||
4470 | } | 4532 | } |
4471 | 4533 | ||
4472 | /* | 4534 | /* |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 26de60efe4b2..6f727e3c53ad 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -3277,13 +3277,16 @@ static int carrier_raised(struct tty_port *port) | |||
3277 | return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; | 3277 | return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; |
3278 | } | 3278 | } |
3279 | 3279 | ||
3280 | static void raise_dtr_rts(struct tty_port *port) | 3280 | static void dtr_rts(struct tty_port *port, int on) |
3281 | { | 3281 | { |
3282 | SLMP_INFO *info = container_of(port, SLMP_INFO, port); | 3282 | SLMP_INFO *info = container_of(port, SLMP_INFO, port); |
3283 | unsigned long flags; | 3283 | unsigned long flags; |
3284 | 3284 | ||
3285 | spin_lock_irqsave(&info->lock,flags); | 3285 | spin_lock_irqsave(&info->lock,flags); |
3286 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | 3286 | if (on) |
3287 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3288 | else | ||
3289 | info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); | ||
3287 | set_signals(info); | 3290 | set_signals(info); |
3288 | spin_unlock_irqrestore(&info->lock,flags); | 3291 | spin_unlock_irqrestore(&info->lock,flags); |
3289 | } | 3292 | } |
@@ -3746,7 +3749,7 @@ static void add_device(SLMP_INFO *info) | |||
3746 | 3749 | ||
3747 | static const struct tty_port_operations port_ops = { | 3750 | static const struct tty_port_operations port_ops = { |
3748 | .carrier_raised = carrier_raised, | 3751 | .carrier_raised = carrier_raised, |
3749 | .raise_dtr_rts = raise_dtr_rts, | 3752 | .dtr_rts = dtr_rts, |
3750 | }; | 3753 | }; |
3751 | 3754 | ||
3752 | /* Allocate and initialize a device instance structure | 3755 | /* Allocate and initialize a device instance structure |
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index 55ba6f142883..ac16fbec72d0 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c | |||
@@ -29,10 +29,7 @@ static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor, | |||
29 | buf = kmalloc(sizeof(*buf), GFP_KERNEL); | 29 | buf = kmalloc(sizeof(*buf), GFP_KERNEL); |
30 | if (!buf) | 30 | if (!buf) |
31 | goto err; | 31 | goto err; |
32 | if (PAGE_SIZE != N_TTY_BUF_SIZE) | 32 | buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL); |
33 | buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL); | ||
34 | else | ||
35 | buf->data = (unsigned char *)__get_free_page(GFP_KERNEL); | ||
36 | if (!buf->data) | 33 | if (!buf->data) |
37 | goto err_buf; | 34 | goto err_buf; |
38 | atomic_set(&buf->count, 1); | 35 | atomic_set(&buf->count, 1); |
@@ -52,10 +49,7 @@ err: | |||
52 | static void tty_audit_buf_free(struct tty_audit_buf *buf) | 49 | static void tty_audit_buf_free(struct tty_audit_buf *buf) |
53 | { | 50 | { |
54 | WARN_ON(buf->valid != 0); | 51 | WARN_ON(buf->valid != 0); |
55 | if (PAGE_SIZE != N_TTY_BUF_SIZE) | 52 | kfree(buf->data); |
56 | kfree(buf->data); | ||
57 | else | ||
58 | free_page((unsigned long)buf->data); | ||
59 | kfree(buf); | 53 | kfree(buf); |
60 | } | 54 | } |
61 | 55 | ||
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 66b99a2049e3..939e198d7670 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -295,7 +295,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) | |||
295 | struct tty_driver *p, *res = NULL; | 295 | struct tty_driver *p, *res = NULL; |
296 | int tty_line = 0; | 296 | int tty_line = 0; |
297 | int len; | 297 | int len; |
298 | char *str; | 298 | char *str, *stp; |
299 | 299 | ||
300 | for (str = name; *str; str++) | 300 | for (str = name; *str; str++) |
301 | if ((*str >= '0' && *str <= '9') || *str == ',') | 301 | if ((*str >= '0' && *str <= '9') || *str == ',') |
@@ -311,13 +311,14 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) | |||
311 | list_for_each_entry(p, &tty_drivers, tty_drivers) { | 311 | list_for_each_entry(p, &tty_drivers, tty_drivers) { |
312 | if (strncmp(name, p->name, len) != 0) | 312 | if (strncmp(name, p->name, len) != 0) |
313 | continue; | 313 | continue; |
314 | if (*str == ',') | 314 | stp = str; |
315 | str++; | 315 | if (*stp == ',') |
316 | if (*str == '\0') | 316 | stp++; |
317 | str = NULL; | 317 | if (*stp == '\0') |
318 | stp = NULL; | ||
318 | 319 | ||
319 | if (tty_line >= 0 && tty_line <= p->num && p->ops && | 320 | if (tty_line >= 0 && tty_line <= p->num && p->ops && |
320 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) { | 321 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) { |
321 | res = tty_driver_kref_get(p); | 322 | res = tty_driver_kref_get(p); |
322 | *line = tty_line; | 323 | *line = tty_line; |
323 | break; | 324 | break; |
@@ -470,43 +471,6 @@ void tty_wakeup(struct tty_struct *tty) | |||
470 | EXPORT_SYMBOL_GPL(tty_wakeup); | 471 | EXPORT_SYMBOL_GPL(tty_wakeup); |
471 | 472 | ||
472 | /** | 473 | /** |
473 | * tty_ldisc_flush - flush line discipline queue | ||
474 | * @tty: tty | ||
475 | * | ||
476 | * Flush the line discipline queue (if any) for this tty. If there | ||
477 | * is no line discipline active this is a no-op. | ||
478 | */ | ||
479 | |||
480 | void tty_ldisc_flush(struct tty_struct *tty) | ||
481 | { | ||
482 | struct tty_ldisc *ld = tty_ldisc_ref(tty); | ||
483 | if (ld) { | ||
484 | if (ld->ops->flush_buffer) | ||
485 | ld->ops->flush_buffer(tty); | ||
486 | tty_ldisc_deref(ld); | ||
487 | } | ||
488 | tty_buffer_flush(tty); | ||
489 | } | ||
490 | |||
491 | EXPORT_SYMBOL_GPL(tty_ldisc_flush); | ||
492 | |||
493 | /** | ||
494 | * tty_reset_termios - reset terminal state | ||
495 | * @tty: tty to reset | ||
496 | * | ||
497 | * Restore a terminal to the driver default state | ||
498 | */ | ||
499 | |||
500 | static void tty_reset_termios(struct tty_struct *tty) | ||
501 | { | ||
502 | mutex_lock(&tty->termios_mutex); | ||
503 | *tty->termios = tty->driver->init_termios; | ||
504 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); | ||
505 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); | ||
506 | mutex_unlock(&tty->termios_mutex); | ||
507 | } | ||
508 | |||
509 | /** | ||
510 | * do_tty_hangup - actual handler for hangup events | 474 | * do_tty_hangup - actual handler for hangup events |
511 | * @work: tty device | 475 | * @work: tty device |
512 | * | 476 | * |
@@ -535,7 +499,6 @@ static void do_tty_hangup(struct work_struct *work) | |||
535 | struct file *cons_filp = NULL; | 499 | struct file *cons_filp = NULL; |
536 | struct file *filp, *f = NULL; | 500 | struct file *filp, *f = NULL; |
537 | struct task_struct *p; | 501 | struct task_struct *p; |
538 | struct tty_ldisc *ld; | ||
539 | int closecount = 0, n; | 502 | int closecount = 0, n; |
540 | unsigned long flags; | 503 | unsigned long flags; |
541 | int refs = 0; | 504 | int refs = 0; |
@@ -566,40 +529,8 @@ static void do_tty_hangup(struct work_struct *work) | |||
566 | filp->f_op = &hung_up_tty_fops; | 529 | filp->f_op = &hung_up_tty_fops; |
567 | } | 530 | } |
568 | file_list_unlock(); | 531 | file_list_unlock(); |
569 | /* | ||
570 | * FIXME! What are the locking issues here? This may me overdoing | ||
571 | * things... This question is especially important now that we've | ||
572 | * removed the irqlock. | ||
573 | */ | ||
574 | ld = tty_ldisc_ref(tty); | ||
575 | if (ld != NULL) { | ||
576 | /* We may have no line discipline at this point */ | ||
577 | if (ld->ops->flush_buffer) | ||
578 | ld->ops->flush_buffer(tty); | ||
579 | tty_driver_flush_buffer(tty); | ||
580 | if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && | ||
581 | ld->ops->write_wakeup) | ||
582 | ld->ops->write_wakeup(tty); | ||
583 | if (ld->ops->hangup) | ||
584 | ld->ops->hangup(tty); | ||
585 | } | ||
586 | /* | ||
587 | * FIXME: Once we trust the LDISC code better we can wait here for | ||
588 | * ldisc completion and fix the driver call race | ||
589 | */ | ||
590 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); | ||
591 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); | ||
592 | /* | ||
593 | * Shutdown the current line discipline, and reset it to | ||
594 | * N_TTY. | ||
595 | */ | ||
596 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) | ||
597 | tty_reset_termios(tty); | ||
598 | /* Defer ldisc switch */ | ||
599 | /* tty_deferred_ldisc_switch(N_TTY); | ||
600 | 532 | ||
601 | This should get done automatically when the port closes and | 533 | tty_ldisc_hangup(tty); |
602 | tty_release is called */ | ||
603 | 534 | ||
604 | read_lock(&tasklist_lock); | 535 | read_lock(&tasklist_lock); |
605 | if (tty->session) { | 536 | if (tty->session) { |
@@ -628,12 +559,15 @@ static void do_tty_hangup(struct work_struct *work) | |||
628 | read_unlock(&tasklist_lock); | 559 | read_unlock(&tasklist_lock); |
629 | 560 | ||
630 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 561 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
631 | tty->flags = 0; | 562 | clear_bit(TTY_THROTTLED, &tty->flags); |
563 | clear_bit(TTY_PUSH, &tty->flags); | ||
564 | clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); | ||
632 | put_pid(tty->session); | 565 | put_pid(tty->session); |
633 | put_pid(tty->pgrp); | 566 | put_pid(tty->pgrp); |
634 | tty->session = NULL; | 567 | tty->session = NULL; |
635 | tty->pgrp = NULL; | 568 | tty->pgrp = NULL; |
636 | tty->ctrl_status = 0; | 569 | tty->ctrl_status = 0; |
570 | set_bit(TTY_HUPPED, &tty->flags); | ||
637 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 571 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
638 | 572 | ||
639 | /* Account for the p->signal references we killed */ | 573 | /* Account for the p->signal references we killed */ |
@@ -659,10 +593,7 @@ static void do_tty_hangup(struct work_struct *work) | |||
659 | * can't yet guarantee all that. | 593 | * can't yet guarantee all that. |
660 | */ | 594 | */ |
661 | set_bit(TTY_HUPPED, &tty->flags); | 595 | set_bit(TTY_HUPPED, &tty->flags); |
662 | if (ld) { | 596 | tty_ldisc_enable(tty); |
663 | tty_ldisc_enable(tty); | ||
664 | tty_ldisc_deref(ld); | ||
665 | } | ||
666 | unlock_kernel(); | 597 | unlock_kernel(); |
667 | if (f) | 598 | if (f) |
668 | fput(f); | 599 | fput(f); |
@@ -2480,6 +2411,24 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int | |||
2480 | return tty->ops->tiocmset(tty, file, set, clear); | 2411 | return tty->ops->tiocmset(tty, file, set, clear); |
2481 | } | 2412 | } |
2482 | 2413 | ||
2414 | struct tty_struct *tty_pair_get_tty(struct tty_struct *tty) | ||
2415 | { | ||
2416 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | ||
2417 | tty->driver->subtype == PTY_TYPE_MASTER) | ||
2418 | tty = tty->link; | ||
2419 | return tty; | ||
2420 | } | ||
2421 | EXPORT_SYMBOL(tty_pair_get_tty); | ||
2422 | |||
2423 | struct tty_struct *tty_pair_get_pty(struct tty_struct *tty) | ||
2424 | { | ||
2425 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | ||
2426 | tty->driver->subtype == PTY_TYPE_MASTER) | ||
2427 | return tty; | ||
2428 | return tty->link; | ||
2429 | } | ||
2430 | EXPORT_SYMBOL(tty_pair_get_pty); | ||
2431 | |||
2483 | /* | 2432 | /* |
2484 | * Split this up, as gcc can choke on it otherwise.. | 2433 | * Split this up, as gcc can choke on it otherwise.. |
2485 | */ | 2434 | */ |
@@ -2495,11 +2444,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2495 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) | 2444 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) |
2496 | return -EINVAL; | 2445 | return -EINVAL; |
2497 | 2446 | ||
2498 | real_tty = tty; | 2447 | real_tty = tty_pair_get_tty(tty); |
2499 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | ||
2500 | tty->driver->subtype == PTY_TYPE_MASTER) | ||
2501 | real_tty = tty->link; | ||
2502 | |||
2503 | 2448 | ||
2504 | /* | 2449 | /* |
2505 | * Factor out some common prep work | 2450 | * Factor out some common prep work |
@@ -2555,7 +2500,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2555 | case TIOCGSID: | 2500 | case TIOCGSID: |
2556 | return tiocgsid(tty, real_tty, p); | 2501 | return tiocgsid(tty, real_tty, p); |
2557 | case TIOCGETD: | 2502 | case TIOCGETD: |
2558 | return put_user(tty->ldisc.ops->num, (int __user *)p); | 2503 | return put_user(tty->ldisc->ops->num, (int __user *)p); |
2559 | case TIOCSETD: | 2504 | case TIOCSETD: |
2560 | return tiocsetd(tty, p); | 2505 | return tiocsetd(tty, p); |
2561 | /* | 2506 | /* |
@@ -2770,6 +2715,7 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
2770 | tty->buf.head = tty->buf.tail = NULL; | 2715 | tty->buf.head = tty->buf.tail = NULL; |
2771 | tty_buffer_init(tty); | 2716 | tty_buffer_init(tty); |
2772 | mutex_init(&tty->termios_mutex); | 2717 | mutex_init(&tty->termios_mutex); |
2718 | mutex_init(&tty->ldisc_mutex); | ||
2773 | init_waitqueue_head(&tty->write_wait); | 2719 | init_waitqueue_head(&tty->write_wait); |
2774 | init_waitqueue_head(&tty->read_wait); | 2720 | init_waitqueue_head(&tty->read_wait); |
2775 | INIT_WORK(&tty->hangup_work, do_tty_hangup); | 2721 | INIT_WORK(&tty->hangup_work, do_tty_hangup); |
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 6f4c7d0a53bf..8116bb1c8f80 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -97,14 +97,19 @@ EXPORT_SYMBOL(tty_driver_flush_buffer); | |||
97 | * @tty: terminal | 97 | * @tty: terminal |
98 | * | 98 | * |
99 | * Indicate that a tty should stop transmitting data down the stack. | 99 | * Indicate that a tty should stop transmitting data down the stack. |
100 | * Takes the termios mutex to protect against parallel throttle/unthrottle | ||
101 | * and also to ensure the driver can consistently reference its own | ||
102 | * termios data at this point when implementing software flow control. | ||
100 | */ | 103 | */ |
101 | 104 | ||
102 | void tty_throttle(struct tty_struct *tty) | 105 | void tty_throttle(struct tty_struct *tty) |
103 | { | 106 | { |
107 | mutex_lock(&tty->termios_mutex); | ||
104 | /* check TTY_THROTTLED first so it indicates our state */ | 108 | /* check TTY_THROTTLED first so it indicates our state */ |
105 | if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) && | 109 | if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) && |
106 | tty->ops->throttle) | 110 | tty->ops->throttle) |
107 | tty->ops->throttle(tty); | 111 | tty->ops->throttle(tty); |
112 | mutex_unlock(&tty->termios_mutex); | ||
108 | } | 113 | } |
109 | EXPORT_SYMBOL(tty_throttle); | 114 | EXPORT_SYMBOL(tty_throttle); |
110 | 115 | ||
@@ -113,13 +118,21 @@ EXPORT_SYMBOL(tty_throttle); | |||
113 | * @tty: terminal | 118 | * @tty: terminal |
114 | * | 119 | * |
115 | * Indicate that a tty may continue transmitting data down the stack. | 120 | * Indicate that a tty may continue transmitting data down the stack. |
121 | * Takes the termios mutex to protect against parallel throttle/unthrottle | ||
122 | * and also to ensure the driver can consistently reference its own | ||
123 | * termios data at this point when implementing software flow control. | ||
124 | * | ||
125 | * Drivers should however remember that the stack can issue a throttle, | ||
126 | * then change flow control method, then unthrottle. | ||
116 | */ | 127 | */ |
117 | 128 | ||
118 | void tty_unthrottle(struct tty_struct *tty) | 129 | void tty_unthrottle(struct tty_struct *tty) |
119 | { | 130 | { |
131 | mutex_lock(&tty->termios_mutex); | ||
120 | if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && | 132 | if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && |
121 | tty->ops->unthrottle) | 133 | tty->ops->unthrottle) |
122 | tty->ops->unthrottle(tty); | 134 | tty->ops->unthrottle(tty); |
135 | mutex_unlock(&tty->termios_mutex); | ||
123 | } | 136 | } |
124 | EXPORT_SYMBOL(tty_unthrottle); | 137 | EXPORT_SYMBOL(tty_unthrottle); |
125 | 138 | ||
@@ -613,9 +626,25 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) | |||
613 | return 0; | 626 | return 0; |
614 | } | 627 | } |
615 | 628 | ||
629 | static void copy_termios(struct tty_struct *tty, struct ktermios *kterm) | ||
630 | { | ||
631 | mutex_lock(&tty->termios_mutex); | ||
632 | memcpy(kterm, tty->termios, sizeof(struct ktermios)); | ||
633 | mutex_unlock(&tty->termios_mutex); | ||
634 | } | ||
635 | |||
636 | static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm) | ||
637 | { | ||
638 | mutex_lock(&tty->termios_mutex); | ||
639 | memcpy(kterm, tty->termios_locked, sizeof(struct ktermios)); | ||
640 | mutex_unlock(&tty->termios_mutex); | ||
641 | } | ||
642 | |||
616 | static int get_termio(struct tty_struct *tty, struct termio __user *termio) | 643 | static int get_termio(struct tty_struct *tty, struct termio __user *termio) |
617 | { | 644 | { |
618 | if (kernel_termios_to_user_termio(termio, tty->termios)) | 645 | struct ktermios kterm; |
646 | copy_termios(tty, &kterm); | ||
647 | if (kernel_termios_to_user_termio(termio, &kterm)) | ||
619 | return -EFAULT; | 648 | return -EFAULT; |
620 | return 0; | 649 | return 0; |
621 | } | 650 | } |
@@ -917,6 +946,8 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
917 | struct tty_struct *real_tty; | 946 | struct tty_struct *real_tty; |
918 | void __user *p = (void __user *)arg; | 947 | void __user *p = (void __user *)arg; |
919 | int ret = 0; | 948 | int ret = 0; |
949 | struct ktermios kterm; | ||
950 | struct termiox ktermx; | ||
920 | 951 | ||
921 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 952 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
922 | tty->driver->subtype == PTY_TYPE_MASTER) | 953 | tty->driver->subtype == PTY_TYPE_MASTER) |
@@ -952,23 +983,20 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
952 | return set_termios(real_tty, p, TERMIOS_OLD); | 983 | return set_termios(real_tty, p, TERMIOS_OLD); |
953 | #ifndef TCGETS2 | 984 | #ifndef TCGETS2 |
954 | case TCGETS: | 985 | case TCGETS: |
955 | mutex_lock(&real_tty->termios_mutex); | 986 | copy_termios(real_tty, &kterm); |
956 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) | 987 | if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm)) |
957 | ret = -EFAULT; | 988 | ret = -EFAULT; |
958 | mutex_unlock(&real_tty->termios_mutex); | ||
959 | return ret; | 989 | return ret; |
960 | #else | 990 | #else |
961 | case TCGETS: | 991 | case TCGETS: |
962 | mutex_lock(&real_tty->termios_mutex); | 992 | copy_termios(real_tty, &kterm); |
963 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) | 993 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm)) |
964 | ret = -EFAULT; | 994 | ret = -EFAULT; |
965 | mutex_unlock(&real_tty->termios_mutex); | ||
966 | return ret; | 995 | return ret; |
967 | case TCGETS2: | 996 | case TCGETS2: |
968 | mutex_lock(&real_tty->termios_mutex); | 997 | copy_termios(real_tty, &kterm); |
969 | if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) | 998 | if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm)) |
970 | ret = -EFAULT; | 999 | ret = -EFAULT; |
971 | mutex_unlock(&real_tty->termios_mutex); | ||
972 | return ret; | 1000 | return ret; |
973 | case TCSETSF2: | 1001 | case TCSETSF2: |
974 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); | 1002 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); |
@@ -987,34 +1015,36 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
987 | return set_termios(real_tty, p, TERMIOS_TERMIO); | 1015 | return set_termios(real_tty, p, TERMIOS_TERMIO); |
988 | #ifndef TCGETS2 | 1016 | #ifndef TCGETS2 |
989 | case TIOCGLCKTRMIOS: | 1017 | case TIOCGLCKTRMIOS: |
990 | mutex_lock(&real_tty->termios_mutex); | 1018 | copy_termios_locked(real_tty, &kterm); |
991 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) | 1019 | if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm)) |
992 | ret = -EFAULT; | 1020 | ret = -EFAULT; |
993 | mutex_unlock(&real_tty->termios_mutex); | ||
994 | return ret; | 1021 | return ret; |
995 | case TIOCSLCKTRMIOS: | 1022 | case TIOCSLCKTRMIOS: |
996 | if (!capable(CAP_SYS_ADMIN)) | 1023 | if (!capable(CAP_SYS_ADMIN)) |
997 | return -EPERM; | 1024 | return -EPERM; |
998 | mutex_lock(&real_tty->termios_mutex); | 1025 | copy_termios_locked(real_tty, &kterm); |
999 | if (user_termios_to_kernel_termios(real_tty->termios_locked, | 1026 | if (user_termios_to_kernel_termios(&kterm, |
1000 | (struct termios __user *) arg)) | 1027 | (struct termios __user *) arg)) |
1001 | ret = -EFAULT; | 1028 | return -EFAULT; |
1029 | mutex_lock(&real_tty->termios_mutex); | ||
1030 | memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios)); | ||
1002 | mutex_unlock(&real_tty->termios_mutex); | 1031 | mutex_unlock(&real_tty->termios_mutex); |
1003 | return ret; | 1032 | return 0; |
1004 | #else | 1033 | #else |
1005 | case TIOCGLCKTRMIOS: | 1034 | case TIOCGLCKTRMIOS: |
1006 | mutex_lock(&real_tty->termios_mutex); | 1035 | copy_termios_locked(real_tty, &kterm); |
1007 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) | 1036 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm)) |
1008 | ret = -EFAULT; | 1037 | ret = -EFAULT; |
1009 | mutex_unlock(&real_tty->termios_mutex); | ||
1010 | return ret; | 1038 | return ret; |
1011 | case TIOCSLCKTRMIOS: | 1039 | case TIOCSLCKTRMIOS: |
1012 | if (!capable(CAP_SYS_ADMIN)) | 1040 | if (!capable(CAP_SYS_ADMIN)) |
1013 | ret = -EPERM; | 1041 | return -EPERM; |
1014 | mutex_lock(&real_tty->termios_mutex); | 1042 | copy_termios_locked(real_tty, &kterm); |
1015 | if (user_termios_to_kernel_termios_1(real_tty->termios_locked, | 1043 | if (user_termios_to_kernel_termios_1(&kterm, |
1016 | (struct termios __user *) arg)) | 1044 | (struct termios __user *) arg)) |
1017 | ret = -EFAULT; | 1045 | return -EFAULT; |
1046 | mutex_lock(&real_tty->termios_mutex); | ||
1047 | memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios)); | ||
1018 | mutex_unlock(&real_tty->termios_mutex); | 1048 | mutex_unlock(&real_tty->termios_mutex); |
1019 | return ret; | 1049 | return ret; |
1020 | #endif | 1050 | #endif |
@@ -1023,9 +1053,10 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
1023 | if (real_tty->termiox == NULL) | 1053 | if (real_tty->termiox == NULL) |
1024 | return -EINVAL; | 1054 | return -EINVAL; |
1025 | mutex_lock(&real_tty->termios_mutex); | 1055 | mutex_lock(&real_tty->termios_mutex); |
1026 | if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox))) | 1056 | memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox)); |
1027 | ret = -EFAULT; | ||
1028 | mutex_unlock(&real_tty->termios_mutex); | 1057 | mutex_unlock(&real_tty->termios_mutex); |
1058 | if (copy_to_user(p, &ktermx, sizeof(struct termiox))) | ||
1059 | ret = -EFAULT; | ||
1029 | return ret; | 1060 | return ret; |
1030 | case TCSETX: | 1061 | case TCSETX: |
1031 | return set_termiox(real_tty, p, 0); | 1062 | return set_termiox(real_tty, p, 0); |
@@ -1035,10 +1066,9 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
1035 | return set_termiox(real_tty, p, TERMIOS_FLUSH); | 1066 | return set_termiox(real_tty, p, TERMIOS_FLUSH); |
1036 | #endif | 1067 | #endif |
1037 | case TIOCGSOFTCAR: | 1068 | case TIOCGSOFTCAR: |
1038 | mutex_lock(&real_tty->termios_mutex); | 1069 | copy_termios(real_tty, &kterm); |
1039 | ret = put_user(C_CLOCAL(real_tty) ? 1 : 0, | 1070 | ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0, |
1040 | (int __user *)arg); | 1071 | (int __user *)arg); |
1041 | mutex_unlock(&real_tty->termios_mutex); | ||
1042 | return ret; | 1072 | return ret; |
1043 | case TIOCSSOFTCAR: | 1073 | case TIOCSSOFTCAR: |
1044 | if (get_user(arg, (unsigned int __user *) arg)) | 1074 | if (get_user(arg, (unsigned int __user *) arg)) |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index f78f5b0127a8..39c8f86dedd4 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
@@ -115,19 +115,22 @@ EXPORT_SYMBOL(tty_unregister_ldisc); | |||
115 | /** | 115 | /** |
116 | * tty_ldisc_try_get - try and reference an ldisc | 116 | * tty_ldisc_try_get - try and reference an ldisc |
117 | * @disc: ldisc number | 117 | * @disc: ldisc number |
118 | * @ld: tty ldisc structure to complete | ||
119 | * | 118 | * |
120 | * Attempt to open and lock a line discipline into place. Return | 119 | * Attempt to open and lock a line discipline into place. Return |
121 | * the line discipline refcounted and assigned in ld. On an error | 120 | * the line discipline refcounted or an error. |
122 | * report the error code back | ||
123 | */ | 121 | */ |
124 | 122 | ||
125 | static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | 123 | static struct tty_ldisc *tty_ldisc_try_get(int disc) |
126 | { | 124 | { |
127 | unsigned long flags; | 125 | unsigned long flags; |
126 | struct tty_ldisc *ld; | ||
128 | struct tty_ldisc_ops *ldops; | 127 | struct tty_ldisc_ops *ldops; |
129 | int err = -EINVAL; | 128 | int err = -EINVAL; |
130 | 129 | ||
130 | ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL); | ||
131 | if (ld == NULL) | ||
132 | return ERR_PTR(-ENOMEM); | ||
133 | |||
131 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 134 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
132 | ld->ops = NULL; | 135 | ld->ops = NULL; |
133 | ldops = tty_ldiscs[disc]; | 136 | ldops = tty_ldiscs[disc]; |
@@ -140,17 +143,19 @@ static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | |||
140 | /* lock it */ | 143 | /* lock it */ |
141 | ldops->refcount++; | 144 | ldops->refcount++; |
142 | ld->ops = ldops; | 145 | ld->ops = ldops; |
146 | ld->refcount = 0; | ||
143 | err = 0; | 147 | err = 0; |
144 | } | 148 | } |
145 | } | 149 | } |
146 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 150 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
147 | return err; | 151 | if (err) |
152 | return ERR_PTR(err); | ||
153 | return ld; | ||
148 | } | 154 | } |
149 | 155 | ||
150 | /** | 156 | /** |
151 | * tty_ldisc_get - take a reference to an ldisc | 157 | * tty_ldisc_get - take a reference to an ldisc |
152 | * @disc: ldisc number | 158 | * @disc: ldisc number |
153 | * @ld: tty line discipline structure to use | ||
154 | * | 159 | * |
155 | * Takes a reference to a line discipline. Deals with refcounts and | 160 | * Takes a reference to a line discipline. Deals with refcounts and |
156 | * module locking counts. Returns NULL if the discipline is not available. | 161 | * module locking counts. Returns NULL if the discipline is not available. |
@@ -161,52 +166,54 @@ static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | |||
161 | * takes tty_ldisc_lock to guard against ldisc races | 166 | * takes tty_ldisc_lock to guard against ldisc races |
162 | */ | 167 | */ |
163 | 168 | ||
164 | static int tty_ldisc_get(int disc, struct tty_ldisc *ld) | 169 | static struct tty_ldisc *tty_ldisc_get(int disc) |
165 | { | 170 | { |
166 | int err; | 171 | struct tty_ldisc *ld; |
167 | 172 | ||
168 | if (disc < N_TTY || disc >= NR_LDISCS) | 173 | if (disc < N_TTY || disc >= NR_LDISCS) |
169 | return -EINVAL; | 174 | return ERR_PTR(-EINVAL); |
170 | err = tty_ldisc_try_get(disc, ld); | 175 | ld = tty_ldisc_try_get(disc); |
171 | if (err < 0) { | 176 | if (IS_ERR(ld)) { |
172 | request_module("tty-ldisc-%d", disc); | 177 | request_module("tty-ldisc-%d", disc); |
173 | err = tty_ldisc_try_get(disc, ld); | 178 | ld = tty_ldisc_try_get(disc); |
174 | } | 179 | } |
175 | return err; | 180 | return ld; |
176 | } | 181 | } |
177 | 182 | ||
178 | /** | 183 | /** |
179 | * tty_ldisc_put - drop ldisc reference | 184 | * tty_ldisc_put - drop ldisc reference |
180 | * @disc: ldisc number | 185 | * @ld: ldisc |
181 | * | 186 | * |
182 | * Drop a reference to a line discipline. Manage refcounts and | 187 | * Drop a reference to a line discipline. Manage refcounts and |
183 | * module usage counts | 188 | * module usage counts. Free the ldisc once the recount hits zero. |
184 | * | 189 | * |
185 | * Locking: | 190 | * Locking: |
186 | * takes tty_ldisc_lock to guard against ldisc races | 191 | * takes tty_ldisc_lock to guard against ldisc races |
187 | */ | 192 | */ |
188 | 193 | ||
189 | static void tty_ldisc_put(struct tty_ldisc_ops *ld) | 194 | static void tty_ldisc_put(struct tty_ldisc *ld) |
190 | { | 195 | { |
191 | unsigned long flags; | 196 | unsigned long flags; |
192 | int disc = ld->num; | 197 | int disc = ld->ops->num; |
198 | struct tty_ldisc_ops *ldo; | ||
193 | 199 | ||
194 | BUG_ON(disc < N_TTY || disc >= NR_LDISCS); | 200 | BUG_ON(disc < N_TTY || disc >= NR_LDISCS); |
195 | 201 | ||
196 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 202 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
197 | ld = tty_ldiscs[disc]; | 203 | ldo = tty_ldiscs[disc]; |
198 | BUG_ON(ld->refcount == 0); | 204 | BUG_ON(ldo->refcount == 0); |
199 | ld->refcount--; | 205 | ldo->refcount--; |
200 | module_put(ld->owner); | 206 | module_put(ldo->owner); |
201 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 207 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
208 | kfree(ld); | ||
202 | } | 209 | } |
203 | 210 | ||
204 | static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) | 211 | static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) |
205 | { | 212 | { |
206 | return (*pos < NR_LDISCS) ? pos : NULL; | 213 | return (*pos < NR_LDISCS) ? pos : NULL; |
207 | } | 214 | } |
208 | 215 | ||
209 | static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) | 216 | static void *tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) |
210 | { | 217 | { |
211 | (*pos)++; | 218 | (*pos)++; |
212 | return (*pos < NR_LDISCS) ? pos : NULL; | 219 | return (*pos < NR_LDISCS) ? pos : NULL; |
@@ -219,12 +226,13 @@ static void tty_ldiscs_seq_stop(struct seq_file *m, void *v) | |||
219 | static int tty_ldiscs_seq_show(struct seq_file *m, void *v) | 226 | static int tty_ldiscs_seq_show(struct seq_file *m, void *v) |
220 | { | 227 | { |
221 | int i = *(loff_t *)v; | 228 | int i = *(loff_t *)v; |
222 | struct tty_ldisc ld; | 229 | struct tty_ldisc *ld; |
223 | 230 | ||
224 | if (tty_ldisc_get(i, &ld) < 0) | 231 | ld = tty_ldisc_try_get(i); |
232 | if (IS_ERR(ld)) | ||
225 | return 0; | 233 | return 0; |
226 | seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i); | 234 | seq_printf(m, "%-10s %2d\n", ld->ops->name ? ld->ops->name : "???", i); |
227 | tty_ldisc_put(ld.ops); | 235 | tty_ldisc_put(ld); |
228 | return 0; | 236 | return 0; |
229 | } | 237 | } |
230 | 238 | ||
@@ -263,8 +271,7 @@ const struct file_operations tty_ldiscs_proc_fops = { | |||
263 | 271 | ||
264 | static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) | 272 | static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) |
265 | { | 273 | { |
266 | ld->refcount = 0; | 274 | tty->ldisc = ld; |
267 | tty->ldisc = *ld; | ||
268 | } | 275 | } |
269 | 276 | ||
270 | /** | 277 | /** |
@@ -286,7 +293,7 @@ static int tty_ldisc_try(struct tty_struct *tty) | |||
286 | int ret = 0; | 293 | int ret = 0; |
287 | 294 | ||
288 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 295 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
289 | ld = &tty->ldisc; | 296 | ld = tty->ldisc; |
290 | if (test_bit(TTY_LDISC, &tty->flags)) { | 297 | if (test_bit(TTY_LDISC, &tty->flags)) { |
291 | ld->refcount++; | 298 | ld->refcount++; |
292 | ret = 1; | 299 | ret = 1; |
@@ -315,10 +322,9 @@ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) | |||
315 | { | 322 | { |
316 | /* wait_event is a macro */ | 323 | /* wait_event is a macro */ |
317 | wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); | 324 | wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); |
318 | WARN_ON(tty->ldisc.refcount == 0); | 325 | WARN_ON(tty->ldisc->refcount == 0); |
319 | return &tty->ldisc; | 326 | return tty->ldisc; |
320 | } | 327 | } |
321 | |||
322 | EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); | 328 | EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); |
323 | 329 | ||
324 | /** | 330 | /** |
@@ -335,10 +341,9 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); | |||
335 | struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) | 341 | struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) |
336 | { | 342 | { |
337 | if (tty_ldisc_try(tty)) | 343 | if (tty_ldisc_try(tty)) |
338 | return &tty->ldisc; | 344 | return tty->ldisc; |
339 | return NULL; | 345 | return NULL; |
340 | } | 346 | } |
341 | |||
342 | EXPORT_SYMBOL_GPL(tty_ldisc_ref); | 347 | EXPORT_SYMBOL_GPL(tty_ldisc_ref); |
343 | 348 | ||
344 | /** | 349 | /** |
@@ -366,7 +371,6 @@ void tty_ldisc_deref(struct tty_ldisc *ld) | |||
366 | wake_up(&tty_ldisc_wait); | 371 | wake_up(&tty_ldisc_wait); |
367 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 372 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
368 | } | 373 | } |
369 | |||
370 | EXPORT_SYMBOL_GPL(tty_ldisc_deref); | 374 | EXPORT_SYMBOL_GPL(tty_ldisc_deref); |
371 | 375 | ||
372 | /** | 376 | /** |
@@ -389,6 +393,26 @@ void tty_ldisc_enable(struct tty_struct *tty) | |||
389 | } | 393 | } |
390 | 394 | ||
391 | /** | 395 | /** |
396 | * tty_ldisc_flush - flush line discipline queue | ||
397 | * @tty: tty | ||
398 | * | ||
399 | * Flush the line discipline queue (if any) for this tty. If there | ||
400 | * is no line discipline active this is a no-op. | ||
401 | */ | ||
402 | |||
403 | void tty_ldisc_flush(struct tty_struct *tty) | ||
404 | { | ||
405 | struct tty_ldisc *ld = tty_ldisc_ref(tty); | ||
406 | if (ld) { | ||
407 | if (ld->ops->flush_buffer) | ||
408 | ld->ops->flush_buffer(tty); | ||
409 | tty_ldisc_deref(ld); | ||
410 | } | ||
411 | tty_buffer_flush(tty); | ||
412 | } | ||
413 | EXPORT_SYMBOL_GPL(tty_ldisc_flush); | ||
414 | |||
415 | /** | ||
392 | * tty_set_termios_ldisc - set ldisc field | 416 | * tty_set_termios_ldisc - set ldisc field |
393 | * @tty: tty structure | 417 | * @tty: tty structure |
394 | * @num: line discipline number | 418 | * @num: line discipline number |
@@ -407,6 +431,39 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
407 | mutex_unlock(&tty->termios_mutex); | 431 | mutex_unlock(&tty->termios_mutex); |
408 | } | 432 | } |
409 | 433 | ||
434 | /** | ||
435 | * tty_ldisc_open - open a line discipline | ||
436 | * @tty: tty we are opening the ldisc on | ||
437 | * @ld: discipline to open | ||
438 | * | ||
439 | * A helper opening method. Also a convenient debugging and check | ||
440 | * point. | ||
441 | */ | ||
442 | |||
443 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | ||
444 | { | ||
445 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); | ||
446 | if (ld->ops->open) | ||
447 | return ld->ops->open(tty); | ||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | /** | ||
452 | * tty_ldisc_close - close a line discipline | ||
453 | * @tty: tty we are opening the ldisc on | ||
454 | * @ld: discipline to close | ||
455 | * | ||
456 | * A helper close method. Also a convenient debugging and check | ||
457 | * point. | ||
458 | */ | ||
459 | |||
460 | static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) | ||
461 | { | ||
462 | WARN_ON(!test_bit(TTY_LDISC_OPEN, &tty->flags)); | ||
463 | clear_bit(TTY_LDISC_OPEN, &tty->flags); | ||
464 | if (ld->ops->close) | ||
465 | ld->ops->close(tty); | ||
466 | } | ||
410 | 467 | ||
411 | /** | 468 | /** |
412 | * tty_ldisc_restore - helper for tty ldisc change | 469 | * tty_ldisc_restore - helper for tty ldisc change |
@@ -420,66 +477,136 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
420 | static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) | 477 | static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) |
421 | { | 478 | { |
422 | char buf[64]; | 479 | char buf[64]; |
423 | struct tty_ldisc new_ldisc; | 480 | struct tty_ldisc *new_ldisc; |
481 | int r; | ||
424 | 482 | ||
425 | /* There is an outstanding reference here so this is safe */ | 483 | /* There is an outstanding reference here so this is safe */ |
426 | tty_ldisc_get(old->ops->num, old); | 484 | old = tty_ldisc_get(old->ops->num); |
485 | WARN_ON(IS_ERR(old)); | ||
427 | tty_ldisc_assign(tty, old); | 486 | tty_ldisc_assign(tty, old); |
428 | tty_set_termios_ldisc(tty, old->ops->num); | 487 | tty_set_termios_ldisc(tty, old->ops->num); |
429 | if (old->ops->open && (old->ops->open(tty) < 0)) { | 488 | if (tty_ldisc_open(tty, old) < 0) { |
430 | tty_ldisc_put(old->ops); | 489 | tty_ldisc_put(old); |
431 | /* This driver is always present */ | 490 | /* This driver is always present */ |
432 | if (tty_ldisc_get(N_TTY, &new_ldisc) < 0) | 491 | new_ldisc = tty_ldisc_get(N_TTY); |
492 | if (IS_ERR(new_ldisc)) | ||
433 | panic("n_tty: get"); | 493 | panic("n_tty: get"); |
434 | tty_ldisc_assign(tty, &new_ldisc); | 494 | tty_ldisc_assign(tty, new_ldisc); |
435 | tty_set_termios_ldisc(tty, N_TTY); | 495 | tty_set_termios_ldisc(tty, N_TTY); |
436 | if (new_ldisc.ops->open) { | 496 | r = tty_ldisc_open(tty, new_ldisc); |
437 | int r = new_ldisc.ops->open(tty); | 497 | if (r < 0) |
438 | if (r < 0) | 498 | panic("Couldn't open N_TTY ldisc for " |
439 | panic("Couldn't open N_TTY ldisc for " | 499 | "%s --- error %d.", |
440 | "%s --- error %d.", | 500 | tty_name(tty, buf), r); |
441 | tty_name(tty, buf), r); | ||
442 | } | ||
443 | } | 501 | } |
444 | } | 502 | } |
445 | 503 | ||
446 | /** | 504 | /** |
505 | * tty_ldisc_halt - shut down the line discipline | ||
506 | * @tty: tty device | ||
507 | * | ||
508 | * Shut down the line discipline and work queue for this tty device. | ||
509 | * The TTY_LDISC flag being cleared ensures no further references can | ||
510 | * be obtained while the delayed work queue halt ensures that no more | ||
511 | * data is fed to the ldisc. | ||
512 | * | ||
513 | * In order to wait for any existing references to complete see | ||
514 | * tty_ldisc_wait_idle. | ||
515 | */ | ||
516 | |||
517 | static int tty_ldisc_halt(struct tty_struct *tty) | ||
518 | { | ||
519 | clear_bit(TTY_LDISC, &tty->flags); | ||
520 | return cancel_delayed_work(&tty->buf.work); | ||
521 | } | ||
522 | |||
523 | /** | ||
524 | * tty_ldisc_wait_idle - wait for the ldisc to become idle | ||
525 | * @tty: tty to wait for | ||
526 | * | ||
527 | * Wait for the line discipline to become idle. The discipline must | ||
528 | * have been halted for this to guarantee it remains idle. | ||
529 | * | ||
530 | * tty_ldisc_lock protects the ref counts currently. | ||
531 | */ | ||
532 | |||
533 | static int tty_ldisc_wait_idle(struct tty_struct *tty) | ||
534 | { | ||
535 | unsigned long flags; | ||
536 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
537 | while (tty->ldisc->refcount) { | ||
538 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
539 | if (wait_event_timeout(tty_ldisc_wait, | ||
540 | tty->ldisc->refcount == 0, 5 * HZ) == 0) | ||
541 | return -EBUSY; | ||
542 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
543 | } | ||
544 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | /** | ||
447 | * tty_set_ldisc - set line discipline | 549 | * tty_set_ldisc - set line discipline |
448 | * @tty: the terminal to set | 550 | * @tty: the terminal to set |
449 | * @ldisc: the line discipline | 551 | * @ldisc: the line discipline |
450 | * | 552 | * |
451 | * Set the discipline of a tty line. Must be called from a process | 553 | * Set the discipline of a tty line. Must be called from a process |
452 | * context. | 554 | * context. The ldisc change logic has to protect itself against any |
555 | * overlapping ldisc change (including on the other end of pty pairs), | ||
556 | * the close of one side of a tty/pty pair, and eventually hangup. | ||
453 | * | 557 | * |
454 | * Locking: takes tty_ldisc_lock. | 558 | * Locking: takes tty_ldisc_lock, termios_mutex |
455 | * called functions take termios_mutex | ||
456 | */ | 559 | */ |
457 | 560 | ||
458 | int tty_set_ldisc(struct tty_struct *tty, int ldisc) | 561 | int tty_set_ldisc(struct tty_struct *tty, int ldisc) |
459 | { | 562 | { |
460 | int retval; | 563 | int retval; |
461 | struct tty_ldisc o_ldisc, new_ldisc; | 564 | struct tty_ldisc *o_ldisc, *new_ldisc; |
462 | int work; | 565 | int work, o_work = 0; |
463 | unsigned long flags; | ||
464 | struct tty_struct *o_tty; | 566 | struct tty_struct *o_tty; |
465 | 567 | ||
466 | restart: | 568 | new_ldisc = tty_ldisc_get(ldisc); |
467 | /* This is a bit ugly for now but means we can break the 'ldisc | 569 | if (IS_ERR(new_ldisc)) |
468 | is part of the tty struct' assumption later */ | 570 | return PTR_ERR(new_ldisc); |
469 | retval = tty_ldisc_get(ldisc, &new_ldisc); | 571 | |
470 | if (retval) | 572 | /* |
471 | return retval; | 573 | * We need to look at the tty locking here for pty/tty pairs |
574 | * when both sides try to change in parallel. | ||
575 | */ | ||
576 | |||
577 | o_tty = tty->link; /* o_tty is the pty side or NULL */ | ||
578 | |||
579 | |||
580 | /* | ||
581 | * Check the no-op case | ||
582 | */ | ||
583 | |||
584 | if (tty->ldisc->ops->num == ldisc) { | ||
585 | tty_ldisc_put(new_ldisc); | ||
586 | return 0; | ||
587 | } | ||
472 | 588 | ||
473 | /* | 589 | /* |
474 | * Problem: What do we do if this blocks ? | 590 | * Problem: What do we do if this blocks ? |
591 | * We could deadlock here | ||
475 | */ | 592 | */ |
476 | 593 | ||
477 | tty_wait_until_sent(tty, 0); | 594 | tty_wait_until_sent(tty, 0); |
478 | 595 | ||
479 | if (tty->ldisc.ops->num == ldisc) { | 596 | mutex_lock(&tty->ldisc_mutex); |
480 | tty_ldisc_put(new_ldisc.ops); | 597 | |
481 | return 0; | 598 | /* |
599 | * We could be midstream of another ldisc change which has | ||
600 | * dropped the lock during processing. If so we need to wait. | ||
601 | */ | ||
602 | |||
603 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | ||
604 | mutex_unlock(&tty->ldisc_mutex); | ||
605 | wait_event(tty_ldisc_wait, | ||
606 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | ||
607 | mutex_lock(&tty->ldisc_mutex); | ||
482 | } | 608 | } |
609 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
483 | 610 | ||
484 | /* | 611 | /* |
485 | * No more input please, we are switching. The new ldisc | 612 | * No more input please, we are switching. The new ldisc |
@@ -489,8 +616,6 @@ restart: | |||
489 | tty->receive_room = 0; | 616 | tty->receive_room = 0; |
490 | 617 | ||
491 | o_ldisc = tty->ldisc; | 618 | o_ldisc = tty->ldisc; |
492 | o_tty = tty->link; | ||
493 | |||
494 | /* | 619 | /* |
495 | * Make sure we don't change while someone holds a | 620 | * Make sure we don't change while someone holds a |
496 | * reference to the line discipline. The TTY_LDISC bit | 621 | * reference to the line discipline. The TTY_LDISC bit |
@@ -501,108 +626,181 @@ restart: | |||
501 | * with a userspace app continually trying to use the tty in | 626 | * with a userspace app continually trying to use the tty in |
502 | * parallel to the change and re-referencing the tty. | 627 | * parallel to the change and re-referencing the tty. |
503 | */ | 628 | */ |
504 | clear_bit(TTY_LDISC, &tty->flags); | ||
505 | if (o_tty) | ||
506 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
507 | 629 | ||
508 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 630 | work = tty_ldisc_halt(tty); |
509 | if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) { | ||
510 | if (tty->ldisc.refcount) { | ||
511 | /* Free the new ldisc we grabbed. Must drop the lock | ||
512 | first. */ | ||
513 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
514 | tty_ldisc_put(o_ldisc.ops); | ||
515 | /* | ||
516 | * There are several reasons we may be busy, including | ||
517 | * random momentary I/O traffic. We must therefore | ||
518 | * retry. We could distinguish between blocking ops | ||
519 | * and retries if we made tty_ldisc_wait() smarter. | ||
520 | * That is up for discussion. | ||
521 | */ | ||
522 | if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0) | ||
523 | return -ERESTARTSYS; | ||
524 | goto restart; | ||
525 | } | ||
526 | if (o_tty && o_tty->ldisc.refcount) { | ||
527 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
528 | tty_ldisc_put(o_tty->ldisc.ops); | ||
529 | if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0) | ||
530 | return -ERESTARTSYS; | ||
531 | goto restart; | ||
532 | } | ||
533 | } | ||
534 | /* | ||
535 | * If the TTY_LDISC bit is set, then we are racing against | ||
536 | * another ldisc change | ||
537 | */ | ||
538 | if (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | ||
539 | struct tty_ldisc *ld; | ||
540 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
541 | tty_ldisc_put(new_ldisc.ops); | ||
542 | ld = tty_ldisc_ref_wait(tty); | ||
543 | tty_ldisc_deref(ld); | ||
544 | goto restart; | ||
545 | } | ||
546 | /* | ||
547 | * This flag is used to avoid two parallel ldisc changes. Once | ||
548 | * open and close are fine grained locked this may work better | ||
549 | * as a mutex shared with the open/close/hup paths | ||
550 | */ | ||
551 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
552 | if (o_tty) | 631 | if (o_tty) |
553 | set_bit(TTY_LDISC_CHANGING, &o_tty->flags); | 632 | o_work = tty_ldisc_halt(o_tty); |
554 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
555 | |||
556 | /* | ||
557 | * From this point on we know nobody has an ldisc | ||
558 | * usage reference, nor can they obtain one until | ||
559 | * we say so later on. | ||
560 | */ | ||
561 | 633 | ||
562 | work = cancel_delayed_work(&tty->buf.work); | ||
563 | /* | 634 | /* |
564 | * Wait for ->hangup_work and ->buf.work handlers to terminate | 635 | * Wait for ->hangup_work and ->buf.work handlers to terminate. |
565 | * MUST NOT hold locks here. | 636 | * We must drop the mutex here in case a hangup is also in process. |
566 | */ | 637 | */ |
638 | |||
639 | mutex_unlock(&tty->ldisc_mutex); | ||
640 | |||
567 | flush_scheduled_work(); | 641 | flush_scheduled_work(); |
642 | |||
643 | /* Let any existing reference holders finish */ | ||
644 | retval = tty_ldisc_wait_idle(tty); | ||
645 | if (retval < 0) { | ||
646 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
647 | tty_ldisc_put(new_ldisc); | ||
648 | return retval; | ||
649 | } | ||
650 | |||
651 | mutex_lock(&tty->ldisc_mutex); | ||
652 | if (test_bit(TTY_HUPPED, &tty->flags)) { | ||
653 | /* We were raced by the hangup method. It will have stomped | ||
654 | the ldisc data and closed the ldisc down */ | ||
655 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
656 | mutex_unlock(&tty->ldisc_mutex); | ||
657 | tty_ldisc_put(new_ldisc); | ||
658 | return -EIO; | ||
659 | } | ||
660 | |||
568 | /* Shutdown the current discipline. */ | 661 | /* Shutdown the current discipline. */ |
569 | if (o_ldisc.ops->close) | 662 | tty_ldisc_close(tty, o_ldisc); |
570 | (o_ldisc.ops->close)(tty); | ||
571 | 663 | ||
572 | /* Now set up the new line discipline. */ | 664 | /* Now set up the new line discipline. */ |
573 | tty_ldisc_assign(tty, &new_ldisc); | 665 | tty_ldisc_assign(tty, new_ldisc); |
574 | tty_set_termios_ldisc(tty, ldisc); | 666 | tty_set_termios_ldisc(tty, ldisc); |
575 | if (new_ldisc.ops->open) | 667 | |
576 | retval = (new_ldisc.ops->open)(tty); | 668 | retval = tty_ldisc_open(tty, new_ldisc); |
577 | if (retval < 0) { | 669 | if (retval < 0) { |
578 | tty_ldisc_put(new_ldisc.ops); | 670 | /* Back to the old one or N_TTY if we can't */ |
579 | tty_ldisc_restore(tty, &o_ldisc); | 671 | tty_ldisc_put(new_ldisc); |
672 | tty_ldisc_restore(tty, o_ldisc); | ||
580 | } | 673 | } |
674 | |||
581 | /* At this point we hold a reference to the new ldisc and a | 675 | /* At this point we hold a reference to the new ldisc and a |
582 | a reference to the old ldisc. If we ended up flipping back | 676 | a reference to the old ldisc. If we ended up flipping back |
583 | to the existing ldisc we have two references to it */ | 677 | to the existing ldisc we have two references to it */ |
584 | 678 | ||
585 | if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc) | 679 | if (tty->ldisc->ops->num != o_ldisc->ops->num && tty->ops->set_ldisc) |
586 | tty->ops->set_ldisc(tty); | 680 | tty->ops->set_ldisc(tty); |
587 | 681 | ||
588 | tty_ldisc_put(o_ldisc.ops); | 682 | tty_ldisc_put(o_ldisc); |
589 | 683 | ||
590 | /* | 684 | /* |
591 | * Allow ldisc referencing to occur as soon as the driver | 685 | * Allow ldisc referencing to occur again |
592 | * ldisc callback completes. | ||
593 | */ | 686 | */ |
594 | 687 | ||
595 | tty_ldisc_enable(tty); | 688 | tty_ldisc_enable(tty); |
596 | if (o_tty) | 689 | if (o_tty) |
597 | tty_ldisc_enable(o_tty); | 690 | tty_ldisc_enable(o_tty); |
598 | 691 | ||
599 | /* Restart it in case no characters kick it off. Safe if | 692 | /* Restart the work queue in case no characters kick it off. Safe if |
600 | already running */ | 693 | already running */ |
601 | if (work) | 694 | if (work) |
602 | schedule_delayed_work(&tty->buf.work, 1); | 695 | schedule_delayed_work(&tty->buf.work, 1); |
696 | if (o_work) | ||
697 | schedule_delayed_work(&o_tty->buf.work, 1); | ||
698 | mutex_unlock(&tty->ldisc_mutex); | ||
603 | return retval; | 699 | return retval; |
604 | } | 700 | } |
605 | 701 | ||
702 | /** | ||
703 | * tty_reset_termios - reset terminal state | ||
704 | * @tty: tty to reset | ||
705 | * | ||
706 | * Restore a terminal to the driver default state. | ||
707 | */ | ||
708 | |||
709 | static void tty_reset_termios(struct tty_struct *tty) | ||
710 | { | ||
711 | mutex_lock(&tty->termios_mutex); | ||
712 | *tty->termios = tty->driver->init_termios; | ||
713 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); | ||
714 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); | ||
715 | mutex_unlock(&tty->termios_mutex); | ||
716 | } | ||
717 | |||
718 | |||
719 | /** | ||
720 | * tty_ldisc_reinit - reinitialise the tty ldisc | ||
721 | * @tty: tty to reinit | ||
722 | * | ||
723 | * Switch the tty back to N_TTY line discipline and leave the | ||
724 | * ldisc state closed | ||
725 | */ | ||
726 | |||
727 | static void tty_ldisc_reinit(struct tty_struct *tty) | ||
728 | { | ||
729 | struct tty_ldisc *ld; | ||
730 | |||
731 | tty_ldisc_close(tty, tty->ldisc); | ||
732 | tty_ldisc_put(tty->ldisc); | ||
733 | tty->ldisc = NULL; | ||
734 | /* | ||
735 | * Switch the line discipline back | ||
736 | */ | ||
737 | ld = tty_ldisc_get(N_TTY); | ||
738 | BUG_ON(IS_ERR(ld)); | ||
739 | tty_ldisc_assign(tty, ld); | ||
740 | tty_set_termios_ldisc(tty, N_TTY); | ||
741 | } | ||
742 | |||
743 | /** | ||
744 | * tty_ldisc_hangup - hangup ldisc reset | ||
745 | * @tty: tty being hung up | ||
746 | * | ||
747 | * Some tty devices reset their termios when they receive a hangup | ||
748 | * event. In that situation we must also switch back to N_TTY properly | ||
749 | * before we reset the termios data. | ||
750 | * | ||
751 | * Locking: We can take the ldisc mutex as the rest of the code is | ||
752 | * careful to allow for this. | ||
753 | * | ||
754 | * In the pty pair case this occurs in the close() path of the | ||
755 | * tty itself so we must be careful about locking rules. | ||
756 | */ | ||
757 | |||
758 | void tty_ldisc_hangup(struct tty_struct *tty) | ||
759 | { | ||
760 | struct tty_ldisc *ld; | ||
761 | |||
762 | /* | ||
763 | * FIXME! What are the locking issues here? This may me overdoing | ||
764 | * things... This question is especially important now that we've | ||
765 | * removed the irqlock. | ||
766 | */ | ||
767 | ld = tty_ldisc_ref(tty); | ||
768 | if (ld != NULL) { | ||
769 | /* We may have no line discipline at this point */ | ||
770 | if (ld->ops->flush_buffer) | ||
771 | ld->ops->flush_buffer(tty); | ||
772 | tty_driver_flush_buffer(tty); | ||
773 | if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && | ||
774 | ld->ops->write_wakeup) | ||
775 | ld->ops->write_wakeup(tty); | ||
776 | if (ld->ops->hangup) | ||
777 | ld->ops->hangup(tty); | ||
778 | tty_ldisc_deref(ld); | ||
779 | } | ||
780 | /* | ||
781 | * FIXME: Once we trust the LDISC code better we can wait here for | ||
782 | * ldisc completion and fix the driver call race | ||
783 | */ | ||
784 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); | ||
785 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); | ||
786 | /* | ||
787 | * Shutdown the current line discipline, and reset it to | ||
788 | * N_TTY. | ||
789 | */ | ||
790 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | ||
791 | /* Avoid racing set_ldisc */ | ||
792 | mutex_lock(&tty->ldisc_mutex); | ||
793 | /* Switch back to N_TTY */ | ||
794 | tty_ldisc_reinit(tty); | ||
795 | /* At this point we have a closed ldisc and we want to | ||
796 | reopen it. We could defer this to the next open but | ||
797 | it means auditing a lot of other paths so this is a FIXME */ | ||
798 | WARN_ON(tty_ldisc_open(tty, tty->ldisc)); | ||
799 | tty_ldisc_enable(tty); | ||
800 | mutex_unlock(&tty->ldisc_mutex); | ||
801 | tty_reset_termios(tty); | ||
802 | } | ||
803 | } | ||
606 | 804 | ||
607 | /** | 805 | /** |
608 | * tty_ldisc_setup - open line discipline | 806 | * tty_ldisc_setup - open line discipline |
@@ -610,24 +808,23 @@ restart: | |||
610 | * @o_tty: pair tty for pty/tty pairs | 808 | * @o_tty: pair tty for pty/tty pairs |
611 | * | 809 | * |
612 | * Called during the initial open of a tty/pty pair in order to set up the | 810 | * Called during the initial open of a tty/pty pair in order to set up the |
613 | * line discplines and bind them to the tty. | 811 | * line disciplines and bind them to the tty. This has no locking issues |
812 | * as the device isn't yet active. | ||
614 | */ | 813 | */ |
615 | 814 | ||
616 | int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) | 815 | int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) |
617 | { | 816 | { |
618 | struct tty_ldisc *ld = &tty->ldisc; | 817 | struct tty_ldisc *ld = tty->ldisc; |
619 | int retval; | 818 | int retval; |
620 | 819 | ||
621 | if (ld->ops->open) { | 820 | retval = tty_ldisc_open(tty, ld); |
622 | retval = (ld->ops->open)(tty); | 821 | if (retval) |
623 | if (retval) | 822 | return retval; |
624 | return retval; | 823 | |
625 | } | 824 | if (o_tty) { |
626 | if (o_tty && o_tty->ldisc.ops->open) { | 825 | retval = tty_ldisc_open(o_tty, o_tty->ldisc); |
627 | retval = (o_tty->ldisc.ops->open)(o_tty); | ||
628 | if (retval) { | 826 | if (retval) { |
629 | if (ld->ops->close) | 827 | tty_ldisc_close(tty, ld); |
630 | (ld->ops->close)(tty); | ||
631 | return retval; | 828 | return retval; |
632 | } | 829 | } |
633 | tty_ldisc_enable(o_tty); | 830 | tty_ldisc_enable(o_tty); |
@@ -635,32 +832,25 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) | |||
635 | tty_ldisc_enable(tty); | 832 | tty_ldisc_enable(tty); |
636 | return 0; | 833 | return 0; |
637 | } | 834 | } |
638 | |||
639 | /** | 835 | /** |
640 | * tty_ldisc_release - release line discipline | 836 | * tty_ldisc_release - release line discipline |
641 | * @tty: tty being shut down | 837 | * @tty: tty being shut down |
642 | * @o_tty: pair tty for pty/tty pairs | 838 | * @o_tty: pair tty for pty/tty pairs |
643 | * | 839 | * |
644 | * Called during the final close of a tty/pty pair in order to shut down the | 840 | * Called during the final close of a tty/pty pair in order to shut down |
645 | * line discpline layer. | 841 | * the line discpline layer. On exit the ldisc assigned is N_TTY and the |
842 | * ldisc has not been opened. | ||
646 | */ | 843 | */ |
647 | 844 | ||
648 | void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | 845 | void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) |
649 | { | 846 | { |
650 | unsigned long flags; | ||
651 | struct tty_ldisc ld; | ||
652 | /* | 847 | /* |
653 | * Prevent flush_to_ldisc() from rescheduling the work for later. Then | 848 | * Prevent flush_to_ldisc() from rescheduling the work for later. Then |
654 | * kill any delayed work. As this is the final close it does not | 849 | * kill any delayed work. As this is the final close it does not |
655 | * race with the set_ldisc code path. | 850 | * race with the set_ldisc code path. |
656 | */ | 851 | */ |
657 | clear_bit(TTY_LDISC, &tty->flags); | ||
658 | cancel_delayed_work(&tty->buf.work); | ||
659 | |||
660 | /* | ||
661 | * Wait for ->hangup_work and ->buf.work handlers to terminate | ||
662 | */ | ||
663 | 852 | ||
853 | tty_ldisc_halt(tty); | ||
664 | flush_scheduled_work(); | 854 | flush_scheduled_work(); |
665 | 855 | ||
666 | /* | 856 | /* |
@@ -668,38 +858,19 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
668 | * side waiters as the file is closing so user count on the file | 858 | * side waiters as the file is closing so user count on the file |
669 | * side is zero. | 859 | * side is zero. |
670 | */ | 860 | */ |
671 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 861 | |
672 | while (tty->ldisc.refcount) { | 862 | tty_ldisc_wait_idle(tty); |
673 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 863 | |
674 | wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0); | ||
675 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
676 | } | ||
677 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
678 | /* | 864 | /* |
679 | * Shutdown the current line discipline, and reset it to N_TTY. | 865 | * Shutdown the current line discipline, and reset it to N_TTY. |
680 | * | 866 | * |
681 | * FIXME: this MUST get fixed for the new reflocking | 867 | * FIXME: this MUST get fixed for the new reflocking |
682 | */ | 868 | */ |
683 | if (tty->ldisc.ops->close) | ||
684 | (tty->ldisc.ops->close)(tty); | ||
685 | tty_ldisc_put(tty->ldisc.ops); | ||
686 | 869 | ||
687 | /* | 870 | tty_ldisc_reinit(tty); |
688 | * Switch the line discipline back | 871 | /* This will need doing differently if we need to lock */ |
689 | */ | 872 | if (o_tty) |
690 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); | 873 | tty_ldisc_release(o_tty, NULL); |
691 | tty_ldisc_assign(tty, &ld); | ||
692 | tty_set_termios_ldisc(tty, N_TTY); | ||
693 | if (o_tty) { | ||
694 | /* FIXME: could o_tty be in setldisc here ? */ | ||
695 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
696 | if (o_tty->ldisc.ops->close) | ||
697 | (o_tty->ldisc.ops->close)(o_tty); | ||
698 | tty_ldisc_put(o_tty->ldisc.ops); | ||
699 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); | ||
700 | tty_ldisc_assign(o_tty, &ld); | ||
701 | tty_set_termios_ldisc(o_tty, N_TTY); | ||
702 | } | ||
703 | } | 874 | } |
704 | 875 | ||
705 | /** | 876 | /** |
@@ -712,10 +883,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
712 | 883 | ||
713 | void tty_ldisc_init(struct tty_struct *tty) | 884 | void tty_ldisc_init(struct tty_struct *tty) |
714 | { | 885 | { |
715 | struct tty_ldisc ld; | 886 | struct tty_ldisc *ld = tty_ldisc_get(N_TTY); |
716 | if (tty_ldisc_get(N_TTY, &ld) < 0) | 887 | if (IS_ERR(ld)) |
717 | panic("n_tty: init_tty"); | 888 | panic("n_tty: init_tty"); |
718 | tty_ldisc_assign(tty, &ld); | 889 | tty_ldisc_assign(tty, ld); |
719 | } | 890 | } |
720 | 891 | ||
721 | void tty_ldisc_begin(void) | 892 | void tty_ldisc_begin(void) |
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index 9b8004c72686..62dadfc95e34 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
@@ -137,7 +137,7 @@ int tty_port_carrier_raised(struct tty_port *port) | |||
137 | EXPORT_SYMBOL(tty_port_carrier_raised); | 137 | EXPORT_SYMBOL(tty_port_carrier_raised); |
138 | 138 | ||
139 | /** | 139 | /** |
140 | * tty_port_raise_dtr_rts - Riase DTR/RTS | 140 | * tty_port_raise_dtr_rts - Raise DTR/RTS |
141 | * @port: tty port | 141 | * @port: tty port |
142 | * | 142 | * |
143 | * Wrapper for the DTR/RTS raise logic. For the moment this is used | 143 | * Wrapper for the DTR/RTS raise logic. For the moment this is used |
@@ -147,12 +147,28 @@ EXPORT_SYMBOL(tty_port_carrier_raised); | |||
147 | 147 | ||
148 | void tty_port_raise_dtr_rts(struct tty_port *port) | 148 | void tty_port_raise_dtr_rts(struct tty_port *port) |
149 | { | 149 | { |
150 | if (port->ops->raise_dtr_rts) | 150 | if (port->ops->dtr_rts) |
151 | port->ops->raise_dtr_rts(port); | 151 | port->ops->dtr_rts(port, 1); |
152 | } | 152 | } |
153 | EXPORT_SYMBOL(tty_port_raise_dtr_rts); | 153 | EXPORT_SYMBOL(tty_port_raise_dtr_rts); |
154 | 154 | ||
155 | /** | 155 | /** |
156 | * tty_port_lower_dtr_rts - Lower DTR/RTS | ||
157 | * @port: tty port | ||
158 | * | ||
159 | * Wrapper for the DTR/RTS raise logic. For the moment this is used | ||
160 | * to hide some internal details. This will eventually become entirely | ||
161 | * internal to the tty port. | ||
162 | */ | ||
163 | |||
164 | void tty_port_lower_dtr_rts(struct tty_port *port) | ||
165 | { | ||
166 | if (port->ops->dtr_rts) | ||
167 | port->ops->dtr_rts(port, 0); | ||
168 | } | ||
169 | EXPORT_SYMBOL(tty_port_lower_dtr_rts); | ||
170 | |||
171 | /** | ||
156 | * tty_port_block_til_ready - Waiting logic for tty open | 172 | * tty_port_block_til_ready - Waiting logic for tty open |
157 | * @port: the tty port being opened | 173 | * @port: the tty port being opened |
158 | * @tty: the tty device being bound | 174 | * @tty: the tty device being bound |
@@ -167,7 +183,7 @@ EXPORT_SYMBOL(tty_port_raise_dtr_rts); | |||
167 | * - port flags and counts | 183 | * - port flags and counts |
168 | * | 184 | * |
169 | * The passed tty_port must implement the carrier_raised method if it can | 185 | * The passed tty_port must implement the carrier_raised method if it can |
170 | * do carrier detect and the raise_dtr_rts method if it supports software | 186 | * do carrier detect and the dtr_rts method if it supports software |
171 | * management of these lines. Note that the dtr/rts raise is done each | 187 | * management of these lines. Note that the dtr/rts raise is done each |
172 | * iteration as a hangup may have previously dropped them while we wait. | 188 | * iteration as a hangup may have previously dropped them while we wait. |
173 | */ | 189 | */ |
@@ -182,7 +198,8 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
182 | 198 | ||
183 | /* block if port is in the process of being closed */ | 199 | /* block if port is in the process of being closed */ |
184 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { | 200 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
185 | interruptible_sleep_on(&port->close_wait); | 201 | wait_event_interruptible(port->close_wait, |
202 | !(port->flags & ASYNC_CLOSING)); | ||
186 | if (port->flags & ASYNC_HUP_NOTIFY) | 203 | if (port->flags & ASYNC_HUP_NOTIFY) |
187 | return -EAGAIN; | 204 | return -EAGAIN; |
188 | else | 205 | else |
@@ -205,7 +222,6 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
205 | before the next open may complete */ | 222 | before the next open may complete */ |
206 | 223 | ||
207 | retval = 0; | 224 | retval = 0; |
208 | add_wait_queue(&port->open_wait, &wait); | ||
209 | 225 | ||
210 | /* The port lock protects the port counts */ | 226 | /* The port lock protects the port counts */ |
211 | spin_lock_irqsave(&port->lock, flags); | 227 | spin_lock_irqsave(&port->lock, flags); |
@@ -219,7 +235,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
219 | if (tty->termios->c_cflag & CBAUD) | 235 | if (tty->termios->c_cflag & CBAUD) |
220 | tty_port_raise_dtr_rts(port); | 236 | tty_port_raise_dtr_rts(port); |
221 | 237 | ||
222 | set_current_state(TASK_INTERRUPTIBLE); | 238 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); |
223 | /* Check for a hangup or uninitialised port. Return accordingly */ | 239 | /* Check for a hangup or uninitialised port. Return accordingly */ |
224 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { | 240 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { |
225 | if (port->flags & ASYNC_HUP_NOTIFY) | 241 | if (port->flags & ASYNC_HUP_NOTIFY) |
@@ -240,8 +256,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
240 | } | 256 | } |
241 | schedule(); | 257 | schedule(); |
242 | } | 258 | } |
243 | set_current_state(TASK_RUNNING); | 259 | finish_wait(&port->open_wait, &wait); |
244 | remove_wait_queue(&port->open_wait, &wait); | ||
245 | 260 | ||
246 | /* Update counts. A parallel hangup will have set count to zero and | 261 | /* Update counts. A parallel hangup will have set count to zero and |
247 | we must not mess that up further */ | 262 | we must not mess that up further */ |
@@ -292,6 +307,17 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f | |||
292 | if (port->flags & ASYNC_INITIALIZED && | 307 | if (port->flags & ASYNC_INITIALIZED && |
293 | port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 308 | port->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
294 | tty_wait_until_sent(tty, port->closing_wait); | 309 | tty_wait_until_sent(tty, port->closing_wait); |
310 | if (port->drain_delay) { | ||
311 | unsigned int bps = tty_get_baud_rate(tty); | ||
312 | long timeout; | ||
313 | |||
314 | if (bps > 1200) | ||
315 | timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps, | ||
316 | HZ / 10); | ||
317 | else | ||
318 | timeout = 2 * HZ; | ||
319 | schedule_timeout_interruptible(timeout); | ||
320 | } | ||
295 | return 1; | 321 | return 1; |
296 | } | 322 | } |
297 | EXPORT_SYMBOL(tty_port_close_start); | 323 | EXPORT_SYMBOL(tty_port_close_start); |
@@ -302,6 +328,9 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) | |||
302 | 328 | ||
303 | tty_ldisc_flush(tty); | 329 | tty_ldisc_flush(tty); |
304 | 330 | ||
331 | if (tty->termios->c_cflag & HUPCL) | ||
332 | tty_port_lower_dtr_rts(port); | ||
333 | |||
305 | spin_lock_irqsave(&port->lock, flags); | 334 | spin_lock_irqsave(&port->lock, flags); |
306 | tty->closing = 0; | 335 | tty->closing = 0; |
307 | 336 | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 08151d4de489..c796a86ab7f3 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -95,7 +95,6 @@ | |||
95 | #include <linux/timer.h> | 95 | #include <linux/timer.h> |
96 | #include <linux/interrupt.h> | 96 | #include <linux/interrupt.h> |
97 | #include <linux/workqueue.h> | 97 | #include <linux/workqueue.h> |
98 | #include <linux/bootmem.h> | ||
99 | #include <linux/pm.h> | 98 | #include <linux/pm.h> |
100 | #include <linux/font.h> | 99 | #include <linux/font.h> |
101 | #include <linux/bitops.h> | 100 | #include <linux/bitops.h> |
@@ -2875,14 +2874,11 @@ static int __init con_init(void) | |||
2875 | mod_timer(&console_timer, jiffies + blankinterval); | 2874 | mod_timer(&console_timer, jiffies + blankinterval); |
2876 | } | 2875 | } |
2877 | 2876 | ||
2878 | /* | ||
2879 | * kmalloc is not running yet - we use the bootmem allocator. | ||
2880 | */ | ||
2881 | for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { | 2877 | for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { |
2882 | vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data)); | 2878 | vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); |
2883 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); | 2879 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
2884 | visual_init(vc, currcons, 1); | 2880 | visual_init(vc, currcons, 1); |
2885 | vc->vc_screenbuf = (unsigned short *)alloc_bootmem(vc->vc_screenbuf_size); | 2881 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); |
2886 | vc->vc_kmalloced = 0; | 2882 | vc->vc_kmalloced = 0; |
2887 | vc_init(vc, vc->vc_rows, vc->vc_cols, | 2883 | vc_init(vc, vc->vc_rows, vc->vc_cols, |
2888 | currcons || !vc->vc_sw->con_save_screen); | 2884 | currcons || !vc->vc_sw->con_save_screen); |