blob: 8d9886b060379356b671e9feeb9626da3d114a86 [file] [log] [blame]
Alan Cox9e485652008-10-13 10:37:07 +01001/*
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>
Alan Cox3e616962009-01-02 13:45:26 +000010#include <linux/serial.h>
Alan Cox9e485652008-10-13 10:37:07 +010011#include <linux/timer.h>
12#include <linux/string.h>
13#include <linux/slab.h>
14#include <linux/sched.h>
Alan Cox9e485652008-10-13 10:37:07 +010015#include <linux/wait.h>
16#include <linux/bitops.h>
17#include <linux/delay.h>
18#include <linux/module.h>
19
Rob Herringc3485ee2017-02-02 13:48:05 -060020static int tty_port_default_receive_buf(struct tty_port *port,
21 const unsigned char *p,
22 const unsigned char *f, size_t count)
23{
24 int ret;
25 struct tty_struct *tty;
26 struct tty_ldisc *disc;
27
28 tty = READ_ONCE(port->itty);
29 if (!tty)
30 return 0;
31
32 disc = tty_ldisc_ref(tty);
33 if (!disc)
34 return 0;
35
36 ret = tty_ldisc_receive_buf(disc, p, (char *)f, count);
37
38 tty_ldisc_deref(disc);
39
40 return ret;
41}
42
43static void tty_port_default_wakeup(struct tty_port *port)
44{
45 struct tty_struct *tty = tty_port_tty_get(port);
46
47 if (tty) {
48 tty_wakeup(tty);
49 tty_kref_put(tty);
50 }
51}
52
53static const struct tty_port_client_operations default_client_ops = {
54 .receive_buf = tty_port_default_receive_buf,
55 .write_wakeup = tty_port_default_wakeup,
56};
57
Alan Cox9e485652008-10-13 10:37:07 +010058void tty_port_init(struct tty_port *port)
59{
60 memset(port, 0, sizeof(*port));
Jiri Slabyecbbfd42012-10-18 22:26:47 +020061 tty_buffer_init(port);
Alan Cox9e485652008-10-13 10:37:07 +010062 init_waitqueue_head(&port->open_wait);
Alan Coxbdc04e32009-09-19 13:13:31 -070063 init_waitqueue_head(&port->delta_msr_wait);
Alan Cox9e485652008-10-13 10:37:07 +010064 mutex_init(&port->mutex);
Alan Cox44e49092009-11-30 13:16:41 +000065 mutex_init(&port->buf_mutex);
Alan Cox4a90f092008-10-13 10:39:46 +010066 spin_lock_init(&port->lock);
Alan Cox9e485652008-10-13 10:37:07 +010067 port->close_delay = (50 * HZ) / 100;
68 port->closing_wait = (3000 * HZ) / 100;
Rob Herringc3485ee2017-02-02 13:48:05 -060069 port->client_ops = &default_client_ops;
Alan Cox568aafc2009-11-30 13:17:14 +000070 kref_init(&port->kref);
Alan Cox9e485652008-10-13 10:37:07 +010071}
72EXPORT_SYMBOL(tty_port_init);
73
Jiri Slaby72a33bf2012-08-07 21:47:49 +020074/**
Jiri Slaby2cb4ca02012-08-07 21:47:50 +020075 * tty_port_link_device - link tty and tty_port
76 * @port: tty_port of the device
77 * @driver: tty_driver for this device
78 * @index: index of the tty
79 *
80 * Provide the tty layer wit ha link from a tty (specified by @index) to a
81 * tty_port (@port). Use this only if neither tty_port_register_device nor
82 * tty_port_install is used in the driver. If used, this has to be called before
83 * tty_register_driver.
84 */
85void tty_port_link_device(struct tty_port *port,
86 struct tty_driver *driver, unsigned index)
87{
88 if (WARN_ON(index >= driver->num))
89 return;
90 driver->ports[index] = port;
91}
92EXPORT_SYMBOL_GPL(tty_port_link_device);
93
94/**
Jiri Slaby72a33bf2012-08-07 21:47:49 +020095 * tty_port_register_device - register tty device
96 * @port: tty_port of the device
97 * @driver: tty_driver for this device
98 * @index: index of the tty
99 * @device: parent if exists, otherwise NULL
100 *
101 * It is the same as tty_register_device except the provided @port is linked to
102 * a concrete tty specified by @index. Use this or tty_port_install (or both).
103 * Call tty_port_link_device as a last resort.
104 */
Jiri Slaby057eb852012-06-04 13:35:37 +0200105struct device *tty_port_register_device(struct tty_port *port,
106 struct tty_driver *driver, unsigned index,
107 struct device *device)
108{
Rob Herring30863652017-01-16 16:54:30 -0600109 return tty_port_register_device_attr(port, driver, index, device, NULL, NULL);
Jiri Slaby057eb852012-06-04 13:35:37 +0200110}
111EXPORT_SYMBOL_GPL(tty_port_register_device);
112
Tomas Hlavacekb1b79912012-09-06 23:17:47 +0200113/**
114 * tty_port_register_device_attr - register tty device
115 * @port: tty_port of the device
116 * @driver: tty_driver for this device
117 * @index: index of the tty
118 * @device: parent if exists, otherwise NULL
119 * @drvdata: Driver data to be set to device.
120 * @attr_grp: Attribute group to be set on device.
121 *
122 * It is the same as tty_register_device_attr except the provided @port is
123 * linked to a concrete tty specified by @index. Use this or tty_port_install
124 * (or both). Call tty_port_link_device as a last resort.
125 */
126struct device *tty_port_register_device_attr(struct tty_port *port,
127 struct tty_driver *driver, unsigned index,
128 struct device *device, void *drvdata,
129 const struct attribute_group **attr_grp)
130{
131 tty_port_link_device(port, driver, index);
132 return tty_register_device_attr(driver, index, device, drvdata,
133 attr_grp);
134}
135EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
136
Alan Cox9e485652008-10-13 10:37:07 +0100137int tty_port_alloc_xmit_buf(struct tty_port *port)
138{
139 /* We may sleep in get_zeroed_page() */
Alan Cox44e49092009-11-30 13:16:41 +0000140 mutex_lock(&port->buf_mutex);
Alan Cox9e485652008-10-13 10:37:07 +0100141 if (port->xmit_buf == NULL)
142 port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
Alan Cox44e49092009-11-30 13:16:41 +0000143 mutex_unlock(&port->buf_mutex);
Alan Cox9e485652008-10-13 10:37:07 +0100144 if (port->xmit_buf == NULL)
145 return -ENOMEM;
146 return 0;
147}
148EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
149
150void tty_port_free_xmit_buf(struct tty_port *port)
151{
Alan Cox44e49092009-11-30 13:16:41 +0000152 mutex_lock(&port->buf_mutex);
Alan Cox9e485652008-10-13 10:37:07 +0100153 if (port->xmit_buf != NULL) {
154 free_page((unsigned long)port->xmit_buf);
155 port->xmit_buf = NULL;
156 }
Alan Cox44e49092009-11-30 13:16:41 +0000157 mutex_unlock(&port->buf_mutex);
Alan Cox9e485652008-10-13 10:37:07 +0100158}
159EXPORT_SYMBOL(tty_port_free_xmit_buf);
160
Jiri Slabyde274bf2012-11-15 09:49:54 +0100161/**
162 * tty_port_destroy -- destroy inited port
163 * @port: tty port to be doestroyed
164 *
165 * When a port was initialized using tty_port_init, one has to destroy the
166 * port by this function. Either indirectly by using tty_port refcounting
167 * (tty_port_put) or directly if refcounting is not used.
168 */
169void tty_port_destroy(struct tty_port *port)
170{
Peter Hurleye1760582015-10-17 16:36:23 -0400171 tty_buffer_cancel_work(port);
Jiri Slabyde274bf2012-11-15 09:49:54 +0100172 tty_buffer_free_all(port);
173}
174EXPORT_SYMBOL(tty_port_destroy);
175
Alan Cox568aafc2009-11-30 13:17:14 +0000176static void tty_port_destructor(struct kref *kref)
177{
178 struct tty_port *port = container_of(kref, struct tty_port, kref);
Peter Hurleye3bfea22013-09-18 20:42:39 -0400179
180 /* check if last port ref was dropped before tty release */
181 if (WARN_ON(port->itty))
182 return;
Alan Cox568aafc2009-11-30 13:17:14 +0000183 if (port->xmit_buf)
184 free_page((unsigned long)port->xmit_buf);
Jiri Slabyde274bf2012-11-15 09:49:54 +0100185 tty_port_destroy(port);
Jiri Slaby81c79832012-11-15 09:49:49 +0100186 if (port->ops && port->ops->destruct)
Alan Cox568aafc2009-11-30 13:17:14 +0000187 port->ops->destruct(port);
188 else
189 kfree(port);
190}
191
192void tty_port_put(struct tty_port *port)
193{
194 if (port)
195 kref_put(&port->kref, tty_port_destructor);
196}
197EXPORT_SYMBOL(tty_port_put);
Alan Cox9e485652008-10-13 10:37:07 +0100198
Alan Cox4a90f092008-10-13 10:39:46 +0100199/**
200 * tty_port_tty_get - get a tty reference
201 * @port: tty port
202 *
203 * Return a refcount protected tty instance or NULL if the port is not
204 * associated with a tty (eg due to close or hangup)
205 */
206
207struct tty_struct *tty_port_tty_get(struct tty_port *port)
208{
209 unsigned long flags;
210 struct tty_struct *tty;
211
212 spin_lock_irqsave(&port->lock, flags);
213 tty = tty_kref_get(port->tty);
214 spin_unlock_irqrestore(&port->lock, flags);
215 return tty;
216}
217EXPORT_SYMBOL(tty_port_tty_get);
218
219/**
220 * tty_port_tty_set - set the tty of a port
221 * @port: tty port
222 * @tty: the tty
223 *
224 * Associate the port and tty pair. Manages any internal refcounts.
225 * Pass NULL to deassociate a port
226 */
227
228void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
229{
230 unsigned long flags;
231
232 spin_lock_irqsave(&port->lock, flags);
Markus Elfringa211b1a2014-11-21 13:42:29 +0100233 tty_kref_put(port->tty);
Alan Coxcb4bca32008-10-21 13:47:44 +0100234 port->tty = tty_kref_get(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100235 spin_unlock_irqrestore(&port->lock, flags);
236}
237EXPORT_SYMBOL(tty_port_tty_set);
Alan Cox31f35932009-01-02 13:45:05 +0000238
Johan Hovold957daca2013-03-07 15:55:51 +0100239static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
Alan Cox7ca0ff92009-09-19 13:13:20 -0700240{
Alan Cox64bc3972009-10-06 16:06:11 +0100241 mutex_lock(&port->mutex);
Johan Hovold8bde9652013-03-07 15:55:48 +0100242 if (port->console)
243 goto out;
244
Peter Hurleyd41861c2016-04-09 17:53:25 -0700245 if (tty_port_initialized(port)) {
246 tty_port_set_initialized(port, 0);
Johan Hovold957daca2013-03-07 15:55:51 +0100247 /*
248 * Drop DTR/RTS if HUPCL is set. This causes any attached
249 * modem to hang up the line.
250 */
251 if (tty && C_HUPCL(tty))
252 tty_port_lower_dtr_rts(port);
253
Johan Hovold8bde9652013-03-07 15:55:48 +0100254 if (port->ops->shutdown)
Alan Cox7ca0ff92009-09-19 13:13:20 -0700255 port->ops->shutdown(port);
Johan Hovold8bde9652013-03-07 15:55:48 +0100256 }
257out:
Alan Cox64bc3972009-10-06 16:06:11 +0100258 mutex_unlock(&port->mutex);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700259}
260
Alan Cox31f35932009-01-02 13:45:05 +0000261/**
Alan Cox3e616962009-01-02 13:45:26 +0000262 * tty_port_hangup - hangup helper
263 * @port: tty port
264 *
265 * Perform port level tty hangup flag and count changes. Drop the tty
266 * reference.
Peter Hurley9c9928b2014-06-16 09:17:02 -0400267 *
268 * Caller holds tty lock.
Alan Cox3e616962009-01-02 13:45:26 +0000269 */
270
271void tty_port_hangup(struct tty_port *port)
272{
Johan Hovold957daca2013-03-07 15:55:51 +0100273 struct tty_struct *tty;
Alan Cox3e616962009-01-02 13:45:26 +0000274 unsigned long flags;
275
276 spin_lock_irqsave(&port->lock, flags);
277 port->count = 0;
Johan Hovold957daca2013-03-07 15:55:51 +0100278 tty = port->tty;
279 if (tty)
280 set_bit(TTY_IO_ERROR, &tty->flags);
Alan Cox3e616962009-01-02 13:45:26 +0000281 port->tty = NULL;
282 spin_unlock_irqrestore(&port->lock, flags);
Peter Hurley807c8d812016-04-09 17:53:22 -0700283 tty_port_set_active(port, 0);
Johan Hovold957daca2013-03-07 15:55:51 +0100284 tty_port_shutdown(port, tty);
285 tty_kref_put(tty);
Alan Cox3e616962009-01-02 13:45:26 +0000286 wake_up_interruptible(&port->open_wait);
Alan Coxbdc04e32009-09-19 13:13:31 -0700287 wake_up_interruptible(&port->delta_msr_wait);
Alan Cox3e616962009-01-02 13:45:26 +0000288}
289EXPORT_SYMBOL(tty_port_hangup);
290
291/**
Jiri Slabyaa27a092013-03-07 13:12:30 +0100292 * tty_port_tty_hangup - helper to hang up a tty
293 *
294 * @port: tty port
295 * @check_clocal: hang only ttys with CLOCAL unset?
296 */
297void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
298{
299 struct tty_struct *tty = tty_port_tty_get(port);
300
Gianluca Anzolin1d9e6892013-07-25 07:26:16 +0200301 if (tty && (!check_clocal || !C_CLOCAL(tty)))
Jiri Slabyaa27a092013-03-07 13:12:30 +0100302 tty_hangup(tty);
Gianluca Anzolin1d9e6892013-07-25 07:26:16 +0200303 tty_kref_put(tty);
Jiri Slabyaa27a092013-03-07 13:12:30 +0100304}
305EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
306
307/**
Jiri Slaby6aad04f2013-03-07 13:12:29 +0100308 * tty_port_tty_wakeup - helper to wake up a tty
309 *
310 * @port: tty port
311 */
312void tty_port_tty_wakeup(struct tty_port *port)
313{
Rob Herringc3485ee2017-02-02 13:48:05 -0600314 port->client_ops->write_wakeup(port);
Jiri Slaby6aad04f2013-03-07 13:12:29 +0100315}
316EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
317
318/**
Alan Cox31f35932009-01-02 13:45:05 +0000319 * tty_port_carrier_raised - carrier raised check
320 * @port: tty port
321 *
322 * Wrapper for the carrier detect logic. For the moment this is used
323 * to hide some internal details. This will eventually become entirely
324 * internal to the tty port.
325 */
326
327int tty_port_carrier_raised(struct tty_port *port)
328{
329 if (port->ops->carrier_raised == NULL)
330 return 1;
331 return port->ops->carrier_raised(port);
332}
333EXPORT_SYMBOL(tty_port_carrier_raised);
Alan Cox5d951fb2009-01-02 13:45:19 +0000334
335/**
Alan Coxfcc8ac12009-06-11 12:24:17 +0100336 * tty_port_raise_dtr_rts - Raise DTR/RTS
Alan Cox5d951fb2009-01-02 13:45:19 +0000337 * @port: tty port
338 *
339 * Wrapper for the DTR/RTS raise logic. For the moment this is used
340 * to hide some internal details. This will eventually become entirely
341 * internal to the tty port.
342 */
343
344void tty_port_raise_dtr_rts(struct tty_port *port)
345{
Alan Coxfcc8ac12009-06-11 12:24:17 +0100346 if (port->ops->dtr_rts)
347 port->ops->dtr_rts(port, 1);
Alan Cox5d951fb2009-01-02 13:45:19 +0000348}
349EXPORT_SYMBOL(tty_port_raise_dtr_rts);
Alan Cox36c621d2009-01-02 13:46:10 +0000350
351/**
Alan Coxfcc8ac12009-06-11 12:24:17 +0100352 * tty_port_lower_dtr_rts - Lower DTR/RTS
353 * @port: tty port
354 *
355 * Wrapper for the DTR/RTS raise logic. For the moment this is used
356 * to hide some internal details. This will eventually become entirely
357 * internal to the tty port.
358 */
359
360void tty_port_lower_dtr_rts(struct tty_port *port)
361{
362 if (port->ops->dtr_rts)
363 port->ops->dtr_rts(port, 0);
364}
365EXPORT_SYMBOL(tty_port_lower_dtr_rts);
366
367/**
Alan Cox36c621d2009-01-02 13:46:10 +0000368 * tty_port_block_til_ready - Waiting logic for tty open
369 * @port: the tty port being opened
370 * @tty: the tty device being bound
Alan Coxed3f0af2017-01-16 16:54:29 -0600371 * @filp: the file pointer of the opener or NULL
Alan Cox36c621d2009-01-02 13:46:10 +0000372 *
373 * Implement the core POSIX/SuS tty behaviour when opening a tty device.
374 * Handles:
375 * - hangup (both before and during)
376 * - non blocking open
377 * - rts/dtr/dcd
378 * - signals
379 * - port flags and counts
380 *
381 * The passed tty_port must implement the carrier_raised method if it can
Alan Coxfcc8ac12009-06-11 12:24:17 +0100382 * do carrier detect and the dtr_rts method if it supports software
Alan Cox36c621d2009-01-02 13:46:10 +0000383 * management of these lines. Note that the dtr/rts raise is done each
384 * iteration as a hangup may have previously dropped them while we wait.
Peter Hurleyc590f6b2014-06-16 09:17:01 -0400385 *
386 * Caller holds tty lock.
387 *
388 * NB: May drop and reacquire tty lock when blocking, so tty and tty_port
389 * may have changed state (eg., may have been hung up).
Alan Cox36c621d2009-01-02 13:46:10 +0000390 */
Alan Coxd774a562009-10-06 16:06:21 +0100391
Alan Cox36c621d2009-01-02 13:46:10 +0000392int tty_port_block_til_ready(struct tty_port *port,
393 struct tty_struct *tty, struct file *filp)
394{
395 int do_clocal = 0, retval;
396 unsigned long flags;
Jiri Slaby6af9a432009-06-24 18:35:05 +0100397 DEFINE_WAIT(wait);
Alan Cox36c621d2009-01-02 13:46:10 +0000398
Alan Cox36c621d2009-01-02 13:46:10 +0000399 /* if non-blocking mode is set we can pass directly to open unless
400 the port has just hung up or is in another error state */
Peter Hurley18900ca2016-04-09 17:06:48 -0700401 if (tty_io_error(tty)) {
Peter Hurley807c8d812016-04-09 17:53:22 -0700402 tty_port_set_active(port, 1);
Alan Cox8627b962009-11-18 14:12:58 +0000403 return 0;
404 }
Alan Coxed3f0af2017-01-16 16:54:29 -0600405 if (filp == NULL || (filp->f_flags & O_NONBLOCK)) {
Alan Cox4175f3e2009-10-28 21:12:32 +0100406 /* Indicate we are open */
Peter Hurley9db276f2016-01-10 20:36:15 -0800407 if (C_BAUD(tty))
Alan Cox4175f3e2009-10-28 21:12:32 +0100408 tty_port_raise_dtr_rts(port);
Peter Hurley807c8d812016-04-09 17:53:22 -0700409 tty_port_set_active(port, 1);
Alan Cox36c621d2009-01-02 13:46:10 +0000410 return 0;
411 }
412
413 if (C_CLOCAL(tty))
414 do_clocal = 1;
415
416 /* Block waiting until we can proceed. We may need to wait for the
417 carrier, but we must also wait for any close that is in progress
418 before the next open may complete */
419
420 retval = 0;
Alan Cox36c621d2009-01-02 13:46:10 +0000421
422 /* The port lock protects the port counts */
423 spin_lock_irqsave(&port->lock, flags);
Peter Hurleye359a4e2014-06-16 09:17:06 -0400424 port->count--;
Alan Cox36c621d2009-01-02 13:46:10 +0000425 port->blocked_open++;
426 spin_unlock_irqrestore(&port->lock, flags);
427
428 while (1) {
429 /* Indicate we are open */
Peter Hurleyd41861c2016-04-09 17:53:25 -0700430 if (C_BAUD(tty) && tty_port_initialized(port))
Alan Cox78349092009-01-02 13:46:43 +0000431 tty_port_raise_dtr_rts(port);
Alan Cox36c621d2009-01-02 13:46:10 +0000432
Jiri Slaby3e3b5c02009-06-11 14:33:37 +0100433 prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
Alan Coxd774a562009-10-06 16:06:21 +0100434 /* Check for a hangup or uninitialised port.
435 Return accordingly */
Peter Hurleyd41861c2016-04-09 17:53:25 -0700436 if (tty_hung_up_p(filp) || !tty_port_initialized(port)) {
Alan Cox36c621d2009-01-02 13:46:10 +0000437 if (port->flags & ASYNC_HUP_NOTIFY)
438 retval = -EAGAIN;
439 else
440 retval = -ERESTARTSYS;
441 break;
442 }
Jiri Slaby0eee50a2012-01-12 22:55:15 +0100443 /*
444 * Probe the carrier. For devices with no carrier detect
445 * tty_port_carrier_raised will always return true.
446 * Never ask drivers if CLOCAL is set, this causes troubles
447 * on some hardware.
448 */
Peter Hurleyfef062c2015-10-10 16:00:52 -0400449 if (do_clocal || tty_port_carrier_raised(port))
Alan Cox36c621d2009-01-02 13:46:10 +0000450 break;
451 if (signal_pending(current)) {
452 retval = -ERESTARTSYS;
453 break;
454 }
Alan Cox89c8d912012-08-08 16:30:13 +0100455 tty_unlock(tty);
Alan Cox36c621d2009-01-02 13:46:10 +0000456 schedule();
Alan Cox89c8d912012-08-08 16:30:13 +0100457 tty_lock(tty);
Alan Cox36c621d2009-01-02 13:46:10 +0000458 }
Jiri Slaby3e3b5c02009-06-11 14:33:37 +0100459 finish_wait(&port->open_wait, &wait);
Alan Cox36c621d2009-01-02 13:46:10 +0000460
461 /* Update counts. A parallel hangup will have set count to zero and
462 we must not mess that up further */
463 spin_lock_irqsave(&port->lock, flags);
464 if (!tty_hung_up_p(filp))
465 port->count++;
466 port->blocked_open--;
Alan Cox36c621d2009-01-02 13:46:10 +0000467 spin_unlock_irqrestore(&port->lock, flags);
Peter Hurley807c8d812016-04-09 17:53:22 -0700468 if (retval == 0)
469 tty_port_set_active(port, 1);
Alan Coxecc2e052009-07-17 16:17:26 +0100470 return retval;
Alan Cox36c621d2009-01-02 13:46:10 +0000471}
472EXPORT_SYMBOL(tty_port_block_til_ready);
473
Johan Hovoldb74414f2013-03-07 15:55:52 +0100474static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
475{
476 unsigned int bps = tty_get_baud_rate(tty);
477 long timeout;
478
479 if (bps > 1200) {
480 timeout = (HZ * 10 * port->drain_delay) / bps;
481 timeout = max_t(long, timeout, HZ / 10);
482 } else {
483 timeout = 2 * HZ;
484 }
485 schedule_timeout_interruptible(timeout);
486}
487
Peter Hurley79c1faa2015-10-10 16:00:51 -0400488/* Caller holds tty lock. */
Alan Coxd774a562009-10-06 16:06:21 +0100489int tty_port_close_start(struct tty_port *port,
490 struct tty_struct *tty, struct file *filp)
Alan Coxa6614992009-01-02 13:46:50 +0000491{
492 unsigned long flags;
493
Peter Hurley633caba2014-11-05 12:40:03 -0500494 if (tty_hung_up_p(filp))
Alan Coxa6614992009-01-02 13:46:50 +0000495 return 0;
Alan Coxa6614992009-01-02 13:46:50 +0000496
Peter Hurley633caba2014-11-05 12:40:03 -0500497 spin_lock_irqsave(&port->lock, flags);
Alan Coxd774a562009-10-06 16:06:21 +0100498 if (tty->count == 1 && port->count != 1) {
Peter Hurley339f36b2015-11-08 13:01:13 -0500499 tty_warn(tty, "%s: tty->count = 1 port count = %d\n", __func__,
500 port->count);
Alan Coxa6614992009-01-02 13:46:50 +0000501 port->count = 1;
502 }
503 if (--port->count < 0) {
Peter Hurley339f36b2015-11-08 13:01:13 -0500504 tty_warn(tty, "%s: bad port count (%d)\n", __func__,
505 port->count);
Alan Coxa6614992009-01-02 13:46:50 +0000506 port->count = 0;
507 }
508
509 if (port->count) {
510 spin_unlock_irqrestore(&port->lock, flags);
511 return 0;
512 }
Alan Coxa6614992009-01-02 13:46:50 +0000513 spin_unlock_irqrestore(&port->lock, flags);
Johan Hovold0b2588c2013-03-07 15:55:53 +0100514
Peter Hurleyddc7b752014-06-16 09:17:03 -0400515 tty->closing = 1;
516
Peter Hurleyd41861c2016-04-09 17:53:25 -0700517 if (tty_port_initialized(port)) {
Johan Hovold0b2588c2013-03-07 15:55:53 +0100518 /* Don't block on a stalled port, just pull the chain */
519 if (tty->flow_stopped)
520 tty_driver_flush_buffer(tty);
521 if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
Peter Hurley79c1faa2015-10-10 16:00:51 -0400522 tty_wait_until_sent(tty, port->closing_wait);
Johan Hovold0b2588c2013-03-07 15:55:53 +0100523 if (port->drain_delay)
524 tty_port_drain_delay(port, tty);
525 }
Alan Coxe707c352009-11-05 13:27:57 +0000526 /* Flush the ldisc buffering */
527 tty_ldisc_flush(tty);
528
Peter Hurley469d6d02013-09-18 20:47:06 -0400529 /* Report to caller this is the last port reference */
Alan Coxa6614992009-01-02 13:46:50 +0000530 return 1;
531}
532EXPORT_SYMBOL(tty_port_close_start);
533
Peter Hurley0733db92014-06-16 09:16:59 -0400534/* Caller holds tty lock */
Alan Coxa6614992009-01-02 13:46:50 +0000535void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
536{
537 unsigned long flags;
538
Peter Hurley3f40f5b2014-11-05 12:40:05 -0500539 tty_ldisc_flush(tty);
Alan Coxa6614992009-01-02 13:46:50 +0000540 tty->closing = 0;
541
Peter Hurleyddc7b752014-06-16 09:17:03 -0400542 spin_lock_irqsave(&port->lock, flags);
543
Alan Coxa6614992009-01-02 13:46:50 +0000544 if (port->blocked_open) {
545 spin_unlock_irqrestore(&port->lock, flags);
Peter Hurley5823323e2016-01-10 20:36:14 -0800546 if (port->close_delay)
547 msleep_interruptible(jiffies_to_msecs(port->close_delay));
Alan Coxa6614992009-01-02 13:46:50 +0000548 spin_lock_irqsave(&port->lock, flags);
549 wake_up_interruptible(&port->open_wait);
550 }
Alan Coxa6614992009-01-02 13:46:50 +0000551 spin_unlock_irqrestore(&port->lock, flags);
Peter Hurley807c8d812016-04-09 17:53:22 -0700552 tty_port_set_active(port, 0);
Alan Coxa6614992009-01-02 13:46:50 +0000553}
554EXPORT_SYMBOL(tty_port_close_end);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700555
Peter Hurley0733db92014-06-16 09:16:59 -0400556/**
557 * tty_port_close
558 *
559 * Caller holds tty lock
Peter Hurley0733db92014-06-16 09:16:59 -0400560 */
Alan Cox7ca0ff92009-09-19 13:13:20 -0700561void tty_port_close(struct tty_port *port, struct tty_struct *tty,
562 struct file *filp)
563{
564 if (tty_port_close_start(port, tty, filp) == 0)
565 return;
Johan Hovold957daca2013-03-07 15:55:51 +0100566 tty_port_shutdown(port, tty);
Alan Coxd74e8282009-11-30 13:16:52 +0000567 set_bit(TTY_IO_ERROR, &tty->flags);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700568 tty_port_close_end(port, tty);
569 tty_port_tty_set(port, NULL);
570}
571EXPORT_SYMBOL(tty_port_close);
Alan Cox64bc3972009-10-06 16:06:11 +0100572
Jiri Slaby72a33bf2012-08-07 21:47:49 +0200573/**
574 * tty_port_install - generic tty->ops->install handler
575 * @port: tty_port of the device
576 * @driver: tty_driver for this device
577 * @tty: tty to be installed
578 *
579 * It is the same as tty_standard_install except the provided @port is linked
580 * to a concrete tty specified by @tty. Use this or tty_port_register_device
581 * (or both). Call tty_port_link_device as a last resort.
582 */
Jiri Slaby695586c2012-06-04 13:35:32 +0200583int tty_port_install(struct tty_port *port, struct tty_driver *driver,
584 struct tty_struct *tty)
585{
586 tty->port = port;
587 return tty_standard_install(driver, tty);
588}
589EXPORT_SYMBOL_GPL(tty_port_install);
590
Peter Hurleyaddd4672014-06-16 09:17:00 -0400591/**
592 * tty_port_open
593 *
594 * Caller holds tty lock.
595 *
596 * NB: may drop and reacquire tty lock (in tty_port_block_til_ready()) so
597 * tty and tty_port may have changed state (eg., may be hung up now)
598 */
Alan Cox64bc3972009-10-06 16:06:11 +0100599int tty_port_open(struct tty_port *port, struct tty_struct *tty,
Alan Coxd774a562009-10-06 16:06:21 +0100600 struct file *filp)
Alan Cox64bc3972009-10-06 16:06:11 +0100601{
602 spin_lock_irq(&port->lock);
Peter Hurleye359a4e2014-06-16 09:17:06 -0400603 ++port->count;
Alan Cox64bc3972009-10-06 16:06:11 +0100604 spin_unlock_irq(&port->lock);
605 tty_port_tty_set(port, tty);
606
607 /*
608 * Do the device-specific open only if the hardware isn't
609 * already initialized. Serialize open and shutdown using the
610 * port mutex.
611 */
612
613 mutex_lock(&port->mutex);
614
Peter Hurleyd41861c2016-04-09 17:53:25 -0700615 if (!tty_port_initialized(port)) {
Alan Coxa9a37ec2009-11-30 13:16:57 +0000616 clear_bit(TTY_IO_ERROR, &tty->flags);
Alan Cox64bc3972009-10-06 16:06:11 +0100617 if (port->ops->activate) {
618 int retval = port->ops->activate(port, tty);
619 if (retval) {
Alan Coxd774a562009-10-06 16:06:21 +0100620 mutex_unlock(&port->mutex);
621 return retval;
622 }
623 }
Peter Hurleyd41861c2016-04-09 17:53:25 -0700624 tty_port_set_initialized(port, 1);
Alan Cox64bc3972009-10-06 16:06:11 +0100625 }
626 mutex_unlock(&port->mutex);
627 return tty_port_block_til_ready(port, tty, filp);
628}
629
630EXPORT_SYMBOL(tty_port_open);