diff options
author | Alan Cox <alan@linux.intel.com> | 2013-01-24 19:28:15 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-02-07 21:02:40 -0500 |
commit | 50e244cc793d511b86adea24972f3a7264cae114 (patch) | |
tree | de59e5f228a256ad09521524639e1b5b6e49b8cc /drivers/video | |
parent | 84b603abd23300df8ee5fb1c23c83634c2aaedea (diff) |
fb: rework locking to fix lock ordering on takeover
Adjust the console layer to allow a take over call where the caller
already holds the locks. Make the fb layer lock in order.
This is partly a band aid, the fb layer is terminally confused about the
locking rules it uses for its notifiers it seems.
[akpm@linux-foundation.org: remove stray non-ascii char, tidy comment]
[akpm@linux-foundation.org: export do_take_over_console()]
[airlied: cleanup another non-ascii char]
Signed-off-by: Alan Cox <alan@linux.intel.com>
Cc: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: stable <stable@vger.kernel.org>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/video')
-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 |
3 files changed, 33 insertions, 4 deletions
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 | } |