Branch data Line data Source code
1 : : /*
2 : : * Tty port functions
3 : : */
4 : :
5 : : #include <linux/types.h>
6 : : #include <linux/errno.h>
7 : : #include <linux/tty.h>
8 : : #include <linux/tty_driver.h>
9 : : #include <linux/tty_flip.h>
10 : : #include <linux/serial.h>
11 : : #include <linux/timer.h>
12 : : #include <linux/string.h>
13 : : #include <linux/slab.h>
14 : : #include <linux/sched.h>
15 : : #include <linux/init.h>
16 : : #include <linux/wait.h>
17 : : #include <linux/bitops.h>
18 : : #include <linux/delay.h>
19 : : #include <linux/module.h>
20 : :
21 : 0 : void tty_port_init(struct tty_port *port)
22 : : {
23 : 248 : memset(port, 0, sizeof(*port));
24 : 248 : tty_buffer_init(port);
25 : 248 : init_waitqueue_head(&port->open_wait);
26 : 248 : init_waitqueue_head(&port->close_wait);
27 : 248 : init_waitqueue_head(&port->delta_msr_wait);
28 : 248 : mutex_init(&port->mutex);
29 : 248 : mutex_init(&port->buf_mutex);
30 : 248 : spin_lock_init(&port->lock);
31 : 248 : port->close_delay = (50 * HZ) / 100;
32 : 248 : port->closing_wait = (3000 * HZ) / 100;
33 : : kref_init(&port->kref);
34 : : }
35 : : EXPORT_SYMBOL(tty_port_init);
36 : :
37 : : /**
38 : : * 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 : : */
48 : 0 : void tty_port_link_device(struct tty_port *port,
49 : : struct tty_driver *driver, unsigned index)
50 : : {
51 [ # # ][ # # ]: 0 : if (WARN_ON(index >= driver->num))
52 : 0 : return;
53 : 0 : driver->ports[index] = port;
54 : : }
55 : : EXPORT_SYMBOL_GPL(tty_port_link_device);
56 : :
57 : : /**
58 : : * 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 : : */
68 : 0 : struct device *tty_port_register_device(struct tty_port *port,
69 : : struct tty_driver *driver, unsigned index,
70 : : struct device *device)
71 : : {
72 : 0 : tty_port_link_device(port, driver, index);
73 : 0 : return tty_register_device(driver, index, device);
74 : : }
75 : : EXPORT_SYMBOL_GPL(tty_port_register_device);
76 : :
77 : : /**
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 : : */
90 : 0 : struct 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 : 0 : tty_port_link_device(port, driver, index);
96 : 0 : return tty_register_device_attr(driver, index, device, drvdata,
97 : : attr_grp);
98 : : }
99 : : EXPORT_SYMBOL_GPL(tty_port_register_device_attr);
100 : :
101 : 0 : int tty_port_alloc_xmit_buf(struct tty_port *port)
102 : : {
103 : : /* We may sleep in get_zeroed_page() */
104 : 0 : mutex_lock(&port->buf_mutex);
105 [ # # ]: 0 : if (port->xmit_buf == NULL)
106 : 0 : port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
107 : 0 : mutex_unlock(&port->buf_mutex);
108 [ # # ]: 0 : if (port->xmit_buf == NULL)
109 : : return -ENOMEM;
110 : 0 : return 0;
111 : : }
112 : : EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
113 : :
114 : 0 : void tty_port_free_xmit_buf(struct tty_port *port)
115 : : {
116 : 0 : mutex_lock(&port->buf_mutex);
117 [ # # ]: 0 : if (port->xmit_buf != NULL) {
118 : 0 : free_page((unsigned long)port->xmit_buf);
119 : 0 : port->xmit_buf = NULL;
120 : : }
121 : 0 : mutex_unlock(&port->buf_mutex);
122 : 0 : }
123 : : EXPORT_SYMBOL(tty_port_free_xmit_buf);
124 : :
125 : : /**
126 : : * tty_port_destroy -- destroy inited port
127 : : * @port: tty port to be doestroyed
128 : : *
129 : : * When a port was initialized using tty_port_init, one has to destroy the
130 : : * port by this function. Either indirectly by using tty_port refcounting
131 : : * (tty_port_put) or directly if refcounting is not used.
132 : : */
133 : 0 : void tty_port_destroy(struct tty_port *port)
134 : : {
135 : 192 : cancel_work_sync(&port->buf.work);
136 : 192 : tty_buffer_free_all(port);
137 : 0 : }
138 : : EXPORT_SYMBOL(tty_port_destroy);
139 : :
140 : 0 : static void tty_port_destructor(struct kref *kref)
141 : : {
142 : 192 : struct tty_port *port = container_of(kref, struct tty_port, kref);
143 : :
144 : : /* check if last port ref was dropped before tty release */
145 [ - + ][ + - ]: 192 : if (WARN_ON(port->itty))
146 : 192 : return;
147 [ - + ]: 192 : if (port->xmit_buf)
148 : 0 : free_page((unsigned long)port->xmit_buf);
149 : : tty_port_destroy(port);
150 [ - + ][ # # ]: 192 : if (port->ops && port->ops->destruct)
151 : 0 : port->ops->destruct(port);
152 : : else
153 : 192 : kfree(port);
154 : : }
155 : :
156 : 0 : void tty_port_put(struct tty_port *port)
157 : : {
158 [ + - ]: 192 : if (port)
159 : 192 : kref_put(&port->kref, tty_port_destructor);
160 : 192 : }
161 : : EXPORT_SYMBOL(tty_port_put);
162 : :
163 : : /**
164 : : * tty_port_tty_get - get a tty reference
165 : : * @port: tty port
166 : : *
167 : : * Return a refcount protected tty instance or NULL if the port is not
168 : : * associated with a tty (eg due to close or hangup)
169 : : */
170 : :
171 : 0 : struct tty_struct *tty_port_tty_get(struct tty_port *port)
172 : : {
173 : : unsigned long flags;
174 : : struct tty_struct *tty;
175 : :
176 : 0 : spin_lock_irqsave(&port->lock, flags);
177 : 0 : tty = tty_kref_get(port->tty);
178 : : spin_unlock_irqrestore(&port->lock, flags);
179 : 0 : return tty;
180 : : }
181 : : EXPORT_SYMBOL(tty_port_tty_get);
182 : :
183 : : /**
184 : : * tty_port_tty_set - set the tty of a port
185 : : * @port: tty port
186 : : * @tty: the tty
187 : : *
188 : : * Associate the port and tty pair. Manages any internal refcounts.
189 : : * Pass NULL to deassociate a port
190 : : */
191 : :
192 : 0 : void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
193 : : {
194 : : unsigned long flags;
195 : :
196 : 1 : spin_lock_irqsave(&port->lock, flags);
197 [ + - ]: 1 : if (port->tty)
198 : 1 : tty_kref_put(port->tty);
199 : 1 : port->tty = tty_kref_get(tty);
200 : : spin_unlock_irqrestore(&port->lock, flags);
201 : 1 : }
202 : : EXPORT_SYMBOL(tty_port_tty_set);
203 : :
204 : 0 : static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
205 : : {
206 : 0 : mutex_lock(&port->mutex);
207 [ # # ]: 0 : if (port->console)
208 : : goto out;
209 : :
210 [ # # ]: 0 : if (test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) {
211 : : /*
212 : : * Drop DTR/RTS if HUPCL is set. This causes any attached
213 : : * modem to hang up the line.
214 : : */
215 [ # # ][ # # ]: 0 : if (tty && C_HUPCL(tty))
216 : : tty_port_lower_dtr_rts(port);
217 : :
218 [ # # ]: 0 : if (port->ops->shutdown)
219 : 0 : port->ops->shutdown(port);
220 : : }
221 : : out:
222 : 0 : mutex_unlock(&port->mutex);
223 : 0 : }
224 : :
225 : : /**
226 : : * tty_port_hangup - hangup helper
227 : : * @port: tty port
228 : : *
229 : : * Perform port level tty hangup flag and count changes. Drop the tty
230 : : * reference.
231 : : */
232 : :
233 : 0 : void tty_port_hangup(struct tty_port *port)
234 : : {
235 : : struct tty_struct *tty;
236 : : unsigned long flags;
237 : :
238 : 0 : spin_lock_irqsave(&port->lock, flags);
239 : 0 : port->count = 0;
240 : 0 : port->flags &= ~ASYNC_NORMAL_ACTIVE;
241 : 0 : tty = port->tty;
242 [ # # ]: 0 : if (tty)
243 : 0 : set_bit(TTY_IO_ERROR, &tty->flags);
244 : 0 : port->tty = NULL;
245 : : spin_unlock_irqrestore(&port->lock, flags);
246 : 0 : tty_port_shutdown(port, tty);
247 : 0 : tty_kref_put(tty);
248 : 0 : wake_up_interruptible(&port->open_wait);
249 : 0 : wake_up_interruptible(&port->delta_msr_wait);
250 : 0 : }
251 : : EXPORT_SYMBOL(tty_port_hangup);
252 : :
253 : : /**
254 : : * tty_port_tty_hangup - helper to hang up a tty
255 : : *
256 : : * @port: tty port
257 : : * @check_clocal: hang only ttys with CLOCAL unset?
258 : : */
259 : 0 : void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
260 : : {
261 : 0 : struct tty_struct *tty = tty_port_tty_get(port);
262 : :
263 [ # # ][ # # ]: 0 : if (tty && (!check_clocal || !C_CLOCAL(tty)))
[ # # ]
264 : 0 : tty_hangup(tty);
265 : 0 : tty_kref_put(tty);
266 : 0 : }
267 : : EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
268 : :
269 : : /**
270 : : * tty_port_tty_wakeup - helper to wake up a tty
271 : : *
272 : : * @port: tty port
273 : : */
274 : 0 : void tty_port_tty_wakeup(struct tty_port *port)
275 : : {
276 : 0 : struct tty_struct *tty = tty_port_tty_get(port);
277 : :
278 [ # # ]: 0 : if (tty) {
279 : 0 : tty_wakeup(tty);
280 : 0 : tty_kref_put(tty);
281 : : }
282 : 0 : }
283 : : EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
284 : :
285 : : /**
286 : : * tty_port_carrier_raised - carrier raised check
287 : : * @port: tty port
288 : : *
289 : : * Wrapper for the carrier detect logic. For the moment this is used
290 : : * to hide some internal details. This will eventually become entirely
291 : : * internal to the tty port.
292 : : */
293 : :
294 : 0 : int tty_port_carrier_raised(struct tty_port *port)
295 : : {
296 [ # # ][ # # ]: 0 : if (port->ops->carrier_raised == NULL)
297 : : return 1;
298 : 0 : return port->ops->carrier_raised(port);
299 : : }
300 : : EXPORT_SYMBOL(tty_port_carrier_raised);
301 : :
302 : : /**
303 : : * tty_port_raise_dtr_rts - Raise DTR/RTS
304 : : * @port: tty port
305 : : *
306 : : * Wrapper for the DTR/RTS raise logic. For the moment this is used
307 : : * to hide some internal details. This will eventually become entirely
308 : : * internal to the tty port.
309 : : */
310 : :
311 : 0 : void tty_port_raise_dtr_rts(struct tty_port *port)
312 : : {
313 [ + - ][ # # ]: 1 : if (port->ops->dtr_rts)
[ # # ]
314 : 1 : port->ops->dtr_rts(port, 1);
315 : 0 : }
316 : : EXPORT_SYMBOL(tty_port_raise_dtr_rts);
317 : :
318 : : /**
319 : : * tty_port_lower_dtr_rts - Lower DTR/RTS
320 : : * @port: tty port
321 : : *
322 : : * Wrapper for the DTR/RTS raise 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 : :
327 : 0 : void tty_port_lower_dtr_rts(struct tty_port *port)
328 : : {
329 [ # # ][ # # ]: 0 : if (port->ops->dtr_rts)
330 : 0 : port->ops->dtr_rts(port, 0);
331 : 0 : }
332 : : EXPORT_SYMBOL(tty_port_lower_dtr_rts);
333 : :
334 : : /**
335 : : * tty_port_block_til_ready - Waiting logic for tty open
336 : : * @port: the tty port being opened
337 : : * @tty: the tty device being bound
338 : : * @filp: the file pointer of the opener
339 : : *
340 : : * Implement the core POSIX/SuS tty behaviour when opening a tty device.
341 : : * Handles:
342 : : * - hangup (both before and during)
343 : : * - non blocking open
344 : : * - rts/dtr/dcd
345 : : * - signals
346 : : * - port flags and counts
347 : : *
348 : : * The passed tty_port must implement the carrier_raised method if it can
349 : : * do carrier detect and the dtr_rts method if it supports software
350 : : * management of these lines. Note that the dtr/rts raise is done each
351 : : * iteration as a hangup may have previously dropped them while we wait.
352 : : */
353 : :
354 : 0 : int tty_port_block_til_ready(struct tty_port *port,
355 : : struct tty_struct *tty, struct file *filp)
356 : : {
357 : : int do_clocal = 0, retval;
358 : : unsigned long flags;
359 : 2 : DEFINE_WAIT(wait);
360 : :
361 : : /* block if port is in the process of being closed */
362 [ + - ][ - + ]: 1 : if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
363 [ # # ][ # # ]: 0 : wait_event_interruptible_tty(tty, port->close_wait,
[ # # ]
364 : : !(port->flags & ASYNC_CLOSING));
365 [ # # ]: 0 : if (port->flags & ASYNC_HUP_NOTIFY)
366 : : return -EAGAIN;
367 : : else
368 : 0 : return -ERESTARTSYS;
369 : : }
370 : :
371 : : /* if non-blocking mode is set we can pass directly to open unless
372 : : the port has just hung up or is in another error state */
373 [ - + ]: 1 : if (tty->flags & (1 << TTY_IO_ERROR)) {
374 : 0 : port->flags |= ASYNC_NORMAL_ACTIVE;
375 : 0 : return 0;
376 : : }
377 [ + - ]: 1 : if (filp->f_flags & O_NONBLOCK) {
378 : : /* Indicate we are open */
379 [ + - ]: 1 : if (tty->termios.c_cflag & CBAUD)
380 : : tty_port_raise_dtr_rts(port);
381 : 1 : port->flags |= ASYNC_NORMAL_ACTIVE;
382 : 1 : return 0;
383 : : }
384 : :
385 [ # # ]: 0 : if (C_CLOCAL(tty))
386 : : do_clocal = 1;
387 : :
388 : : /* Block waiting until we can proceed. We may need to wait for the
389 : : carrier, but we must also wait for any close that is in progress
390 : : before the next open may complete */
391 : :
392 : : retval = 0;
393 : :
394 : : /* The port lock protects the port counts */
395 : 0 : spin_lock_irqsave(&port->lock, flags);
396 [ # # ]: 0 : if (!tty_hung_up_p(filp))
397 : 0 : port->count--;
398 : 0 : port->blocked_open++;
399 : : spin_unlock_irqrestore(&port->lock, flags);
400 : :
401 : : while (1) {
402 : : /* Indicate we are open */
403 [ # # ][ # # ]: 0 : if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
404 : : tty_port_raise_dtr_rts(port);
405 : :
406 : 0 : prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
407 : : /* Check for a hangup or uninitialised port.
408 : : Return accordingly */
409 [ # # ][ # # ]: 0 : if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
410 [ # # ]: 0 : if (port->flags & ASYNC_HUP_NOTIFY)
411 : : retval = -EAGAIN;
412 : : else
413 : : retval = -ERESTARTSYS;
414 : : break;
415 : : }
416 : : /*
417 : : * Probe the carrier. For devices with no carrier detect
418 : : * tty_port_carrier_raised will always return true.
419 : : * Never ask drivers if CLOCAL is set, this causes troubles
420 : : * on some hardware.
421 : : */
422 [ # # ][ # # ]: 0 : if (!(port->flags & ASYNC_CLOSING) &&
423 [ # # ]: 0 : (do_clocal || tty_port_carrier_raised(port)))
424 : : break;
425 [ # # ]: 0 : if (signal_pending(current)) {
426 : : retval = -ERESTARTSYS;
427 : : break;
428 : : }
429 : 0 : tty_unlock(tty);
430 : 0 : schedule();
431 : 0 : tty_lock(tty);
432 : 0 : }
433 : 0 : finish_wait(&port->open_wait, &wait);
434 : :
435 : : /* Update counts. A parallel hangup will have set count to zero and
436 : : we must not mess that up further */
437 : 0 : spin_lock_irqsave(&port->lock, flags);
438 [ # # ]: 0 : if (!tty_hung_up_p(filp))
439 : 0 : port->count++;
440 : 0 : port->blocked_open--;
441 [ # # ]: 0 : if (retval == 0)
442 : 0 : port->flags |= ASYNC_NORMAL_ACTIVE;
443 : : spin_unlock_irqrestore(&port->lock, flags);
444 : 0 : return retval;
445 : : }
446 : : EXPORT_SYMBOL(tty_port_block_til_ready);
447 : :
448 : 0 : static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
449 : : {
450 : : unsigned int bps = tty_get_baud_rate(tty);
451 : : long timeout;
452 : :
453 [ # # ]: 0 : if (bps > 1200) {
454 : 0 : timeout = (HZ * 10 * port->drain_delay) / bps;
455 : 0 : timeout = max_t(long, timeout, HZ / 10);
456 : : } else {
457 : : timeout = 2 * HZ;
458 : : }
459 : 0 : schedule_timeout_interruptible(timeout);
460 : 0 : }
461 : :
462 : 0 : int tty_port_close_start(struct tty_port *port,
463 : : struct tty_struct *tty, struct file *filp)
464 : : {
465 : : unsigned long flags;
466 : :
467 : 1 : spin_lock_irqsave(&port->lock, flags);
468 [ - + ]: 1 : if (tty_hung_up_p(filp)) {
469 : : spin_unlock_irqrestore(&port->lock, flags);
470 : 0 : return 0;
471 : : }
472 : :
473 [ - + ][ # # ]: 1 : if (tty->count == 1 && port->count != 1) {
474 : 0 : printk(KERN_WARNING
475 : : "tty_port_close_start: tty->count = 1 port count = %d.\n",
476 : : port->count);
477 : 0 : port->count = 1;
478 : : }
479 [ - + ]: 1 : if (--port->count < 0) {
480 : 0 : printk(KERN_WARNING "tty_port_close_start: count = %d\n",
481 : : port->count);
482 : 0 : port->count = 0;
483 : : }
484 : :
485 [ + - ]: 1 : if (port->count) {
486 : : spin_unlock_irqrestore(&port->lock, flags);
487 : 1 : return 0;
488 : : }
489 : 0 : set_bit(ASYNCB_CLOSING, &port->flags);
490 : 0 : tty->closing = 1;
491 : : spin_unlock_irqrestore(&port->lock, flags);
492 : :
493 [ # # ]: 0 : if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
494 : : /* Don't block on a stalled port, just pull the chain */
495 [ # # ]: 0 : if (tty->flow_stopped)
496 : 0 : tty_driver_flush_buffer(tty);
497 [ # # ]: 0 : if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
498 : 0 : tty_wait_until_sent_from_close(tty, port->closing_wait);
499 [ # # ]: 0 : if (port->drain_delay)
500 : 0 : tty_port_drain_delay(port, tty);
501 : : }
502 : : /* Flush the ldisc buffering */
503 : 0 : tty_ldisc_flush(tty);
504 : :
505 : : /* Report to caller this is the last port reference */
506 : 0 : return 1;
507 : : }
508 : : EXPORT_SYMBOL(tty_port_close_start);
509 : :
510 : 0 : void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
511 : : {
512 : : unsigned long flags;
513 : :
514 : 0 : spin_lock_irqsave(&port->lock, flags);
515 : 0 : tty->closing = 0;
516 : :
517 [ # # ]: 0 : if (port->blocked_open) {
518 : : spin_unlock_irqrestore(&port->lock, flags);
519 [ # # ]: 0 : if (port->close_delay) {
520 : 0 : msleep_interruptible(
521 : : jiffies_to_msecs(port->close_delay));
522 : : }
523 : 0 : spin_lock_irqsave(&port->lock, flags);
524 : 0 : wake_up_interruptible(&port->open_wait);
525 : : }
526 : 0 : port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
527 : 0 : wake_up_interruptible(&port->close_wait);
528 : : spin_unlock_irqrestore(&port->lock, flags);
529 : 0 : }
530 : : EXPORT_SYMBOL(tty_port_close_end);
531 : :
532 : 0 : void tty_port_close(struct tty_port *port, struct tty_struct *tty,
533 : : struct file *filp)
534 : : {
535 [ # # ]: 0 : if (tty_port_close_start(port, tty, filp) == 0)
536 : 0 : return;
537 : 0 : tty_port_shutdown(port, tty);
538 : 0 : set_bit(TTY_IO_ERROR, &tty->flags);
539 : 0 : tty_port_close_end(port, tty);
540 : 0 : tty_port_tty_set(port, NULL);
541 : : }
542 : : EXPORT_SYMBOL(tty_port_close);
543 : :
544 : : /**
545 : : * tty_port_install - generic tty->ops->install handler
546 : : * @port: tty_port of the device
547 : : * @driver: tty_driver for this device
548 : : * @tty: tty to be installed
549 : : *
550 : : * It is the same as tty_standard_install except the provided @port is linked
551 : : * to a concrete tty specified by @tty. Use this or tty_port_register_device
552 : : * (or both). Call tty_port_link_device as a last resort.
553 : : */
554 : 0 : int tty_port_install(struct tty_port *port, struct tty_driver *driver,
555 : : struct tty_struct *tty)
556 : : {
557 : 285 : tty->port = port;
558 : 285 : return tty_standard_install(driver, tty);
559 : : }
560 : : EXPORT_SYMBOL_GPL(tty_port_install);
561 : :
562 : 0 : int tty_port_open(struct tty_port *port, struct tty_struct *tty,
563 : : struct file *filp)
564 : : {
565 : : spin_lock_irq(&port->lock);
566 [ # # ]: 0 : if (!tty_hung_up_p(filp))
567 : 0 : ++port->count;
568 : : spin_unlock_irq(&port->lock);
569 : 0 : tty_port_tty_set(port, tty);
570 : :
571 : : /*
572 : : * Do the device-specific open only if the hardware isn't
573 : : * already initialized. Serialize open and shutdown using the
574 : : * port mutex.
575 : : */
576 : :
577 : 0 : mutex_lock(&port->mutex);
578 : :
579 [ # # ]: 0 : if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
580 : 0 : clear_bit(TTY_IO_ERROR, &tty->flags);
581 [ # # ]: 0 : if (port->ops->activate) {
582 : 0 : int retval = port->ops->activate(port, tty);
583 [ # # ]: 0 : if (retval) {
584 : 0 : mutex_unlock(&port->mutex);
585 : 0 : return retval;
586 : : }
587 : : }
588 : 0 : set_bit(ASYNCB_INITIALIZED, &port->flags);
589 : : }
590 : 0 : mutex_unlock(&port->mutex);
591 : 0 : return tty_port_block_til_ready(port, tty, filp);
592 : : }
593 : :
594 : : EXPORT_SYMBOL(tty_port_open);
|