blob: fdc42c2d565f4f70fc9495b99a025a37894e9215 [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>
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));
Jiri Slabyecbbfd42012-10-18 22:26:47 +020024 tty_buffer_init(port);
Alan Cox9e485652008-10-13 10:37:07 +010025 init_waitqueue_head(&port->open_wait);
26 init_waitqueue_head(&port->close_wait);
Alan Coxbdc04e32009-09-19 13:13:31 -070027 init_waitqueue_head(&port->delta_msr_wait);
Alan Cox9e485652008-10-13 10:37:07 +010028 mutex_init(&port->mutex);
Alan Cox44e49092009-11-30 13:16:41 +000029 mutex_init(&port->buf_mutex);
Alan Cox4a90f092008-10-13 10:39:46 +010030 spin_lock_init(&port->lock);
Alan Cox9e485652008-10-13 10:37:07 +010031 port->close_delay = (50 * HZ) / 100;
32 port->closing_wait = (3000 * HZ) / 100;
Alan Cox568aafc2009-11-30 13:17:14 +000033 kref_init(&port->kref);
Alan Cox9e485652008-10-13 10:37:07 +010034}
35EXPORT_SYMBOL(tty_port_init);
36
Jiri Slaby72a33bf2012-08-07 21:47:49 +020037/**
Jiri Slaby2cb4ca02012-08-07 21:47:50 +020038 * tty_port_link_device - link tty and tty_port
39 * @port: tty_port of the device
40 * @driver: tty_driver for this device
41 * @index: index of the tty
42 *
43 * Provide the tty layer wit ha link from a tty (specified by @index) to a
44 * tty_port (@port). Use this only if neither tty_port_register_device nor
45 * tty_port_install is used in the driver. If used, this has to be called before
46 * tty_register_driver.
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/**
Jiri Slaby72a33bf2012-08-07 21:47:49 +020058 * tty_port_register_device - register tty device
59 * @port: tty_port of the device
60 * @driver: tty_driver for this device
61 * @index: index of the tty
62 * @device: parent if exists, otherwise NULL
63 *
64 * It is the same as tty_register_device except the provided @port is linked to
65 * a concrete tty specified by @index. Use this or tty_port_install (or both).
66 * Call tty_port_link_device as a last resort.
67 */
Jiri Slaby057eb852012-06-04 13:35:37 +020068struct device *tty_port_register_device(struct tty_port *port,
69 struct tty_driver *driver, unsigned index,
70 struct device *device)
71{
Jiri Slaby2cb4ca02012-08-07 21:47:50 +020072 tty_port_link_device(port, driver, index);
Jiri Slaby057eb852012-06-04 13:35:37 +020073 return tty_register_device(driver, index, device);
74}
75EXPORT_SYMBOL_GPL(tty_port_register_device);
76
Tomas Hlavacekb1b79912012-09-06 23:17:47 +020077/**
78 * tty_port_register_device_attr - register tty device
79 * @port: tty_port of the device
80 * @driver: tty_driver for this device
81 * @index: index of the tty
82 * @device: parent if exists, otherwise NULL
83 * @drvdata: Driver data to be set to device.
84 * @attr_grp: Attribute group to be set on device.
85 *
86 * It is the same as tty_register_device_attr except the provided @port is
87 * linked to a concrete tty specified by @index. Use this or tty_port_install
88 * (or both). Call tty_port_link_device as a last resort.
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
Alan Cox9e485652008-10-13 10:37:07 +0100101int tty_port_alloc_xmit_buf(struct tty_port *port)
102{
103 /* We may sleep in get_zeroed_page() */
Alan Cox44e49092009-11-30 13:16:41 +0000104 mutex_lock(&port->buf_mutex);
Alan Cox9e485652008-10-13 10:37:07 +0100105 if (port->xmit_buf == NULL)
106 port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
Alan Cox44e49092009-11-30 13:16:41 +0000107 mutex_unlock(&port->buf_mutex);
Alan Cox9e485652008-10-13 10:37:07 +0100108 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{
Alan Cox44e49092009-11-30 13:16:41 +0000116 mutex_lock(&port->buf_mutex);
Alan Cox9e485652008-10-13 10:37:07 +0100117 if (port->xmit_buf != NULL) {
118 free_page((unsigned long)port->xmit_buf);
119 port->xmit_buf = NULL;
120 }
Alan Cox44e49092009-11-30 13:16:41 +0000121 mutex_unlock(&port->buf_mutex);
Alan Cox9e485652008-10-13 10:37:07 +0100122}
123EXPORT_SYMBOL(tty_port_free_xmit_buf);
124
Alan Cox568aafc2009-11-30 13:17:14 +0000125static void tty_port_destructor(struct kref *kref)
126{
127 struct tty_port *port = container_of(kref, struct tty_port, kref);
128 if (port->xmit_buf)
129 free_page((unsigned long)port->xmit_buf);
Jiri Slabyecbbfd42012-10-18 22:26:47 +0200130 tty_buffer_free_all(port);
Jiri Slaby81c79832012-11-15 09:49:49 +0100131 if (port->ops && port->ops->destruct)
Alan Cox568aafc2009-11-30 13:17:14 +0000132 port->ops->destruct(port);
133 else
134 kfree(port);
135}
136
137void tty_port_put(struct tty_port *port)
138{
139 if (port)
140 kref_put(&port->kref, tty_port_destructor);
141}
142EXPORT_SYMBOL(tty_port_put);
Alan Cox9e485652008-10-13 10:37:07 +0100143
Alan Cox4a90f092008-10-13 10:39:46 +0100144/**
145 * tty_port_tty_get - get a tty reference
146 * @port: tty port
147 *
148 * Return a refcount protected tty instance or NULL if the port is not
149 * associated with a tty (eg due to close or hangup)
150 */
151
152struct tty_struct *tty_port_tty_get(struct tty_port *port)
153{
154 unsigned long flags;
155 struct tty_struct *tty;
156
157 spin_lock_irqsave(&port->lock, flags);
158 tty = tty_kref_get(port->tty);
159 spin_unlock_irqrestore(&port->lock, flags);
160 return tty;
161}
162EXPORT_SYMBOL(tty_port_tty_get);
163
164/**
165 * tty_port_tty_set - set the tty of a port
166 * @port: tty port
167 * @tty: the tty
168 *
169 * Associate the port and tty pair. Manages any internal refcounts.
170 * Pass NULL to deassociate a port
171 */
172
173void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
174{
175 unsigned long flags;
176
177 spin_lock_irqsave(&port->lock, flags);
178 if (port->tty)
179 tty_kref_put(port->tty);
Alan Coxcb4bca32008-10-21 13:47:44 +0100180 port->tty = tty_kref_get(tty);
Alan Cox4a90f092008-10-13 10:39:46 +0100181 spin_unlock_irqrestore(&port->lock, flags);
182}
183EXPORT_SYMBOL(tty_port_tty_set);
Alan Cox31f35932009-01-02 13:45:05 +0000184
Alan Cox7ca0ff92009-09-19 13:13:20 -0700185static void tty_port_shutdown(struct tty_port *port)
186{
Alan Cox64bc3972009-10-06 16:06:11 +0100187 mutex_lock(&port->mutex);
Jason Wessel336cee42010-03-08 21:50:11 -0600188 if (port->ops->shutdown && !port->console &&
Alan Stern1f5c13f2009-08-20 15:23:47 -0400189 test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
Alan Cox7ca0ff92009-09-19 13:13:20 -0700190 port->ops->shutdown(port);
Alan Cox64bc3972009-10-06 16:06:11 +0100191 mutex_unlock(&port->mutex);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700192}
193
Alan Cox31f35932009-01-02 13:45:05 +0000194/**
Alan Cox3e616962009-01-02 13:45:26 +0000195 * tty_port_hangup - hangup helper
196 * @port: tty port
197 *
198 * Perform port level tty hangup flag and count changes. Drop the tty
199 * reference.
200 */
201
202void tty_port_hangup(struct tty_port *port)
203{
204 unsigned long flags;
205
206 spin_lock_irqsave(&port->lock, flags);
207 port->count = 0;
208 port->flags &= ~ASYNC_NORMAL_ACTIVE;
Alan Coxd74e8282009-11-30 13:16:52 +0000209 if (port->tty) {
210 set_bit(TTY_IO_ERROR, &port->tty->flags);
Alan Cox3e616962009-01-02 13:45:26 +0000211 tty_kref_put(port->tty);
Alan Coxd74e8282009-11-30 13:16:52 +0000212 }
Alan Cox3e616962009-01-02 13:45:26 +0000213 port->tty = NULL;
214 spin_unlock_irqrestore(&port->lock, flags);
215 wake_up_interruptible(&port->open_wait);
Alan Coxbdc04e32009-09-19 13:13:31 -0700216 wake_up_interruptible(&port->delta_msr_wait);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700217 tty_port_shutdown(port);
Alan Cox3e616962009-01-02 13:45:26 +0000218}
219EXPORT_SYMBOL(tty_port_hangup);
220
221/**
Alan Cox31f35932009-01-02 13:45:05 +0000222 * tty_port_carrier_raised - carrier raised check
223 * @port: tty port
224 *
225 * Wrapper for the carrier detect logic. For the moment this is used
226 * to hide some internal details. This will eventually become entirely
227 * internal to the tty port.
228 */
229
230int tty_port_carrier_raised(struct tty_port *port)
231{
232 if (port->ops->carrier_raised == NULL)
233 return 1;
234 return port->ops->carrier_raised(port);
235}
236EXPORT_SYMBOL(tty_port_carrier_raised);
Alan Cox5d951fb2009-01-02 13:45:19 +0000237
238/**
Alan Coxfcc8ac12009-06-11 12:24:17 +0100239 * tty_port_raise_dtr_rts - Raise DTR/RTS
Alan Cox5d951fb2009-01-02 13:45:19 +0000240 * @port: tty port
241 *
242 * Wrapper for the DTR/RTS raise logic. For the moment this is used
243 * to hide some internal details. This will eventually become entirely
244 * internal to the tty port.
245 */
246
247void tty_port_raise_dtr_rts(struct tty_port *port)
248{
Alan Coxfcc8ac12009-06-11 12:24:17 +0100249 if (port->ops->dtr_rts)
250 port->ops->dtr_rts(port, 1);
Alan Cox5d951fb2009-01-02 13:45:19 +0000251}
252EXPORT_SYMBOL(tty_port_raise_dtr_rts);
Alan Cox36c621d2009-01-02 13:46:10 +0000253
254/**
Alan Coxfcc8ac12009-06-11 12:24:17 +0100255 * tty_port_lower_dtr_rts - Lower DTR/RTS
256 * @port: tty port
257 *
258 * Wrapper for the DTR/RTS raise logic. For the moment this is used
259 * to hide some internal details. This will eventually become entirely
260 * internal to the tty port.
261 */
262
263void tty_port_lower_dtr_rts(struct tty_port *port)
264{
265 if (port->ops->dtr_rts)
266 port->ops->dtr_rts(port, 0);
267}
268EXPORT_SYMBOL(tty_port_lower_dtr_rts);
269
270/**
Alan Cox36c621d2009-01-02 13:46:10 +0000271 * tty_port_block_til_ready - Waiting logic for tty open
272 * @port: the tty port being opened
273 * @tty: the tty device being bound
274 * @filp: the file pointer of the opener
275 *
276 * Implement the core POSIX/SuS tty behaviour when opening a tty device.
277 * Handles:
278 * - hangup (both before and during)
279 * - non blocking open
280 * - rts/dtr/dcd
281 * - signals
282 * - port flags and counts
283 *
284 * The passed tty_port must implement the carrier_raised method if it can
Alan Coxfcc8ac12009-06-11 12:24:17 +0100285 * do carrier detect and the dtr_rts method if it supports software
Alan Cox36c621d2009-01-02 13:46:10 +0000286 * management of these lines. Note that the dtr/rts raise is done each
287 * iteration as a hangup may have previously dropped them while we wait.
288 */
Alan Coxd774a562009-10-06 16:06:21 +0100289
Alan Cox36c621d2009-01-02 13:46:10 +0000290int tty_port_block_til_ready(struct tty_port *port,
291 struct tty_struct *tty, struct file *filp)
292{
293 int do_clocal = 0, retval;
294 unsigned long flags;
Jiri Slaby6af9a432009-06-24 18:35:05 +0100295 DEFINE_WAIT(wait);
Alan Cox36c621d2009-01-02 13:46:10 +0000296
297 /* block if port is in the process of being closed */
298 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
Alan Cox89c8d912012-08-08 16:30:13 +0100299 wait_event_interruptible_tty(tty, port->close_wait,
Jiri Slaby5fc5b422009-06-11 14:32:42 +0100300 !(port->flags & ASYNC_CLOSING));
Alan Cox36c621d2009-01-02 13:46:10 +0000301 if (port->flags & ASYNC_HUP_NOTIFY)
302 return -EAGAIN;
303 else
304 return -ERESTARTSYS;
305 }
306
307 /* if non-blocking mode is set we can pass directly to open unless
308 the port has just hung up or is in another error state */
Alan Cox8627b962009-11-18 14:12:58 +0000309 if (tty->flags & (1 << TTY_IO_ERROR)) {
310 port->flags |= ASYNC_NORMAL_ACTIVE;
311 return 0;
312 }
313 if (filp->f_flags & O_NONBLOCK) {
Alan Cox4175f3e2009-10-28 21:12:32 +0100314 /* Indicate we are open */
Alan Coxadc8d742012-07-14 15:31:47 +0100315 if (tty->termios.c_cflag & CBAUD)
Alan Cox4175f3e2009-10-28 21:12:32 +0100316 tty_port_raise_dtr_rts(port);
Alan Cox36c621d2009-01-02 13:46:10 +0000317 port->flags |= ASYNC_NORMAL_ACTIVE;
318 return 0;
319 }
320
321 if (C_CLOCAL(tty))
322 do_clocal = 1;
323
324 /* Block waiting until we can proceed. We may need to wait for the
325 carrier, but we must also wait for any close that is in progress
326 before the next open may complete */
327
328 retval = 0;
Alan Cox36c621d2009-01-02 13:46:10 +0000329
330 /* The port lock protects the port counts */
331 spin_lock_irqsave(&port->lock, flags);
332 if (!tty_hung_up_p(filp))
333 port->count--;
334 port->blocked_open++;
335 spin_unlock_irqrestore(&port->lock, flags);
336
337 while (1) {
338 /* Indicate we are open */
Alan Coxadc8d742012-07-14 15:31:47 +0100339 if (tty->termios.c_cflag & CBAUD)
Alan Cox78349092009-01-02 13:46:43 +0000340 tty_port_raise_dtr_rts(port);
Alan Cox36c621d2009-01-02 13:46:10 +0000341
Jiri Slaby3e3b5c02009-06-11 14:33:37 +0100342 prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
Alan Coxd774a562009-10-06 16:06:21 +0100343 /* Check for a hangup or uninitialised port.
344 Return accordingly */
Alan Cox36c621d2009-01-02 13:46:10 +0000345 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
346 if (port->flags & ASYNC_HUP_NOTIFY)
347 retval = -EAGAIN;
348 else
349 retval = -ERESTARTSYS;
350 break;
351 }
Jiri Slaby0eee50a2012-01-12 22:55:15 +0100352 /*
353 * Probe the carrier. For devices with no carrier detect
354 * tty_port_carrier_raised will always return true.
355 * Never ask drivers if CLOCAL is set, this causes troubles
356 * on some hardware.
357 */
Alan Cox36c621d2009-01-02 13:46:10 +0000358 if (!(port->flags & ASYNC_CLOSING) &&
Jiri Slaby0eee50a2012-01-12 22:55:15 +0100359 (do_clocal || tty_port_carrier_raised(port)))
Alan Cox36c621d2009-01-02 13:46:10 +0000360 break;
361 if (signal_pending(current)) {
362 retval = -ERESTARTSYS;
363 break;
364 }
Alan Cox89c8d912012-08-08 16:30:13 +0100365 tty_unlock(tty);
Alan Cox36c621d2009-01-02 13:46:10 +0000366 schedule();
Alan Cox89c8d912012-08-08 16:30:13 +0100367 tty_lock(tty);
Alan Cox36c621d2009-01-02 13:46:10 +0000368 }
Jiri Slaby3e3b5c02009-06-11 14:33:37 +0100369 finish_wait(&port->open_wait, &wait);
Alan Cox36c621d2009-01-02 13:46:10 +0000370
371 /* Update counts. A parallel hangup will have set count to zero and
372 we must not mess that up further */
373 spin_lock_irqsave(&port->lock, flags);
374 if (!tty_hung_up_p(filp))
375 port->count++;
376 port->blocked_open--;
377 if (retval == 0)
378 port->flags |= ASYNC_NORMAL_ACTIVE;
379 spin_unlock_irqrestore(&port->lock, flags);
Alan Coxecc2e052009-07-17 16:17:26 +0100380 return retval;
Alan Cox36c621d2009-01-02 13:46:10 +0000381}
382EXPORT_SYMBOL(tty_port_block_til_ready);
383
Alan Coxd774a562009-10-06 16:06:21 +0100384int tty_port_close_start(struct tty_port *port,
385 struct tty_struct *tty, struct file *filp)
Alan Coxa6614992009-01-02 13:46:50 +0000386{
387 unsigned long flags;
388
389 spin_lock_irqsave(&port->lock, flags);
390 if (tty_hung_up_p(filp)) {
391 spin_unlock_irqrestore(&port->lock, flags);
392 return 0;
393 }
394
Alan Coxd774a562009-10-06 16:06:21 +0100395 if (tty->count == 1 && port->count != 1) {
Alan Coxa6614992009-01-02 13:46:50 +0000396 printk(KERN_WARNING
397 "tty_port_close_start: tty->count = 1 port count = %d.\n",
398 port->count);
399 port->count = 1;
400 }
401 if (--port->count < 0) {
402 printk(KERN_WARNING "tty_port_close_start: count = %d\n",
403 port->count);
404 port->count = 0;
405 }
406
407 if (port->count) {
408 spin_unlock_irqrestore(&port->lock, flags);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700409 if (port->ops->drop)
410 port->ops->drop(port);
Alan Coxa6614992009-01-02 13:46:50 +0000411 return 0;
412 }
Alan Stern1f5c13f2009-08-20 15:23:47 -0400413 set_bit(ASYNCB_CLOSING, &port->flags);
Alan Coxa6614992009-01-02 13:46:50 +0000414 tty->closing = 1;
415 spin_unlock_irqrestore(&port->lock, flags);
Alan Coxfba85e02009-01-02 13:48:39 +0000416 /* Don't block on a stalled port, just pull the chain */
417 if (tty->flow_stopped)
418 tty_driver_flush_buffer(tty);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700419 if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
Alan Cox6ed1dba2009-01-02 13:48:11 +0000420 port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
Jiri Slaby424cc032011-08-25 15:12:07 +0200421 tty_wait_until_sent_from_close(tty, port->closing_wait);
Alan Cox1ec739b2009-06-11 12:25:25 +0100422 if (port->drain_delay) {
423 unsigned int bps = tty_get_baud_rate(tty);
424 long timeout;
425
426 if (bps > 1200)
Alan Coxd774a562009-10-06 16:06:21 +0100427 timeout = max_t(long,
428 (HZ * 10 * port->drain_delay) / bps, HZ / 10);
Alan Cox1ec739b2009-06-11 12:25:25 +0100429 else
430 timeout = 2 * HZ;
431 schedule_timeout_interruptible(timeout);
432 }
Alan Coxe707c352009-11-05 13:27:57 +0000433 /* Flush the ldisc buffering */
434 tty_ldisc_flush(tty);
435
436 /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
437 hang up the line */
Alan Coxadc8d742012-07-14 15:31:47 +0100438 if (tty->termios.c_cflag & HUPCL)
Alan Coxe707c352009-11-05 13:27:57 +0000439 tty_port_lower_dtr_rts(port);
440
Alan Cox7ca0ff92009-09-19 13:13:20 -0700441 /* Don't call port->drop for the last reference. Callers will want
442 to drop the last active reference in ->shutdown() or the tty
443 shutdown path */
Alan Coxa6614992009-01-02 13:46:50 +0000444 return 1;
445}
446EXPORT_SYMBOL(tty_port_close_start);
447
448void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
449{
450 unsigned long flags;
451
Alan Coxa6614992009-01-02 13:46:50 +0000452 spin_lock_irqsave(&port->lock, flags);
453 tty->closing = 0;
454
455 if (port->blocked_open) {
456 spin_unlock_irqrestore(&port->lock, flags);
457 if (port->close_delay) {
458 msleep_interruptible(
459 jiffies_to_msecs(port->close_delay));
460 }
461 spin_lock_irqsave(&port->lock, flags);
462 wake_up_interruptible(&port->open_wait);
463 }
464 port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
465 wake_up_interruptible(&port->close_wait);
466 spin_unlock_irqrestore(&port->lock, flags);
467}
468EXPORT_SYMBOL(tty_port_close_end);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700469
470void tty_port_close(struct tty_port *port, struct tty_struct *tty,
471 struct file *filp)
472{
473 if (tty_port_close_start(port, tty, filp) == 0)
474 return;
475 tty_port_shutdown(port);
Alan Coxd74e8282009-11-30 13:16:52 +0000476 set_bit(TTY_IO_ERROR, &tty->flags);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700477 tty_port_close_end(port, tty);
478 tty_port_tty_set(port, NULL);
479}
480EXPORT_SYMBOL(tty_port_close);
Alan Cox64bc3972009-10-06 16:06:11 +0100481
Jiri Slaby72a33bf2012-08-07 21:47:49 +0200482/**
483 * tty_port_install - generic tty->ops->install handler
484 * @port: tty_port of the device
485 * @driver: tty_driver for this device
486 * @tty: tty to be installed
487 *
488 * It is the same as tty_standard_install except the provided @port is linked
489 * to a concrete tty specified by @tty. Use this or tty_port_register_device
490 * (or both). Call tty_port_link_device as a last resort.
491 */
Jiri Slaby695586c2012-06-04 13:35:32 +0200492int tty_port_install(struct tty_port *port, struct tty_driver *driver,
493 struct tty_struct *tty)
494{
495 tty->port = port;
496 return tty_standard_install(driver, tty);
497}
498EXPORT_SYMBOL_GPL(tty_port_install);
499
Alan Cox64bc3972009-10-06 16:06:11 +0100500int tty_port_open(struct tty_port *port, struct tty_struct *tty,
Alan Coxd774a562009-10-06 16:06:21 +0100501 struct file *filp)
Alan Cox64bc3972009-10-06 16:06:11 +0100502{
503 spin_lock_irq(&port->lock);
504 if (!tty_hung_up_p(filp))
505 ++port->count;
506 spin_unlock_irq(&port->lock);
507 tty_port_tty_set(port, tty);
508
509 /*
510 * Do the device-specific open only if the hardware isn't
511 * already initialized. Serialize open and shutdown using the
512 * port mutex.
513 */
514
515 mutex_lock(&port->mutex);
516
517 if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
Alan Coxa9a37ec2009-11-30 13:16:57 +0000518 clear_bit(TTY_IO_ERROR, &tty->flags);
Alan Cox64bc3972009-10-06 16:06:11 +0100519 if (port->ops->activate) {
520 int retval = port->ops->activate(port, tty);
521 if (retval) {
Alan Coxd774a562009-10-06 16:06:21 +0100522 mutex_unlock(&port->mutex);
523 return retval;
524 }
525 }
Alan Cox64bc3972009-10-06 16:06:11 +0100526 set_bit(ASYNCB_INITIALIZED, &port->flags);
527 }
528 mutex_unlock(&port->mutex);
529 return tty_port_block_til_ready(port, tty, filp);
530}
531
532EXPORT_SYMBOL(tty_port_open);