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/tty_io.c | |
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/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 174 |
1 files changed, 72 insertions, 102 deletions
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); |