aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/n_tty.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2008-04-30 03:54:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 11:29:47 -0400
commitf34d7a5b7010b82fe97da95496b9971435530062 (patch)
tree87e2abec1e33ed4fe5e63ee2fd000bc2ad745e57 /drivers/char/n_tty.c
parent251b8dd7eee30fda089a1dc088abf4fc9a0dee9c (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/n_tty.c')
-rw-r--r--drivers/char/n_tty.c103
1 files changed, 43 insertions, 60 deletions
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 }
392break_out: 392break_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
409static 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)
423static void echo_char(unsigned char c, struct tty_struct *tty) 410static 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)
433static inline void finish_erasing(struct tty_struct *tty) 420static 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
1564static unsigned int normal_poll(struct tty_struct *tty, struct file *file, 1547static 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}