aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/vt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/vt.c')
-rw-r--r--drivers/char/vt.c89
1 files changed, 33 insertions, 56 deletions
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 60359c360912..a0f7ffb68087 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -100,10 +100,10 @@
100#include <linux/font.h> 100#include <linux/font.h>
101#include <linux/bitops.h> 101#include <linux/bitops.h>
102#include <linux/notifier.h> 102#include <linux/notifier.h>
103 103#include <linux/device.h>
104#include <asm/io.h> 104#include <linux/io.h>
105#include <asm/system.h> 105#include <asm/system.h>
106#include <asm/uaccess.h> 106#include <linux/uaccess.h>
107 107
108#define MAX_NR_CON_DRIVER 16 108#define MAX_NR_CON_DRIVER 16
109 109
@@ -301,7 +301,7 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
301 d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t); 301 d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
302 s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr)); 302 s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
303 scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row); 303 scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
304 scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_scrl_erase_char, 304 scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
305 vc->vc_size_row * nr); 305 vc->vc_size_row * nr);
306} 306}
307 307
@@ -319,7 +319,7 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
319 s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t); 319 s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
320 step = vc->vc_cols * nr; 320 step = vc->vc_cols * nr;
321 scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row); 321 scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
322 scr_memsetw(s, vc->vc_scrl_erase_char, 2 * step); 322 scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
323} 323}
324 324
325static void do_update_region(struct vc_data *vc, unsigned long start, int count) 325static void do_update_region(struct vc_data *vc, unsigned long start, int count)
@@ -434,7 +434,6 @@ static void update_attr(struct vc_data *vc)
434 vc->vc_blink, vc->vc_underline, 434 vc->vc_blink, vc->vc_underline,
435 vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic); 435 vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
436 vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' '; 436 vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
437 vc->vc_scrl_erase_char = (build_attr(vc, vc->vc_def_color, 1, false, false, vc->vc_decscnm, false) << 8) | ' ';
438} 437}
439 438
440/* Note: inverting the screen twice should revert to the original state */ 439/* Note: inverting the screen twice should revert to the original state */
@@ -2136,27 +2135,9 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
2136 release_console_sem(); 2135 release_console_sem();
2137 return 0; 2136 return 0;
2138 } 2137 }
2139 release_console_sem();
2140
2141 orig_buf = buf; 2138 orig_buf = buf;
2142 orig_count = count; 2139 orig_count = count;
2143 2140
2144 /* At this point 'buf' is guaranteed to be a kernel buffer
2145 * and therefore no access to userspace (and therefore sleeping)
2146 * will be needed. The con_buf_mtx serializes all tty based
2147 * console rendering and vcs write/read operations. We hold
2148 * the console spinlock during the entire write.
2149 */
2150
2151 acquire_console_sem();
2152
2153 vc = tty->driver_data;
2154 if (vc == NULL) {
2155 printk(KERN_ERR "vt: argh, driver_data _became_ NULL !\n");
2156 release_console_sem();
2157 goto out;
2158 }
2159
2160 himask = vc->vc_hi_font_mask; 2141 himask = vc->vc_hi_font_mask;
2161 charmask = himask ? 0x1ff : 0xff; 2142 charmask = himask ? 0x1ff : 0xff;
2162 2143
@@ -2370,8 +2351,6 @@ rescan_last_byte:
2370 FLUSH 2351 FLUSH
2371 console_conditional_schedule(); 2352 console_conditional_schedule();
2372 release_console_sem(); 2353 release_console_sem();
2373
2374out:
2375 notify_update(vc); 2354 notify_update(vc);
2376 return n; 2355 return n;
2377#undef FLUSH 2356#undef FLUSH
@@ -2583,8 +2562,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
2583 int lines; 2562 int lines;
2584 int ret; 2563 int ret;
2585 2564
2586 if (tty->driver->type != TTY_DRIVER_TYPE_CONSOLE)
2587 return -EINVAL;
2588 if (current->signal->tty != tty && !capable(CAP_SYS_ADMIN)) 2565 if (current->signal->tty != tty && !capable(CAP_SYS_ADMIN))
2589 return -EPERM; 2566 return -EPERM;
2590 if (get_user(type, p)) 2567 if (get_user(type, p))
@@ -2778,6 +2755,12 @@ static int con_open(struct tty_struct *tty, struct file *filp)
2778 ret = vc_allocate(currcons); 2755 ret = vc_allocate(currcons);
2779 if (ret == 0) { 2756 if (ret == 0) {
2780 struct vc_data *vc = vc_cons[currcons].d; 2757 struct vc_data *vc = vc_cons[currcons].d;
2758
2759 /* Still being freed */
2760 if (vc->vc_tty) {
2761 release_console_sem();
2762 return -ERESTARTSYS;
2763 }
2781 tty->driver_data = vc; 2764 tty->driver_data = vc;
2782 vc->vc_tty = tty; 2765 vc->vc_tty = tty;
2783 2766
@@ -2798,34 +2781,20 @@ static int con_open(struct tty_struct *tty, struct file *filp)
2798 return ret; 2781 return ret;
2799} 2782}
2800 2783
2801/*
2802 * We take tty_mutex in here to prevent another thread from coming in via init_dev
2803 * and taking a ref against the tty while we're in the process of forgetting
2804 * about it and cleaning things up.
2805 *
2806 * This is because vcs_remove_sysfs() can sleep and will drop the BKL.
2807 */
2808static void con_close(struct tty_struct *tty, struct file *filp) 2784static void con_close(struct tty_struct *tty, struct file *filp)
2809{ 2785{
2810 mutex_lock(&tty_mutex); 2786 /* Nothing to do - we defer to shutdown */
2811 acquire_console_sem(); 2787}
2812 if (tty && tty->count == 1) {
2813 struct vc_data *vc = tty->driver_data;
2814 2788
2815 if (vc) 2789static void con_shutdown(struct tty_struct *tty)
2816 vc->vc_tty = NULL; 2790{
2817 tty->driver_data = NULL; 2791 struct vc_data *vc = tty->driver_data;
2818 vcs_remove_sysfs(tty); 2792 BUG_ON(vc == NULL);
2819 release_console_sem(); 2793 acquire_console_sem();
2820 mutex_unlock(&tty_mutex); 2794 vc->vc_tty = NULL;
2821 /* 2795 vcs_remove_sysfs(tty);
2822 * tty_mutex is released, but we still hold BKL, so there is
2823 * still exclusion against init_dev()
2824 */
2825 return;
2826 }
2827 release_console_sem(); 2796 release_console_sem();
2828 mutex_unlock(&tty_mutex); 2797 tty_shutdown(tty);
2829} 2798}
2830 2799
2831static int default_italic_color = 2; // green (ASCII) 2800static int default_italic_color = 2; // green (ASCII)
@@ -2950,10 +2919,19 @@ static const struct tty_operations con_ops = {
2950 .throttle = con_throttle, 2919 .throttle = con_throttle,
2951 .unthrottle = con_unthrottle, 2920 .unthrottle = con_unthrottle,
2952 .resize = vt_resize, 2921 .resize = vt_resize,
2922 .shutdown = con_shutdown
2953}; 2923};
2954 2924
2955int __init vty_init(void) 2925static struct cdev vc0_cdev;
2926
2927int __init vty_init(const struct file_operations *console_fops)
2956{ 2928{
2929 cdev_init(&vc0_cdev, console_fops);
2930 if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
2931 register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
2932 panic("Couldn't register /dev/tty0 driver\n");
2933 device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
2934
2957 vcs_init(); 2935 vcs_init();
2958 2936
2959 console_driver = alloc_tty_driver(MAX_NR_CONSOLES); 2937 console_driver = alloc_tty_driver(MAX_NR_CONSOLES);
@@ -2972,7 +2950,6 @@ int __init vty_init(void)
2972 tty_set_operations(console_driver, &con_ops); 2950 tty_set_operations(console_driver, &con_ops);
2973 if (tty_register_driver(console_driver)) 2951 if (tty_register_driver(console_driver))
2974 panic("Couldn't register console driver\n"); 2952 panic("Couldn't register console driver\n");
2975
2976 kbd_init(); 2953 kbd_init();
2977 console_map_init(); 2954 console_map_init();
2978#ifdef CONFIG_PROM_CONSOLE 2955#ifdef CONFIG_PROM_CONSOLE
@@ -3466,7 +3443,7 @@ int register_con_driver(const struct consw *csw, int first, int last)
3466 if (retval) 3443 if (retval)
3467 goto err; 3444 goto err;
3468 3445
3469 con_driver->dev = device_create_drvdata(vtconsole_class, NULL, 3446 con_driver->dev = device_create(vtconsole_class, NULL,
3470 MKDEV(0, con_driver->node), 3447 MKDEV(0, con_driver->node),
3471 NULL, "vtcon%i", 3448 NULL, "vtcon%i",
3472 con_driver->node); 3449 con_driver->node);
@@ -3577,7 +3554,7 @@ static int __init vtconsole_class_init(void)
3577 struct con_driver *con = &registered_con_driver[i]; 3554 struct con_driver *con = &registered_con_driver[i];
3578 3555
3579 if (con->con && !con->dev) { 3556 if (con->con && !con->dev) {
3580 con->dev = device_create_drvdata(vtconsole_class, NULL, 3557 con->dev = device_create(vtconsole_class, NULL,
3581 MKDEV(0, con->node), 3558 MKDEV(0, con->node),
3582 NULL, "vtcon%i", 3559 NULL, "vtcon%i",
3583 con->node); 3560 con->node);