Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * Tty port functions
4 : : */
5 : :
6 : : #include <linux/types.h>
7 : : #include <linux/errno.h>
8 : : #include <linux/tty.h>
9 : : #include <linux/tty_driver.h>
10 : : #include <linux/tty_flip.h>
11 : : #include <linux/serial.h>
12 : : #include <linux/timer.h>
13 : : #include <linux/string.h>
14 : : #include <linux/slab.h>
15 : : #include <linux/sched/signal.h>
16 : : #include <linux/wait.h>
17 : : #include <linux/bitops.h>
18 : : #include <linux/delay.h>
19 : : #include <linux/module.h>
20 : : #include <linux/serdev.h>
21 : :
22 : 88720 : static int tty_port_default_receive_buf(struct tty_port *port,
23 : : const unsigned char *p,
24 : : const unsigned char *f, size_t count)
25 : : {
26 : : int ret;
27 : : struct tty_struct *tty;
28 : : struct tty_ldisc *disc;
29 : :
30 : 88720 : tty = READ_ONCE(port->itty);
31 [ + - ]: 88720 : if (!tty)
32 : : return 0;
33 : :
34 : 88720 : disc = tty_ldisc_ref(tty);
35 [ + - ]: 88720 : if (!disc)
36 : : return 0;
37 : :
38 : 88720 : ret = tty_ldisc_receive_buf(disc, p, (char *)f, count);
39 : :
40 : 88720 : tty_ldisc_deref(disc);
41 : :
42 : 88720 : return ret;
43 : : }
44 : :
45 : 196514 : static void tty_port_default_wakeup(struct tty_port *port)
46 : : {
47 : 196514 : struct tty_struct *tty = tty_port_tty_get(port);
48 : :
49 [ + - ]: 196514 : if (tty) {
50 : 196514 : tty_wakeup(tty);
51 : 196514 : tty_kref_put(tty);
52 : : }
53 : 196514 : }
54 : :
55 : : const struct tty_port_client_operations tty_port_default_client_ops = {
56 : : .receive_buf = tty_port_default_receive_buf,
57 : : .write_wakeup = tty_port_default_wakeup,
58 : : };
59 : : EXPORT_SYMBOL_GPL(tty_port_default_client_ops);
60 : :
61 : 9708 : void tty_port_init(struct tty_port *port)
62 : : {
63 : 9708 : memset(port, 0, sizeof(*port));
64 : 9708 : tty_buffer_init(port);
65 : 9708 : init_waitqueue_head(&port->open_wait);
66 : 9708 : init_waitqueue_head(&port->delta_msr_wait);
67 : 9708 : mutex_init(&port->mutex);
68 : 9708 : mutex_init(&port->buf_mutex);
69 : 9708 : spin_lock_init(&port->lock);
70 : 9708 : port->close_delay = (50 * HZ) / 100;
71 : 9708 : port->closing_wait = (3000 * HZ) / 100;
72 : 9708 : port->client_ops = &tty_port_default_client_ops;
73 : : kref_init(&port->kref);
74 : 9708 : }
75 : : EXPORT_SYMBOL(tty_port_init);
76 : :
77 : : /**
78 : : * tty_port_link_device - link tty and tty_port
79 : : * @port: tty_port of the device
80 : : * @driver: tty_driver for this device
81 : : * @index: index of the tty
82 : : *
83 : : * Provide the tty layer with a link from a tty (specified by @index) to a
84 : : * tty_port (@port). Use this only if neither tty_port_register_device nor
85 : : * tty_port_install is used in the driver. If used, this has to be called before
86 : : * tty_register_driver.
87 : : */
88 : 1212 : void tty_port_link_device(struct tty_port *port,
89 : : struct tty_driver *driver, unsigned index)
90 : : {
91 [ - + + - ]: 1212 : if (WARN_ON(index >= driver->num))
92 : 1212 : return;
93 : 1212 : driver->ports[index] = port;
94 : : }
95 : : EXPORT_SYMBOL_GPL(tty_port_link_device);
96 : :
97 : : /**
98 : : * tty_port_register_device - register tty device
99 : : * @port: tty_port of the device
100 : : * @driver: tty_driver for this device
101 : : * @index: index of the tty
102 : : * @device: parent if exists, otherwise NULL
103 : : *
104 : : * It is the same as tty_register_device except the provided @port is linked to
105 : : * a concrete tty specified by @index. Use this or tty_port_install (or both).
106 : : * Call tty_port_link_device as a last resort.
107 : : */
108 : 0 : struct device *tty_port_register_device(struct tty_port *port,
109 : : struct tty_driver *driver, unsigned index,
110 : : struct device *device)
111 : : {
112 : 0 : return tty_port_register_device_attr(port, driver, index, device, NULL, NULL);
113 : : }
114 : : EXPORT_SYMBOL_GPL(tty_port_register_device);
115 : :
116 : : /**
117 : : * tty_port_register_device_attr - register tty device
118 : : * @port: tty_port of the device
119 : : * @driver: tty_driver for this device
120 : : * @index: index of the tty
121 : : * @device: parent if exists, otherwise NULL
122 : : * @drvdata: Driver data to be set to device.
123 : : * @attr_grp: Attribute group to be set on device.
124 : : *
125 : : * It is the same as tty_register_device_attr except the provided @port is
126 : : * linked to a concrete tty specified by @index. Use this or tty_port_install
127 : : * (or both). Call tty_port_link_device as a last resort.
128 : : */
129 : 0 : struct device *tty_port_register_device_attr(struct tty_port *port,
130 : : struct tty_driver *driver, unsigned index,
131 : : struct device *device, void *drvdata,
132 : : const struct attribute_group **attr_grp)
133 : : {
134 : 0 : tty_port_link_device(port, driver, index);
135 : 0 : return tty_register_device_attr(driver, index, device, drvdata,
136 : : attr_grp);
137 : : }
138 : : EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
139 : :
140 : : /**
141 : : * tty_port_register_device_attr_serdev - register tty or serdev device
142 : : * @port: tty_port of the device
143 : : * @driver: tty_driver for this device
144 : : * @index: index of the tty
145 : : * @device: parent if exists, otherwise NULL
146 : : * @drvdata: driver data for the device
147 : : * @attr_grp: attribute group for the device
148 : : *
149 : : * Register a serdev or tty device depending on if the parent device has any
150 : : * defined serdev clients or not.
151 : : */
152 : 404 : struct device *tty_port_register_device_attr_serdev(struct tty_port *port,
153 : : struct tty_driver *driver, unsigned index,
154 : : struct device *device, void *drvdata,
155 : : const struct attribute_group **attr_grp)
156 : : {
157 : : struct device *dev;
158 : :
159 : 404 : tty_port_link_device(port, driver, index);
160 : :
161 : 404 : dev = serdev_tty_port_register(port, device, driver, index);
162 [ + - ]: 404 : if (PTR_ERR(dev) != -ENODEV) {
163 : : /* Skip creating cdev if we registered a serdev device */
164 : : return dev;
165 : : }
166 : :
167 : 404 : return tty_register_device_attr(driver, index, device, drvdata,
168 : : attr_grp);
169 : : }
170 : : EXPORT_SYMBOL_GPL(tty_port_register_device_attr_serdev);
171 : :
172 : : /**
173 : : * tty_port_register_device_serdev - register tty or serdev device
174 : : * @port: tty_port of the device
175 : : * @driver: tty_driver for this device
176 : : * @index: index of the tty
177 : : * @device: parent if exists, otherwise NULL
178 : : *
179 : : * Register a serdev or tty device depending on if the parent device has any
180 : : * defined serdev clients or not.
181 : : */
182 : 0 : struct device *tty_port_register_device_serdev(struct tty_port *port,
183 : : struct tty_driver *driver, unsigned index,
184 : : struct device *device)
185 : : {
186 : 0 : return tty_port_register_device_attr_serdev(port, driver, index,
187 : : device, NULL, NULL);
188 : : }
189 : : EXPORT_SYMBOL_GPL(tty_port_register_device_serdev);
190 : :
191 : : /**
192 : : * tty_port_unregister_device - deregister a tty or serdev device
193 : : * @port: tty_port of the device
194 : : * @driver: tty_driver for this device
195 : : * @index: index of the tty
196 : : *
197 : : * If a tty or serdev device is registered with a call to
198 : : * tty_port_register_device_serdev() then this function must be called when
199 : : * the device is gone.
200 : : */
201 : 0 : void tty_port_unregister_device(struct tty_port *port,
202 : : struct tty_driver *driver, unsigned index)
203 : : {
204 : : int ret;
205 : :
206 : 0 : ret = serdev_tty_port_unregister(port);
207 [ # # ]: 0 : if (ret == 0)
208 : 0 : return;
209 : :
210 : 0 : tty_unregister_device(driver, index);
211 : : }
212 : : EXPORT_SYMBOL_GPL(tty_port_unregister_device);
213 : :
214 : 0 : int tty_port_alloc_xmit_buf(struct tty_port *port)
215 : : {
216 : : /* We may sleep in get_zeroed_page() */
217 : 0 : mutex_lock(&port->buf_mutex);
218 [ # # ]: 0 : if (port->xmit_buf == NULL)
219 : 0 : port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
220 : 0 : mutex_unlock(&port->buf_mutex);
221 [ # # ]: 0 : if (port->xmit_buf == NULL)
222 : : return -ENOMEM;
223 : 0 : return 0;
224 : : }
225 : : EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
226 : :
227 : 0 : void tty_port_free_xmit_buf(struct tty_port *port)
228 : : {
229 : 0 : mutex_lock(&port->buf_mutex);
230 [ # # ]: 0 : if (port->xmit_buf != NULL) {
231 : 0 : free_page((unsigned long)port->xmit_buf);
232 : 0 : port->xmit_buf = NULL;
233 : : }
234 : 0 : mutex_unlock(&port->buf_mutex);
235 : 0 : }
236 : : EXPORT_SYMBOL(tty_port_free_xmit_buf);
237 : :
238 : : /**
239 : : * tty_port_destroy -- destroy inited port
240 : : * @port: tty port to be destroyed
241 : : *
242 : : * When a port was initialized using tty_port_init, one has to destroy the
243 : : * port by this function. Either indirectly by using tty_port refcounting
244 : : * (tty_port_put) or directly if refcounting is not used.
245 : : */
246 : 0 : void tty_port_destroy(struct tty_port *port)
247 : : {
248 : 816 : tty_buffer_cancel_work(port);
249 : 816 : tty_buffer_free_all(port);
250 : 0 : }
251 : : EXPORT_SYMBOL(tty_port_destroy);
252 : :
253 : 816 : static void tty_port_destructor(struct kref *kref)
254 : : {
255 : 816 : struct tty_port *port = container_of(kref, struct tty_port, kref);
256 : :
257 : : /* check if last port ref was dropped before tty release */
258 [ - + + - ]: 816 : if (WARN_ON(port->itty))
259 : 816 : return;
260 [ - + ]: 816 : if (port->xmit_buf)
261 : 0 : free_page((unsigned long)port->xmit_buf);
262 : : tty_port_destroy(port);
263 [ - + # # ]: 816 : if (port->ops && port->ops->destruct)
264 : 0 : port->ops->destruct(port);
265 : : else
266 : 816 : kfree(port);
267 : : }
268 : :
269 : 17212 : void tty_port_put(struct tty_port *port)
270 : : {
271 [ + - ]: 17212 : if (port)
272 : 17212 : kref_put(&port->kref, tty_port_destructor);
273 : 17212 : }
274 : : EXPORT_SYMBOL(tty_port_put);
275 : :
276 : : /**
277 : : * tty_port_tty_get - get a tty reference
278 : : * @port: tty port
279 : : *
280 : : * Return a refcount protected tty instance or NULL if the port is not
281 : : * associated with a tty (eg due to close or hangup)
282 : : */
283 : 196514 : struct tty_struct *tty_port_tty_get(struct tty_port *port)
284 : : {
285 : : unsigned long flags;
286 : : struct tty_struct *tty;
287 : :
288 : 196514 : spin_lock_irqsave(&port->lock, flags);
289 : 196514 : tty = tty_kref_get(port->tty);
290 : : spin_unlock_irqrestore(&port->lock, flags);
291 : 196514 : return tty;
292 : : }
293 : : EXPORT_SYMBOL(tty_port_tty_get);
294 : :
295 : : /**
296 : : * tty_port_tty_set - set the tty of a port
297 : : * @port: tty port
298 : : * @tty: the tty
299 : : *
300 : : * Associate the port and tty pair. Manages any internal refcounts.
301 : : * Pass NULL to deassociate a port
302 : : */
303 : 87394 : void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
304 : : {
305 : : unsigned long flags;
306 : :
307 : 87394 : spin_lock_irqsave(&port->lock, flags);
308 : 87394 : tty_kref_put(port->tty);
309 : 87394 : port->tty = tty_kref_get(tty);
310 : : spin_unlock_irqrestore(&port->lock, flags);
311 : 87394 : }
312 : : EXPORT_SYMBOL(tty_port_tty_set);
313 : :
314 : 24650 : static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
315 : : {
316 : 24650 : mutex_lock(&port->mutex);
317 [ - + ]: 24650 : if (port->console)
318 : : goto out;
319 : :
320 [ # # ]: 0 : if (tty_port_initialized(port)) {
321 : 0 : tty_port_set_initialized(port, 0);
322 : : /*
323 : : * Drop DTR/RTS if HUPCL is set. This causes any attached
324 : : * modem to hang up the line.
325 : : */
326 [ # # # # ]: 0 : if (tty && C_HUPCL(tty))
327 : : tty_port_lower_dtr_rts(port);
328 : :
329 [ # # ]: 0 : if (port->ops->shutdown)
330 : 0 : port->ops->shutdown(port);
331 : : }
332 : : out:
333 : 24650 : mutex_unlock(&port->mutex);
334 : 24650 : }
335 : :
336 : : /**
337 : : * tty_port_hangup - hangup helper
338 : : * @port: tty port
339 : : *
340 : : * Perform port level tty hangup flag and count changes. Drop the tty
341 : : * reference.
342 : : *
343 : : * Caller holds tty lock.
344 : : */
345 : 0 : void tty_port_hangup(struct tty_port *port)
346 : : {
347 : : struct tty_struct *tty;
348 : : unsigned long flags;
349 : :
350 : 0 : spin_lock_irqsave(&port->lock, flags);
351 : 0 : port->count = 0;
352 : 0 : tty = port->tty;
353 [ # # ]: 0 : if (tty)
354 : 0 : set_bit(TTY_IO_ERROR, &tty->flags);
355 : 0 : port->tty = NULL;
356 : : spin_unlock_irqrestore(&port->lock, flags);
357 : 0 : tty_port_set_active(port, 0);
358 : 0 : tty_port_shutdown(port, tty);
359 : 0 : tty_kref_put(tty);
360 : 0 : wake_up_interruptible(&port->open_wait);
361 : 0 : wake_up_interruptible(&port->delta_msr_wait);
362 : 0 : }
363 : : EXPORT_SYMBOL(tty_port_hangup);
364 : :
365 : : /**
366 : : * tty_port_tty_hangup - helper to hang up a tty
367 : : *
368 : : * @port: tty port
369 : : * @check_clocal: hang only ttys with CLOCAL unset?
370 : : */
371 : 0 : void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
372 : : {
373 : 0 : struct tty_struct *tty = tty_port_tty_get(port);
374 : :
375 [ # # # # : 0 : if (tty && (!check_clocal || !C_CLOCAL(tty)))
# # ]
376 : 0 : tty_hangup(tty);
377 : 0 : tty_kref_put(tty);
378 : 0 : }
379 : : EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
380 : :
381 : : /**
382 : : * tty_port_tty_wakeup - helper to wake up a tty
383 : : *
384 : : * @port: tty port
385 : : */
386 : 196514 : void tty_port_tty_wakeup(struct tty_port *port)
387 : : {
388 : 196514 : port->client_ops->write_wakeup(port);
389 : 196514 : }
390 : : EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
391 : :
392 : : /**
393 : : * tty_port_carrier_raised - carrier raised check
394 : : * @port: tty port
395 : : *
396 : : * Wrapper for the carrier detect logic. For the moment this is used
397 : : * to hide some internal details. This will eventually become entirely
398 : : * internal to the tty port.
399 : : */
400 : 0 : int tty_port_carrier_raised(struct tty_port *port)
401 : : {
402 [ # # # # ]: 0 : if (port->ops->carrier_raised == NULL)
403 : : return 1;
404 : 0 : return port->ops->carrier_raised(port);
405 : : }
406 : : EXPORT_SYMBOL(tty_port_carrier_raised);
407 : :
408 : : /**
409 : : * tty_port_raise_dtr_rts - Raise DTR/RTS
410 : : * @port: tty port
411 : : *
412 : : * Wrapper for the DTR/RTS raise logic. For the moment this is used
413 : : * to hide some internal details. This will eventually become entirely
414 : : * internal to the tty port.
415 : : */
416 : 0 : void tty_port_raise_dtr_rts(struct tty_port *port)
417 : : {
418 [ # # # # : 0 : if (port->ops->dtr_rts)
# # ]
419 : 0 : port->ops->dtr_rts(port, 1);
420 : 0 : }
421 : : EXPORT_SYMBOL(tty_port_raise_dtr_rts);
422 : :
423 : : /**
424 : : * tty_port_lower_dtr_rts - Lower DTR/RTS
425 : : * @port: tty port
426 : : *
427 : : * Wrapper for the DTR/RTS raise logic. For the moment this is used
428 : : * to hide some internal details. This will eventually become entirely
429 : : * internal to the tty port.
430 : : */
431 : 0 : void tty_port_lower_dtr_rts(struct tty_port *port)
432 : : {
433 [ # # # # ]: 0 : if (port->ops->dtr_rts)
434 : 0 : port->ops->dtr_rts(port, 0);
435 : 0 : }
436 : : EXPORT_SYMBOL(tty_port_lower_dtr_rts);
437 : :
438 : : /**
439 : : * tty_port_block_til_ready - Waiting logic for tty open
440 : : * @port: the tty port being opened
441 : : * @tty: the tty device being bound
442 : : * @filp: the file pointer of the opener or NULL
443 : : *
444 : : * Implement the core POSIX/SuS tty behaviour when opening a tty device.
445 : : * Handles:
446 : : * - hangup (both before and during)
447 : : * - non blocking open
448 : : * - rts/dtr/dcd
449 : : * - signals
450 : : * - port flags and counts
451 : : *
452 : : * The passed tty_port must implement the carrier_raised method if it can
453 : : * do carrier detect and the dtr_rts method if it supports software
454 : : * management of these lines. Note that the dtr/rts raise is done each
455 : : * iteration as a hangup may have previously dropped them while we wait.
456 : : *
457 : : * Caller holds tty lock.
458 : : *
459 : : * NB: May drop and reacquire tty lock when blocking, so tty and tty_port
460 : : * may have changed state (eg., may have been hung up).
461 : : */
462 : 62340 : int tty_port_block_til_ready(struct tty_port *port,
463 : : struct tty_struct *tty, struct file *filp)
464 : : {
465 : : int do_clocal = 0, retval;
466 : : unsigned long flags;
467 : 124680 : DEFINE_WAIT(wait);
468 : :
469 : : /* if non-blocking mode is set we can pass directly to open unless
470 : : the port has just hung up or is in another error state */
471 [ - + ]: 62340 : if (tty_io_error(tty)) {
472 : 0 : tty_port_set_active(port, 1);
473 : 0 : return 0;
474 : : }
475 [ + - + - ]: 62340 : if (filp == NULL || (filp->f_flags & O_NONBLOCK)) {
476 : : /* Indicate we are open */
477 [ - + ]: 62340 : if (C_BAUD(tty))
478 : : tty_port_raise_dtr_rts(port);
479 : 62340 : tty_port_set_active(port, 1);
480 : 62340 : return 0;
481 : : }
482 : :
483 [ # # ]: 0 : if (C_CLOCAL(tty))
484 : : do_clocal = 1;
485 : :
486 : : /* Block waiting until we can proceed. We may need to wait for the
487 : : carrier, but we must also wait for any close that is in progress
488 : : before the next open may complete */
489 : :
490 : : retval = 0;
491 : :
492 : : /* The port lock protects the port counts */
493 : 0 : spin_lock_irqsave(&port->lock, flags);
494 : 0 : port->count--;
495 : 0 : port->blocked_open++;
496 : : spin_unlock_irqrestore(&port->lock, flags);
497 : :
498 : : while (1) {
499 : : /* Indicate we are open */
500 [ # # # # ]: 0 : if (C_BAUD(tty) && tty_port_initialized(port))
501 : : tty_port_raise_dtr_rts(port);
502 : :
503 : 0 : prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
504 : : /* Check for a hangup or uninitialised port.
505 : : Return accordingly */
506 [ # # # # ]: 0 : if (tty_hung_up_p(filp) || !tty_port_initialized(port)) {
507 [ # # ]: 0 : if (port->flags & ASYNC_HUP_NOTIFY)
508 : : retval = -EAGAIN;
509 : : else
510 : : retval = -ERESTARTSYS;
511 : : break;
512 : : }
513 : : /*
514 : : * Probe the carrier. For devices with no carrier detect
515 : : * tty_port_carrier_raised will always return true.
516 : : * Never ask drivers if CLOCAL is set, this causes troubles
517 : : * on some hardware.
518 : : */
519 [ # # # # ]: 0 : if (do_clocal || tty_port_carrier_raised(port))
520 : : break;
521 [ # # ]: 0 : if (signal_pending(current)) {
522 : : retval = -ERESTARTSYS;
523 : : break;
524 : : }
525 : 0 : tty_unlock(tty);
526 : 0 : schedule();
527 : 0 : tty_lock(tty);
528 : 0 : }
529 : 0 : finish_wait(&port->open_wait, &wait);
530 : :
531 : : /* Update counts. A parallel hangup will have set count to zero and
532 : : we must not mess that up further */
533 : 0 : spin_lock_irqsave(&port->lock, flags);
534 [ # # ]: 0 : if (!tty_hung_up_p(filp))
535 : 0 : port->count++;
536 : 0 : port->blocked_open--;
537 : : spin_unlock_irqrestore(&port->lock, flags);
538 [ # # ]: 0 : if (retval == 0)
539 : 0 : tty_port_set_active(port, 1);
540 : 0 : return retval;
541 : : }
542 : : EXPORT_SYMBOL(tty_port_block_til_ready);
543 : :
544 : 0 : static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
545 : : {
546 : : unsigned int bps = tty_get_baud_rate(tty);
547 : : long timeout;
548 : :
549 [ # # ]: 0 : if (bps > 1200) {
550 : 0 : timeout = (HZ * 10 * port->drain_delay) / bps;
551 : 0 : timeout = max_t(long, timeout, HZ / 10);
552 : : } else {
553 : : timeout = 2 * HZ;
554 : : }
555 : 0 : schedule_timeout_interruptible(timeout);
556 : 0 : }
557 : :
558 : : /* Caller holds tty lock. */
559 : 61936 : int tty_port_close_start(struct tty_port *port,
560 : : struct tty_struct *tty, struct file *filp)
561 : : {
562 : : unsigned long flags;
563 : :
564 [ + + ]: 61936 : if (tty_hung_up_p(filp))
565 : : return 0;
566 : :
567 : 61532 : spin_lock_irqsave(&port->lock, flags);
568 [ + + - + ]: 61532 : if (tty->count == 1 && port->count != 1) {
569 : 0 : tty_warn(tty, "%s: tty->count = 1 port count = %d\n", __func__,
570 : : port->count);
571 : 0 : port->count = 1;
572 : : }
573 [ - + ]: 61532 : if (--port->count < 0) {
574 : 0 : tty_warn(tty, "%s: bad port count (%d)\n", __func__,
575 : : port->count);
576 : 0 : port->count = 0;
577 : : }
578 : :
579 [ + + ]: 61532 : if (port->count) {
580 : : spin_unlock_irqrestore(&port->lock, flags);
581 : 36882 : return 0;
582 : : }
583 : : spin_unlock_irqrestore(&port->lock, flags);
584 : :
585 : 24650 : tty->closing = 1;
586 : :
587 [ + - ]: 24650 : if (tty_port_initialized(port)) {
588 : : /* Don't block on a stalled port, just pull the chain */
589 [ - + ]: 24650 : if (tty->flow_stopped)
590 : 0 : tty_driver_flush_buffer(tty);
591 [ + - ]: 24650 : if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
592 : 24650 : tty_wait_until_sent(tty, port->closing_wait);
593 [ - + ]: 24650 : if (port->drain_delay)
594 : 0 : tty_port_drain_delay(port, tty);
595 : : }
596 : : /* Flush the ldisc buffering */
597 : 24650 : tty_ldisc_flush(tty);
598 : :
599 : : /* Report to caller this is the last port reference */
600 : 24650 : return 1;
601 : : }
602 : : EXPORT_SYMBOL(tty_port_close_start);
603 : :
604 : : /* Caller holds tty lock */
605 : 24650 : void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
606 : : {
607 : : unsigned long flags;
608 : :
609 : 24650 : tty_ldisc_flush(tty);
610 : 24650 : tty->closing = 0;
611 : :
612 : 24650 : spin_lock_irqsave(&port->lock, flags);
613 : :
614 [ - + ]: 24650 : if (port->blocked_open) {
615 : : spin_unlock_irqrestore(&port->lock, flags);
616 [ # # ]: 0 : if (port->close_delay)
617 : 0 : msleep_interruptible(jiffies_to_msecs(port->close_delay));
618 : 0 : spin_lock_irqsave(&port->lock, flags);
619 : 0 : wake_up_interruptible(&port->open_wait);
620 : : }
621 : : spin_unlock_irqrestore(&port->lock, flags);
622 : 24650 : tty_port_set_active(port, 0);
623 : 24650 : }
624 : : EXPORT_SYMBOL(tty_port_close_end);
625 : :
626 : : /**
627 : : * tty_port_close
628 : : *
629 : : * Caller holds tty lock
630 : : */
631 : 61936 : void tty_port_close(struct tty_port *port, struct tty_struct *tty,
632 : : struct file *filp)
633 : : {
634 [ + + ]: 61936 : if (tty_port_close_start(port, tty, filp) == 0)
635 : 61936 : return;
636 : 24650 : tty_port_shutdown(port, tty);
637 [ - + ]: 24650 : if (!port->console)
638 : 0 : set_bit(TTY_IO_ERROR, &tty->flags);
639 : 24650 : tty_port_close_end(port, tty);
640 : 24650 : tty_port_tty_set(port, NULL);
641 : : }
642 : : EXPORT_SYMBOL(tty_port_close);
643 : :
644 : : /**
645 : : * tty_port_install - generic tty->ops->install handler
646 : : * @port: tty_port of the device
647 : : * @driver: tty_driver for this device
648 : : * @tty: tty to be installed
649 : : *
650 : : * It is the same as tty_standard_install except the provided @port is linked
651 : : * to a concrete tty specified by @tty. Use this or tty_port_register_device
652 : : * (or both). Call tty_port_link_device as a last resort.
653 : : */
654 : 17608 : int tty_port_install(struct tty_port *port, struct tty_driver *driver,
655 : : struct tty_struct *tty)
656 : : {
657 : 17608 : tty->port = port;
658 : 17608 : return tty_standard_install(driver, tty);
659 : : }
660 : : EXPORT_SYMBOL_GPL(tty_port_install);
661 : :
662 : : /**
663 : : * tty_port_open
664 : : *
665 : : * Caller holds tty lock.
666 : : *
667 : : * NB: may drop and reacquire tty lock (in tty_port_block_til_ready()) so
668 : : * tty and tty_port may have changed state (eg., may be hung up now)
669 : : */
670 : 62340 : int tty_port_open(struct tty_port *port, struct tty_struct *tty,
671 : : struct file *filp)
672 : : {
673 : : spin_lock_irq(&port->lock);
674 : 62340 : ++port->count;
675 : : spin_unlock_irq(&port->lock);
676 : 62340 : tty_port_tty_set(port, tty);
677 : :
678 : : /*
679 : : * Do the device-specific open only if the hardware isn't
680 : : * already initialized. Serialize open and shutdown using the
681 : : * port mutex.
682 : : */
683 : :
684 : 62340 : mutex_lock(&port->mutex);
685 : :
686 [ + + ]: 62340 : if (!tty_port_initialized(port)) {
687 : 808 : clear_bit(TTY_IO_ERROR, &tty->flags);
688 [ + - ]: 808 : if (port->ops->activate) {
689 : 808 : int retval = port->ops->activate(port, tty);
690 [ - + ]: 808 : if (retval) {
691 : 0 : mutex_unlock(&port->mutex);
692 : 0 : return retval;
693 : : }
694 : : }
695 : 808 : tty_port_set_initialized(port, 1);
696 : : }
697 : 62340 : mutex_unlock(&port->mutex);
698 : 62340 : return tty_port_block_til_ready(port, tty, filp);
699 : : }
700 : :
701 : : EXPORT_SYMBOL(tty_port_open);
|