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