diff options
Diffstat (limited to 'drivers/tty/vt/vt.c')
-rw-r--r-- | drivers/tty/vt/vt.c | 134 |
1 files changed, 97 insertions, 37 deletions
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index b3915b7ad3e..e41288a0003 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c | |||
@@ -3016,7 +3016,7 @@ int __init vty_init(const struct file_operations *console_fops) | |||
3016 | 3016 | ||
3017 | static struct class *vtconsole_class; | 3017 | static struct class *vtconsole_class; |
3018 | 3018 | ||
3019 | static int bind_con_driver(const struct consw *csw, int first, int last, | 3019 | static int do_bind_con_driver(const struct consw *csw, int first, int last, |
3020 | int deflt) | 3020 | int deflt) |
3021 | { | 3021 | { |
3022 | struct module *owner = csw->owner; | 3022 | struct module *owner = csw->owner; |
@@ -3027,7 +3027,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last, | |||
3027 | if (!try_module_get(owner)) | 3027 | if (!try_module_get(owner)) |
3028 | return -ENODEV; | 3028 | return -ENODEV; |
3029 | 3029 | ||
3030 | console_lock(); | 3030 | WARN_CONSOLE_UNLOCKED(); |
3031 | 3031 | ||
3032 | /* check if driver is registered */ | 3032 | /* check if driver is registered */ |
3033 | for (i = 0; i < MAX_NR_CON_DRIVER; i++) { | 3033 | for (i = 0; i < MAX_NR_CON_DRIVER; i++) { |
@@ -3112,11 +3112,22 @@ static int bind_con_driver(const struct consw *csw, int first, int last, | |||
3112 | 3112 | ||
3113 | retval = 0; | 3113 | retval = 0; |
3114 | err: | 3114 | err: |
3115 | console_unlock(); | ||
3116 | module_put(owner); | 3115 | module_put(owner); |
3117 | return retval; | 3116 | return retval; |
3118 | }; | 3117 | }; |
3119 | 3118 | ||
3119 | |||
3120 | static int bind_con_driver(const struct consw *csw, int first, int last, | ||
3121 | int deflt) | ||
3122 | { | ||
3123 | int ret; | ||
3124 | |||
3125 | console_lock(); | ||
3126 | ret = do_bind_con_driver(csw, first, last, deflt); | ||
3127 | console_unlock(); | ||
3128 | return ret; | ||
3129 | } | ||
3130 | |||
3120 | #ifdef CONFIG_VT_HW_CONSOLE_BINDING | 3131 | #ifdef CONFIG_VT_HW_CONSOLE_BINDING |
3121 | static int con_is_graphics(const struct consw *csw, int first, int last) | 3132 | static int con_is_graphics(const struct consw *csw, int first, int last) |
3122 | { | 3133 | { |
@@ -3153,6 +3164,18 @@ static int con_is_graphics(const struct consw *csw, int first, int last) | |||
3153 | */ | 3164 | */ |
3154 | int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | 3165 | int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) |
3155 | { | 3166 | { |
3167 | int retval; | ||
3168 | |||
3169 | console_lock(); | ||
3170 | retval = do_unbind_con_driver(csw, first, last, deflt); | ||
3171 | console_unlock(); | ||
3172 | return retval; | ||
3173 | } | ||
3174 | EXPORT_SYMBOL(unbind_con_driver); | ||
3175 | |||
3176 | /* unlocked version of unbind_con_driver() */ | ||
3177 | int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | ||
3178 | { | ||
3156 | struct module *owner = csw->owner; | 3179 | struct module *owner = csw->owner; |
3157 | const struct consw *defcsw = NULL; | 3180 | const struct consw *defcsw = NULL; |
3158 | struct con_driver *con_driver = NULL, *con_back = NULL; | 3181 | struct con_driver *con_driver = NULL, *con_back = NULL; |
@@ -3161,7 +3184,7 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | |||
3161 | if (!try_module_get(owner)) | 3184 | if (!try_module_get(owner)) |
3162 | return -ENODEV; | 3185 | return -ENODEV; |
3163 | 3186 | ||
3164 | console_lock(); | 3187 | WARN_CONSOLE_UNLOCKED(); |
3165 | 3188 | ||
3166 | /* check if driver is registered and if it is unbindable */ | 3189 | /* check if driver is registered and if it is unbindable */ |
3167 | for (i = 0; i < MAX_NR_CON_DRIVER; i++) { | 3190 | for (i = 0; i < MAX_NR_CON_DRIVER; i++) { |
@@ -3174,10 +3197,8 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | |||
3174 | } | 3197 | } |
3175 | } | 3198 | } |
3176 | 3199 | ||
3177 | if (retval) { | 3200 | if (retval) |
3178 | console_unlock(); | ||
3179 | goto err; | 3201 | goto err; |
3180 | } | ||
3181 | 3202 | ||
3182 | retval = -ENODEV; | 3203 | retval = -ENODEV; |
3183 | 3204 | ||
@@ -3193,15 +3214,11 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | |||
3193 | } | 3214 | } |
3194 | } | 3215 | } |
3195 | 3216 | ||
3196 | if (retval) { | 3217 | if (retval) |
3197 | console_unlock(); | ||
3198 | goto err; | 3218 | goto err; |
3199 | } | ||
3200 | 3219 | ||
3201 | if (!con_is_bound(csw)) { | 3220 | if (!con_is_bound(csw)) |
3202 | console_unlock(); | ||
3203 | goto err; | 3221 | goto err; |
3204 | } | ||
3205 | 3222 | ||
3206 | first = max(first, con_driver->first); | 3223 | first = max(first, con_driver->first); |
3207 | last = min(last, con_driver->last); | 3224 | last = min(last, con_driver->last); |
@@ -3228,15 +3245,14 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | |||
3228 | if (!con_is_bound(csw)) | 3245 | if (!con_is_bound(csw)) |
3229 | con_driver->flag &= ~CON_DRIVER_FLAG_INIT; | 3246 | con_driver->flag &= ~CON_DRIVER_FLAG_INIT; |
3230 | 3247 | ||
3231 | console_unlock(); | ||
3232 | /* ignore return value, binding should not fail */ | 3248 | /* ignore return value, binding should not fail */ |
3233 | bind_con_driver(defcsw, first, last, deflt); | 3249 | do_bind_con_driver(defcsw, first, last, deflt); |
3234 | err: | 3250 | err: |
3235 | module_put(owner); | 3251 | module_put(owner); |
3236 | return retval; | 3252 | return retval; |
3237 | 3253 | ||
3238 | } | 3254 | } |
3239 | EXPORT_SYMBOL(unbind_con_driver); | 3255 | EXPORT_SYMBOL_GPL(do_unbind_con_driver); |
3240 | 3256 | ||
3241 | static int vt_bind(struct con_driver *con) | 3257 | static int vt_bind(struct con_driver *con) |
3242 | { | 3258 | { |
@@ -3508,28 +3524,18 @@ int con_debug_leave(void) | |||
3508 | } | 3524 | } |
3509 | EXPORT_SYMBOL_GPL(con_debug_leave); | 3525 | EXPORT_SYMBOL_GPL(con_debug_leave); |
3510 | 3526 | ||
3511 | /** | 3527 | static int do_register_con_driver(const struct consw *csw, int first, int last) |
3512 | * register_con_driver - register console driver to console layer | ||
3513 | * @csw: console driver | ||
3514 | * @first: the first console to take over, minimum value is 0 | ||
3515 | * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1 | ||
3516 | * | ||
3517 | * DESCRIPTION: This function registers a console driver which can later | ||
3518 | * bind to a range of consoles specified by @first and @last. It will | ||
3519 | * also initialize the console driver by calling con_startup(). | ||
3520 | */ | ||
3521 | int register_con_driver(const struct consw *csw, int first, int last) | ||
3522 | { | 3528 | { |
3523 | struct module *owner = csw->owner; | 3529 | struct module *owner = csw->owner; |
3524 | struct con_driver *con_driver; | 3530 | struct con_driver *con_driver; |
3525 | const char *desc; | 3531 | const char *desc; |
3526 | int i, retval = 0; | 3532 | int i, retval = 0; |
3527 | 3533 | ||
3534 | WARN_CONSOLE_UNLOCKED(); | ||
3535 | |||
3528 | if (!try_module_get(owner)) | 3536 | if (!try_module_get(owner)) |
3529 | return -ENODEV; | 3537 | return -ENODEV; |
3530 | 3538 | ||
3531 | console_lock(); | ||
3532 | |||
3533 | for (i = 0; i < MAX_NR_CON_DRIVER; i++) { | 3539 | for (i = 0; i < MAX_NR_CON_DRIVER; i++) { |
3534 | con_driver = ®istered_con_driver[i]; | 3540 | con_driver = ®istered_con_driver[i]; |
3535 | 3541 | ||
@@ -3582,10 +3588,29 @@ int register_con_driver(const struct consw *csw, int first, int last) | |||
3582 | } | 3588 | } |
3583 | 3589 | ||
3584 | err: | 3590 | err: |
3585 | console_unlock(); | ||
3586 | module_put(owner); | 3591 | module_put(owner); |
3587 | return retval; | 3592 | return retval; |
3588 | } | 3593 | } |
3594 | |||
3595 | /** | ||
3596 | * register_con_driver - register console driver to console layer | ||
3597 | * @csw: console driver | ||
3598 | * @first: the first console to take over, minimum value is 0 | ||
3599 | * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1 | ||
3600 | * | ||
3601 | * DESCRIPTION: This function registers a console driver which can later | ||
3602 | * bind to a range of consoles specified by @first and @last. It will | ||
3603 | * also initialize the console driver by calling con_startup(). | ||
3604 | */ | ||
3605 | int register_con_driver(const struct consw *csw, int first, int last) | ||
3606 | { | ||
3607 | int retval; | ||
3608 | |||
3609 | console_lock(); | ||
3610 | retval = do_register_con_driver(csw, first, last); | ||
3611 | console_unlock(); | ||
3612 | return retval; | ||
3613 | } | ||
3589 | EXPORT_SYMBOL(register_con_driver); | 3614 | EXPORT_SYMBOL(register_con_driver); |
3590 | 3615 | ||
3591 | /** | 3616 | /** |
@@ -3601,9 +3626,18 @@ EXPORT_SYMBOL(register_con_driver); | |||
3601 | */ | 3626 | */ |
3602 | int unregister_con_driver(const struct consw *csw) | 3627 | int unregister_con_driver(const struct consw *csw) |
3603 | { | 3628 | { |
3604 | int i, retval = -ENODEV; | 3629 | int retval; |
3605 | 3630 | ||
3606 | console_lock(); | 3631 | console_lock(); |
3632 | retval = do_unregister_con_driver(csw); | ||
3633 | console_unlock(); | ||
3634 | return retval; | ||
3635 | } | ||
3636 | EXPORT_SYMBOL(unregister_con_driver); | ||
3637 | |||
3638 | int do_unregister_con_driver(const struct consw *csw) | ||
3639 | { | ||
3640 | int i, retval = -ENODEV; | ||
3607 | 3641 | ||
3608 | /* cannot unregister a bound driver */ | 3642 | /* cannot unregister a bound driver */ |
3609 | if (con_is_bound(csw)) | 3643 | if (con_is_bound(csw)) |
@@ -3629,27 +3663,53 @@ int unregister_con_driver(const struct consw *csw) | |||
3629 | } | 3663 | } |
3630 | } | 3664 | } |
3631 | err: | 3665 | err: |
3632 | console_unlock(); | ||
3633 | return retval; | 3666 | return retval; |
3634 | } | 3667 | } |
3635 | EXPORT_SYMBOL(unregister_con_driver); | 3668 | EXPORT_SYMBOL_GPL(do_unregister_con_driver); |
3636 | 3669 | ||
3637 | /* | 3670 | /* |
3638 | * If we support more console drivers, this function is used | 3671 | * If we support more console drivers, this function is used |
3639 | * when a driver wants to take over some existing consoles | 3672 | * when a driver wants to take over some existing consoles |
3640 | * and become default driver for newly opened ones. | 3673 | * and become default driver for newly opened ones. |
3641 | * | 3674 | * |
3642 | * take_over_console is basically a register followed by unbind | 3675 | * take_over_console is basically a register followed by unbind |
3676 | */ | ||
3677 | int do_take_over_console(const struct consw *csw, int first, int last, int deflt) | ||
3678 | { | ||
3679 | int err; | ||
3680 | |||
3681 | err = do_register_con_driver(csw, first, last); | ||
3682 | /* | ||
3683 | * If we get an busy error we still want to bind the console driver | ||
3684 | * and return success, as we may have unbound the console driver | ||
3685 | * but not unregistered it. | ||
3686 | */ | ||
3687 | if (err == -EBUSY) | ||
3688 | err = 0; | ||
3689 | if (!err) | ||
3690 | do_bind_con_driver(csw, first, last, deflt); | ||
3691 | |||
3692 | return err; | ||
3693 | } | ||
3694 | EXPORT_SYMBOL_GPL(do_take_over_console); | ||
3695 | |||
3696 | /* | ||
3697 | * If we support more console drivers, this function is used | ||
3698 | * when a driver wants to take over some existing consoles | ||
3699 | * and become default driver for newly opened ones. | ||
3700 | * | ||
3701 | * take_over_console is basically a register followed by unbind | ||
3643 | */ | 3702 | */ |
3644 | int take_over_console(const struct consw *csw, int first, int last, int deflt) | 3703 | int take_over_console(const struct consw *csw, int first, int last, int deflt) |
3645 | { | 3704 | { |
3646 | int err; | 3705 | int err; |
3647 | 3706 | ||
3648 | err = register_con_driver(csw, first, last); | 3707 | err = register_con_driver(csw, first, last); |
3649 | /* if we get an busy error we still want to bind the console driver | 3708 | /* |
3709 | * If we get an busy error we still want to bind the console driver | ||
3650 | * and return success, as we may have unbound the console driver | 3710 | * and return success, as we may have unbound the console driver |
3651 | * but not unregistered it. | 3711 | * but not unregistered it. |
3652 | */ | 3712 | */ |
3653 | if (err == -EBUSY) | 3713 | if (err == -EBUSY) |
3654 | err = 0; | 3714 | err = 0; |
3655 | if (!err) | 3715 | if (!err) |