tty_port: handle the nonblocking open of a dead port corner case
[linux-2.6.git] / drivers / char / tty_port.c
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 void 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         init_waitqueue_head(&port->delta_msr_wait);
27         mutex_init(&port->mutex);
28         spin_lock_init(&port->lock);
29         port->close_delay = (50 * HZ) / 100;
30         port->closing_wait = (3000 * HZ) / 100;
31 }
32 EXPORT_SYMBOL(tty_port_init);
33
34 int tty_port_alloc_xmit_buf(struct tty_port *port)
35 {
36         /* We may sleep in get_zeroed_page() */
37         mutex_lock(&port->mutex);
38         if (port->xmit_buf == NULL)
39                 port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
40         mutex_unlock(&port->mutex);
41         if (port->xmit_buf == NULL)
42                 return -ENOMEM;
43         return 0;
44 }
45 EXPORT_SYMBOL(tty_port_alloc_xmit_buf);
46
47 void tty_port_free_xmit_buf(struct tty_port *port)
48 {
49         mutex_lock(&port->mutex);
50         if (port->xmit_buf != NULL) {
51                 free_page((unsigned long)port->xmit_buf);
52                 port->xmit_buf = NULL;
53         }
54         mutex_unlock(&port->mutex);
55 }
56 EXPORT_SYMBOL(tty_port_free_xmit_buf);
57
58
59 /**
60  *      tty_port_tty_get        -       get a tty reference
61  *      @port: tty port
62  *
63  *      Return a refcount protected tty instance or NULL if the port is not
64  *      associated with a tty (eg due to close or hangup)
65  */
66
67 struct tty_struct *tty_port_tty_get(struct tty_port *port)
68 {
69         unsigned long flags;
70         struct tty_struct *tty;
71
72         spin_lock_irqsave(&port->lock, flags);
73         tty = tty_kref_get(port->tty);
74         spin_unlock_irqrestore(&port->lock, flags);
75         return tty;
76 }
77 EXPORT_SYMBOL(tty_port_tty_get);
78
79 /**
80  *      tty_port_tty_set        -       set the tty of a port
81  *      @port: tty port
82  *      @tty: the tty
83  *
84  *      Associate the port and tty pair. Manages any internal refcounts.
85  *      Pass NULL to deassociate a port
86  */
87
88 void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
89 {
90         unsigned long flags;
91
92         spin_lock_irqsave(&port->lock, flags);
93         if (port->tty)
94                 tty_kref_put(port->tty);
95         port->tty = tty_kref_get(tty);
96         spin_unlock_irqrestore(&port->lock, flags);
97 }
98 EXPORT_SYMBOL(tty_port_tty_set);
99
100 static void tty_port_shutdown(struct tty_port *port)
101 {
102         if (port->ops->shutdown &&
103                 test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
104                         port->ops->shutdown(port);
105
106 }
107
108 /**
109  *      tty_port_hangup         -       hangup helper
110  *      @port: tty port
111  *
112  *      Perform port level tty hangup flag and count changes. Drop the tty
113  *      reference.
114  */
115
116 void tty_port_hangup(struct tty_port *port)
117 {
118         unsigned long flags;
119
120         spin_lock_irqsave(&port->lock, flags);
121         port->count = 0;
122         port->flags &= ~ASYNC_NORMAL_ACTIVE;
123         if (port->tty)
124                 tty_kref_put(port->tty);
125         port->tty = NULL;
126         spin_unlock_irqrestore(&port->lock, flags);
127         wake_up_interruptible(&port->open_wait);
128         wake_up_interruptible(&port->delta_msr_wait);
129         tty_port_shutdown(port);
130 }
131 EXPORT_SYMBOL(tty_port_hangup);
132
133 /**
134  *      tty_port_carrier_raised -       carrier raised check
135  *      @port: tty port
136  *
137  *      Wrapper for the carrier detect logic. For the moment this is used
138  *      to hide some internal details. This will eventually become entirely
139  *      internal to the tty port.
140  */
141
142 int tty_port_carrier_raised(struct tty_port *port)
143 {
144         if (port->ops->carrier_raised == NULL)
145                 return 1;
146         return port->ops->carrier_raised(port);
147 }
148 EXPORT_SYMBOL(tty_port_carrier_raised);
149
150 /**
151  *      tty_port_raise_dtr_rts  -       Raise DTR/RTS
152  *      @port: tty port
153  *
154  *      Wrapper for the DTR/RTS raise logic. For the moment this is used
155  *      to hide some internal details. This will eventually become entirely
156  *      internal to the tty port.
157  */
158
159 void tty_port_raise_dtr_rts(struct tty_port *port)
160 {
161         if (port->ops->dtr_rts)
162                 port->ops->dtr_rts(port, 1);
163 }
164 EXPORT_SYMBOL(tty_port_raise_dtr_rts);
165
166 /**
167  *      tty_port_lower_dtr_rts  -       Lower DTR/RTS
168  *      @port: tty port
169  *
170  *      Wrapper for the DTR/RTS raise logic. For the moment this is used
171  *      to hide some internal details. This will eventually become entirely
172  *      internal to the tty port.
173  */
174
175 void tty_port_lower_dtr_rts(struct tty_port *port)
176 {
177         if (port->ops->dtr_rts)
178                 port->ops->dtr_rts(port, 0);
179 }
180 EXPORT_SYMBOL(tty_port_lower_dtr_rts);
181
182 /**
183  *      tty_port_block_til_ready        -       Waiting logic for tty open
184  *      @port: the tty port being opened
185  *      @tty: the tty device being bound
186  *      @filp: the file pointer of the opener
187  *
188  *      Implement the core POSIX/SuS tty behaviour when opening a tty device.
189  *      Handles:
190  *              - hangup (both before and during)
191  *              - non blocking open
192  *              - rts/dtr/dcd
193  *              - signals
194  *              - port flags and counts
195  *
196  *      The passed tty_port must implement the carrier_raised method if it can
197  *      do carrier detect and the dtr_rts method if it supports software
198  *      management of these lines. Note that the dtr/rts raise is done each
199  *      iteration as a hangup may have previously dropped them while we wait.
200  */
201  
202 int tty_port_block_til_ready(struct tty_port *port,
203                                 struct tty_struct *tty, struct file *filp)
204 {
205         int do_clocal = 0, retval;
206         unsigned long flags;
207         DEFINE_WAIT(wait);
208         int cd;
209
210         /* block if port is in the process of being closed */
211         if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
212                 wait_event_interruptible(port->close_wait,
213                                 !(port->flags & ASYNC_CLOSING));
214                 if (port->flags & ASYNC_HUP_NOTIFY)
215                         return -EAGAIN;
216                 else
217                         return -ERESTARTSYS;
218         }
219
220         /* if non-blocking mode is set we can pass directly to open unless
221            the port has just hung up or is in another error state */
222         if (tty->flags & (1 << TTY_IO_ERROR)) {
223                 port->flags |= ASYNC_NORMAL_ACTIVE;
224                 return 0;
225         }
226         if (filp->f_flags & O_NONBLOCK) {
227                 /* Indicate we are open */
228                 if (tty->termios->c_cflag & CBAUD)
229                         tty_port_raise_dtr_rts(port);
230                 port->flags |= ASYNC_NORMAL_ACTIVE;
231                 return 0;
232         }
233
234         if (C_CLOCAL(tty))
235                 do_clocal = 1;
236
237         /* Block waiting until we can proceed. We may need to wait for the
238            carrier, but we must also wait for any close that is in progress
239            before the next open may complete */
240
241         retval = 0;
242
243         /* The port lock protects the port counts */
244         spin_lock_irqsave(&port->lock, flags);
245         if (!tty_hung_up_p(filp))
246                 port->count--;
247         port->blocked_open++;
248         spin_unlock_irqrestore(&port->lock, flags);
249
250         while (1) {
251                 /* Indicate we are open */
252                 if (tty->termios->c_cflag & CBAUD)
253                         tty_port_raise_dtr_rts(port);
254
255                 prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
256                 /* Check for a hangup or uninitialised port. Return accordingly */
257                 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
258                         if (port->flags & ASYNC_HUP_NOTIFY)
259                                 retval = -EAGAIN;
260                         else
261                                 retval = -ERESTARTSYS;
262                         break;
263                 }
264                 /* Probe the carrier. For devices with no carrier detect this
265                    will always return true */
266                 cd = tty_port_carrier_raised(port);
267                 if (!(port->flags & ASYNC_CLOSING) &&
268                                 (do_clocal || cd))
269                         break;
270                 if (signal_pending(current)) {
271                         retval = -ERESTARTSYS;
272                         break;
273                 }
274                 schedule();
275         }
276         finish_wait(&port->open_wait, &wait);
277
278         /* Update counts. A parallel hangup will have set count to zero and
279            we must not mess that up further */
280         spin_lock_irqsave(&port->lock, flags);
281         if (!tty_hung_up_p(filp))
282                 port->count++;
283         port->blocked_open--;
284         if (retval == 0)
285                 port->flags |= ASYNC_NORMAL_ACTIVE;
286         spin_unlock_irqrestore(&port->lock, flags);
287         return retval;
288         
289 }
290 EXPORT_SYMBOL(tty_port_block_til_ready);
291
292 int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct file *filp)
293 {
294         unsigned long flags;
295
296         spin_lock_irqsave(&port->lock, flags);
297         if (tty_hung_up_p(filp)) {
298                 spin_unlock_irqrestore(&port->lock, flags);
299                 return 0;
300         }
301
302         if( tty->count == 1 && port->count != 1) {
303                 printk(KERN_WARNING
304                     "tty_port_close_start: tty->count = 1 port count = %d.\n",
305                                                                 port->count);
306                 port->count = 1;
307         }
308         if (--port->count < 0) {
309                 printk(KERN_WARNING "tty_port_close_start: count = %d\n",
310                                                                 port->count);
311                 port->count = 0;
312         }
313
314         if (port->count) {
315                 spin_unlock_irqrestore(&port->lock, flags);
316                 if (port->ops->drop)
317                         port->ops->drop(port);
318                 return 0;
319         }
320         set_bit(ASYNCB_CLOSING, &port->flags);
321         tty->closing = 1;
322         spin_unlock_irqrestore(&port->lock, flags);
323         /* Don't block on a stalled port, just pull the chain */
324         if (tty->flow_stopped)
325                 tty_driver_flush_buffer(tty);
326         if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
327                         port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
328                 tty_wait_until_sent(tty, port->closing_wait);
329         if (port->drain_delay) {
330                 unsigned int bps = tty_get_baud_rate(tty);
331                 long timeout;
332
333                 if (bps > 1200)
334                         timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps,
335                                                                 HZ / 10);
336                 else
337                         timeout = 2 * HZ;
338                 schedule_timeout_interruptible(timeout);
339         }
340         /* Don't call port->drop for the last reference. Callers will want
341            to drop the last active reference in ->shutdown() or the tty
342            shutdown path */
343         return 1;
344 }
345 EXPORT_SYMBOL(tty_port_close_start);
346
347 void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
348 {
349         unsigned long flags;
350
351         tty_ldisc_flush(tty);
352
353         if (tty->termios->c_cflag & HUPCL)
354                 tty_port_lower_dtr_rts(port);
355
356         spin_lock_irqsave(&port->lock, flags);
357         tty->closing = 0;
358
359         if (port->blocked_open) {
360                 spin_unlock_irqrestore(&port->lock, flags);
361                 if (port->close_delay) {
362                         msleep_interruptible(
363                                 jiffies_to_msecs(port->close_delay));
364                 }
365                 spin_lock_irqsave(&port->lock, flags);
366                 wake_up_interruptible(&port->open_wait);
367         }
368         port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
369         wake_up_interruptible(&port->close_wait);
370         spin_unlock_irqrestore(&port->lock, flags);
371 }
372 EXPORT_SYMBOL(tty_port_close_end);
373
374 void tty_port_close(struct tty_port *port, struct tty_struct *tty,
375                                                         struct file *filp)
376 {
377         if (tty_port_close_start(port, tty, filp) == 0)
378                 return;
379         tty_port_shutdown(port);
380         tty_port_close_end(port, tty);
381         tty_port_tty_set(port, NULL);
382 }
383 EXPORT_SYMBOL(tty_port_close);