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 0 : 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 0 : int ret;
27 0 : struct tty_struct *tty;
28 0 : struct tty_ldisc *disc;
29 :
30 0 : tty = READ_ONCE(port->itty);
31 0 : if (!tty)
32 : return 0;
33 :
34 0 : disc = tty_ldisc_ref(tty);
35 0 : if (!disc)
36 : return 0;
37 :
38 0 : ret = tty_ldisc_receive_buf(disc, p, (char *)f, count);
39 :
40 0 : tty_ldisc_deref(disc);
41 :
42 0 : return ret;
43 : }
44 :
45 713 : static void tty_port_default_wakeup(struct tty_port *port)
46 : {
47 713 : struct tty_struct *tty = tty_port_tty_get(port);
48 :
49 713 : if (tty) {
50 713 : tty_wakeup(tty);
51 713 : tty_kref_put(tty);
52 : }
53 713 : }
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 10 : void tty_port_init(struct tty_port *port)
62 : {
63 10 : memset(port, 0, sizeof(*port));
64 10 : tty_buffer_init(port);
65 10 : init_waitqueue_head(&port->open_wait);
66 10 : init_waitqueue_head(&port->delta_msr_wait);
67 10 : mutex_init(&port->mutex);
68 10 : mutex_init(&port->buf_mutex);
69 10 : spin_lock_init(&port->lock);
70 10 : port->close_delay = (50 * HZ) / 100;
71 10 : port->closing_wait = (3000 * HZ) / 100;
72 10 : port->client_ops = &tty_port_default_client_ops;
73 10 : kref_init(&port->kref);
74 10 : }
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 8 : void tty_port_link_device(struct tty_port *port,
89 : struct tty_driver *driver, unsigned index)
90 : {
91 8 : if (WARN_ON(index >= driver->num))
92 : return;
93 8 : 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 4 : 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 4 : struct device *dev;
158 :
159 4 : tty_port_link_device(port, driver, index);
160 :
161 4 : dev = serdev_tty_port_register(port, device, driver, index);
162 4 : if (PTR_ERR(dev) != -ENODEV) {
163 : /* Skip creating cdev if we registered a serdev device */
164 : return dev;
165 : }
166 :
167 4 : 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 0 : int ret;
205 :
206 0 : ret = serdev_tty_port_unregister(port);
207 0 : if (ret == 0)
208 : 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 0 : return -ENOMEM;
223 : 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 0 : tty_buffer_cancel_work(port);
249 0 : tty_buffer_free_all(port);
250 0 : }
251 : EXPORT_SYMBOL(tty_port_destroy);
252 :
253 0 : static void tty_port_destructor(struct kref *kref)
254 : {
255 0 : struct tty_port *port = container_of(kref, struct tty_port, kref);
256 :
257 : /* check if last port ref was dropped before tty release */
258 0 : if (WARN_ON(port->itty))
259 : return;
260 0 : if (port->xmit_buf)
261 0 : free_page((unsigned long)port->xmit_buf);
262 0 : tty_port_destroy(port);
263 0 : if (port->ops && port->ops->destruct)
264 0 : port->ops->destruct(port);
265 : else
266 0 : kfree(port);
267 : }
268 :
269 26 : void tty_port_put(struct tty_port *port)
270 : {
271 26 : if (port)
272 26 : kref_put(&port->kref, tty_port_destructor);
273 26 : }
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 713 : struct tty_struct *tty_port_tty_get(struct tty_port *port)
284 : {
285 713 : unsigned long flags;
286 713 : struct tty_struct *tty;
287 :
288 713 : spin_lock_irqsave(&port->lock, flags);
289 713 : tty = tty_kref_get(port->tty);
290 713 : spin_unlock_irqrestore(&port->lock, flags);
291 713 : 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 270 : void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
304 : {
305 270 : unsigned long flags;
306 :
307 270 : spin_lock_irqsave(&port->lock, flags);
308 270 : tty_kref_put(port->tty);
309 270 : port->tty = tty_kref_get(tty);
310 270 : spin_unlock_irqrestore(&port->lock, flags);
311 270 : }
312 : EXPORT_SYMBOL(tty_port_tty_set);
313 :
314 135 : static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
315 : {
316 135 : mutex_lock(&port->mutex);
317 135 : if (port->console)
318 135 : 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 0 : tty_port_lower_dtr_rts(port);
328 :
329 0 : if (port->ops->shutdown)
330 0 : port->ops->shutdown(port);
331 : }
332 0 : out:
333 135 : mutex_unlock(&port->mutex);
334 135 : }
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 0 : struct tty_struct *tty;
348 0 : 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 0 : 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 713 : void tty_port_tty_wakeup(struct tty_port *port)
387 : {
388 713 : port->client_ops->write_wakeup(port);
389 713 : }
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 135 : void tty_port_raise_dtr_rts(struct tty_port *port)
417 : {
418 135 : if (port->ops->dtr_rts)
419 135 : port->ops->dtr_rts(port, 1);
420 135 : }
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 135 : int tty_port_block_til_ready(struct tty_port *port,
463 : struct tty_struct *tty, struct file *filp)
464 : {
465 135 : int do_clocal = 0, retval;
466 135 : unsigned long flags;
467 135 : 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 135 : if (tty_io_error(tty)) {
472 0 : tty_port_set_active(port, 1);
473 0 : return 0;
474 : }
475 135 : if (filp == NULL || (filp->f_flags & O_NONBLOCK)) {
476 : /* Indicate we are open */
477 135 : if (C_BAUD(tty))
478 135 : tty_port_raise_dtr_rts(port);
479 135 : tty_port_set_active(port, 1);
480 135 : return 0;
481 : }
482 :
483 0 : if (C_CLOCAL(tty))
484 0 : 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 0 : 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 0 : spin_unlock_irqrestore(&port->lock, flags);
497 :
498 0 : while (1) {
499 : /* Indicate we are open */
500 0 : if (C_BAUD(tty) && tty_port_initialized(port))
501 0 : 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 0 : 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 : }
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 0 : spin_unlock_irqrestore(&port->lock, flags);
538 0 : if (retval == 0)
539 0 : tty_port_set_active(port, 1);
540 : 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 0 : unsigned int bps = tty_get_baud_rate(tty);
547 0 : 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 135 : int tty_port_close_start(struct tty_port *port,
560 : struct tty_struct *tty, struct file *filp)
561 : {
562 135 : unsigned long flags;
563 :
564 135 : if (tty_hung_up_p(filp))
565 : return 0;
566 :
567 135 : spin_lock_irqsave(&port->lock, flags);
568 135 : 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 135 : 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 135 : if (port->count) {
580 0 : spin_unlock_irqrestore(&port->lock, flags);
581 0 : return 0;
582 : }
583 135 : spin_unlock_irqrestore(&port->lock, flags);
584 :
585 135 : tty->closing = 1;
586 :
587 135 : if (tty_port_initialized(port)) {
588 : /* Don't block on a stalled port, just pull the chain */
589 135 : if (tty->flow_stopped)
590 0 : tty_driver_flush_buffer(tty);
591 135 : if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
592 135 : tty_wait_until_sent(tty, port->closing_wait);
593 135 : if (port->drain_delay)
594 0 : tty_port_drain_delay(port, tty);
595 : }
596 : /* Flush the ldisc buffering */
597 135 : tty_ldisc_flush(tty);
598 :
599 : /* Report to caller this is the last port reference */
600 135 : return 1;
601 : }
602 : EXPORT_SYMBOL(tty_port_close_start);
603 :
604 : /* Caller holds tty lock */
605 135 : void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
606 : {
607 135 : unsigned long flags;
608 :
609 135 : tty_ldisc_flush(tty);
610 135 : tty->closing = 0;
611 :
612 135 : spin_lock_irqsave(&port->lock, flags);
613 :
614 135 : if (port->blocked_open) {
615 0 : 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 135 : spin_unlock_irqrestore(&port->lock, flags);
622 135 : tty_port_set_active(port, 0);
623 135 : }
624 : EXPORT_SYMBOL(tty_port_close_end);
625 :
626 : /*
627 : * tty_port_close
628 : *
629 : * Caller holds tty lock
630 : */
631 135 : void tty_port_close(struct tty_port *port, struct tty_struct *tty,
632 : struct file *filp)
633 : {
634 135 : if (tty_port_close_start(port, tty, filp) == 0)
635 : return;
636 135 : tty_port_shutdown(port, tty);
637 135 : if (!port->console)
638 0 : set_bit(TTY_IO_ERROR, &tty->flags);
639 135 : tty_port_close_end(port, tty);
640 135 : 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 28 : int tty_port_install(struct tty_port *port, struct tty_driver *driver,
655 : struct tty_struct *tty)
656 : {
657 28 : tty->port = port;
658 28 : 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 135 : int tty_port_open(struct tty_port *port, struct tty_struct *tty,
671 : struct file *filp)
672 : {
673 135 : spin_lock_irq(&port->lock);
674 135 : ++port->count;
675 135 : spin_unlock_irq(&port->lock);
676 135 : 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 135 : mutex_lock(&port->mutex);
685 :
686 135 : if (!tty_port_initialized(port)) {
687 1 : clear_bit(TTY_IO_ERROR, &tty->flags);
688 1 : if (port->ops->activate) {
689 1 : int retval = port->ops->activate(port, tty);
690 1 : if (retval) {
691 0 : mutex_unlock(&port->mutex);
692 0 : return retval;
693 : }
694 : }
695 1 : tty_port_set_initialized(port, 1);
696 : }
697 135 : mutex_unlock(&port->mutex);
698 135 : return tty_port_block_til_ready(port, tty, filp);
699 : }
700 :
701 : EXPORT_SYMBOL(tty_port_open);
|