diff options
Diffstat (limited to 'drivers/char/tty_io.c')
| -rw-r--r-- | drivers/char/tty_io.c | 92 |
1 files changed, 37 insertions, 55 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 8b2a59969868..a1143238feca 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
| @@ -102,7 +102,6 @@ | |||
| 102 | #include <linux/kbd_kern.h> | 102 | #include <linux/kbd_kern.h> |
| 103 | #include <linux/vt_kern.h> | 103 | #include <linux/vt_kern.h> |
| 104 | #include <linux/selection.h> | 104 | #include <linux/selection.h> |
| 105 | #include <linux/devfs_fs_kernel.h> | ||
| 106 | 105 | ||
| 107 | #include <linux/kmod.h> | 106 | #include <linux/kmod.h> |
| 108 | 107 | ||
| @@ -267,7 +266,6 @@ static struct tty_buffer *tty_buffer_alloc(size_t size) | |||
| 267 | p->used = 0; | 266 | p->used = 0; |
| 268 | p->size = size; | 267 | p->size = size; |
| 269 | p->next = NULL; | 268 | p->next = NULL; |
| 270 | p->active = 0; | ||
| 271 | p->commit = 0; | 269 | p->commit = 0; |
| 272 | p->read = 0; | 270 | p->read = 0; |
| 273 | p->char_buf_ptr = (char *)(p->data); | 271 | p->char_buf_ptr = (char *)(p->data); |
| @@ -327,10 +325,9 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
| 327 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to | 325 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to |
| 328 | remove this conditional if its worth it. This would be invisible | 326 | remove this conditional if its worth it. This would be invisible |
| 329 | to the callers */ | 327 | to the callers */ |
| 330 | if ((b = tty->buf.tail) != NULL) { | 328 | if ((b = tty->buf.tail) != NULL) |
| 331 | left = b->size - b->used; | 329 | left = b->size - b->used; |
| 332 | b->active = 1; | 330 | else |
| 333 | } else | ||
| 334 | left = 0; | 331 | left = 0; |
| 335 | 332 | ||
| 336 | if (left < size) { | 333 | if (left < size) { |
| @@ -338,12 +335,10 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) | |||
| 338 | if ((n = tty_buffer_find(tty, size)) != NULL) { | 335 | if ((n = tty_buffer_find(tty, size)) != NULL) { |
| 339 | if (b != NULL) { | 336 | if (b != NULL) { |
| 340 | b->next = n; | 337 | b->next = n; |
| 341 | b->active = 0; | ||
| 342 | b->commit = b->used; | 338 | b->commit = b->used; |
| 343 | } else | 339 | } else |
| 344 | tty->buf.head = n; | 340 | tty->buf.head = n; |
| 345 | tty->buf.tail = n; | 341 | tty->buf.tail = n; |
| 346 | n->active = 1; | ||
| 347 | } else | 342 | } else |
| 348 | size = left; | 343 | size = left; |
| 349 | } | 344 | } |
| @@ -404,10 +399,8 @@ void tty_schedule_flip(struct tty_struct *tty) | |||
| 404 | { | 399 | { |
| 405 | unsigned long flags; | 400 | unsigned long flags; |
| 406 | spin_lock_irqsave(&tty->buf.lock, flags); | 401 | spin_lock_irqsave(&tty->buf.lock, flags); |
| 407 | if (tty->buf.tail != NULL) { | 402 | if (tty->buf.tail != NULL) |
| 408 | tty->buf.tail->active = 0; | ||
| 409 | tty->buf.tail->commit = tty->buf.tail->used; | 403 | tty->buf.tail->commit = tty->buf.tail->used; |
| 410 | } | ||
| 411 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 404 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
| 412 | schedule_delayed_work(&tty->buf.work, 1); | 405 | schedule_delayed_work(&tty->buf.work, 1); |
| 413 | } | 406 | } |
| @@ -784,11 +777,8 @@ restart: | |||
| 784 | } | 777 | } |
| 785 | 778 | ||
| 786 | clear_bit(TTY_LDISC, &tty->flags); | 779 | clear_bit(TTY_LDISC, &tty->flags); |
| 787 | clear_bit(TTY_DONT_FLIP, &tty->flags); | 780 | if (o_tty) |
| 788 | if (o_tty) { | ||
| 789 | clear_bit(TTY_LDISC, &o_tty->flags); | 781 | clear_bit(TTY_LDISC, &o_tty->flags); |
| 790 | clear_bit(TTY_DONT_FLIP, &o_tty->flags); | ||
| 791 | } | ||
| 792 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 782 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
| 793 | 783 | ||
| 794 | /* | 784 | /* |
| @@ -1955,7 +1945,6 @@ static void release_dev(struct file * filp) | |||
| 1955 | * race with the set_ldisc code path. | 1945 | * race with the set_ldisc code path. |
| 1956 | */ | 1946 | */ |
| 1957 | clear_bit(TTY_LDISC, &tty->flags); | 1947 | clear_bit(TTY_LDISC, &tty->flags); |
| 1958 | clear_bit(TTY_DONT_FLIP, &tty->flags); | ||
| 1959 | cancel_delayed_work(&tty->buf.work); | 1948 | cancel_delayed_work(&tty->buf.work); |
| 1960 | 1949 | ||
| 1961 | /* | 1950 | /* |
| @@ -2621,10 +2610,9 @@ int tty_ioctl(struct inode * inode, struct file * file, | |||
| 2621 | tty->driver->break_ctl(tty, 0); | 2610 | tty->driver->break_ctl(tty, 0); |
| 2622 | return 0; | 2611 | return 0; |
| 2623 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | 2612 | case TCSBRK: /* SVID version: non-zero arg --> no break */ |
| 2624 | /* | 2613 | /* non-zero arg means wait for all output data |
| 2625 | * XXX is the above comment correct, or the | 2614 | * to be sent (performed above) but don't send break. |
| 2626 | * code below correct? Is this ioctl used at | 2615 | * This is used by the tcdrain() termios function. |
| 2627 | * all by anyone? | ||
| 2628 | */ | 2616 | */ |
| 2629 | if (!arg) | 2617 | if (!arg) |
| 2630 | return send_break(tty, 250); | 2618 | return send_break(tty, 250); |
| @@ -2776,8 +2764,7 @@ static void flush_to_ldisc(void *private_) | |||
| 2776 | struct tty_struct *tty = (struct tty_struct *) private_; | 2764 | struct tty_struct *tty = (struct tty_struct *) private_; |
| 2777 | unsigned long flags; | 2765 | unsigned long flags; |
| 2778 | struct tty_ldisc *disc; | 2766 | struct tty_ldisc *disc; |
| 2779 | struct tty_buffer *tbuf; | 2767 | struct tty_buffer *tbuf, *head; |
| 2780 | int count; | ||
| 2781 | char *char_buf; | 2768 | char *char_buf; |
| 2782 | unsigned char *flag_buf; | 2769 | unsigned char *flag_buf; |
| 2783 | 2770 | ||
| @@ -2785,32 +2772,37 @@ static void flush_to_ldisc(void *private_) | |||
| 2785 | if (disc == NULL) /* !TTY_LDISC */ | 2772 | if (disc == NULL) /* !TTY_LDISC */ |
| 2786 | return; | 2773 | return; |
| 2787 | 2774 | ||
| 2788 | if (test_bit(TTY_DONT_FLIP, &tty->flags)) { | ||
| 2789 | /* | ||
| 2790 | * Do it after the next timer tick: | ||
| 2791 | */ | ||
| 2792 | schedule_delayed_work(&tty->buf.work, 1); | ||
| 2793 | goto out; | ||
| 2794 | } | ||
| 2795 | spin_lock_irqsave(&tty->buf.lock, flags); | 2775 | spin_lock_irqsave(&tty->buf.lock, flags); |
| 2796 | while((tbuf = tty->buf.head) != NULL) { | 2776 | head = tty->buf.head; |
| 2797 | while ((count = tbuf->commit - tbuf->read) != 0) { | 2777 | if (head != NULL) { |
| 2798 | char_buf = tbuf->char_buf_ptr + tbuf->read; | 2778 | tty->buf.head = NULL; |
| 2799 | flag_buf = tbuf->flag_buf_ptr + tbuf->read; | 2779 | for (;;) { |
| 2800 | tbuf->read += count; | 2780 | int count = head->commit - head->read; |
| 2781 | if (!count) { | ||
| 2782 | if (head->next == NULL) | ||
| 2783 | break; | ||
| 2784 | tbuf = head; | ||
| 2785 | head = head->next; | ||
| 2786 | tty_buffer_free(tty, tbuf); | ||
| 2787 | continue; | ||
| 2788 | } | ||
| 2789 | if (!tty->receive_room) { | ||
| 2790 | schedule_delayed_work(&tty->buf.work, 1); | ||
| 2791 | break; | ||
| 2792 | } | ||
| 2793 | if (count > tty->receive_room) | ||
| 2794 | count = tty->receive_room; | ||
| 2795 | char_buf = head->char_buf_ptr + head->read; | ||
| 2796 | flag_buf = head->flag_buf_ptr + head->read; | ||
| 2797 | head->read += count; | ||
| 2801 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 2798 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
| 2802 | disc->receive_buf(tty, char_buf, flag_buf, count); | 2799 | disc->receive_buf(tty, char_buf, flag_buf, count); |
| 2803 | spin_lock_irqsave(&tty->buf.lock, flags); | 2800 | spin_lock_irqsave(&tty->buf.lock, flags); |
| 2804 | } | 2801 | } |
| 2805 | if (tbuf->active) | 2802 | tty->buf.head = head; |
| 2806 | break; | ||
| 2807 | tty->buf.head = tbuf->next; | ||
| 2808 | if (tty->buf.head == NULL) | ||
| 2809 | tty->buf.tail = NULL; | ||
| 2810 | tty_buffer_free(tty, tbuf); | ||
| 2811 | } | 2803 | } |
| 2812 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 2804 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
| 2813 | out: | 2805 | |
| 2814 | tty_ldisc_deref(disc); | 2806 | tty_ldisc_deref(disc); |
| 2815 | } | 2807 | } |
| 2816 | 2808 | ||
| @@ -2903,10 +2895,8 @@ void tty_flip_buffer_push(struct tty_struct *tty) | |||
| 2903 | { | 2895 | { |
| 2904 | unsigned long flags; | 2896 | unsigned long flags; |
| 2905 | spin_lock_irqsave(&tty->buf.lock, flags); | 2897 | spin_lock_irqsave(&tty->buf.lock, flags); |
| 2906 | if (tty->buf.tail != NULL) { | 2898 | if (tty->buf.tail != NULL) |
| 2907 | tty->buf.tail->active = 0; | ||
| 2908 | tty->buf.tail->commit = tty->buf.tail->used; | 2899 | tty->buf.tail->commit = tty->buf.tail->used; |
| 2909 | } | ||
| 2910 | spin_unlock_irqrestore(&tty->buf.lock, flags); | 2900 | spin_unlock_irqrestore(&tty->buf.lock, flags); |
| 2911 | 2901 | ||
| 2912 | if (tty->low_latency) | 2902 | if (tty->low_latency) |
| @@ -2964,8 +2954,8 @@ static struct class *tty_class; | |||
| 2964 | * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error). | 2954 | * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error). |
| 2965 | * | 2955 | * |
| 2966 | * This call is required to be made to register an individual tty device if | 2956 | * This call is required to be made to register an individual tty device if |
| 2967 | * the tty driver's flags have the TTY_DRIVER_NO_DEVFS bit set. If that | 2957 | * the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If that |
| 2968 | * bit is not set, this function should not be called. | 2958 | * bit is not set, this function should not be called by a tty driver. |
| 2969 | */ | 2959 | */ |
| 2970 | struct class_device *tty_register_device(struct tty_driver *driver, | 2960 | struct class_device *tty_register_device(struct tty_driver *driver, |
| 2971 | unsigned index, struct device *device) | 2961 | unsigned index, struct device *device) |
| @@ -2979,9 +2969,6 @@ struct class_device *tty_register_device(struct tty_driver *driver, | |||
| 2979 | return ERR_PTR(-EINVAL); | 2969 | return ERR_PTR(-EINVAL); |
| 2980 | } | 2970 | } |
| 2981 | 2971 | ||
| 2982 | devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, | ||
| 2983 | "%s%d", driver->devfs_name, index + driver->name_base); | ||
| 2984 | |||
| 2985 | if (driver->type == TTY_DRIVER_TYPE_PTY) | 2972 | if (driver->type == TTY_DRIVER_TYPE_PTY) |
| 2986 | pty_line_name(driver, index, name); | 2973 | pty_line_name(driver, index, name); |
| 2987 | else | 2974 | else |
| @@ -3000,7 +2987,6 @@ struct class_device *tty_register_device(struct tty_driver *driver, | |||
| 3000 | */ | 2987 | */ |
| 3001 | void tty_unregister_device(struct tty_driver *driver, unsigned index) | 2988 | void tty_unregister_device(struct tty_driver *driver, unsigned index) |
| 3002 | { | 2989 | { |
| 3003 | devfs_remove("%s%d", driver->devfs_name, index + driver->name_base); | ||
| 3004 | class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index); | 2990 | class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index); |
| 3005 | } | 2991 | } |
| 3006 | 2992 | ||
| @@ -3122,7 +3108,7 @@ int tty_register_driver(struct tty_driver *driver) | |||
| 3122 | 3108 | ||
| 3123 | list_add(&driver->tty_drivers, &tty_drivers); | 3109 | list_add(&driver->tty_drivers, &tty_drivers); |
| 3124 | 3110 | ||
| 3125 | if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) { | 3111 | if ( !(driver->flags & TTY_DRIVER_DYNAMIC_DEV) ) { |
| 3126 | for(i = 0; i < driver->num; i++) | 3112 | for(i = 0; i < driver->num; i++) |
| 3127 | tty_register_device(driver, i, NULL); | 3113 | tty_register_device(driver, i, NULL); |
| 3128 | } | 3114 | } |
| @@ -3165,7 +3151,7 @@ int tty_unregister_driver(struct tty_driver *driver) | |||
| 3165 | driver->termios_locked[i] = NULL; | 3151 | driver->termios_locked[i] = NULL; |
| 3166 | kfree(tp); | 3152 | kfree(tp); |
| 3167 | } | 3153 | } |
| 3168 | if (!(driver->flags & TTY_DRIVER_NO_DEVFS)) | 3154 | if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) |
| 3169 | tty_unregister_device(driver, i); | 3155 | tty_unregister_device(driver, i); |
| 3170 | } | 3156 | } |
| 3171 | p = driver->ttys; | 3157 | p = driver->ttys; |
| @@ -3241,14 +3227,12 @@ static int __init tty_init(void) | |||
| 3241 | if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || | 3227 | if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || |
| 3242 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) | 3228 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) |
| 3243 | panic("Couldn't register /dev/tty driver\n"); | 3229 | panic("Couldn't register /dev/tty driver\n"); |
| 3244 | devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty"); | ||
| 3245 | class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty"); | 3230 | class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty"); |
| 3246 | 3231 | ||
| 3247 | cdev_init(&console_cdev, &console_fops); | 3232 | cdev_init(&console_cdev, &console_fops); |
| 3248 | if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || | 3233 | if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || |
| 3249 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) | 3234 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) |
| 3250 | panic("Couldn't register /dev/console driver\n"); | 3235 | panic("Couldn't register /dev/console driver\n"); |
| 3251 | devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console"); | ||
| 3252 | class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console"); | 3236 | class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console"); |
| 3253 | 3237 | ||
| 3254 | #ifdef CONFIG_UNIX98_PTYS | 3238 | #ifdef CONFIG_UNIX98_PTYS |
| @@ -3256,7 +3240,6 @@ static int __init tty_init(void) | |||
| 3256 | if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || | 3240 | if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || |
| 3257 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) | 3241 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) |
| 3258 | panic("Couldn't register /dev/ptmx driver\n"); | 3242 | panic("Couldn't register /dev/ptmx driver\n"); |
| 3259 | devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx"); | ||
| 3260 | class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); | 3243 | class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); |
| 3261 | #endif | 3244 | #endif |
| 3262 | 3245 | ||
| @@ -3265,7 +3248,6 @@ static int __init tty_init(void) | |||
| 3265 | if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || | 3248 | if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || |
| 3266 | register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) | 3249 | register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) |
| 3267 | panic("Couldn't register /dev/tty0 driver\n"); | 3250 | panic("Couldn't register /dev/tty0 driver\n"); |
| 3268 | devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0"); | ||
| 3269 | class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); | 3251 | class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); |
| 3270 | 3252 | ||
| 3271 | vty_init(); | 3253 | vty_init(); |
