commit
e93a9a868792ad71cdd09d75e5a02d8067473c4e upstream.
I've still got lockdep warnings even after Alan's patch, and it seems that
yet more band aids are required to paper over similar paths for
unbind_con_driver() and unregister_con_driver(). After this hack, lockdep
warnings are finally gone.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Cc: Alan Cox <alan@linux.intel.com>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Jiri Kosina <jkosina@suse.cz>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
* or 0 on success.
*/
int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
* or 0 on success.
*/
int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
+{
+ int retval;
+
+ console_lock();
+ retval = do_unbind_con_driver(csw, first, last, deflt);
+ console_unlock();
+ return retval;
+}
+EXPORT_SYMBOL(unbind_con_driver);
+
+/* unlocked version of unbind_con_driver() */
+int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
{
struct module *owner = csw->owner;
const struct consw *defcsw = NULL;
{
struct module *owner = csw->owner;
const struct consw *defcsw = NULL;
if (!try_module_get(owner))
return -ENODEV;
if (!try_module_get(owner))
return -ENODEV;
+ WARN_CONSOLE_UNLOCKED();
/* check if driver is registered and if it is unbindable */
for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
/* check if driver is registered and if it is unbindable */
for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
- if (retval) {
- console_unlock();
- if (retval) {
- console_unlock();
- if (!con_is_bound(csw)) {
- console_unlock();
+ if (!con_is_bound(csw))
first = max(first, con_driver->first);
last = min(last, con_driver->last);
first = max(first, con_driver->first);
last = min(last, con_driver->last);
/* ignore return value, binding should not fail */
do_bind_con_driver(defcsw, first, last, deflt);
/* ignore return value, binding should not fail */
do_bind_con_driver(defcsw, first, last, deflt);
err:
module_put(owner);
return retval;
}
err:
module_put(owner);
return retval;
}
-EXPORT_SYMBOL(unbind_con_driver);
+EXPORT_SYMBOL_GPL(do_unbind_con_driver);
static int vt_bind(struct con_driver *con)
{
static int vt_bind(struct con_driver *con)
{
*/
int unregister_con_driver(const struct consw *csw)
{
*/
int unregister_con_driver(const struct consw *csw)
{
- int i, retval = -ENODEV;
+ retval = do_unregister_con_driver(csw);
+ console_unlock();
+ return retval;
+}
+EXPORT_SYMBOL(unregister_con_driver);
+
+int do_unregister_con_driver(const struct consw *csw)
+{
+ int i, retval = -ENODEV;
/* cannot unregister a bound driver */
if (con_is_bound(csw))
/* cannot unregister a bound driver */
if (con_is_bound(csw))
-EXPORT_SYMBOL(unregister_con_driver);
+EXPORT_SYMBOL_GPL(do_unregister_con_driver);
/*
* If we support more console drivers, this function is used
/*
* If we support more console drivers, this function is used
- ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
+ ret = do_unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc,
fbcon_is_default);
if (!ret)
fbcon_is_default);
if (!ret)
primary_device = -1;
if (!num_registered_fb)
primary_device = -1;
if (!num_registered_fb)
- unregister_con_driver(&fb_con);
+ do_unregister_con_driver(&fb_con);
if (!lock_fb_info(fb_info))
return -ENODEV;
if (!lock_fb_info(fb_info))
return -ENODEV;
event.info = fb_info;
ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
event.info = fb_info;
ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event);
unlock_fb_info(fb_info);
if (ret)
unlock_fb_info(fb_info);
if (ret)
num_registered_fb--;
fb_cleanup_device(fb_info);
event.info = fb_info;
num_registered_fb--;
fb_cleanup_device(fb_info);
event.info = fb_info;
fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
/* this may free fb info */
put_fb_info(fb_info);
/* this may free fb info */
put_fb_info(fb_info);
int con_is_bound(const struct consw *csw);
int register_con_driver(const struct consw *csw, int first, int last);
int unregister_con_driver(const struct consw *csw);
int con_is_bound(const struct consw *csw);
int register_con_driver(const struct consw *csw, int first, int last);
int unregister_con_driver(const struct consw *csw);
+int do_unregister_con_driver(const struct consw *csw);
int take_over_console(const struct consw *sw, int first, int last, int deflt);
int do_take_over_console(const struct consw *sw, int first, int last, int deflt);
void give_up_console(const struct consw *sw);
int take_over_console(const struct consw *sw, int first, int last, int deflt);
int do_take_over_console(const struct consw *sw, int first, int last, int deflt);
void give_up_console(const struct consw *sw);
int vt_waitactive(int n);
void change_console(struct vc_data *new_vc);
void reset_vc(struct vc_data *vc);
int vt_waitactive(int n);
void change_console(struct vc_data *new_vc);
void reset_vc(struct vc_data *vc);
+extern int do_unbind_con_driver(const struct consw *csw, int first, int last,
+ int deflt);
extern int unbind_con_driver(const struct consw *csw, int first, int last,
int deflt);
int vty_init(const struct file_operations *console_fops);
extern int unbind_con_driver(const struct consw *csw, int first, int last,
int deflt);
int vty_init(const struct file_operations *console_fops);