diff options
author | Dave Airlie <airlied@gmail.com> | 2013-01-24 20:38:56 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-02-07 21:02:43 -0500 |
commit | 054430e773c9a1e26f38e30156eff02dedfffc17 (patch) | |
tree | 9866f12c399f63de3ac285624226b19c0501b191 /drivers/video/console | |
parent | e93a9a868792ad71cdd09d75e5a02d8067473c4e (diff) |
fbcon: fix locking harder
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>
Diffstat (limited to 'drivers/video/console')
-rw-r--r-- | drivers/video/console/fbcon.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 2aef9cac4d18..2e2d959acae6 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -842,6 +842,8 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, | |||
842 | * | 842 | * |
843 | * Maps a virtual console @unit to a frame buffer device | 843 | * Maps a virtual console @unit to a frame buffer device |
844 | * @newidx. | 844 | * @newidx. |
845 | * | ||
846 | * This should be called with the console lock held. | ||
845 | */ | 847 | */ |
846 | static int set_con2fb_map(int unit, int newidx, int user) | 848 | static int set_con2fb_map(int unit, int newidx, int user) |
847 | { | 849 | { |
@@ -859,7 +861,7 @@ static int set_con2fb_map(int unit, int newidx, int user) | |||
859 | 861 | ||
860 | if (!search_for_mapped_con() || !con_is_bound(&fb_con)) { | 862 | if (!search_for_mapped_con() || !con_is_bound(&fb_con)) { |
861 | info_idx = newidx; | 863 | info_idx = newidx; |
862 | return fbcon_takeover(0); | 864 | return do_fbcon_takeover(0); |
863 | } | 865 | } |
864 | 866 | ||
865 | if (oldidx != -1) | 867 | if (oldidx != -1) |
@@ -867,7 +869,6 @@ static int set_con2fb_map(int unit, int newidx, int user) | |||
867 | 869 | ||
868 | found = search_fb_in_map(newidx); | 870 | found = search_fb_in_map(newidx); |
869 | 871 | ||
870 | console_lock(); | ||
871 | con2fb_map[unit] = newidx; | 872 | con2fb_map[unit] = newidx; |
872 | if (!err && !found) | 873 | if (!err && !found) |
873 | err = con2fb_acquire_newinfo(vc, info, unit, oldidx); | 874 | err = con2fb_acquire_newinfo(vc, info, unit, oldidx); |
@@ -894,7 +895,6 @@ static int set_con2fb_map(int unit, int newidx, int user) | |||
894 | if (!search_fb_in_map(info_idx)) | 895 | if (!search_fb_in_map(info_idx)) |
895 | info_idx = newidx; | 896 | info_idx = newidx; |
896 | 897 | ||
897 | console_unlock(); | ||
898 | return err; | 898 | return err; |
899 | } | 899 | } |
900 | 900 | ||
@@ -3019,6 +3019,7 @@ static inline int fbcon_unbind(void) | |||
3019 | } | 3019 | } |
3020 | #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ | 3020 | #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ |
3021 | 3021 | ||
3022 | /* called with console_lock held */ | ||
3022 | static int fbcon_fb_unbind(int idx) | 3023 | static int fbcon_fb_unbind(int idx) |
3023 | { | 3024 | { |
3024 | int i, new_idx = -1, ret = 0; | 3025 | int i, new_idx = -1, ret = 0; |
@@ -3045,6 +3046,7 @@ static int fbcon_fb_unbind(int idx) | |||
3045 | return ret; | 3046 | return ret; |
3046 | } | 3047 | } |
3047 | 3048 | ||
3049 | /* called with console_lock held */ | ||
3048 | static int fbcon_fb_unregistered(struct fb_info *info) | 3050 | static int fbcon_fb_unregistered(struct fb_info *info) |
3049 | { | 3051 | { |
3050 | int i, idx; | 3052 | int i, idx; |
@@ -3082,6 +3084,7 @@ static int fbcon_fb_unregistered(struct fb_info *info) | |||
3082 | return 0; | 3084 | return 0; |
3083 | } | 3085 | } |
3084 | 3086 | ||
3087 | /* called with console_lock held */ | ||
3085 | static void fbcon_remap_all(int idx) | 3088 | static void fbcon_remap_all(int idx) |
3086 | { | 3089 | { |
3087 | int i; | 3090 | int i; |
@@ -3126,6 +3129,7 @@ static inline void fbcon_select_primary(struct fb_info *info) | |||
3126 | } | 3129 | } |
3127 | #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ | 3130 | #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ |
3128 | 3131 | ||
3132 | /* called with console_lock held */ | ||
3129 | static int fbcon_fb_registered(struct fb_info *info) | 3133 | static int fbcon_fb_registered(struct fb_info *info) |
3130 | { | 3134 | { |
3131 | int ret = 0, i, idx; | 3135 | int ret = 0, i, idx; |
@@ -3278,6 +3282,7 @@ static int fbcon_event_notify(struct notifier_block *self, | |||
3278 | ret = fbcon_fb_unregistered(info); | 3282 | ret = fbcon_fb_unregistered(info); |
3279 | break; | 3283 | break; |
3280 | case FB_EVENT_SET_CONSOLE_MAP: | 3284 | case FB_EVENT_SET_CONSOLE_MAP: |
3285 | /* called with console lock held */ | ||
3281 | con2fb = event->data; | 3286 | con2fb = event->data; |
3282 | ret = set_con2fb_map(con2fb->console - 1, | 3287 | ret = set_con2fb_map(con2fb->console - 1, |
3283 | con2fb->framebuffer, 1); | 3288 | con2fb->framebuffer, 1); |