blob: 549bd0fa8bb6b4972279b5152243da227a7c744f [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));
24 init_waitqueue_head(&port->open_wait);
25 init_waitqueue_head(&port->close_wait);
26 mutex_init(&port->mutex);
Alan Cox4a90f092008-10-13 10:39:46 +010027 spin_lock_init(&port->lock);
Alan Cox9e485652008-10-13 10:37:07 +010028 port->close_delay = (50 * HZ) / 100;
29 port->closing_wait = (3000 * HZ) / 100;
30}
31EXPORT_SYMBOL(tty_port_init);
32
33int tty_port_alloc_xmit_buf(struct tty_port *port)
34{
35 /* We may sleep in get_zeroed_page() */
36 mutex_lock(&port->mutex);
37 if (port->xmit_buf == NULL)
38 port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
39 mutex_unlock(&port->mutex);
40 if (port->xmit_buf == NULL)
41 return -ENOMEM;
42 return 0;
43}
44EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
45
46void tty_port_free_xmit_buf(struct tty_port *port)
47{
48 mutex_lock(&port->mutex);
49 if (port->xmit_buf != NULL) {
50 free_page((unsigned long)port->xmit_buf);
51 port->xmit_buf = NULL;
52 }
53 mutex_unlock(&port->mutex);
54}
55EXPORT_SYMBOL(tty_port_free_xmit_buf);
56
57
Alan Cox4a90f092008-10-13 10:39:46 +010058/**
59 * tty_port_tty_get - get a tty reference
60 * @port: tty port
61 *
62 * Return a refcount protected tty instance or NULL if the port is not
63 * associated with a tty (eg due to close or hangup)
64 */
65
66struct tty_struct *tty_port_tty_get(struct tty_port *port)
67{
68 unsigned long flags;
69 struct tty_struct *tty;
70
71 spin_lock_irqsave(&port->lock, flags);
72 tty = tty_kref_get(port->tty);
73 spin_unlock_irqrestore(&port->lock, flags);
74 return tty;
75}
76EXPORT_SYMBOL(tty_port_tty_get);
77
78/**
79 * tty_port_tty_set - set the tty of a port
80 * @port: tty port
81 * @tty: the tty
82 *
83 * Associate the port and tty pair. Manages any internal refcounts.
84 * Pass NULL to deassociate a port
85 */
86
87void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
88{
89 unsigned long flags;
90
91 spin_lock_irqsave(&port->lock, flags);
92 if (port->tty)
93 tty_kref_put(port->tty);
Alan Coxcb4bca32008-10-21 13:47:44 +010094 port->tty = tty_kref_get(tty);
Alan Cox4a90f092008-10-13 10:39:46 +010095 spin_unlock_irqrestore(&port->lock, flags);
96}
97EXPORT_SYMBOL(tty_port_tty_set);
Alan Cox31f35932009-01-02 13:45:05 +000098
Alan Cox7ca0ff92009-09-19 13:13:20 -070099static void tty_port_shutdown(struct tty_port *port)
100{
101 if (port->ops->shutdown &&
102 test_and_clear_bit(ASYNC_INITIALIZED, &port->flags))
103 port->ops->shutdown(port);
104
105}
106
Alan Cox31f35932009-01-02 13:45:05 +0000107/**
Alan Cox3e616962009-01-02 13:45:26 +0000108 * tty_port_hangup - hangup helper
109 * @port: tty port
110 *
111 * Perform port level tty hangup flag and count changes. Drop the tty
112 * reference.
113 */
114
115void tty_port_hangup(struct tty_port *port)
116{
117 unsigned long flags;
118
119 spin_lock_irqsave(&port->lock, flags);
120 port->count = 0;
121 port->flags &= ~ASYNC_NORMAL_ACTIVE;
122 if (port->tty)
123 tty_kref_put(port->tty);
124 port->tty = NULL;
125 spin_unlock_irqrestore(&port->lock, flags);
126 wake_up_interruptible(&port->open_wait);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700127 tty_port_shutdown(port);
Alan Cox3e616962009-01-02 13:45:26 +0000128}
129EXPORT_SYMBOL(tty_port_hangup);
130
131/**
Alan Cox31f35932009-01-02 13:45:05 +0000132 * tty_port_carrier_raised - carrier raised check
133 * @port: tty port
134 *
135 * Wrapper for the carrier detect logic. For the moment this is used
136 * to hide some internal details. This will eventually become entirely
137 * internal to the tty port.
138 */
139
140int tty_port_carrier_raised(struct tty_port *port)
141{
142 if (port->ops->carrier_raised == NULL)
143 return 1;
144 return port->ops->carrier_raised(port);
145}
146EXPORT_SYMBOL(tty_port_carrier_raised);
Alan Cox5d951fb2009-01-02 13:45:19 +0000147
148/**
Alan Coxfcc8ac12009-06-11 12:24:17 +0100149 * tty_port_raise_dtr_rts - Raise DTR/RTS
Alan Cox5d951fb2009-01-02 13:45:19 +0000150 * @port: tty port
151 *
152 * Wrapper for the DTR/RTS raise logic. For the moment this is used
153 * to hide some internal details. This will eventually become entirely
154 * internal to the tty port.
155 */
156
157void tty_port_raise_dtr_rts(struct tty_port *port)
158{
Alan Coxfcc8ac12009-06-11 12:24:17 +0100159 if (port->ops->dtr_rts)
160 port->ops->dtr_rts(port, 1);
Alan Cox5d951fb2009-01-02 13:45:19 +0000161}
162EXPORT_SYMBOL(tty_port_raise_dtr_rts);
Alan Cox36c621d2009-01-02 13:46:10 +0000163
164/**
Alan Coxfcc8ac12009-06-11 12:24:17 +0100165 * tty_port_lower_dtr_rts - Lower DTR/RTS
166 * @port: tty port
167 *
168 * Wrapper for the DTR/RTS raise logic. For the moment this is used
169 * to hide some internal details. This will eventually become entirely
170 * internal to the tty port.
171 */
172
173void tty_port_lower_dtr_rts(struct tty_port *port)
174{
175 if (port->ops->dtr_rts)
176 port->ops->dtr_rts(port, 0);
177}
178EXPORT_SYMBOL(tty_port_lower_dtr_rts);
179
180/**
Alan Cox36c621d2009-01-02 13:46:10 +0000181 * tty_port_block_til_ready - Waiting logic for tty open
182 * @port: the tty port being opened
183 * @tty: the tty device being bound
184 * @filp: the file pointer of the opener
185 *
186 * Implement the core POSIX/SuS tty behaviour when opening a tty device.
187 * Handles:
188 * - hangup (both before and during)
189 * - non blocking open
190 * - rts/dtr/dcd
191 * - signals
192 * - port flags and counts
193 *
194 * The passed tty_port must implement the carrier_raised method if it can
Alan Coxfcc8ac12009-06-11 12:24:17 +0100195 * do carrier detect and the dtr_rts method if it supports software
Alan Cox36c621d2009-01-02 13:46:10 +0000196 * management of these lines. Note that the dtr/rts raise is done each
197 * iteration as a hangup may have previously dropped them while we wait.
198 */
199
200int tty_port_block_til_ready(struct tty_port *port,
201 struct tty_struct *tty, struct file *filp)
202{
203 int do_clocal = 0, retval;
204 unsigned long flags;
Jiri Slaby6af9a432009-06-24 18:35:05 +0100205 DEFINE_WAIT(wait);
Alan Cox36c621d2009-01-02 13:46:10 +0000206 int cd;
207
208 /* block if port is in the process of being closed */
209 if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
Jiri Slaby5fc5b422009-06-11 14:32:42 +0100210 wait_event_interruptible(port->close_wait,
211 !(port->flags & ASYNC_CLOSING));
Alan Cox36c621d2009-01-02 13:46:10 +0000212 if (port->flags & ASYNC_HUP_NOTIFY)
213 return -EAGAIN;
214 else
215 return -ERESTARTSYS;
216 }
217
218 /* if non-blocking mode is set we can pass directly to open unless
219 the port has just hung up or is in another error state */
220 if ((filp->f_flags & O_NONBLOCK) ||
221 (tty->flags & (1 << TTY_IO_ERROR))) {
222 port->flags |= ASYNC_NORMAL_ACTIVE;
223 return 0;
224 }
225
226 if (C_CLOCAL(tty))
227 do_clocal = 1;
228
229 /* Block waiting until we can proceed. We may need to wait for the
230 carrier, but we must also wait for any close that is in progress
231 before the next open may complete */
232
233 retval = 0;
Alan Cox36c621d2009-01-02 13:46:10 +0000234
235 /* The port lock protects the port counts */
236 spin_lock_irqsave(&port->lock, flags);
237 if (!tty_hung_up_p(filp))
238 port->count--;
239 port->blocked_open++;
240 spin_unlock_irqrestore(&port->lock, flags);
241
242 while (1) {
243 /* Indicate we are open */
Alan Cox78349092009-01-02 13:46:43 +0000244 if (tty->termios->c_cflag & CBAUD)
245 tty_port_raise_dtr_rts(port);
Alan Cox36c621d2009-01-02 13:46:10 +0000246
Jiri Slaby3e3b5c02009-06-11 14:33:37 +0100247 prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
Alan Cox36c621d2009-01-02 13:46:10 +0000248 /* Check for a hangup or uninitialised port. Return accordingly */
249 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
250 if (port->flags & ASYNC_HUP_NOTIFY)
251 retval = -EAGAIN;
252 else
253 retval = -ERESTARTSYS;
254 break;
255 }
256 /* Probe the carrier. For devices with no carrier detect this
257 will always return true */
258 cd = tty_port_carrier_raised(port);
259 if (!(port->flags & ASYNC_CLOSING) &&
260 (do_clocal || cd))
261 break;
262 if (signal_pending(current)) {
263 retval = -ERESTARTSYS;
264 break;
265 }
266 schedule();
267 }
Jiri Slaby3e3b5c02009-06-11 14:33:37 +0100268 finish_wait(&port->open_wait, &wait);
Alan Cox36c621d2009-01-02 13:46:10 +0000269
270 /* Update counts. A parallel hangup will have set count to zero and
271 we must not mess that up further */
272 spin_lock_irqsave(&port->lock, flags);
273 if (!tty_hung_up_p(filp))
274 port->count++;
275 port->blocked_open--;
276 if (retval == 0)
277 port->flags |= ASYNC_NORMAL_ACTIVE;
278 spin_unlock_irqrestore(&port->lock, flags);
Alan Coxecc2e052009-07-17 16:17:26 +0100279 return retval;
Alan Cox36c621d2009-01-02 13:46:10 +0000280
281}
282EXPORT_SYMBOL(tty_port_block_til_ready);
283
Alan Coxa6614992009-01-02 13:46:50 +0000284int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp)
285{
286 unsigned long flags;
287
288 spin_lock_irqsave(&port->lock, flags);
289 if (tty_hung_up_p(filp)) {
290 spin_unlock_irqrestore(&port->lock, flags);
291 return 0;
292 }
293
294 if( tty->count == 1 && port->count != 1) {
295 printk(KERN_WARNING
296 "tty_port_close_start: tty->count = 1 port count = %d.\n",
297 port->count);
298 port->count = 1;
299 }
300 if (--port->count < 0) {
301 printk(KERN_WARNING "tty_port_close_start: count = %d\n",
302 port->count);
303 port->count = 0;
304 }
305
306 if (port->count) {
307 spin_unlock_irqrestore(&port->lock, flags);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700308 if (port->ops->drop)
309 port->ops->drop(port);
Alan Coxa6614992009-01-02 13:46:50 +0000310 return 0;
311 }
Alan Cox7ca0ff92009-09-19 13:13:20 -0700312 set_bit(ASYNC_CLOSING, &port->flags);
Alan Coxa6614992009-01-02 13:46:50 +0000313 tty->closing = 1;
314 spin_unlock_irqrestore(&port->lock, flags);
Alan Coxfba85e02009-01-02 13:48:39 +0000315 /* Don't block on a stalled port, just pull the chain */
316 if (tty->flow_stopped)
317 tty_driver_flush_buffer(tty);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700318 if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
Alan Cox6ed1dba2009-01-02 13:48:11 +0000319 port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
Alan Coxa6614992009-01-02 13:46:50 +0000320 tty_wait_until_sent(tty, port->closing_wait);
Alan Cox1ec739b2009-06-11 12:25:25 +0100321 if (port->drain_delay) {
322 unsigned int bps = tty_get_baud_rate(tty);
323 long timeout;
324
325 if (bps > 1200)
326 timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps,
327 HZ / 10);
328 else
329 timeout = 2 * HZ;
330 schedule_timeout_interruptible(timeout);
331 }
Alan Cox7ca0ff92009-09-19 13:13:20 -0700332 /* Don't call port->drop for the last reference. Callers will want
333 to drop the last active reference in ->shutdown() or the tty
334 shutdown path */
Alan Coxa6614992009-01-02 13:46:50 +0000335 return 1;
336}
337EXPORT_SYMBOL(tty_port_close_start);
338
339void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
340{
341 unsigned long flags;
342
343 tty_ldisc_flush(tty);
344
Alan Coxfcc8ac12009-06-11 12:24:17 +0100345 if (tty->termios->c_cflag & HUPCL)
346 tty_port_lower_dtr_rts(port);
347
Alan Coxa6614992009-01-02 13:46:50 +0000348 spin_lock_irqsave(&port->lock, flags);
349 tty->closing = 0;
350
351 if (port->blocked_open) {
352 spin_unlock_irqrestore(&port->lock, flags);
353 if (port->close_delay) {
354 msleep_interruptible(
355 jiffies_to_msecs(port->close_delay));
356 }
357 spin_lock_irqsave(&port->lock, flags);
358 wake_up_interruptible(&port->open_wait);
359 }
360 port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
361 wake_up_interruptible(&port->close_wait);
362 spin_unlock_irqrestore(&port->lock, flags);
363}
364EXPORT_SYMBOL(tty_port_close_end);
Alan Cox7ca0ff92009-09-19 13:13:20 -0700365
366void tty_port_close(struct tty_port *port, struct tty_struct *tty,
367 struct file *filp)
368{
369 if (tty_port_close_start(port, tty, filp) == 0)
370 return;
371 tty_port_shutdown(port);
372 tty_port_close_end(port, tty);
373 tty_port_tty_set(port, NULL);
374}
375EXPORT_SYMBOL(tty_port_close);