diff options
author | Dave Airlie <airlied@redhat.com> | 2013-02-07 21:10:18 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-02-07 21:10:18 -0500 |
commit | 6dc1c49da6dd3bf020a66b2a135b9625ac01c2c7 (patch) | |
tree | 38a6c5d4896de01449e9d224088ae223161fcd3c /drivers/tty/vt/vt.c | |
parent | cd17ef4114ad5c514b17e6a0bb02a309ab90b692 (diff) | |
parent | 5845b81bdad374f98f809a658ec747d92c9595c4 (diff) |
Merge branch 'fbcon-locking-fixes' of ssh://people.freedesktop.org/~airlied/linux into drm-next
This pulls in most of Linus tree up to -rc6, this fixes the worst lockdep
reported issues and re-enables fbcon lockdep.
(not the fbcon maintainer)
* 'fbcon-locking-fixes' of ssh://people.freedesktop.org/~airlied/linux: (529 commits)
Revert "Revert "console: implement lockdep support for console_lock""
fbcon: fix locking harder
fb: Yet another band-aid for fixing lockdep mess
fb: rework locking to fix lock ordering on takeover
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 8fd89687d068..457c41fe7eb9 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 | { |
@@ -3124,6 +3135,18 @@ static int con_is_graphics(const struct consw *csw, int first, int last) | |||
3124 | */ | 3135 | */ |
3125 | int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | 3136 | int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) |
3126 | { | 3137 | { |
3138 | int retval; | ||
3139 | |||
3140 | console_lock(); | ||
3141 | retval = do_unbind_con_driver(csw, first, last, deflt); | ||
3142 | console_unlock(); | ||
3143 | return retval; | ||
3144 | } | ||
3145 | EXPORT_SYMBOL(unbind_con_driver); | ||
3146 | |||
3147 | /* unlocked version of unbind_con_driver() */ | ||
3148 | int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | ||
3149 | { | ||
3127 | struct module *owner = csw->owner; | 3150 | struct module *owner = csw->owner; |
3128 | const struct consw *defcsw = NULL; | 3151 | const struct consw *defcsw = NULL; |
3129 | struct con_driver *con_driver = NULL, *con_back = NULL; | 3152 | struct con_driver *con_driver = NULL, *con_back = NULL; |
@@ -3132,7 +3155,7 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | |||
3132 | if (!try_module_get(owner)) | 3155 | if (!try_module_get(owner)) |
3133 | return -ENODEV; | 3156 | return -ENODEV; |
3134 | 3157 | ||
3135 | console_lock(); | 3158 | WARN_CONSOLE_UNLOCKED(); |
3136 | 3159 | ||
3137 | /* check if driver is registered and if it is unbindable */ | 3160 | /* check if driver is registered and if it is unbindable */ |
3138 | for (i = 0; i < MAX_NR_CON_DRIVER; i++) { | 3161 | for (i = 0; i < MAX_NR_CON_DRIVER; i++) { |
@@ -3145,10 +3168,8 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | |||
3145 | } | 3168 | } |
3146 | } | 3169 | } |
3147 | 3170 | ||
3148 | if (retval) { | 3171 | if (retval) |
3149 | console_unlock(); | ||
3150 | goto err; | 3172 | goto err; |
3151 | } | ||
3152 | 3173 | ||
3153 | retval = -ENODEV; | 3174 | retval = -ENODEV; |
3154 | 3175 | ||
@@ -3164,15 +3185,11 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | |||
3164 | } | 3185 | } |
3165 | } | 3186 | } |
3166 | 3187 | ||
3167 | if (retval) { | 3188 | if (retval) |
3168 | console_unlock(); | ||
3169 | goto err; | 3189 | goto err; |
3170 | } | ||
3171 | 3190 | ||
3172 | if (!con_is_bound(csw)) { | 3191 | if (!con_is_bound(csw)) |
3173 | console_unlock(); | ||
3174 | goto err; | 3192 | goto err; |
3175 | } | ||
3176 | 3193 | ||
3177 | first = max(first, con_driver->first); | 3194 | first = max(first, con_driver->first); |
3178 | last = min(last, con_driver->last); | 3195 | last = min(last, con_driver->last); |
@@ -3199,15 +3216,14 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) | |||
3199 | if (!con_is_bound(csw)) | 3216 | if (!con_is_bound(csw)) |
3200 | con_driver->flag &= ~CON_DRIVER_FLAG_INIT; | 3217 | con_driver->flag &= ~CON_DRIVER_FLAG_INIT; |
3201 | 3218 | ||
3202 | console_unlock(); | ||
3203 | /* ignore return value, binding should not fail */ | 3219 | /* ignore return value, binding should not fail */ |
3204 | bind_con_driver(defcsw, first, last, deflt); | 3220 | do_bind_con_driver(defcsw, first, last, deflt); |
3205 | err: | 3221 | err: |
3206 | module_put(owner); | 3222 | module_put(owner); |
3207 | return retval; | 3223 | return retval; |
3208 | 3224 | ||
3209 | } | 3225 | } |
3210 | EXPORT_SYMBOL(unbind_con_driver); | 3226 | EXPORT_SYMBOL_GPL(do_unbind_con_driver); |
3211 | 3227 | ||
3212 | static int vt_bind(struct con_driver *con) | 3228 | static int vt_bind(struct con_driver *con) |
3213 | { | 3229 | { |
@@ -3492,28 +3508,18 @@ int con_debug_leave(void) | |||
3492 | } | 3508 | } |
3493 | EXPORT_SYMBOL_GPL(con_debug_leave); | 3509 | EXPORT_SYMBOL_GPL(con_debug_leave); |
3494 | 3510 | ||
3495 | /** | 3511 | 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 | { | 3512 | { |
3507 | struct module *owner = csw->owner; | 3513 | struct module *owner = csw->owner; |
3508 | struct con_driver *con_driver; | 3514 | struct con_driver *con_driver; |
3509 | const char *desc; | 3515 | const char *desc; |
3510 | int i, retval = 0; | 3516 | int i, retval = 0; |
3511 | 3517 | ||
3518 | WARN_CONSOLE_UNLOCKED(); | ||
3519 | |||
3512 | if (!try_module_get(owner)) | 3520 | if (!try_module_get(owner)) |
3513 | return -ENODEV; | 3521 | return -ENODEV; |
3514 | 3522 | ||
3515 | console_lock(); | ||
3516 | |||
3517 | for (i = 0; i < MAX_NR_CON_DRIVER; i++) { | 3523 | for (i = 0; i < MAX_NR_CON_DRIVER; i++) { |
3518 | con_driver = ®istered_con_driver[i]; | 3524 | con_driver = ®istered_con_driver[i]; |
3519 | 3525 | ||
@@ -3566,10 +3572,29 @@ int register_con_driver(const struct consw *csw, int first, int last) | |||
3566 | } | 3572 | } |
3567 | 3573 | ||
3568 | err: | 3574 | err: |
3569 | console_unlock(); | ||
3570 | module_put(owner); | 3575 | module_put(owner); |
3571 | return retval; | 3576 | return retval; |
3572 | } | 3577 | } |
3578 | |||
3579 | /** | ||
3580 | * register_con_driver - register console driver to console layer | ||
3581 | * @csw: console driver | ||
3582 | * @first: the first console to take over, minimum value is 0 | ||
3583 | * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1 | ||
3584 | * | ||
3585 | * DESCRIPTION: This function registers a console driver which can later | ||
3586 | * bind to a range of consoles specified by @first and @last. It will | ||
3587 | * also initialize the console driver by calling con_startup(). | ||
3588 | */ | ||
3589 | int register_con_driver(const struct consw *csw, int first, int last) | ||
3590 | { | ||
3591 | int retval; | ||
3592 | |||
3593 | console_lock(); | ||
3594 | retval = do_register_con_driver(csw, first, last); | ||
3595 | console_unlock(); | ||
3596 | return retval; | ||
3597 | } | ||
3573 | EXPORT_SYMBOL(register_con_driver); | 3598 | EXPORT_SYMBOL(register_con_driver); |
3574 | 3599 | ||
3575 | /** | 3600 | /** |
@@ -3585,9 +3610,18 @@ EXPORT_SYMBOL(register_con_driver); | |||
3585 | */ | 3610 | */ |
3586 | int unregister_con_driver(const struct consw *csw) | 3611 | int unregister_con_driver(const struct consw *csw) |
3587 | { | 3612 | { |
3588 | int i, retval = -ENODEV; | 3613 | int retval; |
3589 | 3614 | ||
3590 | console_lock(); | 3615 | console_lock(); |
3616 | retval = do_unregister_con_driver(csw); | ||
3617 | console_unlock(); | ||
3618 | return retval; | ||
3619 | } | ||
3620 | EXPORT_SYMBOL(unregister_con_driver); | ||
3621 | |||
3622 | int do_unregister_con_driver(const struct consw *csw) | ||
3623 | { | ||
3624 | int i, retval = -ENODEV; | ||
3591 | 3625 | ||
3592 | /* cannot unregister a bound driver */ | 3626 | /* cannot unregister a bound driver */ |
3593 | if (con_is_bound(csw)) | 3627 | if (con_is_bound(csw)) |
@@ -3613,27 +3647,53 @@ int unregister_con_driver(const struct consw *csw) | |||
3613 | } | 3647 | } |
3614 | } | 3648 | } |
3615 | err: | 3649 | err: |
3616 | console_unlock(); | ||
3617 | return retval; | 3650 | return retval; |
3618 | } | 3651 | } |
3619 | EXPORT_SYMBOL(unregister_con_driver); | 3652 | EXPORT_SYMBOL_GPL(do_unregister_con_driver); |
3620 | 3653 | ||
3621 | /* | 3654 | /* |
3622 | * If we support more console drivers, this function is used | 3655 | * If we support more console drivers, this function is used |
3623 | * when a driver wants to take over some existing consoles | 3656 | * when a driver wants to take over some existing consoles |
3624 | * and become default driver for newly opened ones. | 3657 | * and become default driver for newly opened ones. |
3625 | * | 3658 | * |
3626 | * take_over_console is basically a register followed by unbind | 3659 | * take_over_console is basically a register followed by unbind |
3660 | */ | ||
3661 | int do_take_over_console(const struct consw *csw, int first, int last, int deflt) | ||
3662 | { | ||
3663 | int err; | ||
3664 | |||
3665 | err = do_register_con_driver(csw, first, last); | ||
3666 | /* | ||
3667 | * If we get an busy error we still want to bind the console driver | ||
3668 | * and return success, as we may have unbound the console driver | ||
3669 | * but not unregistered it. | ||
3670 | */ | ||
3671 | if (err == -EBUSY) | ||
3672 | err = 0; | ||
3673 | if (!err) | ||
3674 | do_bind_con_driver(csw, first, last, deflt); | ||
3675 | |||
3676 | return err; | ||
3677 | } | ||
3678 | EXPORT_SYMBOL_GPL(do_take_over_console); | ||
3679 | |||
3680 | /* | ||
3681 | * If we support more console drivers, this function is used | ||
3682 | * when a driver wants to take over some existing consoles | ||
3683 | * and become default driver for newly opened ones. | ||
3684 | * | ||
3685 | * take_over_console is basically a register followed by unbind | ||
3627 | */ | 3686 | */ |
3628 | int take_over_console(const struct consw *csw, int first, int last, int deflt) | 3687 | int take_over_console(const struct consw *csw, int first, int last, int deflt) |
3629 | { | 3688 | { |
3630 | int err; | 3689 | int err; |
3631 | 3690 | ||
3632 | err = register_con_driver(csw, first, last); | 3691 | err = register_con_driver(csw, first, last); |
3633 | /* if we get an busy error we still want to bind the console driver | 3692 | /* |
3693 | * 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 | 3694 | * and return success, as we may have unbound the console driver |
3635 | * but not unregistered it. | 3695 | * but not unregistered it. |
3636 | */ | 3696 | */ |
3637 | if (err == -EBUSY) | 3697 | if (err == -EBUSY) |
3638 | err = 0; | 3698 | err = 0; |
3639 | if (!err) | 3699 | if (!err) |