diff options
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 63 |
1 files changed, 37 insertions, 26 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 26e5e19ed854..6e4be3bb2d89 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -94,6 +94,7 @@ | |||
94 | #include <linux/idr.h> | 94 | #include <linux/idr.h> |
95 | #include <linux/wait.h> | 95 | #include <linux/wait.h> |
96 | #include <linux/bitops.h> | 96 | #include <linux/bitops.h> |
97 | #include <linux/delay.h> | ||
97 | 98 | ||
98 | #include <asm/uaccess.h> | 99 | #include <asm/uaccess.h> |
99 | #include <asm/system.h> | 100 | #include <asm/system.h> |
@@ -251,7 +252,7 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
251 | 252 | ||
252 | static DEFINE_SPINLOCK(tty_ldisc_lock); | 253 | static DEFINE_SPINLOCK(tty_ldisc_lock); |
253 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); | 254 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); |
254 | static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ | 255 | static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ |
255 | 256 | ||
256 | int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) | 257 | int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) |
257 | { | 258 | { |
@@ -262,24 +263,35 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) | |||
262 | return -EINVAL; | 263 | return -EINVAL; |
263 | 264 | ||
264 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 265 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
265 | if (new_ldisc) { | 266 | tty_ldiscs[disc] = *new_ldisc; |
266 | tty_ldiscs[disc] = *new_ldisc; | 267 | tty_ldiscs[disc].num = disc; |
267 | tty_ldiscs[disc].num = disc; | 268 | tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED; |
268 | tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED; | 269 | tty_ldiscs[disc].refcount = 0; |
269 | tty_ldiscs[disc].refcount = 0; | ||
270 | } else { | ||
271 | if(tty_ldiscs[disc].refcount) | ||
272 | ret = -EBUSY; | ||
273 | else | ||
274 | tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED; | ||
275 | } | ||
276 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 270 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
277 | 271 | ||
278 | return ret; | 272 | return ret; |
279 | } | 273 | } |
280 | |||
281 | EXPORT_SYMBOL(tty_register_ldisc); | 274 | EXPORT_SYMBOL(tty_register_ldisc); |
282 | 275 | ||
276 | int tty_unregister_ldisc(int disc) | ||
277 | { | ||
278 | unsigned long flags; | ||
279 | int ret = 0; | ||
280 | |||
281 | if (disc < N_TTY || disc >= NR_LDISCS) | ||
282 | return -EINVAL; | ||
283 | |||
284 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
285 | if (tty_ldiscs[disc].refcount) | ||
286 | ret = -EBUSY; | ||
287 | else | ||
288 | tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED; | ||
289 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
290 | |||
291 | return ret; | ||
292 | } | ||
293 | EXPORT_SYMBOL(tty_unregister_ldisc); | ||
294 | |||
283 | struct tty_ldisc *tty_ldisc_get(int disc) | 295 | struct tty_ldisc *tty_ldisc_get(int disc) |
284 | { | 296 | { |
285 | unsigned long flags; | 297 | unsigned long flags; |
@@ -2169,12 +2181,11 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) | |||
2169 | return tty_set_ldisc(tty, ldisc); | 2181 | return tty_set_ldisc(tty, ldisc); |
2170 | } | 2182 | } |
2171 | 2183 | ||
2172 | static int send_break(struct tty_struct *tty, int duration) | 2184 | static int send_break(struct tty_struct *tty, unsigned int duration) |
2173 | { | 2185 | { |
2174 | tty->driver->break_ctl(tty, -1); | 2186 | tty->driver->break_ctl(tty, -1); |
2175 | if (!signal_pending(current)) { | 2187 | if (!signal_pending(current)) { |
2176 | set_current_state(TASK_INTERRUPTIBLE); | 2188 | msleep_interruptible(duration); |
2177 | schedule_timeout(duration); | ||
2178 | } | 2189 | } |
2179 | tty->driver->break_ctl(tty, 0); | 2190 | tty->driver->break_ctl(tty, 0); |
2180 | if (signal_pending(current)) | 2191 | if (signal_pending(current)) |
@@ -2355,10 +2366,10 @@ int tty_ioctl(struct inode * inode, struct file * file, | |||
2355 | * all by anyone? | 2366 | * all by anyone? |
2356 | */ | 2367 | */ |
2357 | if (!arg) | 2368 | if (!arg) |
2358 | return send_break(tty, HZ/4); | 2369 | return send_break(tty, 250); |
2359 | return 0; | 2370 | return 0; |
2360 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | 2371 | case TCSBRKP: /* support for POSIX tcsendbreak() */ |
2361 | return send_break(tty, arg ? arg*(HZ/10) : HZ/4); | 2372 | return send_break(tty, arg ? arg*100 : 250); |
2362 | 2373 | ||
2363 | case TIOCMGET: | 2374 | case TIOCMGET: |
2364 | return tty_tiocmget(tty, file, p); | 2375 | return tty_tiocmget(tty, file, p); |
@@ -2654,7 +2665,7 @@ static void tty_default_put_char(struct tty_struct *tty, unsigned char ch) | |||
2654 | tty->driver->write(tty, &ch, 1); | 2665 | tty->driver->write(tty, &ch, 1); |
2655 | } | 2666 | } |
2656 | 2667 | ||
2657 | static struct class_simple *tty_class; | 2668 | static struct class *tty_class; |
2658 | 2669 | ||
2659 | /** | 2670 | /** |
2660 | * tty_register_device - register a tty device | 2671 | * tty_register_device - register a tty device |
@@ -2687,7 +2698,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index, | |||
2687 | pty_line_name(driver, index, name); | 2698 | pty_line_name(driver, index, name); |
2688 | else | 2699 | else |
2689 | tty_line_name(driver, index, name); | 2700 | tty_line_name(driver, index, name); |
2690 | class_simple_device_add(tty_class, dev, device, name); | 2701 | class_device_create(tty_class, dev, device, name); |
2691 | } | 2702 | } |
2692 | 2703 | ||
2693 | /** | 2704 | /** |
@@ -2701,7 +2712,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index, | |||
2701 | void tty_unregister_device(struct tty_driver *driver, unsigned index) | 2712 | void tty_unregister_device(struct tty_driver *driver, unsigned index) |
2702 | { | 2713 | { |
2703 | devfs_remove("%s%d", driver->devfs_name, index + driver->name_base); | 2714 | devfs_remove("%s%d", driver->devfs_name, index + driver->name_base); |
2704 | class_simple_device_remove(MKDEV(driver->major, driver->minor_start) + index); | 2715 | class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index); |
2705 | } | 2716 | } |
2706 | 2717 | ||
2707 | EXPORT_SYMBOL(tty_register_device); | 2718 | EXPORT_SYMBOL(tty_register_device); |
@@ -2918,7 +2929,7 @@ extern int vty_init(void); | |||
2918 | 2929 | ||
2919 | static int __init tty_class_init(void) | 2930 | static int __init tty_class_init(void) |
2920 | { | 2931 | { |
2921 | tty_class = class_simple_create(THIS_MODULE, "tty"); | 2932 | tty_class = class_create(THIS_MODULE, "tty"); |
2922 | if (IS_ERR(tty_class)) | 2933 | if (IS_ERR(tty_class)) |
2923 | return PTR_ERR(tty_class); | 2934 | return PTR_ERR(tty_class); |
2924 | return 0; | 2935 | return 0; |
@@ -2947,14 +2958,14 @@ static int __init tty_init(void) | |||
2947 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) | 2958 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) |
2948 | panic("Couldn't register /dev/tty driver\n"); | 2959 | panic("Couldn't register /dev/tty driver\n"); |
2949 | devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty"); | 2960 | devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty"); |
2950 | class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty"); | 2961 | class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty"); |
2951 | 2962 | ||
2952 | cdev_init(&console_cdev, &console_fops); | 2963 | cdev_init(&console_cdev, &console_fops); |
2953 | if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || | 2964 | if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || |
2954 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) | 2965 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) |
2955 | panic("Couldn't register /dev/console driver\n"); | 2966 | panic("Couldn't register /dev/console driver\n"); |
2956 | devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console"); | 2967 | devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console"); |
2957 | class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console"); | 2968 | class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console"); |
2958 | 2969 | ||
2959 | #ifdef CONFIG_UNIX98_PTYS | 2970 | #ifdef CONFIG_UNIX98_PTYS |
2960 | cdev_init(&ptmx_cdev, &ptmx_fops); | 2971 | cdev_init(&ptmx_cdev, &ptmx_fops); |
@@ -2962,7 +2973,7 @@ static int __init tty_init(void) | |||
2962 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) | 2973 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) |
2963 | panic("Couldn't register /dev/ptmx driver\n"); | 2974 | panic("Couldn't register /dev/ptmx driver\n"); |
2964 | devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx"); | 2975 | devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx"); |
2965 | class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); | 2976 | class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); |
2966 | #endif | 2977 | #endif |
2967 | 2978 | ||
2968 | #ifdef CONFIG_VT | 2979 | #ifdef CONFIG_VT |
@@ -2971,7 +2982,7 @@ static int __init tty_init(void) | |||
2971 | register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) | 2982 | register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) |
2972 | panic("Couldn't register /dev/tty0 driver\n"); | 2983 | panic("Couldn't register /dev/tty0 driver\n"); |
2973 | devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0"); | 2984 | devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0"); |
2974 | class_simple_device_add(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); | 2985 | class_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); |
2975 | 2986 | ||
2976 | vty_init(); | 2987 | vty_init(); |
2977 | #endif | 2988 | #endif |