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