aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/vt/vt.c93
-rw-r--r--drivers/video/console/fbcon.c29
-rw-r--r--drivers/video/fbmem.c5
-rw-r--r--drivers/video/fbsysfs.c3
-rw-r--r--include/linux/console.h1
5 files changed, 104 insertions, 27 deletions
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 8fd89687d068..c076af0b300b 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -2987,7 +2987,7 @@ int __init vty_init(const struct file_operations *console_fops)
2987 2987
2988static struct class *vtconsole_class; 2988static struct class *vtconsole_class;
2989 2989
2990static int bind_con_driver(const struct consw *csw, int first, int last, 2990static int do_bind_con_driver(const struct consw *csw, int first, int last,
2991 int deflt) 2991 int deflt)
2992{ 2992{
2993 struct module *owner = csw->owner; 2993 struct module *owner = csw->owner;
@@ -2998,7 +2998,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last,
2998 if (!try_module_get(owner)) 2998 if (!try_module_get(owner))
2999 return -ENODEV; 2999 return -ENODEV;
3000 3000
3001 console_lock(); 3001 WARN_CONSOLE_UNLOCKED();
3002 3002
3003 /* check if driver is registered */ 3003 /* check if driver is registered */
3004 for (i = 0; i < MAX_NR_CON_DRIVER; i++) { 3004 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
@@ -3083,11 +3083,22 @@ static int bind_con_driver(const struct consw *csw, int first, int last,
3083 3083
3084 retval = 0; 3084 retval = 0;
3085err: 3085err:
3086 console_unlock();
3087 module_put(owner); 3086 module_put(owner);
3088 return retval; 3087 return retval;
3089}; 3088};
3090 3089
3090
3091static int bind_con_driver(const struct consw *csw, int first, int last,
3092 int deflt)
3093{
3094 int ret;
3095
3096 console_lock();
3097 ret = do_bind_con_driver(csw, first, last, deflt);
3098 console_unlock();
3099 return ret;
3100}
3101
3091#ifdef CONFIG_VT_HW_CONSOLE_BINDING 3102#ifdef CONFIG_VT_HW_CONSOLE_BINDING
3092static int con_is_graphics(const struct consw *csw, int first, int last) 3103static int con_is_graphics(const struct consw *csw, int first, int last)
3093{ 3104{
@@ -3199,9 +3210,9 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
3199 if (!con_is_bound(csw)) 3210 if (!con_is_bound(csw))
3200 con_driver->flag &= ~CON_DRIVER_FLAG_INIT; 3211 con_driver->flag &= ~CON_DRIVER_FLAG_INIT;
3201 3212
3202 console_unlock();
3203 /* ignore return value, binding should not fail */ 3213 /* ignore return value, binding should not fail */
3204 bind_con_driver(defcsw, first, last, deflt); 3214 do_bind_con_driver(defcsw, first, last, deflt);
3215 console_unlock();
3205err: 3216err:
3206 module_put(owner); 3217 module_put(owner);
3207 return retval; 3218 return retval;
@@ -3492,28 +3503,18 @@ int con_debug_leave(void)
3492} 3503}
3493EXPORT_SYMBOL_GPL(con_debug_leave); 3504EXPORT_SYMBOL_GPL(con_debug_leave);
3494 3505
3495/** 3506static int do_register_con_driver(const struct consw *csw, int first, int last)
3496 * register_con_driver - register console driver to console layer
3497 * @csw: console driver
3498 * @first: the first console to take over, minimum value is 0
3499 * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
3500 *
3501 * DESCRIPTION: This function registers a console driver which can later
3502 * bind to a range of consoles specified by @first and @last. It will
3503 * also initialize the console driver by calling con_startup().
3504 */
3505int register_con_driver(const struct consw *csw, int first, int last)
3506{ 3507{
3507 struct module *owner = csw->owner; 3508 struct module *owner = csw->owner;
3508 struct con_driver *con_driver; 3509 struct con_driver *con_driver;
3509 const char *desc; 3510 const char *desc;
3510 int i, retval = 0; 3511 int i, retval = 0;
3511 3512
3513 WARN_CONSOLE_UNLOCKED();
3514
3512 if (!try_module_get(owner)) 3515 if (!try_module_get(owner))
3513 return -ENODEV; 3516 return -ENODEV;
3514 3517
3515 console_lock();
3516
3517 for (i = 0; i < MAX_NR_CON_DRIVER; i++) { 3518 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
3518 con_driver = &registered_con_driver[i]; 3519 con_driver = &registered_con_driver[i];
3519 3520
@@ -3566,10 +3567,29 @@ int register_con_driver(const struct consw *csw, int first, int last)
3566 } 3567 }
3567 3568
3568err: 3569err:
3569 console_unlock();
3570 module_put(owner); 3570 module_put(owner);
3571 return retval; 3571 return retval;
3572} 3572}
3573
3574/**
3575 * register_con_driver - register console driver to console layer
3576 * @csw: console driver
3577 * @first: the first console to take over, minimum value is 0
3578 * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
3579 *
3580 * DESCRIPTION: This function registers a console driver which can later
3581 * bind to a range of consoles specified by @first and @last. It will
3582 * also initialize the console driver by calling con_startup().
3583 */
3584int register_con_driver(const struct consw *csw, int first, int last)
3585{
3586 int retval;
3587
3588 console_lock();
3589 retval = do_register_con_driver(csw, first, last);
3590 console_unlock();
3591 return retval;
3592}
3573EXPORT_SYMBOL(register_con_driver); 3593EXPORT_SYMBOL(register_con_driver);
3574 3594
3575/** 3595/**
@@ -3623,17 +3643,44 @@ EXPORT_SYMBOL(unregister_con_driver);
3623 * when a driver wants to take over some existing consoles 3643 * when a driver wants to take over some existing consoles
3624 * and become default driver for newly opened ones. 3644 * and become default driver for newly opened ones.
3625 * 3645 *
3626 * take_over_console is basically a register followed by unbind 3646 * take_over_console is basically a register followed by unbind
3647 */
3648int do_take_over_console(const struct consw *csw, int first, int last, int deflt)
3649{
3650 int err;
3651
3652 err = do_register_con_driver(csw, first, last);
3653 /*
3654 * If we get an busy error we still want to bind the console driver
3655 * and return success, as we may have unbound the console driver
3656 * but not unregistered it.
3657 */
3658 if (err == -EBUSY)
3659 err = 0;
3660 if (!err)
3661 do_bind_con_driver(csw, first, last, deflt);
3662
3663 return err;
3664}
3665EXPORT_SYMBOL_GPL(do_take_over_console);
3666
3667/*
3668 * If we support more console drivers, this function is used
3669 * when a driver wants to take over some existing consoles
3670 * and become default driver for newly opened ones.
3671 *
3672 * take_over_console is basically a register followed by unbind
3627 */ 3673 */
3628int take_over_console(const struct consw *csw, int first, int last, int deflt) 3674int take_over_console(const struct consw *csw, int first, int last, int deflt)
3629{ 3675{
3630 int err; 3676 int err;
3631 3677
3632 err = register_con_driver(csw, first, last); 3678 err = register_con_driver(csw, first, last);
3633 /* if we get an busy error we still want to bind the console driver 3679 /*
3680 * If we get an busy error we still want to bind the console driver
3634 * and return success, as we may have unbound the console driver 3681 * and return success, as we may have unbound the console driver
3635  * but not unregistered it. 3682 * but not unregistered it.
3636 */ 3683 */
3637 if (err == -EBUSY) 3684 if (err == -EBUSY)
3638 err = 0; 3685 err = 0;
3639 if (!err) 3686 if (!err)
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index fdefa8fd72c4..4bd7820cf4d0 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -529,6 +529,33 @@ static int search_for_mapped_con(void)
529 return retval; 529 return retval;
530} 530}
531 531
532static int do_fbcon_takeover(int show_logo)
533{
534 int err, i;
535
536 if (!num_registered_fb)
537 return -ENODEV;
538
539 if (!show_logo)
540 logo_shown = FBCON_LOGO_DONTSHOW;
541
542 for (i = first_fb_vc; i <= last_fb_vc; i++)
543 con2fb_map[i] = info_idx;
544
545 err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc,
546 fbcon_is_default);
547
548 if (err) {
549 for (i = first_fb_vc; i <= last_fb_vc; i++)
550 con2fb_map[i] = -1;
551 info_idx = -1;
552 } else {
553 fbcon_has_console_bind = 1;
554 }
555
556 return err;
557}
558
532static int fbcon_takeover(int show_logo) 559static int fbcon_takeover(int show_logo)
533{ 560{
534 int err, i; 561 int err, i;
@@ -3115,7 +3142,7 @@ static int fbcon_fb_registered(struct fb_info *info)
3115 } 3142 }
3116 3143
3117 if (info_idx != -1) 3144 if (info_idx != -1)
3118 ret = fbcon_takeover(1); 3145 ret = do_fbcon_takeover(1);
3119 } else { 3146 } else {
3120 for (i = first_fb_vc; i <= last_fb_vc; i++) { 3147 for (i = first_fb_vc; i <= last_fb_vc; i++) {
3121 if (con2fb_map_boot[i] == idx) 3148 if (con2fb_map_boot[i] == idx)
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 3ff0105a496a..d8d9831b3fdb 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1650,7 +1650,9 @@ static int do_register_framebuffer(struct fb_info *fb_info)
1650 event.info = fb_info; 1650 event.info = fb_info;
1651 if (!lock_fb_info(fb_info)) 1651 if (!lock_fb_info(fb_info))
1652 return -ENODEV; 1652 return -ENODEV;
1653 console_lock();
1653 fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); 1654 fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
1655 console_unlock();
1654 unlock_fb_info(fb_info); 1656 unlock_fb_info(fb_info);
1655 return 0; 1657 return 0;
1656} 1658}
@@ -1853,11 +1855,8 @@ int fb_new_modelist(struct fb_info *info)
1853 err = 1; 1855 err = 1;
1854 1856
1855 if (!list_empty(&info->modelist)) { 1857 if (!list_empty(&info->modelist)) {
1856 if (!lock_fb_info(info))
1857 return -ENODEV;
1858 event.info = info; 1858 event.info = info;
1859 err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); 1859 err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event);
1860 unlock_fb_info(info);
1861 } 1860 }
1862 1861
1863 return err; 1862 return err;
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index a55e3669d135..ef476b02fbe5 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -177,6 +177,8 @@ static ssize_t store_modes(struct device *device,
177 if (i * sizeof(struct fb_videomode) != count) 177 if (i * sizeof(struct fb_videomode) != count)
178 return -EINVAL; 178 return -EINVAL;
179 179
180 if (!lock_fb_info(fb_info))
181 return -ENODEV;
180 console_lock(); 182 console_lock();
181 list_splice(&fb_info->modelist, &old_list); 183 list_splice(&fb_info->modelist, &old_list);
182 fb_videomode_to_modelist((const struct fb_videomode *)buf, i, 184 fb_videomode_to_modelist((const struct fb_videomode *)buf, i,
@@ -188,6 +190,7 @@ static ssize_t store_modes(struct device *device,
188 fb_destroy_modelist(&old_list); 190 fb_destroy_modelist(&old_list);
189 191
190 console_unlock(); 192 console_unlock();
193 unlock_fb_info(fb_info);
191 194
192 return 0; 195 return 0;
193} 196}
diff --git a/include/linux/console.h b/include/linux/console.h
index dedb082fe50f..4ef4307dfb82 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -78,6 +78,7 @@ int con_is_bound(const struct consw *csw);
78int register_con_driver(const struct consw *csw, int first, int last); 78int register_con_driver(const struct consw *csw, int first, int last);
79int unregister_con_driver(const struct consw *csw); 79int unregister_con_driver(const struct consw *csw);
80int take_over_console(const struct consw *sw, int first, int last, int deflt); 80int take_over_console(const struct consw *sw, int first, int last, int deflt);
81int do_take_over_console(const struct consw *sw, int first, int last, int deflt);
81void give_up_console(const struct consw *sw); 82void give_up_console(const struct consw *sw);
82#ifdef CONFIG_HW_CONSOLE 83#ifdef CONFIG_HW_CONSOLE
83int con_debug_enter(struct vc_data *vc); 84int con_debug_enter(struct vc_data *vc);