]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/tty/tty_port.c
TTY: tty_port, add some documentation
[mirror_ubuntu-hirsute-kernel.git] / drivers / tty / tty_port.c
CommitLineData
9e48565d
AC
1/*
2 * Tty port functions
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>
3e61696b 10#include <linux/serial.h>
9e48565d
AC
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 init_waitqueue_head(&port->open_wait);
25 init_waitqueue_head(&port->close_wait);
bdc04e31 26 init_waitqueue_head(&port->delta_msr_wait);
9e48565d 27 mutex_init(&port->mutex);
44e4909e 28 mutex_init(&port->buf_mutex);
4a90f09b 29 spin_lock_init(&port->lock);
9e48565d
AC
30 port->close_delay = (50 * HZ) / 100;
31 port->closing_wait = (3000 * HZ) / 100;
568aafc6 32 kref_init(&port->kref);
9e48565d
AC
33}
34EXPORT_SYMBOL(tty_port_init);
35
72a33bf5
JS
36/**
37 * tty_port_register_device - register tty device
38 * @port: tty_port of the device
39 * @driver: tty_driver for this device
40 * @index: index of the tty
41 * @device: parent if exists, otherwise NULL
42 *
43 * It is the same as tty_register_device except the provided @port is linked to
44 * a concrete tty specified by @index. Use this or tty_port_install (or both).
45 * Call tty_port_link_device as a last resort.
46 */
057eb856
JS
47struct device *tty_port_register_device(struct tty_port *port,
48 struct tty_driver *driver, unsigned index,
49 struct device *device)
50{
51 driver->ports[index] = port;
52 return tty_register_device(driver, index, device);
53}
54EXPORT_SYMBOL_GPL(tty_port_register_device);
55
9e48565d
AC
56int tty_port_alloc_xmit_buf(struct tty_port *port)
57{
58 /* We may sleep in get_zeroed_page() */
44e4909e 59 mutex_lock(&port->buf_mutex);
9e48565d
AC
60 if (port->xmit_buf == NULL)
61 port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
44e4909e 62 mutex_unlock(&port->buf_mutex);
9e48565d
AC
63 if (port->xmit_buf == NULL)
64 return -ENOMEM;
65 return 0;
66}
67EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
68
69void tty_port_free_xmit_buf(struct tty_port *port)
70{
44e4909e 71 mutex_lock(&port->buf_mutex);
9e48565d
AC
72 if (port->xmit_buf != NULL) {
73 free_page((unsigned long)port->xmit_buf);
74 port->xmit_buf = NULL;
75 }
44e4909e 76 mutex_unlock(&port->buf_mutex);
9e48565d
AC
77}
78EXPORT_SYMBOL(tty_port_free_xmit_buf);
79
568aafc6
AC
80static void tty_port_destructor(struct kref *kref)
81{
82 struct tty_port *port = container_of(kref, struct tty_port, kref);
83 if (port->xmit_buf)
84 free_page((unsigned long)port->xmit_buf);
85 if (port->ops->destruct)
86 port->ops->destruct(port);
87 else
88 kfree(port);
89}
90
91void tty_port_put(struct tty_port *port)
92{
93 if (port)
94 kref_put(&port->kref, tty_port_destructor);
95}
96EXPORT_SYMBOL(tty_port_put);
9e48565d 97
4a90f09b
AC
98/**
99 * tty_port_tty_get - get a tty reference
100 * @port: tty port
101 *
102 * Return a refcount protected tty instance or NULL if the port is not
103 * associated with a tty (eg due to close or hangup)
104 */
105
106struct tty_struct *tty_port_tty_get(struct tty_port *port)
107{
108 unsigned long flags;
109 struct tty_struct *tty;
110
111 spin_lock_irqsave(&port->lock, flags);
112 tty = tty_kref_get(port->tty);
113 spin_unlock_irqrestore(&port->lock, flags);
114 return tty;
115}
116EXPORT_SYMBOL(tty_port_tty_get);
117
118/**
119 * tty_port_tty_set - set the tty of a port
120 * @port: tty port
121 * @tty: the tty
122 *
123 * Associate the port and tty pair. Manages any internal refcounts.
124 * Pass NULL to deassociate a port
125 */
126
127void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
128{
129 unsigned long flags;
130
131 spin_lock_irqsave(&port->lock, flags);
132 if (port->tty)
133 tty_kref_put(port->tty);
cb4bca35 134 port->tty = tty_kref_get(tty);
4a90f09b
AC
135 spin_unlock_irqrestore(&port->lock, flags);
136}
137EXPORT_SYMBOL(tty_port_tty_set);
31f35939 138
7ca0ff9a
AC
139static void tty_port_shutdown(struct tty_port *port)
140{
64bc3979 141 mutex_lock(&port->mutex);
336cee42 142 if (port->ops->shutdown && !port->console &&
1f5c13fa 143 test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
7ca0ff9a 144 port->ops->shutdown(port);
64bc3979 145 mutex_unlock(&port->mutex);
7ca0ff9a
AC
146}
147
3e61696b
AC
148/**
149 * tty_port_hangup - hangup helper
150 * @port: tty port
151 *
152 * Perform port level tty hangup flag and count changes. Drop the tty
153 * reference.
154 */
155
156void tty_port_hangup(struct tty_port *port)
157{
158 unsigned long flags;
159
160 spin_lock_irqsave(&port->lock, flags);
161 port->count = 0;
162 port->flags &= ~ASYNC_NORMAL_ACTIVE;
d74e8286
AC
163 if (port->tty) {
164 set_bit(TTY_IO_ERROR, &port->tty->flags);
3e61696b 165 tty_kref_put(port->tty);
d74e8286 166 }
3e61696b
AC
167 port->tty = NULL;
168 spin_unlock_irqrestore(&port->lock, flags);
169 wake_up_interruptible(&port->open_wait);
bdc04e31 170 wake_up_interruptible(&port->delta_msr_wait);
7ca0ff9a 171 tty_port_shutdown(port);
3e61696b
AC
172}
173EXPORT_SYMBOL(tty_port_hangup);
174
31f35939
AC
175/**
176 * tty_port_carrier_raised - carrier raised check
177 * @port: tty port
178 *
179 * Wrapper for the carrier detect logic. For the moment this is used
180 * to hide some internal details. This will eventually become entirely
181 * internal to the tty port.
182 */
183
184int tty_port_carrier_raised(struct tty_port *port)
185{
186 if (port->ops->carrier_raised == NULL)
187 return 1;
188 return port->ops->carrier_raised(port);
189}
190EXPORT_SYMBOL(tty_port_carrier_raised);
5d951fb4
AC
191
192/**
fcc8ac18 193 * tty_port_raise_dtr_rts - Raise DTR/RTS
5d951fb4
AC
194 * @port: tty port
195 *
196 * Wrapper for the DTR/RTS raise logic. For the moment this is used
197 * to hide some internal details. This will eventually become entirely
198 * internal to the tty port.
199 */
200
201void tty_port_raise_dtr_rts(struct tty_port *port)
202{
fcc8ac18
AC
203 if (port->ops->dtr_rts)
204 port->ops->dtr_rts(port, 1);
5d951fb4
AC
205}
206EXPORT_SYMBOL(tty_port_raise_dtr_rts);
36c621d8 207
fcc8ac18
AC
208/**
209 * tty_port_lower_dtr_rts - Lower DTR/RTS
210 * @port: tty port
211 *
212 * Wrapper for the DTR/RTS raise logic. For the moment this is used
213 * to hide some internal details. This will eventually become entirely
214 * internal to the tty port.
215 */
216
217void tty_port_lower_dtr_rts(struct tty_port *port)
218{
219 if (port->ops->dtr_rts)
220 port->ops->dtr_rts(port, 0);
221}
222EXPORT_SYMBOL(tty_port_lower_dtr_rts);
223
36c621d8
AC
224/**
225 * tty_port_block_til_ready - Waiting logic for tty open
226 * @port: the tty port being opened
227 * @tty: the tty device being bound
228 * @filp: the file pointer of the opener
229 *
230 * Implement the core POSIX/SuS tty behaviour when opening a tty device.
231 * Handles:
232 * - hangup (both before and during)
233 * - non blocking open
234 * - rts/dtr/dcd
235 * - signals
236 * - port flags and counts
237 *
238 * The passed tty_port must implement the carrier_raised method if it can
fcc8ac18 239 * do carrier detect and the dtr_rts method if it supports software
36c621d8
AC
240 * management of these lines. Note that the dtr/rts raise is done each
241 * iteration as a hangup may have previously dropped them while we wait.
242 */
d774a56d 243
36c621d8
AC
244int tty_port_block_til_ready(struct tty_port *port,
245 struct tty_struct *tty, struct file *filp)
246{
247 int do_clocal = 0, retval;
248 unsigned long flags;
6af9a43d 249 DEFINE_WAIT(wait);
36c621d8
AC
250
251 /* block if port is in the process of being closed */
252 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
89c8d91e 253 wait_event_interruptible_tty(tty, port->close_wait,
5fc5b42a 254 !(port->flags & ASYNC_CLOSING));
36c621d8
AC
255 if (port->flags & ASYNC_HUP_NOTIFY)
256 return -EAGAIN;
257 else
258 return -ERESTARTSYS;
259 }
260
261 /* if non-blocking mode is set we can pass directly to open unless
262 the port has just hung up or is in another error state */
8627b96d
AC
263 if (tty->flags & (1 << TTY_IO_ERROR)) {
264 port->flags |= ASYNC_NORMAL_ACTIVE;
265 return 0;
266 }
267 if (filp->f_flags & O_NONBLOCK) {
4175f3e3 268 /* Indicate we are open */
adc8d746 269 if (tty->termios.c_cflag & CBAUD)
4175f3e3 270 tty_port_raise_dtr_rts(port);
36c621d8
AC
271 port->flags |= ASYNC_NORMAL_ACTIVE;
272 return 0;
273 }
274
275 if (C_CLOCAL(tty))
276 do_clocal = 1;
277
278 /* Block waiting until we can proceed. We may need to wait for the
279 carrier, but we must also wait for any close that is in progress
280 before the next open may complete */
281
282 retval = 0;
36c621d8
AC
283
284 /* The port lock protects the port counts */
285 spin_lock_irqsave(&port->lock, flags);
286 if (!tty_hung_up_p(filp))
287 port->count--;
288 port->blocked_open++;
289 spin_unlock_irqrestore(&port->lock, flags);
290
291 while (1) {
292 /* Indicate we are open */
adc8d746 293 if (tty->termios.c_cflag & CBAUD)
7834909f 294 tty_port_raise_dtr_rts(port);
36c621d8 295
3e3b5c08 296 prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
d774a56d
AC
297 /* Check for a hangup or uninitialised port.
298 Return accordingly */
36c621d8
AC
299 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
300 if (port->flags & ASYNC_HUP_NOTIFY)
301 retval = -EAGAIN;
302 else
303 retval = -ERESTARTSYS;
304 break;
305 }
0eee50af
JS
306 /*
307 * Probe the carrier. For devices with no carrier detect
308 * tty_port_carrier_raised will always return true.
309 * Never ask drivers if CLOCAL is set, this causes troubles
310 * on some hardware.
311 */
36c621d8 312 if (!(port->flags & ASYNC_CLOSING) &&
0eee50af 313 (do_clocal || tty_port_carrier_raised(port)))
36c621d8
AC
314 break;
315 if (signal_pending(current)) {
316 retval = -ERESTARTSYS;
317 break;
318 }
89c8d91e 319 tty_unlock(tty);
36c621d8 320 schedule();
89c8d91e 321 tty_lock(tty);
36c621d8 322 }
3e3b5c08 323 finish_wait(&port->open_wait, &wait);
36c621d8
AC
324
325 /* Update counts. A parallel hangup will have set count to zero and
326 we must not mess that up further */
327 spin_lock_irqsave(&port->lock, flags);
328 if (!tty_hung_up_p(filp))
329 port->count++;
330 port->blocked_open--;
331 if (retval == 0)
332 port->flags |= ASYNC_NORMAL_ACTIVE;
333 spin_unlock_irqrestore(&port->lock, flags);
ecc2e05e 334 return retval;
36c621d8
AC
335}
336EXPORT_SYMBOL(tty_port_block_til_ready);
337
d774a56d
AC
338int tty_port_close_start(struct tty_port *port,
339 struct tty_struct *tty, struct file *filp)
a6614999
AC
340{
341 unsigned long flags;
342
343 spin_lock_irqsave(&port->lock, flags);
344 if (tty_hung_up_p(filp)) {
345 spin_unlock_irqrestore(&port->lock, flags);
346 return 0;
347 }
348
d774a56d 349 if (tty->count == 1 && port->count != 1) {
a6614999
AC
350 printk(KERN_WARNING
351 "tty_port_close_start: tty->count = 1 port count = %d.\n",
352 port->count);
353 port->count = 1;
354 }
355 if (--port->count < 0) {
356 printk(KERN_WARNING "tty_port_close_start: count = %d\n",
357 port->count);
358 port->count = 0;
359 }
360
361 if (port->count) {
362 spin_unlock_irqrestore(&port->lock, flags);
7ca0ff9a
AC
363 if (port->ops->drop)
364 port->ops->drop(port);
a6614999
AC
365 return 0;
366 }
1f5c13fa 367 set_bit(ASYNCB_CLOSING, &port->flags);
a6614999
AC
368 tty->closing = 1;
369 spin_unlock_irqrestore(&port->lock, flags);
fba85e01
AC
370 /* Don't block on a stalled port, just pull the chain */
371 if (tty->flow_stopped)
372 tty_driver_flush_buffer(tty);
7ca0ff9a 373 if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
6ed1dbae 374 port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
424cc039 375 tty_wait_until_sent_from_close(tty, port->closing_wait);
1ec739be
AC
376 if (port->drain_delay) {
377 unsigned int bps = tty_get_baud_rate(tty);
378 long timeout;
379
380 if (bps > 1200)
d774a56d
AC
381 timeout = max_t(long,
382 (HZ * 10 * port->drain_delay) / bps, HZ / 10);
1ec739be
AC
383 else
384 timeout = 2 * HZ;
385 schedule_timeout_interruptible(timeout);
386 }
e707c35c
AC
387 /* Flush the ldisc buffering */
388 tty_ldisc_flush(tty);
389
390 /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
391 hang up the line */
adc8d746 392 if (tty->termios.c_cflag & HUPCL)
e707c35c
AC
393 tty_port_lower_dtr_rts(port);
394
7ca0ff9a
AC
395 /* Don't call port->drop for the last reference. Callers will want
396 to drop the last active reference in ->shutdown() or the tty
397 shutdown path */
a6614999
AC
398 return 1;
399}
400EXPORT_SYMBOL(tty_port_close_start);
401
402void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
403{
404 unsigned long flags;
405
a6614999
AC
406 spin_lock_irqsave(&port->lock, flags);
407 tty->closing = 0;
408
409 if (port->blocked_open) {
410 spin_unlock_irqrestore(&port->lock, flags);
411 if (port->close_delay) {
412 msleep_interruptible(
413 jiffies_to_msecs(port->close_delay));
414 }
415 spin_lock_irqsave(&port->lock, flags);
416 wake_up_interruptible(&port->open_wait);
417 }
418 port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
419 wake_up_interruptible(&port->close_wait);
420 spin_unlock_irqrestore(&port->lock, flags);
421}
422EXPORT_SYMBOL(tty_port_close_end);
7ca0ff9a
AC
423
424void tty_port_close(struct tty_port *port, struct tty_struct *tty,
425 struct file *filp)
426{
427 if (tty_port_close_start(port, tty, filp) == 0)
428 return;
429 tty_port_shutdown(port);
d74e8286 430 set_bit(TTY_IO_ERROR, &tty->flags);
7ca0ff9a
AC
431 tty_port_close_end(port, tty);
432 tty_port_tty_set(port, NULL);
433}
434EXPORT_SYMBOL(tty_port_close);
64bc3979 435
72a33bf5
JS
436/**
437 * tty_port_install - generic tty->ops->install handler
438 * @port: tty_port of the device
439 * @driver: tty_driver for this device
440 * @tty: tty to be installed
441 *
442 * It is the same as tty_standard_install except the provided @port is linked
443 * to a concrete tty specified by @tty. Use this or tty_port_register_device
444 * (or both). Call tty_port_link_device as a last resort.
445 */
695586ca
JS
446int tty_port_install(struct tty_port *port, struct tty_driver *driver,
447 struct tty_struct *tty)
448{
449 tty->port = port;
450 return tty_standard_install(driver, tty);
451}
452EXPORT_SYMBOL_GPL(tty_port_install);
453
64bc3979 454int tty_port_open(struct tty_port *port, struct tty_struct *tty,
d774a56d 455 struct file *filp)
64bc3979
AC
456{
457 spin_lock_irq(&port->lock);
458 if (!tty_hung_up_p(filp))
459 ++port->count;
460 spin_unlock_irq(&port->lock);
461 tty_port_tty_set(port, tty);
462
463 /*
464 * Do the device-specific open only if the hardware isn't
465 * already initialized. Serialize open and shutdown using the
466 * port mutex.
467 */
468
469 mutex_lock(&port->mutex);
470
471 if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
a9a37ec3 472 clear_bit(TTY_IO_ERROR, &tty->flags);
64bc3979
AC
473 if (port->ops->activate) {
474 int retval = port->ops->activate(port, tty);
475 if (retval) {
d774a56d
AC
476 mutex_unlock(&port->mutex);
477 return retval;
478 }
479 }
64bc3979
AC
480 set_bit(ASYNCB_INITIALIZED, &port->flags);
481 }
482 mutex_unlock(&port->mutex);
483 return tty_port_block_til_ready(port, tty, filp);
484}
485
486EXPORT_SYMBOL(tty_port_open);