fb: Yet another band-aid for fixing lockdep mess
authorTakashi Iwai <tiwai@suse.de>
Fri, 25 Jan 2013 00:28:18 +0000 (10:28 +1000)
committerBen Hutchings <ben@decadent.org.uk>
Wed, 6 Mar 2013 03:23:52 +0000 (03:23 +0000)
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>
drivers/tty/vt/vt.c
drivers/video/console/fbcon.c
drivers/video/fbmem.c
include/linux/console.h
include/linux/vt_kern.h

index e2345d4..632df54 100644 (file)
@@ -3163,6 +3163,18 @@ static int con_is_graphics(const struct consw *csw, int first, int last)
  * 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;
@@ -3172,7 +3184,7 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
        if (!try_module_get(owner))
                return -ENODEV;
 
        if (!try_module_get(owner))
                return -ENODEV;
 
-       console_lock();
+       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++) {
@@ -3185,10 +3197,8 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
                }
        }
 
                }
        }
 
-       if (retval) {
-               console_unlock();
+       if (retval)
                goto err;
                goto err;
-       }
 
        retval = -ENODEV;
 
 
        retval = -ENODEV;
 
@@ -3204,15 +3214,11 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
                }
        }
 
                }
        }
 
-       if (retval) {
-               console_unlock();
+       if (retval)
                goto err;
                goto err;
-       }
 
 
-       if (!con_is_bound(csw)) {
-               console_unlock();
+       if (!con_is_bound(csw))
                goto err;
                goto err;
-       }
 
        first = max(first, con_driver->first);
        last = min(last, con_driver->last);
 
        first = max(first, con_driver->first);
        last = min(last, con_driver->last);
@@ -3241,13 +3247,12 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
 
        /* 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);
-       console_unlock();
 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)
 {
@@ -3621,9 +3626,18 @@ EXPORT_SYMBOL(register_con_driver);
  */
 int unregister_con_driver(const struct consw *csw)
 {
  */
 int unregister_con_driver(const struct consw *csw)
 {
-       int i, retval = -ENODEV;
+       int retval;
 
        console_lock();
 
        console_lock();
+       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))
@@ -3649,10 +3663,9 @@ int unregister_con_driver(const struct consw *csw)
                }
        }
 err:
                }
        }
 err:
-       console_unlock();
        return retval;
 }
        return retval;
 }
-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
index 18d02c6..9b8bcab 100644 (file)
@@ -3011,7 +3011,7 @@ static int fbcon_unbind(void)
 {
        int ret;
 
 {
        int ret;
 
-       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)
@@ -3084,7 +3084,7 @@ static int fbcon_fb_unregistered(struct fb_info *info)
                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);
 
        return 0;
 }
 
        return 0;
 }
index a94edc3..c133dde 100644 (file)
@@ -1646,8 +1646,10 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
 
        if (!lock_fb_info(fb_info))
                return -ENODEV;
 
        if (!lock_fb_info(fb_info))
                return -ENODEV;
+       console_lock();
        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);
+       console_unlock();
        unlock_fb_info(fb_info);
 
        if (ret)
        unlock_fb_info(fb_info);
 
        if (ret)
@@ -1662,7 +1664,9 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
        num_registered_fb--;
        fb_cleanup_device(fb_info);
        event.info = fb_info;
        num_registered_fb--;
        fb_cleanup_device(fb_info);
        event.info = fb_info;
+       console_lock();
        fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
        fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
+       console_unlock();
 
        /* this may free fb info */
        put_fb_info(fb_info);
 
        /* this may free fb info */
        put_fb_info(fb_info);
index 49b1061..6ae6a15 100644 (file)
@@ -77,6 +77,7 @@ extern const struct consw prom_con;   /* SPARC PROM console */
 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);
index 932276d..644921f 100644 (file)
@@ -132,6 +132,8 @@ void vt_event_post(unsigned int event, unsigned int old, unsigned int new);
 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);