1
2
3
4
5#include <linux/types.h>
6#include <linux/errno.h>
7#include <linux/tty.h>
8#include <linux/tty_driver.h>
9#include <linux/tty_flip.h>
10#include <linux/serial.h>
11#include <linux/timer.h>
12#include <linux/string.h>
13#include <linux/slab.h>
14#include <linux/sched.h>
15#include <linux/init.h>
16#include <linux/wait.h>
17#include <linux/bitops.h>
18#include <linux/delay.h>
19#include <linux/module.h>
20
21void tty_port_init(struct tty_port *port)
22{
23 memset(port, 0, sizeof(*port));
24 tty_buffer_init(port);
25 init_waitqueue_head(&port->open_wait);
26 init_waitqueue_head(&port->close_wait);
27 init_waitqueue_head(&port->delta_msr_wait);
28 mutex_init(&port->mutex);
29 mutex_init(&port->buf_mutex);
30 spin_lock_init(&port->lock);
31 port->close_delay = (50 * HZ) / 100;
32 port->closing_wait = (3000 * HZ) / 100;
33 kref_init(&port->kref);
34}
35EXPORT_SYMBOL(tty_port_init);
36
37
38
39
40
41
42
43
44
45
46
47
48void tty_port_link_device(struct tty_port *port,
49 struct tty_driver *driver, unsigned index)
50{
51 if (WARN_ON(index >= driver->num))
52 return;
53 driver->ports[index] = port;
54}
55EXPORT_SYMBOL_GPL(tty_port_link_device);
56
57
58
59
60
61
62
63
64
65
66
67
68struct device *tty_port_register_device(struct tty_port *port,
69 struct tty_driver *driver, unsigned index,
70 struct device *device)
71{
72 tty_port_link_device(port, driver, index);
73 return tty_register_device(driver, index, device);
74}
75EXPORT_SYMBOL_GPL(tty_port_register_device);
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90struct device *tty_port_register_device_attr(struct tty_port *port,
91 struct tty_driver *driver, unsigned index,
92 struct device *device, void *drvdata,
93 const struct attribute_group **attr_grp)
94{
95 tty_port_link_device(port, driver, index);
96 return tty_register_device_attr(driver, index, device, drvdata,
97 attr_grp);
98}
99EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
100
101int tty_port_alloc_xmit_buf(struct tty_port *port)
102{
103
104 mutex_lock(&port->buf_mutex);
105 if (port->xmit_buf == NULL)
106 port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
107 mutex_unlock(&port->buf_mutex);
108 if (port->xmit_buf == NULL)
109 return -ENOMEM;
110 return 0;
111}
112EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
113
114void tty_port_free_xmit_buf(struct tty_port *port)
115{
116 mutex_lock(&port->buf_mutex);
117 if (port->xmit_buf != NULL) {
118 free_page((unsigned long)port->xmit_buf);
119 port->xmit_buf = NULL;
120 }
121 mutex_unlock(&port->buf_mutex);
122}
123EXPORT_SYMBOL(tty_port_free_xmit_buf);
124
125
126
127
128
129
130
131
132
133void tty_port_destroy(struct tty_port *port)
134{
135 tty_buffer_free_all(port);
136}
137EXPORT_SYMBOL(tty_port_destroy);
138
139static void tty_port_destructor(struct kref *kref)
140{
141 struct tty_port *port = container_of(kref, struct tty_port, kref);
142 if (port->xmit_buf)
143 free_page((unsigned long)port->xmit_buf);
144 tty_port_destroy(port);
145 if (port->ops && port->ops->destruct)
146 port->ops->destruct(port);
147 else
148 kfree(port);
149}
150
151void tty_port_put(struct tty_port *port)
152{
153 if (port)
154 kref_put(&port->kref, tty_port_destructor);
155}
156EXPORT_SYMBOL(tty_port_put);
157
158
159
160
161
162
163
164
165
166struct tty_struct *tty_port_tty_get(struct tty_port *port)
167{
168 unsigned long flags;
169 struct tty_struct *tty;
170
171 spin_lock_irqsave(&port->lock, flags);
172 tty = tty_kref_get(port->tty);
173 spin_unlock_irqrestore(&port->lock, flags);
174 return tty;
175}
176EXPORT_SYMBOL(tty_port_tty_get);
177
178
179
180
181
182
183
184
185
186
187void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
188{
189 unsigned long flags;
190
191 spin_lock_irqsave(&port->lock, flags);
192 if (port->tty)
193 tty_kref_put(port->tty);
194 port->tty = tty_kref_get(tty);
195 spin_unlock_irqrestore(&port->lock, flags);
196}
197EXPORT_SYMBOL(tty_port_tty_set);
198
199static void tty_port_shutdown(struct tty_port *port)
200{
201 mutex_lock(&port->mutex);
202 if (port->ops->shutdown && !port->console &&
203 test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
204 port->ops->shutdown(port);
205 mutex_unlock(&port->mutex);
206}
207
208
209
210
211
212
213
214
215
216void tty_port_hangup(struct tty_port *port)
217{
218 unsigned long flags;
219
220 spin_lock_irqsave(&port->lock, flags);
221 port->count = 0;
222 port->flags &= ~ASYNC_NORMAL_ACTIVE;
223 if (port->tty) {
224 set_bit(TTY_IO_ERROR, &port->tty->flags);
225 tty_kref_put(port->tty);
226 }
227 port->tty = NULL;
228 spin_unlock_irqrestore(&port->lock, flags);
229 wake_up_interruptible(&port->open_wait);
230 wake_up_interruptible(&port->delta_msr_wait);
231 tty_port_shutdown(port);
232}
233EXPORT_SYMBOL(tty_port_hangup);
234
235
236
237
238
239
240
241
242
243
244int tty_port_carrier_raised(struct tty_port *port)
245{
246 if (port->ops->carrier_raised == NULL)
247 return 1;
248 return port->ops->carrier_raised(port);
249}
250EXPORT_SYMBOL(tty_port_carrier_raised);
251
252
253
254
255
256
257
258
259
260
261void tty_port_raise_dtr_rts(struct tty_port *port)
262{
263 if (port->ops->dtr_rts)
264 port->ops->dtr_rts(port, 1);
265}
266EXPORT_SYMBOL(tty_port_raise_dtr_rts);
267
268
269
270
271
272
273
274
275
276
277void tty_port_lower_dtr_rts(struct tty_port *port)
278{
279 if (port->ops->dtr_rts)
280 port->ops->dtr_rts(port, 0);
281}
282EXPORT_SYMBOL(tty_port_lower_dtr_rts);
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304int tty_port_block_til_ready(struct tty_port *port,
305 struct tty_struct *tty, struct file *filp)
306{
307 int do_clocal = 0, retval;
308 unsigned long flags;
309 DEFINE_WAIT(wait);
310
311
312 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
313 wait_event_interruptible_tty(tty, port->close_wait,
314 !(port->flags & ASYNC_CLOSING));
315 if (port->flags & ASYNC_HUP_NOTIFY)
316 return -EAGAIN;
317 else
318 return -ERESTARTSYS;
319 }
320
321
322
323 if (tty->flags & (1 << TTY_IO_ERROR)) {
324 port->flags |= ASYNC_NORMAL_ACTIVE;
325 return 0;
326 }
327 if (filp->f_flags & O_NONBLOCK) {
328
329 if (tty->termios.c_cflag & CBAUD)
330 tty_port_raise_dtr_rts(port);
331 port->flags |= ASYNC_NORMAL_ACTIVE;
332 return 0;
333 }
334
335 if (C_CLOCAL(tty))
336 do_clocal = 1;
337
338
339
340
341
342 retval = 0;
343
344
345 spin_lock_irqsave(&port->lock, flags);
346 if (!tty_hung_up_p(filp))
347 port->count--;
348 port->blocked_open++;
349 spin_unlock_irqrestore(&port->lock, flags);
350
351 while (1) {
352
353 if (tty->termios.c_cflag & CBAUD)
354 tty_port_raise_dtr_rts(port);
355
356 prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
357
358
359 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
360 if (port->flags & ASYNC_HUP_NOTIFY)
361 retval = -EAGAIN;
362 else
363 retval = -ERESTARTSYS;
364 break;
365 }
366
367
368
369
370
371
372 if (!(port->flags & ASYNC_CLOSING) &&
373 (do_clocal || tty_port_carrier_raised(port)))
374 break;
375 if (signal_pending(current)) {
376 retval = -ERESTARTSYS;
377 break;
378 }
379 tty_unlock(tty);
380 schedule();
381 tty_lock(tty);
382 }
383 finish_wait(&port->open_wait, &wait);
384
385
386
387 spin_lock_irqsave(&port->lock, flags);
388 if (!tty_hung_up_p(filp))
389 port->count++;
390 port->blocked_open--;
391 if (retval == 0)
392 port->flags |= ASYNC_NORMAL_ACTIVE;
393 spin_unlock_irqrestore(&port->lock, flags);
394 return retval;
395}
396EXPORT_SYMBOL(tty_port_block_til_ready);
397
398int tty_port_close_start(struct tty_port *port,
399 struct tty_struct *tty, struct file *filp)
400{
401 unsigned long flags;
402
403 spin_lock_irqsave(&port->lock, flags);
404 if (tty_hung_up_p(filp)) {
405 spin_unlock_irqrestore(&port->lock, flags);
406 return 0;
407 }
408
409 if (tty->count == 1 && port->count != 1) {
410 printk(KERN_WARNING
411 "tty_port_close_start: tty->count = 1 port count = %d.\n",
412 port->count);
413 port->count = 1;
414 }
415 if (--port->count < 0) {
416 printk(KERN_WARNING "tty_port_close_start: count = %d\n",
417 port->count);
418 port->count = 0;
419 }
420
421 if (port->count) {
422 spin_unlock_irqrestore(&port->lock, flags);
423 if (port->ops->drop)
424 port->ops->drop(port);
425 return 0;
426 }
427 set_bit(ASYNCB_CLOSING, &port->flags);
428 tty->closing = 1;
429 spin_unlock_irqrestore(&port->lock, flags);
430
431 if (tty->flow_stopped)
432 tty_driver_flush_buffer(tty);
433 if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
434 port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
435 tty_wait_until_sent_from_close(tty, port->closing_wait);
436 if (port->drain_delay) {
437 unsigned int bps = tty_get_baud_rate(tty);
438 long timeout;
439
440 if (bps > 1200)
441 timeout = max_t(long,
442 (HZ * 10 * port->drain_delay) / bps, HZ / 10);
443 else
444 timeout = 2 * HZ;
445 schedule_timeout_interruptible(timeout);
446 }
447
448 tty_ldisc_flush(tty);
449
450
451
452 if (tty->termios.c_cflag & HUPCL)
453 tty_port_lower_dtr_rts(port);
454
455
456
457
458 return 1;
459}
460EXPORT_SYMBOL(tty_port_close_start);
461
462void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
463{
464 unsigned long flags;
465
466 spin_lock_irqsave(&port->lock, flags);
467 tty->closing = 0;
468
469 if (port->blocked_open) {
470 spin_unlock_irqrestore(&port->lock, flags);
471 if (port->close_delay) {
472 msleep_interruptible(
473 jiffies_to_msecs(port->close_delay));
474 }
475 spin_lock_irqsave(&port->lock, flags);
476 wake_up_interruptible(&port->open_wait);
477 }
478 port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
479 wake_up_interruptible(&port->close_wait);
480 spin_unlock_irqrestore(&port->lock, flags);
481}
482EXPORT_SYMBOL(tty_port_close_end);
483
484void tty_port_close(struct tty_port *port, struct tty_struct *tty,
485 struct file *filp)
486{
487 if (tty_port_close_start(port, tty, filp) == 0)
488 return;
489 tty_port_shutdown(port);
490 set_bit(TTY_IO_ERROR, &tty->flags);
491 tty_port_close_end(port, tty);
492 tty_port_tty_set(port, NULL);
493}
494EXPORT_SYMBOL(tty_port_close);
495
496
497
498
499
500
501
502
503
504
505
506int tty_port_install(struct tty_port *port, struct tty_driver *driver,
507 struct tty_struct *tty)
508{
509 tty->port = port;
510 return tty_standard_install(driver, tty);
511}
512EXPORT_SYMBOL_GPL(tty_port_install);
513
514int tty_port_open(struct tty_port *port, struct tty_struct *tty,
515 struct file *filp)
516{
517 spin_lock_irq(&port->lock);
518 if (!tty_hung_up_p(filp))
519 ++port->count;
520 spin_unlock_irq(&port->lock);
521 tty_port_tty_set(port, tty);
522
523
524
525
526
527
528
529 mutex_lock(&port->mutex);
530
531 if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
532 clear_bit(TTY_IO_ERROR, &tty->flags);
533 if (port->ops->activate) {
534 int retval = port->ops->activate(port, tty);
535 if (retval) {
536 mutex_unlock(&port->mutex);
537 return retval;
538 }
539 }
540 set_bit(ASYNCB_INITIALIZED, &port->flags);
541 }
542 mutex_unlock(&port->mutex);
543 return tty_port_block_til_ready(port, tty, filp);
544}
545
546EXPORT_SYMBOL(tty_port_open);
547