OSDN Git Service

tty_port: Move hupcl handling
[android-x86/kernel.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         mutex_lock(&port->mutex);
103         if (port->ops->shutdown &&
104                 test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
105                         port->ops->shutdown(port);
106         mutex_unlock(&port->mutex);
107 }
108
109 /**
110  *      tty_port_hangup         -       hangup helper
111  *      @port: tty port
112  *
113  *      Perform port level tty hangup flag and count changes. Drop the tty
114  *      reference.
115  */
116
117 void tty_port_hangup(struct tty_port *port)
118 {
119         unsigned long flags;
120
121         spin_lock_irqsave(&port->lock, flags);
122         port->count = 0;
123         port->flags &= ~ASYNC_NORMAL_ACTIVE;
124         if (port->tty)
125                 tty_kref_put(port->tty);
126         port->tty = NULL;
127         spin_unlock_irqrestore(&port->lock, flags);
128         wake_up_interruptible(&port->open_wait);
129         wake_up_interruptible(&port->delta_msr_wait);
130         tty_port_shutdown(port);
131 }
132 EXPORT_SYMBOL(tty_port_hangup);
133
134 /**
135  *      tty_port_carrier_raised -       carrier raised check
136  *      @port: tty port
137  *
138  *      Wrapper for the carrier detect logic. For the moment this is used
139  *      to hide some internal details. This will eventually become entirely
140  *      internal to the tty port.
141  */
142
143 int tty_port_carrier_raised(struct tty_port *port)
144 {
145         if (port->ops->carrier_raised == NULL)
146                 return 1;
147         return port->ops->carrier_raised(port);
148 }
149 EXPORT_SYMBOL(tty_port_carrier_raised);
150
151 /**
152  *      tty_port_raise_dtr_rts  -       Raise DTR/RTS
153  *      @port: tty port
154  *
155  *      Wrapper for the DTR/RTS raise logic. For the moment this is used
156  *      to hide some internal details. This will eventually become entirely
157  *      internal to the tty port.
158  */
159
160 void tty_port_raise_dtr_rts(struct tty_port *port)
161 {
162         if (port->ops->dtr_rts)
163                 port->ops->dtr_rts(port, 1);
164 }
165 EXPORT_SYMBOL(tty_port_raise_dtr_rts);
166
167 /**
168  *      tty_port_lower_dtr_rts  -       Lower DTR/RTS
169  *      @port: tty port
170  *
171  *      Wrapper for the DTR/RTS raise logic. For the moment this is used
172  *      to hide some internal details. This will eventually become entirely
173  *      internal to the tty port.
174  */
175
176 void tty_port_lower_dtr_rts(struct tty_port *port)
177 {
178         if (port->ops->dtr_rts)
179                 port->ops->dtr_rts(port, 0);
180 }
181 EXPORT_SYMBOL(tty_port_lower_dtr_rts);
182
183 /**
184  *      tty_port_block_til_ready        -       Waiting logic for tty open
185  *      @port: the tty port being opened
186  *      @tty: the tty device being bound
187  *      @filp: the file pointer of the opener
188  *
189  *      Implement the core POSIX/SuS tty behaviour when opening a tty device.
190  *      Handles:
191  *              - hangup (both before and during)
192  *              - non blocking open
193  *              - rts/dtr/dcd
194  *              - signals
195  *              - port flags and counts
196  *
197  *      The passed tty_port must implement the carrier_raised method if it can
198  *      do carrier detect and the dtr_rts method if it supports software
199  *      management of these lines. Note that the dtr/rts raise is done each
200  *      iteration as a hangup may have previously dropped them while we wait.
201  */
202
203 int tty_port_block_til_ready(struct tty_port *port,
204                                 struct tty_struct *tty, struct file *filp)
205 {
206         int do_clocal = 0, retval;
207         unsigned long flags;
208         DEFINE_WAIT(wait);
209         int cd;
210
211         /* block if port is in the process of being closed */
212         if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
213                 wait_event_interruptible(port->close_wait,
214                                 !(port->flags & ASYNC_CLOSING));
215                 if (port->flags & ASYNC_HUP_NOTIFY)
216                         return -EAGAIN;
217                 else
218                         return -ERESTARTSYS;
219         }
220
221         /* if non-blocking mode is set we can pass directly to open unless
222            the port has just hung up or is in another error state */
223         if (tty->flags & (1 << TTY_IO_ERROR)) {
224                 port->flags |= ASYNC_NORMAL_ACTIVE;
225                 return 0;
226         }
227         if (filp->f_flags & O_NONBLOCK) {
228                 /* Indicate we are open */
229                 if (tty->termios->c_cflag & CBAUD)
230                         tty_port_raise_dtr_rts(port);
231                 port->flags |= ASYNC_NORMAL_ACTIVE;
232                 return 0;
233         }
234
235         if (C_CLOCAL(tty))
236                 do_clocal = 1;
237
238         /* Block waiting until we can proceed. We may need to wait for the
239            carrier, but we must also wait for any close that is in progress
240            before the next open may complete */
241
242         retval = 0;
243
244         /* The port lock protects the port counts */
245         spin_lock_irqsave(&port->lock, flags);
246         if (!tty_hung_up_p(filp))
247                 port->count--;
248         port->blocked_open++;
249         spin_unlock_irqrestore(&port->lock, flags);
250
251         while (1) {
252                 /* Indicate we are open */
253                 if (tty->termios->c_cflag & CBAUD)
254                         tty_port_raise_dtr_rts(port);
255
256                 prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
257                 /* Check for a hangup or uninitialised port.
258                                                         Return accordingly */
259                 if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
260                         if (port->flags & ASYNC_HUP_NOTIFY)
261                                 retval = -EAGAIN;
262                         else
263                                 retval = -ERESTARTSYS;
264                         break;
265                 }
266                 /* Probe the carrier. For devices with no carrier detect this
267                    will always return true */
268                 cd = tty_port_carrier_raised(port);
269                 if (!(port->flags & ASYNC_CLOSING) &&
270                                 (do_clocal || cd))
271                         break;
272                 if (signal_pending(current)) {
273                         retval = -ERESTARTSYS;
274                         break;
275                 }
276                 schedule();
277         }
278         finish_wait(&port->open_wait, &wait);
279
280         /* Update counts. A parallel hangup will have set count to zero and
281            we must not mess that up further */
282         spin_lock_irqsave(&port->lock, flags);
283         if (!tty_hung_up_p(filp))
284                 port->count++;
285         port->blocked_open--;
286         if (retval == 0)
287                 port->flags |= ASYNC_NORMAL_ACTIVE;
288         spin_unlock_irqrestore(&port->lock, flags);
289         return retval;
290 }
291 EXPORT_SYMBOL(tty_port_block_til_ready);
292
293 int tty_port_close_start(struct tty_port *port,
294                                 struct tty_struct *tty, struct file *filp)
295 {
296         unsigned long flags;
297
298         spin_lock_irqsave(&port->lock, flags);
299         if (tty_hung_up_p(filp)) {
300                 spin_unlock_irqrestore(&port->lock, flags);
301                 return 0;
302         }
303
304         if (tty->count == 1 && port->count != 1) {
305                 printk(KERN_WARNING
306                     "tty_port_close_start: tty->count = 1 port count = %d.\n",
307                                                                 port->count);
308                 port->count = 1;
309         }
310         if (--port->count < 0) {
311                 printk(KERN_WARNING "tty_port_close_start: count = %d\n",
312                                                                 port->count);
313                 port->count = 0;
314         }
315
316         if (port->count) {
317                 spin_unlock_irqrestore(&port->lock, flags);
318                 if (port->ops->drop)
319                         port->ops->drop(port);
320                 return 0;
321         }
322         set_bit(ASYNCB_CLOSING, &port->flags);
323         tty->closing = 1;
324         spin_unlock_irqrestore(&port->lock, flags);
325         /* Don't block on a stalled port, just pull the chain */
326         if (tty->flow_stopped)
327                 tty_driver_flush_buffer(tty);
328         if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
329                         port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
330                 tty_wait_until_sent(tty, port->closing_wait);
331         if (port->drain_delay) {
332                 unsigned int bps = tty_get_baud_rate(tty);
333                 long timeout;
334
335                 if (bps > 1200)
336                         timeout = max_t(long,
337                                 (HZ * 10 * port->drain_delay) / bps, HZ / 10);
338                 else
339                         timeout = 2 * HZ;
340                 schedule_timeout_interruptible(timeout);
341         }
342         /* Flush the ldisc buffering */
343         tty_ldisc_flush(tty);
344
345         /* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
346            hang up the line */
347         if (tty->termios->c_cflag & HUPCL)
348                 tty_port_lower_dtr_rts(port);
349
350         /* Don't call port->drop for the last reference. Callers will want
351            to drop the last active reference in ->shutdown() or the tty
352            shutdown path */
353         return 1;
354 }
355 EXPORT_SYMBOL(tty_port_close_start);
356
357 void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
358 {
359         unsigned long flags;
360
361         spin_lock_irqsave(&port->lock, flags);
362         tty->closing = 0;
363
364         if (port->blocked_open) {
365                 spin_unlock_irqrestore(&port->lock, flags);
366                 if (port->close_delay) {
367                         msleep_interruptible(
368                                 jiffies_to_msecs(port->close_delay));
369                 }
370                 spin_lock_irqsave(&port->lock, flags);
371                 wake_up_interruptible(&port->open_wait);
372         }
373         port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
374         wake_up_interruptible(&port->close_wait);
375         spin_unlock_irqrestore(&port->lock, flags);
376 }
377 EXPORT_SYMBOL(tty_port_close_end);
378
379 void tty_port_close(struct tty_port *port, struct tty_struct *tty,
380                                                         struct file *filp)
381 {
382         if (tty_port_close_start(port, tty, filp) == 0)
383                 return;
384         tty_port_shutdown(port);
385         tty_port_close_end(port, tty);
386         tty_port_tty_set(port, NULL);
387 }
388 EXPORT_SYMBOL(tty_port_close);
389
390 int tty_port_open(struct tty_port *port, struct tty_struct *tty,
391                                                         struct file *filp)
392 {
393         spin_lock_irq(&port->lock);
394         if (!tty_hung_up_p(filp))
395                 ++port->count;
396         spin_unlock_irq(&port->lock);
397         tty_port_tty_set(port, tty);
398
399         /*
400          * Do the device-specific open only if the hardware isn't
401          * already initialized. Serialize open and shutdown using the
402          * port mutex.
403          */
404
405         mutex_lock(&port->mutex);
406
407         if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
408                 if (port->ops->activate) {
409                         int retval = port->ops->activate(port, tty);
410                         if (retval) {
411                                 mutex_unlock(&port->mutex);
412                                 return retval;
413                         }
414                 }
415                 set_bit(ASYNCB_INITIALIZED, &port->flags);
416         }
417         mutex_unlock(&port->mutex);
418         return tty_port_block_til_ready(port, tty, filp);
419 }
420
421 EXPORT_SYMBOL(tty_port_open);