diff options
-rw-r--r-- | drivers/tty/vt/vt.c | 93 | ||||
-rw-r--r-- | drivers/video/console/fbcon.c | 29 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 5 | ||||
-rw-r--r-- | drivers/video/fbsysfs.c | 3 | ||||
-rw-r--r-- | include/linux/console.h | 1 |
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 | ||
2988 | static struct class *vtconsole_class; | 2988 | static struct class *vtconsole_class; |
2989 | 2989 | ||
2990 | static int bind_con_driver(const struct consw *csw, int first, int last, | 2990 | static 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; |
3085 | err: | 3085 | err: |
3086 | console_unlock(); | ||
3087 | module_put(owner); | 3086 | module_put(owner); |
3088 | return retval; | 3087 | return retval; |
3089 | }; | 3088 | }; |
3090 | 3089 | ||
3090 | |||
3091 | static 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 |
3092 | static int con_is_graphics(const struct consw *csw, int first, int last) | 3103 | static 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(); | ||
3205 | err: | 3216 | err: |
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 | } |
3493 | EXPORT_SYMBOL_GPL(con_debug_leave); | 3504 | EXPORT_SYMBOL_GPL(con_debug_leave); |
3494 | 3505 | ||
3495 | /** | 3506 | static 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 | */ | ||
3505 | int 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 = ®istered_con_driver[i]; | 3519 | con_driver = ®istered_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 | ||
3568 | err: | 3569 | err: |
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 | */ | ||
3584 | int 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 | } | ||
3573 | EXPORT_SYMBOL(register_con_driver); | 3593 | EXPORT_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 | */ | ||
3648 | int 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 | } | ||
3665 | EXPORT_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 | */ |
3628 | int take_over_console(const struct consw *csw, int first, int last, int deflt) | 3674 | int 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 | ||
532 | static 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 | |||
532 | static int fbcon_takeover(int show_logo) | 559 | static 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); | |||
78 | int register_con_driver(const struct consw *csw, int first, int last); | 78 | int register_con_driver(const struct consw *csw, int first, int last); |
79 | int unregister_con_driver(const struct consw *csw); | 79 | int unregister_con_driver(const struct consw *csw); |
80 | int take_over_console(const struct consw *sw, int first, int last, int deflt); | 80 | int take_over_console(const struct consw *sw, int first, int last, int deflt); |
81 | int do_take_over_console(const struct consw *sw, int first, int last, int deflt); | ||
81 | void give_up_console(const struct consw *sw); | 82 | void give_up_console(const struct consw *sw); |
82 | #ifdef CONFIG_HW_CONSOLE | 83 | #ifdef CONFIG_HW_CONSOLE |
83 | int con_debug_enter(struct vc_data *vc); | 84 | int con_debug_enter(struct vc_data *vc); |