diff options
author | Dave Airlie <airlied@gmail.com> | 2013-01-25 11:38:56 +1000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-25 21:23:48 -0700 |
commit | 22fd0f0bb5e791b7cd5b5e0c7d4c2172c722844d (patch) | |
tree | 3fd530a384354dca12eacbbb89bb9f984906b7e6 /drivers/video | |
parent | 456edf57d7a6fe1b238ec708b19063d78cf4b250 (diff) |
fbcon: fix locking harder
commit 054430e773c9a1e26f38e30156eff02dedfffc17 upstream.
Okay so Alan's patch handled the case where there was no registered fbcon,
however the other path entered in set_con2fb_map pit.
In there we called fbcon_takeover, but we also took the console lock in a couple
of places. So push the console lock out to the callers of set_con2fb_map,
this means fbmem and switcheroo needed to take the lock around the fb notifier
entry points that lead to this.
This should fix the efifb regression seen by Maarten.
Tested-by: Maarten Lankhorst <maarten.lankhorst@canonical.com>
Tested-by: Lu Hua <huax.lu@intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/console/fbcon.c | 11 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 2 |
2 files changed, 10 insertions, 3 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 9b8bcab0ae3..7a36dffb957 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -843,6 +843,8 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, * * Maps a virtual console @unit to a frame buffer device * @newidx. + * + * This should be called with the console lock held. */ static int set_con2fb_map(int unit, int newidx, int user) { @@ -860,7 +862,7 @@ static int set_con2fb_map(int unit, int newidx, int user) if (!search_for_mapped_con() || !con_is_bound(&fb_con)) { info_idx = newidx; - return fbcon_takeover(0); + return do_fbcon_takeover(0); } if (oldidx != -1) @@ -868,7 +870,6 @@ static int set_con2fb_map(int unit, int newidx, int user) found = search_fb_in_map(newidx); - console_lock(); con2fb_map[unit] = newidx; if (!err && !found) err = con2fb_acquire_newinfo(vc, info, unit, oldidx); @@ -895,7 +896,6 @@ static int set_con2fb_map(int unit, int newidx, int user) if (!search_fb_in_map(info_idx)) info_idx = newidx; - console_unlock(); return err; } @@ -3026,6 +3026,7 @@ static inline int fbcon_unbind(void) } #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ +/* called with console_lock held */ static int fbcon_fb_unbind(int idx) { int i, new_idx = -1, ret = 0; @@ -3052,6 +3053,7 @@ static int fbcon_fb_unbind(int idx) return ret; } +/* called with console_lock held */ static int fbcon_fb_unregistered(struct fb_info *info) { int i, idx; @@ -3089,6 +3091,7 @@ static int fbcon_fb_unregistered(struct fb_info *info) return 0; } +/* called with console_lock held */ static void fbcon_remap_all(int idx) { int i; @@ -3133,6 +3136,7 @@ static inline void fbcon_select_primary(struct fb_info *info) } #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ +/* called with console_lock held */ static int fbcon_fb_registered(struct fb_info *info) { int ret = 0, i, idx; @@ -3285,6 +3289,7 @@ static int fbcon_event_notify(struct notifier_block *self, ret = fbcon_fb_unregistered(info); break; case FB_EVENT_SET_CONSOLE_MAP: + /* called with console lock held */ con2fb = event->data; ret = set_con2fb_map(con2fb->console - 1, con2fb->framebuffer, 1); diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index c133dde79cd..babbb07f030 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1154,8 +1154,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, event.data = &con2fb; if (!lock_fb_info(info)) return -ENODEV; + console_lock(); event.info = info; ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); + console_unlock(); unlock_fb_info(info); break; case FBIOBLANK: |