diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-04-30 03:54:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:47 -0400 |
commit | f34d7a5b7010b82fe97da95496b9971435530062 (patch) | |
tree | 87e2abec1e33ed4fe5e63ee2fd000bc2ad745e57 /drivers/char | |
parent | 251b8dd7eee30fda089a1dc088abf4fc9a0dee9c (diff) |
tty: The big operations rework
- Operations are now a shared const function block as with most other Linux
objects
- Introduce wrappers for some optional functions to get consistent behaviour
- Wrap put_char which used to be patched by the tty layer
- Document which functions are needed/optional
- Make put_char report success/fail
- Cache the driver->ops pointer in the tty as tty->ops
- Remove various surplus lock calls we no longer need
- Remove proc_write method as noted by Alexey Dobriyan
- Introduce some missing sanity checks where certain driver/ldisc
combinations would oops as they didn't check needed methods were present
[akpm@linux-foundation.org: fix fs/compat_ioctl.c build]
[akpm@linux-foundation.org: fix isicom]
[akpm@linux-foundation.org: fix arch/ia64/hp/sim/simserial.c build]
[akpm@linux-foundation.org: fix kgdb]
Signed-off-by: Alan Cox <alan@redhat.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/ip2/ip2main.c | 12 | ||||
-rw-r--r-- | drivers/char/isicom.c | 15 | ||||
-rw-r--r-- | drivers/char/keyboard.c | 2 | ||||
-rw-r--r-- | drivers/char/n_hdlc.c | 11 | ||||
-rw-r--r-- | drivers/char/n_r3964.c | 17 | ||||
-rw-r--r-- | drivers/char/n_tty.c | 103 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 174 | ||||
-rw-r--r-- | drivers/char/tty_ioctl.c | 62 |
8 files changed, 183 insertions, 213 deletions
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index c4f4ca31f7c0..5ef69dcd2588 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -169,7 +169,7 @@ static int Fip_firmware_size; | |||
169 | static int ip2_open(PTTY, struct file *); | 169 | static int ip2_open(PTTY, struct file *); |
170 | static void ip2_close(PTTY, struct file *); | 170 | static void ip2_close(PTTY, struct file *); |
171 | static int ip2_write(PTTY, const unsigned char *, int); | 171 | static int ip2_write(PTTY, const unsigned char *, int); |
172 | static void ip2_putchar(PTTY, unsigned char); | 172 | static int ip2_putchar(PTTY, unsigned char); |
173 | static void ip2_flush_chars(PTTY); | 173 | static void ip2_flush_chars(PTTY); |
174 | static int ip2_write_room(PTTY); | 174 | static int ip2_write_room(PTTY); |
175 | static int ip2_chars_in_buf(PTTY); | 175 | static int ip2_chars_in_buf(PTTY); |
@@ -1616,10 +1616,9 @@ ip2_close( PTTY tty, struct file *pFile ) | |||
1616 | 1616 | ||
1617 | serviceOutgoingFifo ( pCh->pMyBord ); | 1617 | serviceOutgoingFifo ( pCh->pMyBord ); |
1618 | 1618 | ||
1619 | if ( tty->driver->flush_buffer ) | 1619 | if ( tty->driver->ops->flush_buffer ) |
1620 | tty->driver->flush_buffer(tty); | 1620 | tty->driver->ops->flush_buffer(tty); |
1621 | if ( tty->ldisc.flush_buffer ) | 1621 | tty_ldisc_flush(tty); |
1622 | tty->ldisc.flush_buffer(tty); | ||
1623 | tty->closing = 0; | 1622 | tty->closing = 0; |
1624 | 1623 | ||
1625 | pCh->pTTY = NULL; | 1624 | pCh->pTTY = NULL; |
@@ -1738,7 +1737,7 @@ ip2_write( PTTY tty, const unsigned char *pData, int count) | |||
1738 | /* */ | 1737 | /* */ |
1739 | /* */ | 1738 | /* */ |
1740 | /******************************************************************************/ | 1739 | /******************************************************************************/ |
1741 | static void | 1740 | static int |
1742 | ip2_putchar( PTTY tty, unsigned char ch ) | 1741 | ip2_putchar( PTTY tty, unsigned char ch ) |
1743 | { | 1742 | { |
1744 | i2ChanStrPtr pCh = tty->driver_data; | 1743 | i2ChanStrPtr pCh = tty->driver_data; |
@@ -1753,6 +1752,7 @@ ip2_putchar( PTTY tty, unsigned char ch ) | |||
1753 | ip2_flush_chars( tty ); | 1752 | ip2_flush_chars( tty ); |
1754 | } else | 1753 | } else |
1755 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); | 1754 | write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags); |
1755 | return 1; | ||
1756 | 1756 | ||
1757 | // ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch ); | 1757 | // ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch ); |
1758 | } | 1758 | } |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 57b115272aaa..9c6be8da220c 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -1140,28 +1140,29 @@ static int isicom_write(struct tty_struct *tty, const unsigned char *buf, | |||
1140 | } | 1140 | } |
1141 | 1141 | ||
1142 | /* put_char et all */ | 1142 | /* put_char et all */ |
1143 | static void isicom_put_char(struct tty_struct *tty, unsigned char ch) | 1143 | static int isicom_put_char(struct tty_struct *tty, unsigned char ch) |
1144 | { | 1144 | { |
1145 | struct isi_port *port = tty->driver_data; | 1145 | struct isi_port *port = tty->driver_data; |
1146 | struct isi_board *card = port->card; | 1146 | struct isi_board *card = port->card; |
1147 | unsigned long flags; | 1147 | unsigned long flags; |
1148 | 1148 | ||
1149 | if (isicom_paranoia_check(port, tty->name, "isicom_put_char")) | 1149 | if (isicom_paranoia_check(port, tty->name, "isicom_put_char")) |
1150 | return; | 1150 | return 0; |
1151 | 1151 | ||
1152 | if (!port->xmit_buf) | 1152 | if (!port->xmit_buf) |
1153 | return; | 1153 | return 0; |
1154 | 1154 | ||
1155 | spin_lock_irqsave(&card->card_lock, flags); | 1155 | spin_lock_irqsave(&card->card_lock, flags); |
1156 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) | 1156 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { |
1157 | goto out; | 1157 | spin_unlock_irqrestore(&card->card_lock, flags); |
1158 | return 0; | ||
1159 | } | ||
1158 | 1160 | ||
1159 | port->xmit_buf[port->xmit_head++] = ch; | 1161 | port->xmit_buf[port->xmit_head++] = ch; |
1160 | port->xmit_head &= (SERIAL_XMIT_SIZE - 1); | 1162 | port->xmit_head &= (SERIAL_XMIT_SIZE - 1); |
1161 | port->xmit_cnt++; | 1163 | port->xmit_cnt++; |
1162 | spin_unlock_irqrestore(&card->card_lock, flags); | 1164 | spin_unlock_irqrestore(&card->card_lock, flags); |
1163 | out: | 1165 | return 1; |
1164 | return; | ||
1165 | } | 1166 | } |
1166 | 1167 | ||
1167 | /* flush_chars et all */ | 1168 | /* flush_chars et all */ |
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 60b934adea65..d1c50b3302e5 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -1230,7 +1230,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1230 | 1230 | ||
1231 | if (rep && | 1231 | if (rep && |
1232 | (!vc_kbd_mode(kbd, VC_REPEAT) || | 1232 | (!vc_kbd_mode(kbd, VC_REPEAT) || |
1233 | (tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) { | 1233 | (tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) { |
1234 | /* | 1234 | /* |
1235 | * Don't repeat a key if the input buffers are not empty and the | 1235 | * Don't repeat a key if the input buffers are not empty and the |
1236 | * characters get aren't echoed locally. This makes key repeat | 1236 | * characters get aren't echoed locally. This makes key repeat |
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index a07c0af4819e..a35bfd7ee80e 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
@@ -342,12 +342,10 @@ static int n_hdlc_tty_open (struct tty_struct *tty) | |||
342 | #endif | 342 | #endif |
343 | 343 | ||
344 | /* Flush any pending characters in the driver and discipline. */ | 344 | /* Flush any pending characters in the driver and discipline. */ |
345 | |||
346 | if (tty->ldisc.flush_buffer) | 345 | if (tty->ldisc.flush_buffer) |
347 | tty->ldisc.flush_buffer (tty); | 346 | tty->ldisc.flush_buffer(tty); |
348 | 347 | ||
349 | if (tty->driver->flush_buffer) | 348 | tty_driver_flush_buffer(tty); |
350 | tty->driver->flush_buffer (tty); | ||
351 | 349 | ||
352 | if (debuglevel >= DEBUG_LEVEL_INFO) | 350 | if (debuglevel >= DEBUG_LEVEL_INFO) |
353 | printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__,__LINE__); | 351 | printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__,__LINE__); |
@@ -399,7 +397,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) | |||
399 | 397 | ||
400 | /* Send the next block of data to device */ | 398 | /* Send the next block of data to device */ |
401 | tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); | 399 | tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); |
402 | actual = tty->driver->write(tty, tbuf->buf, tbuf->count); | 400 | actual = tty->ops->write(tty, tbuf->buf, tbuf->count); |
403 | 401 | ||
404 | /* rollback was possible and has been done */ | 402 | /* rollback was possible and has been done */ |
405 | if (actual == -ERESTARTSYS) { | 403 | if (actual == -ERESTARTSYS) { |
@@ -752,8 +750,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, | |||
752 | 750 | ||
753 | case TIOCOUTQ: | 751 | case TIOCOUTQ: |
754 | /* get the pending tx byte count in the driver */ | 752 | /* get the pending tx byte count in the driver */ |
755 | count = tty->driver->chars_in_buffer ? | 753 | count = tty_chars_in_buffer(tty); |
756 | tty->driver->chars_in_buffer(tty) : 0; | ||
757 | /* add size of next output frame in queue */ | 754 | /* add size of next output frame in queue */ |
758 | spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags); | 755 | spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags); |
759 | if (n_hdlc->tx_buf_list.head) | 756 | if (n_hdlc->tx_buf_list.head) |
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 3f6486e9f1ec..902169062332 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -376,8 +376,9 @@ static void put_char(struct r3964_info *pInfo, unsigned char ch) | |||
376 | if (tty == NULL) | 376 | if (tty == NULL) |
377 | return; | 377 | return; |
378 | 378 | ||
379 | if (tty->driver->put_char) { | 379 | /* FIXME: put_char should not be called from an IRQ */ |
380 | tty->driver->put_char(tty, ch); | 380 | if (tty->ops->put_char) { |
381 | tty->ops->put_char(tty, ch); | ||
381 | } | 382 | } |
382 | pInfo->bcc ^= ch; | 383 | pInfo->bcc ^= ch; |
383 | } | 384 | } |
@@ -386,12 +387,9 @@ static void flush(struct r3964_info *pInfo) | |||
386 | { | 387 | { |
387 | struct tty_struct *tty = pInfo->tty; | 388 | struct tty_struct *tty = pInfo->tty; |
388 | 389 | ||
389 | if (tty == NULL) | 390 | if (tty == NULL || tty->ops->flush_chars == NULL) |
390 | return; | 391 | return; |
391 | 392 | tty->ops->flush_chars(tty); | |
392 | if (tty->driver->flush_chars) { | ||
393 | tty->driver->flush_chars(tty); | ||
394 | } | ||
395 | } | 393 | } |
396 | 394 | ||
397 | static void trigger_transmit(struct r3964_info *pInfo) | 395 | static void trigger_transmit(struct r3964_info *pInfo) |
@@ -449,12 +447,11 @@ static void transmit_block(struct r3964_info *pInfo) | |||
449 | struct r3964_block_header *pBlock = pInfo->tx_first; | 447 | struct r3964_block_header *pBlock = pInfo->tx_first; |
450 | int room = 0; | 448 | int room = 0; |
451 | 449 | ||
452 | if ((tty == NULL) || (pBlock == NULL)) { | 450 | if (tty == NULL || pBlock == NULL) { |
453 | return; | 451 | return; |
454 | } | 452 | } |
455 | 453 | ||
456 | if (tty->driver->write_room) | 454 | room = tty_write_room(tty); |
457 | room = tty->driver->write_room(tty); | ||
458 | 455 | ||
459 | TRACE_PS("transmit_block %p, room %d, length %d", | 456 | TRACE_PS("transmit_block %p, room %d, length %d", |
460 | pBlock, room, pBlock->length); | 457 | pBlock, room, pBlock->length); |
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index e1518e17e09d..abc93a93dcdd 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -149,8 +149,8 @@ static void check_unthrottle(struct tty_struct *tty) | |||
149 | { | 149 | { |
150 | if (tty->count && | 150 | if (tty->count && |
151 | test_and_clear_bit(TTY_THROTTLED, &tty->flags) && | 151 | test_and_clear_bit(TTY_THROTTLED, &tty->flags) && |
152 | tty->driver->unthrottle) | 152 | tty->ops->unthrottle) |
153 | tty->driver->unthrottle(tty); | 153 | tty->ops->unthrottle(tty); |
154 | } | 154 | } |
155 | 155 | ||
156 | /** | 156 | /** |
@@ -273,7 +273,7 @@ static int opost(unsigned char c, struct tty_struct *tty) | |||
273 | { | 273 | { |
274 | int space, spaces; | 274 | int space, spaces; |
275 | 275 | ||
276 | space = tty->driver->write_room(tty); | 276 | space = tty_write_room(tty); |
277 | if (!space) | 277 | if (!space) |
278 | return -1; | 278 | return -1; |
279 | 279 | ||
@@ -286,7 +286,7 @@ static int opost(unsigned char c, struct tty_struct *tty) | |||
286 | if (O_ONLCR(tty)) { | 286 | if (O_ONLCR(tty)) { |
287 | if (space < 2) | 287 | if (space < 2) |
288 | return -1; | 288 | return -1; |
289 | tty->driver->put_char(tty, '\r'); | 289 | tty_put_char(tty, '\r'); |
290 | tty->column = 0; | 290 | tty->column = 0; |
291 | } | 291 | } |
292 | tty->canon_column = tty->column; | 292 | tty->canon_column = tty->column; |
@@ -308,7 +308,7 @@ static int opost(unsigned char c, struct tty_struct *tty) | |||
308 | if (space < spaces) | 308 | if (space < spaces) |
309 | return -1; | 309 | return -1; |
310 | tty->column += spaces; | 310 | tty->column += spaces; |
311 | tty->driver->write(tty, " ", spaces); | 311 | tty->ops->write(tty, " ", spaces); |
312 | return 0; | 312 | return 0; |
313 | } | 313 | } |
314 | tty->column += spaces; | 314 | tty->column += spaces; |
@@ -325,7 +325,7 @@ static int opost(unsigned char c, struct tty_struct *tty) | |||
325 | break; | 325 | break; |
326 | } | 326 | } |
327 | } | 327 | } |
328 | tty->driver->put_char(tty, c); | 328 | tty_put_char(tty, c); |
329 | unlock_kernel(); | 329 | unlock_kernel(); |
330 | return 0; | 330 | return 0; |
331 | } | 331 | } |
@@ -352,7 +352,7 @@ static ssize_t opost_block(struct tty_struct *tty, | |||
352 | int i; | 352 | int i; |
353 | const unsigned char *cp; | 353 | const unsigned char *cp; |
354 | 354 | ||
355 | space = tty->driver->write_room(tty); | 355 | space = tty_write_room(tty); |
356 | if (!space) | 356 | if (!space) |
357 | return 0; | 357 | return 0; |
358 | if (nr > space) | 358 | if (nr > space) |
@@ -390,28 +390,15 @@ static ssize_t opost_block(struct tty_struct *tty, | |||
390 | } | 390 | } |
391 | } | 391 | } |
392 | break_out: | 392 | break_out: |
393 | if (tty->driver->flush_chars) | 393 | if (tty->ops->flush_chars) |
394 | tty->driver->flush_chars(tty); | 394 | tty->ops->flush_chars(tty); |
395 | i = tty->driver->write(tty, buf, i); | 395 | i = tty->ops->write(tty, buf, i); |
396 | unlock_kernel(); | 396 | unlock_kernel(); |
397 | return i; | 397 | return i; |
398 | } | 398 | } |
399 | 399 | ||
400 | 400 | ||
401 | /** | 401 | /** |
402 | * put_char - write character to driver | ||
403 | * @c: character (or part of unicode symbol) | ||
404 | * @tty: terminal device | ||
405 | * | ||
406 | * Queue a byte to the driver layer for output | ||
407 | */ | ||
408 | |||
409 | static inline void put_char(unsigned char c, struct tty_struct *tty) | ||
410 | { | ||
411 | tty->driver->put_char(tty, c); | ||
412 | } | ||
413 | |||
414 | /** | ||
415 | * echo_char - echo characters | 402 | * echo_char - echo characters |
416 | * @c: unicode byte to echo | 403 | * @c: unicode byte to echo |
417 | * @tty: terminal device | 404 | * @tty: terminal device |
@@ -423,8 +410,8 @@ static inline void put_char(unsigned char c, struct tty_struct *tty) | |||
423 | static void echo_char(unsigned char c, struct tty_struct *tty) | 410 | static void echo_char(unsigned char c, struct tty_struct *tty) |
424 | { | 411 | { |
425 | if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') { | 412 | if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') { |
426 | put_char('^', tty); | 413 | tty_put_char(tty, '^'); |
427 | put_char(c ^ 0100, tty); | 414 | tty_put_char(tty, c ^ 0100); |
428 | tty->column += 2; | 415 | tty->column += 2; |
429 | } else | 416 | } else |
430 | opost(c, tty); | 417 | opost(c, tty); |
@@ -433,7 +420,7 @@ static void echo_char(unsigned char c, struct tty_struct *tty) | |||
433 | static inline void finish_erasing(struct tty_struct *tty) | 420 | static inline void finish_erasing(struct tty_struct *tty) |
434 | { | 421 | { |
435 | if (tty->erasing) { | 422 | if (tty->erasing) { |
436 | put_char('/', tty); | 423 | tty_put_char(tty, '/'); |
437 | tty->column++; | 424 | tty->column++; |
438 | tty->erasing = 0; | 425 | tty->erasing = 0; |
439 | } | 426 | } |
@@ -517,7 +504,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) | |||
517 | if (L_ECHO(tty)) { | 504 | if (L_ECHO(tty)) { |
518 | if (L_ECHOPRT(tty)) { | 505 | if (L_ECHOPRT(tty)) { |
519 | if (!tty->erasing) { | 506 | if (!tty->erasing) { |
520 | put_char('\\', tty); | 507 | tty_put_char(tty, '\\'); |
521 | tty->column++; | 508 | tty->column++; |
522 | tty->erasing = 1; | 509 | tty->erasing = 1; |
523 | } | 510 | } |
@@ -525,7 +512,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) | |||
525 | echo_char(c, tty); | 512 | echo_char(c, tty); |
526 | while (--cnt > 0) { | 513 | while (--cnt > 0) { |
527 | head = (head+1) & (N_TTY_BUF_SIZE-1); | 514 | head = (head+1) & (N_TTY_BUF_SIZE-1); |
528 | put_char(tty->read_buf[head], tty); | 515 | tty_put_char(tty, tty->read_buf[head]); |
529 | } | 516 | } |
530 | } else if (kill_type == ERASE && !L_ECHOE(tty)) { | 517 | } else if (kill_type == ERASE && !L_ECHOE(tty)) { |
531 | echo_char(ERASE_CHAR(tty), tty); | 518 | echo_char(ERASE_CHAR(tty), tty); |
@@ -553,22 +540,22 @@ static void eraser(unsigned char c, struct tty_struct *tty) | |||
553 | /* Now backup to that column. */ | 540 | /* Now backup to that column. */ |
554 | while (tty->column > col) { | 541 | while (tty->column > col) { |
555 | /* Can't use opost here. */ | 542 | /* Can't use opost here. */ |
556 | put_char('\b', tty); | 543 | tty_put_char(tty, '\b'); |
557 | if (tty->column > 0) | 544 | if (tty->column > 0) |
558 | tty->column--; | 545 | tty->column--; |
559 | } | 546 | } |
560 | } else { | 547 | } else { |
561 | if (iscntrl(c) && L_ECHOCTL(tty)) { | 548 | if (iscntrl(c) && L_ECHOCTL(tty)) { |
562 | put_char('\b', tty); | 549 | tty_put_char(tty, '\b'); |
563 | put_char(' ', tty); | 550 | tty_put_char(tty, ' '); |
564 | put_char('\b', tty); | 551 | tty_put_char(tty, '\b'); |
565 | if (tty->column > 0) | 552 | if (tty->column > 0) |
566 | tty->column--; | 553 | tty->column--; |
567 | } | 554 | } |
568 | if (!iscntrl(c) || L_ECHOCTL(tty)) { | 555 | if (!iscntrl(c) || L_ECHOCTL(tty)) { |
569 | put_char('\b', tty); | 556 | tty_put_char(tty, '\b'); |
570 | put_char(' ', tty); | 557 | tty_put_char(tty, ' '); |
571 | put_char('\b', tty); | 558 | tty_put_char(tty, '\b'); |
572 | if (tty->column > 0) | 559 | if (tty->column > 0) |
573 | tty->column--; | 560 | tty->column--; |
574 | } | 561 | } |
@@ -599,8 +586,7 @@ static inline void isig(int sig, struct tty_struct *tty, int flush) | |||
599 | kill_pgrp(tty->pgrp, sig, 1); | 586 | kill_pgrp(tty->pgrp, sig, 1); |
600 | if (flush || !L_NOFLSH(tty)) { | 587 | if (flush || !L_NOFLSH(tty)) { |
601 | n_tty_flush_buffer(tty); | 588 | n_tty_flush_buffer(tty); |
602 | if (tty->driver->flush_buffer) | 589 | tty_driver_flush_buffer(tty); |
603 | tty->driver->flush_buffer(tty); | ||
604 | } | 590 | } |
605 | } | 591 | } |
606 | 592 | ||
@@ -732,7 +718,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
732 | tty->lnext = 0; | 718 | tty->lnext = 0; |
733 | if (L_ECHO(tty)) { | 719 | if (L_ECHO(tty)) { |
734 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) { | 720 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) { |
735 | put_char('\a', tty); /* beep if no space */ | 721 | tty_put_char(tty, '\a'); /* beep if no space */ |
736 | return; | 722 | return; |
737 | } | 723 | } |
738 | /* Record the column of first canon char. */ | 724 | /* Record the column of first canon char. */ |
@@ -776,8 +762,7 @@ send_signal: | |||
776 | */ | 762 | */ |
777 | if (!L_NOFLSH(tty)) { | 763 | if (!L_NOFLSH(tty)) { |
778 | n_tty_flush_buffer(tty); | 764 | n_tty_flush_buffer(tty); |
779 | if (tty->driver->flush_buffer) | 765 | tty_driver_flush_buffer(tty); |
780 | tty->driver->flush_buffer(tty); | ||
781 | } | 766 | } |
782 | if (L_ECHO(tty)) | 767 | if (L_ECHO(tty)) |
783 | echo_char(c, tty); | 768 | echo_char(c, tty); |
@@ -806,8 +791,8 @@ send_signal: | |||
806 | if (L_ECHO(tty)) { | 791 | if (L_ECHO(tty)) { |
807 | finish_erasing(tty); | 792 | finish_erasing(tty); |
808 | if (L_ECHOCTL(tty)) { | 793 | if (L_ECHOCTL(tty)) { |
809 | put_char('^', tty); | 794 | tty_put_char(tty, '^'); |
810 | put_char('\b', tty); | 795 | tty_put_char(tty, '\b'); |
811 | } | 796 | } |
812 | } | 797 | } |
813 | return; | 798 | return; |
@@ -828,7 +813,7 @@ send_signal: | |||
828 | if (c == '\n') { | 813 | if (c == '\n') { |
829 | if (L_ECHO(tty) || L_ECHONL(tty)) { | 814 | if (L_ECHO(tty) || L_ECHONL(tty)) { |
830 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) | 815 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) |
831 | put_char('\a', tty); | 816 | tty_put_char(tty, '\a'); |
832 | opost('\n', tty); | 817 | opost('\n', tty); |
833 | } | 818 | } |
834 | goto handle_newline; | 819 | goto handle_newline; |
@@ -846,7 +831,7 @@ send_signal: | |||
846 | */ | 831 | */ |
847 | if (L_ECHO(tty)) { | 832 | if (L_ECHO(tty)) { |
848 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) | 833 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) |
849 | put_char('\a', tty); | 834 | tty_put_char(tty, '\a'); |
850 | /* Record the column of first canon char. */ | 835 | /* Record the column of first canon char. */ |
851 | if (tty->canon_head == tty->read_head) | 836 | if (tty->canon_head == tty->read_head) |
852 | tty->canon_column = tty->column; | 837 | tty->canon_column = tty->column; |
@@ -876,7 +861,7 @@ handle_newline: | |||
876 | finish_erasing(tty); | 861 | finish_erasing(tty); |
877 | if (L_ECHO(tty)) { | 862 | if (L_ECHO(tty)) { |
878 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) { | 863 | if (tty->read_cnt >= N_TTY_BUF_SIZE-1) { |
879 | put_char('\a', tty); /* beep if no space */ | 864 | tty_put_char(tty, '\a'); /* beep if no space */ |
880 | return; | 865 | return; |
881 | } | 866 | } |
882 | if (c == '\n') | 867 | if (c == '\n') |
@@ -980,8 +965,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
980 | break; | 965 | break; |
981 | } | 966 | } |
982 | } | 967 | } |
983 | if (tty->driver->flush_chars) | 968 | if (tty->ops->flush_chars) |
984 | tty->driver->flush_chars(tty); | 969 | tty->ops->flush_chars(tty); |
985 | } | 970 | } |
986 | 971 | ||
987 | n_tty_set_room(tty); | 972 | n_tty_set_room(tty); |
@@ -1000,8 +985,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, | |||
1000 | if (tty->receive_room < TTY_THRESHOLD_THROTTLE) { | 985 | if (tty->receive_room < TTY_THRESHOLD_THROTTLE) { |
1001 | /* check TTY_THROTTLED first so it indicates our state */ | 986 | /* check TTY_THROTTLED first so it indicates our state */ |
1002 | if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) && | 987 | if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) && |
1003 | tty->driver->throttle) | 988 | tty->ops->throttle) |
1004 | tty->driver->throttle(tty); | 989 | tty->ops->throttle(tty); |
1005 | } | 990 | } |
1006 | } | 991 | } |
1007 | 992 | ||
@@ -1086,6 +1071,9 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
1086 | tty->real_raw = 0; | 1071 | tty->real_raw = 0; |
1087 | } | 1072 | } |
1088 | n_tty_set_room(tty); | 1073 | n_tty_set_room(tty); |
1074 | /* The termios change make the tty ready for I/O */ | ||
1075 | wake_up_interruptible(&tty->write_wait); | ||
1076 | wake_up_interruptible(&tty->read_wait); | ||
1089 | } | 1077 | } |
1090 | 1078 | ||
1091 | /** | 1079 | /** |
@@ -1513,11 +1501,11 @@ static ssize_t write_chan(struct tty_struct *tty, struct file *file, | |||
1513 | break; | 1501 | break; |
1514 | b++; nr--; | 1502 | b++; nr--; |
1515 | } | 1503 | } |
1516 | if (tty->driver->flush_chars) | 1504 | if (tty->ops->flush_chars) |
1517 | tty->driver->flush_chars(tty); | 1505 | tty->ops->flush_chars(tty); |
1518 | } else { | 1506 | } else { |
1519 | while (nr > 0) { | 1507 | while (nr > 0) { |
1520 | c = tty->driver->write(tty, b, nr); | 1508 | c = tty->ops->write(tty, b, nr); |
1521 | if (c < 0) { | 1509 | if (c < 0) { |
1522 | retval = c; | 1510 | retval = c; |
1523 | goto break_out; | 1511 | goto break_out; |
@@ -1554,11 +1542,6 @@ break_out: | |||
1554 | * | 1542 | * |
1555 | * This code must be sure never to sleep through a hangup. | 1543 | * This code must be sure never to sleep through a hangup. |
1556 | * Called without the kernel lock held - fine | 1544 | * Called without the kernel lock held - fine |
1557 | * | ||
1558 | * FIXME: if someone changes the VMIN or discipline settings for the | ||
1559 | * terminal while another process is in poll() the poll does not | ||
1560 | * recompute the new limits. Possibly set_termios should issue | ||
1561 | * a read wakeup to fix this bug. | ||
1562 | */ | 1545 | */ |
1563 | 1546 | ||
1564 | static unsigned int normal_poll(struct tty_struct *tty, struct file *file, | 1547 | static unsigned int normal_poll(struct tty_struct *tty, struct file *file, |
@@ -1582,9 +1565,9 @@ static unsigned int normal_poll(struct tty_struct *tty, struct file *file, | |||
1582 | else | 1565 | else |
1583 | tty->minimum_to_wake = 1; | 1566 | tty->minimum_to_wake = 1; |
1584 | } | 1567 | } |
1585 | if (!tty_is_writelocked(tty) && | 1568 | if (tty->ops->write && !tty_is_writelocked(tty) && |
1586 | tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS && | 1569 | tty_chars_in_buffer(tty) < WAKEUP_CHARS && |
1587 | tty->driver->write_room(tty) > 0) | 1570 | tty_write_room(tty) > 0) |
1588 | mask |= POLLOUT | POLLWRNORM; | 1571 | mask |= POLLOUT | POLLWRNORM; |
1589 | return mask; | 1572 | return mask; |
1590 | } | 1573 | } |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index b1692afd797e..f69fb8d7a680 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -1108,8 +1108,8 @@ restart: | |||
1108 | a reference to the old ldisc. If we ended up flipping back | 1108 | a reference to the old ldisc. If we ended up flipping back |
1109 | to the existing ldisc we have two references to it */ | 1109 | to the existing ldisc we have two references to it */ |
1110 | 1110 | ||
1111 | if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc) | 1111 | if (tty->ldisc.num != o_ldisc.num && tty->ops->set_ldisc) |
1112 | tty->driver->set_ldisc(tty); | 1112 | tty->ops->set_ldisc(tty); |
1113 | 1113 | ||
1114 | tty_ldisc_put(o_ldisc.num); | 1114 | tty_ldisc_put(o_ldisc.num); |
1115 | 1115 | ||
@@ -1181,9 +1181,8 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) | |||
1181 | if (*str == '\0') | 1181 | if (*str == '\0') |
1182 | str = NULL; | 1182 | str = NULL; |
1183 | 1183 | ||
1184 | if (tty_line >= 0 && tty_line <= p->num && p->poll_init && | 1184 | if (tty_line >= 0 && tty_line <= p->num && p->ops && |
1185 | !p->poll_init(p, tty_line, str)) { | 1185 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) { |
1186 | |||
1187 | res = p; | 1186 | res = p; |
1188 | *line = tty_line; | 1187 | *line = tty_line; |
1189 | break; | 1188 | break; |
@@ -1452,8 +1451,7 @@ static void do_tty_hangup(struct work_struct *work) | |||
1452 | /* We may have no line discipline at this point */ | 1451 | /* We may have no line discipline at this point */ |
1453 | if (ld->flush_buffer) | 1452 | if (ld->flush_buffer) |
1454 | ld->flush_buffer(tty); | 1453 | ld->flush_buffer(tty); |
1455 | if (tty->driver->flush_buffer) | 1454 | tty_driver_flush_buffer(tty); |
1456 | tty->driver->flush_buffer(tty); | ||
1457 | if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && | 1455 | if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && |
1458 | ld->write_wakeup) | 1456 | ld->write_wakeup) |
1459 | ld->write_wakeup(tty); | 1457 | ld->write_wakeup(tty); |
@@ -1516,11 +1514,11 @@ static void do_tty_hangup(struct work_struct *work) | |||
1516 | * So we just call close() the right number of times. | 1514 | * So we just call close() the right number of times. |
1517 | */ | 1515 | */ |
1518 | if (cons_filp) { | 1516 | if (cons_filp) { |
1519 | if (tty->driver->close) | 1517 | if (tty->ops->close) |
1520 | for (n = 0; n < closecount; n++) | 1518 | for (n = 0; n < closecount; n++) |
1521 | tty->driver->close(tty, cons_filp); | 1519 | tty->ops->close(tty, cons_filp); |
1522 | } else if (tty->driver->hangup) | 1520 | } else if (tty->ops->hangup) |
1523 | (tty->driver->hangup)(tty); | 1521 | (tty->ops->hangup)(tty); |
1524 | /* | 1522 | /* |
1525 | * We don't want to have driver/ldisc interactions beyond | 1523 | * We don't want to have driver/ldisc interactions beyond |
1526 | * the ones we did here. The driver layer expects no | 1524 | * the ones we did here. The driver layer expects no |
@@ -1752,8 +1750,8 @@ void stop_tty(struct tty_struct *tty) | |||
1752 | wake_up_interruptible(&tty->link->read_wait); | 1750 | wake_up_interruptible(&tty->link->read_wait); |
1753 | } | 1751 | } |
1754 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 1752 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
1755 | if (tty->driver->stop) | 1753 | if (tty->ops->stop) |
1756 | (tty->driver->stop)(tty); | 1754 | (tty->ops->stop)(tty); |
1757 | } | 1755 | } |
1758 | 1756 | ||
1759 | EXPORT_SYMBOL(stop_tty); | 1757 | EXPORT_SYMBOL(stop_tty); |
@@ -1786,8 +1784,8 @@ void start_tty(struct tty_struct *tty) | |||
1786 | wake_up_interruptible(&tty->link->read_wait); | 1784 | wake_up_interruptible(&tty->link->read_wait); |
1787 | } | 1785 | } |
1788 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 1786 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
1789 | if (tty->driver->start) | 1787 | if (tty->ops->start) |
1790 | (tty->driver->start)(tty); | 1788 | (tty->ops->start)(tty); |
1791 | /* If we have a running line discipline it may need kicking */ | 1789 | /* If we have a running line discipline it may need kicking */ |
1792 | tty_wakeup(tty); | 1790 | tty_wakeup(tty); |
1793 | } | 1791 | } |
@@ -1972,10 +1970,13 @@ static ssize_t tty_write(struct file *file, const char __user *buf, | |||
1972 | tty = (struct tty_struct *)file->private_data; | 1970 | tty = (struct tty_struct *)file->private_data; |
1973 | if (tty_paranoia_check(tty, inode, "tty_write")) | 1971 | if (tty_paranoia_check(tty, inode, "tty_write")) |
1974 | return -EIO; | 1972 | return -EIO; |
1975 | if (!tty || !tty->driver->write || | 1973 | if (!tty || !tty->ops->write || |
1976 | (test_bit(TTY_IO_ERROR, &tty->flags))) | 1974 | (test_bit(TTY_IO_ERROR, &tty->flags))) |
1977 | return -EIO; | 1975 | return -EIO; |
1978 | 1976 | /* Short term debug to catch buggy drivers */ | |
1977 | if (tty->ops->write_room == NULL) | ||
1978 | printk(KERN_ERR "tty driver %s lacks a write_room method.\n", | ||
1979 | tty->driver->name); | ||
1979 | ld = tty_ldisc_ref_wait(tty); | 1980 | ld = tty_ldisc_ref_wait(tty); |
1980 | if (!ld->write) | 1981 | if (!ld->write) |
1981 | ret = -EIO; | 1982 | ret = -EIO; |
@@ -2122,6 +2123,7 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2122 | goto fail_no_mem; | 2123 | goto fail_no_mem; |
2123 | initialize_tty_struct(tty); | 2124 | initialize_tty_struct(tty); |
2124 | tty->driver = driver; | 2125 | tty->driver = driver; |
2126 | tty->ops = driver->ops; | ||
2125 | tty->index = idx; | 2127 | tty->index = idx; |
2126 | tty_line_name(driver, idx, tty->name); | 2128 | tty_line_name(driver, idx, tty->name); |
2127 | 2129 | ||
@@ -2152,6 +2154,7 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2152 | goto free_mem_out; | 2154 | goto free_mem_out; |
2153 | initialize_tty_struct(o_tty); | 2155 | initialize_tty_struct(o_tty); |
2154 | o_tty->driver = driver->other; | 2156 | o_tty->driver = driver->other; |
2157 | o_tty->ops = driver->ops; | ||
2155 | o_tty->index = idx; | 2158 | o_tty->index = idx; |
2156 | tty_line_name(driver->other, idx, o_tty->name); | 2159 | tty_line_name(driver->other, idx, o_tty->name); |
2157 | 2160 | ||
@@ -2456,8 +2459,8 @@ static void release_dev(struct file *filp) | |||
2456 | } | 2459 | } |
2457 | } | 2460 | } |
2458 | #endif | 2461 | #endif |
2459 | if (tty->driver->close) | 2462 | if (tty->ops->close) |
2460 | tty->driver->close(tty, filp); | 2463 | tty->ops->close(tty, filp); |
2461 | 2464 | ||
2462 | /* | 2465 | /* |
2463 | * Sanity check: if tty->count is going to zero, there shouldn't be | 2466 | * Sanity check: if tty->count is going to zero, there shouldn't be |
@@ -2740,8 +2743,8 @@ got_driver: | |||
2740 | printk(KERN_DEBUG "opening %s...", tty->name); | 2743 | printk(KERN_DEBUG "opening %s...", tty->name); |
2741 | #endif | 2744 | #endif |
2742 | if (!retval) { | 2745 | if (!retval) { |
2743 | if (tty->driver->open) | 2746 | if (tty->ops->open) |
2744 | retval = tty->driver->open(tty, filp); | 2747 | retval = tty->ops->open(tty, filp); |
2745 | else | 2748 | else |
2746 | retval = -ENODEV; | 2749 | retval = -ENODEV; |
2747 | } | 2750 | } |
@@ -2840,7 +2843,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
2840 | goto out1; | 2843 | goto out1; |
2841 | 2844 | ||
2842 | check_tty_count(tty, "tty_open"); | 2845 | check_tty_count(tty, "tty_open"); |
2843 | retval = ptm_driver->open(tty, filp); | 2846 | retval = ptm_driver->ops->open(tty, filp); |
2844 | if (!retval) | 2847 | if (!retval) |
2845 | return 0; | 2848 | return 0; |
2846 | out1: | 2849 | out1: |
@@ -3336,25 +3339,20 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) | |||
3336 | 3339 | ||
3337 | static int send_break(struct tty_struct *tty, unsigned int duration) | 3340 | static int send_break(struct tty_struct *tty, unsigned int duration) |
3338 | { | 3341 | { |
3339 | int retval = -EINTR; | ||
3340 | |||
3341 | lock_kernel(); | ||
3342 | if (tty_write_lock(tty, 0) < 0) | 3342 | if (tty_write_lock(tty, 0) < 0) |
3343 | goto out; | 3343 | return -EINTR; |
3344 | tty->driver->break_ctl(tty, -1); | 3344 | tty->ops->break_ctl(tty, -1); |
3345 | if (!signal_pending(current)) | 3345 | if (!signal_pending(current)) |
3346 | msleep_interruptible(duration); | 3346 | msleep_interruptible(duration); |
3347 | tty->driver->break_ctl(tty, 0); | 3347 | tty->ops->break_ctl(tty, 0); |
3348 | tty_write_unlock(tty); | 3348 | tty_write_unlock(tty); |
3349 | if (!signal_pending(current)) | 3349 | if (!signal_pending(current)) |
3350 | retval = 0; | 3350 | return -EINTR; |
3351 | out: | 3351 | return 0; |
3352 | unlock_kernel(); | ||
3353 | return retval; | ||
3354 | } | 3352 | } |
3355 | 3353 | ||
3356 | /** | 3354 | /** |
3357 | * tiocmget - get modem status | 3355 | * tty_tiocmget - get modem status |
3358 | * @tty: tty device | 3356 | * @tty: tty device |
3359 | * @file: user file pointer | 3357 | * @file: user file pointer |
3360 | * @p: pointer to result | 3358 | * @p: pointer to result |
@@ -3369,10 +3367,8 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p | |||
3369 | { | 3367 | { |
3370 | int retval = -EINVAL; | 3368 | int retval = -EINVAL; |
3371 | 3369 | ||
3372 | if (tty->driver->tiocmget) { | 3370 | if (tty->ops->tiocmget) { |
3373 | lock_kernel(); | 3371 | retval = tty->ops->tiocmget(tty, file); |
3374 | retval = tty->driver->tiocmget(tty, file); | ||
3375 | unlock_kernel(); | ||
3376 | 3372 | ||
3377 | if (retval >= 0) | 3373 | if (retval >= 0) |
3378 | retval = put_user(retval, p); | 3374 | retval = put_user(retval, p); |
@@ -3381,7 +3377,7 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p | |||
3381 | } | 3377 | } |
3382 | 3378 | ||
3383 | /** | 3379 | /** |
3384 | * tiocmset - set modem status | 3380 | * tty_tiocmset - set modem status |
3385 | * @tty: tty device | 3381 | * @tty: tty device |
3386 | * @file: user file pointer | 3382 | * @file: user file pointer |
3387 | * @cmd: command - clear bits, set bits or set all | 3383 | * @cmd: command - clear bits, set bits or set all |
@@ -3398,7 +3394,7 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int | |||
3398 | { | 3394 | { |
3399 | int retval = -EINVAL; | 3395 | int retval = -EINVAL; |
3400 | 3396 | ||
3401 | if (tty->driver->tiocmset) { | 3397 | if (tty->ops->tiocmset) { |
3402 | unsigned int set, clear, val; | 3398 | unsigned int set, clear, val; |
3403 | 3399 | ||
3404 | retval = get_user(val, p); | 3400 | retval = get_user(val, p); |
@@ -3422,9 +3418,7 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int | |||
3422 | set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP; | 3418 | set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP; |
3423 | clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP; | 3419 | clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP; |
3424 | 3420 | ||
3425 | lock_kernel(); | 3421 | retval = tty->ops->tiocmset(tty, file, set, clear); |
3426 | retval = tty->driver->tiocmset(tty, file, set, clear); | ||
3427 | unlock_kernel(); | ||
3428 | } | 3422 | } |
3429 | return retval; | 3423 | return retval; |
3430 | } | 3424 | } |
@@ -3455,23 +3449,25 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3455 | 3449 | ||
3456 | retval = -EINVAL; | 3450 | retval = -EINVAL; |
3457 | 3451 | ||
3458 | if (!tty->driver->break_ctl) { | 3452 | if (!tty->ops->break_ctl) { |
3459 | switch (cmd) { | 3453 | switch (cmd) { |
3460 | case TIOCSBRK: | 3454 | case TIOCSBRK: |
3461 | case TIOCCBRK: | 3455 | case TIOCCBRK: |
3462 | if (tty->driver->ioctl) | 3456 | if (tty->ops->ioctl) |
3463 | retval = tty->driver->ioctl(tty, file, cmd, arg); | 3457 | retval = tty->ops->ioctl(tty, file, cmd, arg); |
3458 | if (retval != -EINVAL && retval != -ENOIOCTLCMD) | ||
3459 | printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name); | ||
3464 | return retval; | 3460 | return retval; |
3465 | 3461 | ||
3466 | /* These two ioctl's always return success; even if */ | 3462 | /* These two ioctl's always return success; even if */ |
3467 | /* the driver doesn't support them. */ | 3463 | /* the driver doesn't support them. */ |
3468 | case TCSBRK: | 3464 | case TCSBRK: |
3469 | case TCSBRKP: | 3465 | case TCSBRKP: |
3470 | if (!tty->driver->ioctl) | 3466 | if (!tty->ops->ioctl) |
3471 | return 0; | 3467 | return 0; |
3472 | lock_kernel(); | 3468 | retval = tty->ops->ioctl(tty, file, cmd, arg); |
3473 | retval = tty->driver->ioctl(tty, file, cmd, arg); | 3469 | if (retval != -EINVAL && retval != -ENOIOCTLCMD) |
3474 | unlock_kernel(); | 3470 | printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name); |
3475 | if (retval == -ENOIOCTLCMD) | 3471 | if (retval == -ENOIOCTLCMD) |
3476 | retval = 0; | 3472 | retval = 0; |
3477 | return retval; | 3473 | return retval; |
@@ -3491,9 +3487,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3491 | if (retval) | 3487 | if (retval) |
3492 | return retval; | 3488 | return retval; |
3493 | if (cmd != TIOCCBRK) { | 3489 | if (cmd != TIOCCBRK) { |
3494 | lock_kernel(); | ||
3495 | tty_wait_until_sent(tty, 0); | 3490 | tty_wait_until_sent(tty, 0); |
3496 | unlock_kernel(); | ||
3497 | if (signal_pending(current)) | 3491 | if (signal_pending(current)) |
3498 | return -EINTR; | 3492 | return -EINTR; |
3499 | } | 3493 | } |
@@ -3531,7 +3525,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3531 | case TIOCGSID: | 3525 | case TIOCGSID: |
3532 | return tiocgsid(tty, real_tty, p); | 3526 | return tiocgsid(tty, real_tty, p); |
3533 | case TIOCGETD: | 3527 | case TIOCGETD: |
3534 | /* FIXME: check this is ok */ | ||
3535 | return put_user(tty->ldisc.num, (int __user *)p); | 3528 | return put_user(tty->ldisc.num, (int __user *)p); |
3536 | case TIOCSETD: | 3529 | case TIOCSETD: |
3537 | return tiocsetd(tty, p); | 3530 | return tiocsetd(tty, p); |
@@ -3543,15 +3536,13 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3543 | * Break handling | 3536 | * Break handling |
3544 | */ | 3537 | */ |
3545 | case TIOCSBRK: /* Turn break on, unconditionally */ | 3538 | case TIOCSBRK: /* Turn break on, unconditionally */ |
3546 | lock_kernel(); | 3539 | if (tty->ops->break_ctl) |
3547 | tty->driver->break_ctl(tty, -1); | 3540 | tty->ops->break_ctl(tty, -1); |
3548 | unlock_kernel(); | ||
3549 | return 0; | 3541 | return 0; |
3550 | 3542 | ||
3551 | case TIOCCBRK: /* Turn break off, unconditionally */ | 3543 | case TIOCCBRK: /* Turn break off, unconditionally */ |
3552 | lock_kernel(); | 3544 | if (tty->ops->break_ctl) |
3553 | tty->driver->break_ctl(tty, 0); | 3545 | tty->ops->break_ctl(tty, 0); |
3554 | unlock_kernel(); | ||
3555 | return 0; | 3546 | return 0; |
3556 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | 3547 | case TCSBRK: /* SVID version: non-zero arg --> no break */ |
3557 | /* non-zero arg means wait for all output data | 3548 | /* non-zero arg means wait for all output data |
@@ -3580,8 +3571,8 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3580 | } | 3571 | } |
3581 | break; | 3572 | break; |
3582 | } | 3573 | } |
3583 | if (tty->driver->ioctl) { | 3574 | if (tty->ops->ioctl) { |
3584 | retval = (tty->driver->ioctl)(tty, file, cmd, arg); | 3575 | retval = (tty->ops->ioctl)(tty, file, cmd, arg); |
3585 | if (retval != -ENOIOCTLCMD) | 3576 | if (retval != -ENOIOCTLCMD) |
3586 | return retval; | 3577 | return retval; |
3587 | } | 3578 | } |
@@ -3608,8 +3599,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, | |||
3608 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) | 3599 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) |
3609 | return -EINVAL; | 3600 | return -EINVAL; |
3610 | 3601 | ||
3611 | if (tty->driver->compat_ioctl) { | 3602 | if (tty->ops->compat_ioctl) { |
3612 | retval = (tty->driver->compat_ioctl)(tty, file, cmd, arg); | 3603 | retval = (tty->ops->compat_ioctl)(tty, file, cmd, arg); |
3613 | if (retval != -ENOIOCTLCMD) | 3604 | if (retval != -ENOIOCTLCMD) |
3614 | return retval; | 3605 | return retval; |
3615 | } | 3606 | } |
@@ -3659,8 +3650,7 @@ void __do_SAK(struct tty_struct *tty) | |||
3659 | 3650 | ||
3660 | tty_ldisc_flush(tty); | 3651 | tty_ldisc_flush(tty); |
3661 | 3652 | ||
3662 | if (tty->driver->flush_buffer) | 3653 | tty_driver_flush_buffer(tty); |
3663 | tty->driver->flush_buffer(tty); | ||
3664 | 3654 | ||
3665 | read_lock(&tasklist_lock); | 3655 | read_lock(&tasklist_lock); |
3666 | /* Kill the entire session */ | 3656 | /* Kill the entire session */ |
@@ -3871,15 +3861,27 @@ static void initialize_tty_struct(struct tty_struct *tty) | |||
3871 | INIT_WORK(&tty->SAK_work, do_SAK_work); | 3861 | INIT_WORK(&tty->SAK_work, do_SAK_work); |
3872 | } | 3862 | } |
3873 | 3863 | ||
3874 | /* | 3864 | /** |
3875 | * The default put_char routine if the driver did not define one. | 3865 | * tty_put_char - write one character to a tty |
3866 | * @tty: tty | ||
3867 | * @ch: character | ||
3868 | * | ||
3869 | * Write one byte to the tty using the provided put_char method | ||
3870 | * if present. Returns the number of characters successfully output. | ||
3871 | * | ||
3872 | * Note: the specific put_char operation in the driver layer may go | ||
3873 | * away soon. Don't call it directly, use this method | ||
3876 | */ | 3874 | */ |
3877 | 3875 | ||
3878 | static void tty_default_put_char(struct tty_struct *tty, unsigned char ch) | 3876 | int tty_put_char(struct tty_struct *tty, unsigned char ch) |
3879 | { | 3877 | { |
3880 | tty->driver->write(tty, &ch, 1); | 3878 | if (tty->ops->put_char) |
3879 | return tty->ops->put_char(tty, ch); | ||
3880 | return tty->ops->write(tty, &ch, 1); | ||
3881 | } | 3881 | } |
3882 | 3882 | ||
3883 | EXPORT_SYMBOL_GPL(tty_put_char); | ||
3884 | |||
3883 | static struct class *tty_class; | 3885 | static struct class *tty_class; |
3884 | 3886 | ||
3885 | /** | 3887 | /** |
@@ -3962,37 +3964,8 @@ void put_tty_driver(struct tty_driver *driver) | |||
3962 | void tty_set_operations(struct tty_driver *driver, | 3964 | void tty_set_operations(struct tty_driver *driver, |
3963 | const struct tty_operations *op) | 3965 | const struct tty_operations *op) |
3964 | { | 3966 | { |
3965 | driver->open = op->open; | 3967 | driver->ops = op; |
3966 | driver->close = op->close; | 3968 | }; |
3967 | driver->write = op->write; | ||
3968 | driver->put_char = op->put_char; | ||
3969 | driver->flush_chars = op->flush_chars; | ||
3970 | driver->write_room = op->write_room; | ||
3971 | driver->chars_in_buffer = op->chars_in_buffer; | ||
3972 | driver->ioctl = op->ioctl; | ||
3973 | driver->compat_ioctl = op->compat_ioctl; | ||
3974 | driver->set_termios = op->set_termios; | ||
3975 | driver->throttle = op->throttle; | ||
3976 | driver->unthrottle = op->unthrottle; | ||
3977 | driver->stop = op->stop; | ||
3978 | driver->start = op->start; | ||
3979 | driver->hangup = op->hangup; | ||
3980 | driver->break_ctl = op->break_ctl; | ||
3981 | driver->flush_buffer = op->flush_buffer; | ||
3982 | driver->set_ldisc = op->set_ldisc; | ||
3983 | driver->wait_until_sent = op->wait_until_sent; | ||
3984 | driver->send_xchar = op->send_xchar; | ||
3985 | driver->read_proc = op->read_proc; | ||
3986 | driver->write_proc = op->write_proc; | ||
3987 | driver->tiocmget = op->tiocmget; | ||
3988 | driver->tiocmset = op->tiocmset; | ||
3989 | #ifdef CONFIG_CONSOLE_POLL | ||
3990 | driver->poll_init = op->poll_init; | ||
3991 | driver->poll_get_char = op->poll_get_char; | ||
3992 | driver->poll_put_char = op->poll_put_char; | ||
3993 | #endif | ||
3994 | } | ||
3995 | |||
3996 | 3969 | ||
3997 | EXPORT_SYMBOL(alloc_tty_driver); | 3970 | EXPORT_SYMBOL(alloc_tty_driver); |
3998 | EXPORT_SYMBOL(put_tty_driver); | 3971 | EXPORT_SYMBOL(put_tty_driver); |
@@ -4055,9 +4028,6 @@ int tty_register_driver(struct tty_driver *driver) | |||
4055 | return error; | 4028 | return error; |
4056 | } | 4029 | } |
4057 | 4030 | ||
4058 | if (!driver->put_char) | ||
4059 | driver->put_char = tty_default_put_char; | ||
4060 | |||
4061 | mutex_lock(&tty_mutex); | 4031 | mutex_lock(&tty_mutex); |
4062 | list_add(&driver->tty_drivers, &tty_drivers); | 4032 | list_add(&driver->tty_drivers, &tty_drivers); |
4063 | mutex_unlock(&tty_mutex); | 4033 | mutex_unlock(&tty_mutex); |
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 8c4bf3e48d5b..c10d40c4c5ca 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -40,6 +40,34 @@ | |||
40 | #define TERMIOS_OLD 8 | 40 | #define TERMIOS_OLD 8 |
41 | 41 | ||
42 | 42 | ||
43 | int tty_chars_in_buffer(struct tty_struct *tty) | ||
44 | { | ||
45 | if (tty->ops->chars_in_buffer) | ||
46 | return tty->ops->chars_in_buffer(tty); | ||
47 | else | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | EXPORT_SYMBOL(tty_chars_in_buffer); | ||
52 | |||
53 | int tty_write_room(struct tty_struct *tty) | ||
54 | { | ||
55 | if (tty->ops->write_room) | ||
56 | return tty->ops->write_room(tty); | ||
57 | return 2048; | ||
58 | } | ||
59 | |||
60 | EXPORT_SYMBOL(tty_write_room); | ||
61 | |||
62 | void tty_driver_flush_buffer(struct tty_struct *tty) | ||
63 | { | ||
64 | if (tty->ops->flush_buffer) | ||
65 | tty->ops->flush_buffer(tty); | ||
66 | } | ||
67 | |||
68 | EXPORT_SYMBOL(tty_driver_flush_buffer); | ||
69 | |||
70 | |||
43 | /** | 71 | /** |
44 | * tty_wait_until_sent - wait for I/O to finish | 72 | * tty_wait_until_sent - wait for I/O to finish |
45 | * @tty: tty we are waiting for | 73 | * @tty: tty we are waiting for |
@@ -58,17 +86,13 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout) | |||
58 | 86 | ||
59 | printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf)); | 87 | printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf)); |
60 | #endif | 88 | #endif |
61 | if (!tty->driver->chars_in_buffer) | ||
62 | return; | ||
63 | if (!timeout) | 89 | if (!timeout) |
64 | timeout = MAX_SCHEDULE_TIMEOUT; | 90 | timeout = MAX_SCHEDULE_TIMEOUT; |
65 | lock_kernel(); | ||
66 | if (wait_event_interruptible_timeout(tty->write_wait, | 91 | if (wait_event_interruptible_timeout(tty->write_wait, |
67 | !tty->driver->chars_in_buffer(tty), timeout) >= 0) { | 92 | !tty_chars_in_buffer(tty), timeout) >= 0) { |
68 | if (tty->driver->wait_until_sent) | 93 | if (tty->ops->wait_until_sent) |
69 | tty->driver->wait_until_sent(tty, timeout); | 94 | tty->ops->wait_until_sent(tty, timeout); |
70 | } | 95 | } |
71 | unlock_kernel(); | ||
72 | } | 96 | } |
73 | EXPORT_SYMBOL(tty_wait_until_sent); | 97 | EXPORT_SYMBOL(tty_wait_until_sent); |
74 | 98 | ||
@@ -444,8 +468,8 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) | |||
444 | } | 468 | } |
445 | } | 469 | } |
446 | 470 | ||
447 | if (tty->driver->set_termios) | 471 | if (tty->ops->set_termios) |
448 | (*tty->driver->set_termios)(tty, &old_termios); | 472 | (*tty->ops->set_termios)(tty, &old_termios); |
449 | else | 473 | else |
450 | tty_termios_copy_hw(tty->termios, &old_termios); | 474 | tty_termios_copy_hw(tty->termios, &old_termios); |
451 | 475 | ||
@@ -748,8 +772,8 @@ static int send_prio_char(struct tty_struct *tty, char ch) | |||
748 | { | 772 | { |
749 | int was_stopped = tty->stopped; | 773 | int was_stopped = tty->stopped; |
750 | 774 | ||
751 | if (tty->driver->send_xchar) { | 775 | if (tty->ops->send_xchar) { |
752 | tty->driver->send_xchar(tty, ch); | 776 | tty->ops->send_xchar(tty, ch); |
753 | return 0; | 777 | return 0; |
754 | } | 778 | } |
755 | 779 | ||
@@ -758,7 +782,7 @@ static int send_prio_char(struct tty_struct *tty, char ch) | |||
758 | 782 | ||
759 | if (was_stopped) | 783 | if (was_stopped) |
760 | start_tty(tty); | 784 | start_tty(tty); |
761 | tty->driver->write(tty, &ch, 1); | 785 | tty->ops->write(tty, &ch, 1); |
762 | if (was_stopped) | 786 | if (was_stopped) |
763 | stop_tty(tty); | 787 | stop_tty(tty); |
764 | tty_write_unlock(tty); | 788 | tty_write_unlock(tty); |
@@ -778,13 +802,14 @@ static int tty_change_softcar(struct tty_struct *tty, int arg) | |||
778 | { | 802 | { |
779 | int ret = 0; | 803 | int ret = 0; |
780 | int bit = arg ? CLOCAL : 0; | 804 | int bit = arg ? CLOCAL : 0; |
781 | struct ktermios old = *tty->termios; | 805 | struct ktermios old; |
782 | 806 | ||
783 | mutex_lock(&tty->termios_mutex); | 807 | mutex_lock(&tty->termios_mutex); |
808 | old = *tty->termios; | ||
784 | tty->termios->c_cflag &= ~CLOCAL; | 809 | tty->termios->c_cflag &= ~CLOCAL; |
785 | tty->termios->c_cflag |= bit; | 810 | tty->termios->c_cflag |= bit; |
786 | if (tty->driver->set_termios) | 811 | if (tty->ops->set_termios) |
787 | tty->driver->set_termios(tty, &old); | 812 | tty->ops->set_termios(tty, &old); |
788 | if ((tty->termios->c_cflag & CLOCAL) != bit) | 813 | if ((tty->termios->c_cflag & CLOCAL) != bit) |
789 | ret = -EINVAL; | 814 | ret = -EINVAL; |
790 | mutex_unlock(&tty->termios_mutex); | 815 | mutex_unlock(&tty->termios_mutex); |
@@ -926,8 +951,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg) | |||
926 | ld->flush_buffer(tty); | 951 | ld->flush_buffer(tty); |
927 | /* fall through */ | 952 | /* fall through */ |
928 | case TCOFLUSH: | 953 | case TCOFLUSH: |
929 | if (tty->driver->flush_buffer) | 954 | tty_driver_flush_buffer(tty); |
930 | tty->driver->flush_buffer(tty); | ||
931 | break; | 955 | break; |
932 | default: | 956 | default: |
933 | tty_ldisc_deref(ld); | 957 | tty_ldisc_deref(ld); |
@@ -984,9 +1008,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file, | |||
984 | case TCFLSH: | 1008 | case TCFLSH: |
985 | return tty_perform_flush(tty, arg); | 1009 | return tty_perform_flush(tty, arg); |
986 | case TIOCOUTQ: | 1010 | case TIOCOUTQ: |
987 | return put_user(tty->driver->chars_in_buffer ? | 1011 | return put_user(tty_chars_in_buffer(tty), (int __user *) arg); |
988 | tty->driver->chars_in_buffer(tty) : 0, | ||
989 | (int __user *) arg); | ||
990 | case TIOCINQ: | 1012 | case TIOCINQ: |
991 | retval = tty->read_cnt; | 1013 | retval = tty->read_cnt; |
992 | if (L_ICANON(tty)) | 1014 | if (L_ICANON(tty)) |