aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2013-01-24 20:38:56 -0500
committerDave Airlie <airlied@redhat.com>2013-02-07 21:02:43 -0500
commit054430e773c9a1e26f38e30156eff02dedfffc17 (patch)
tree9866f12c399f63de3ac285624226b19c0501b191
parente93a9a868792ad71cdd09d75e5a02d8067473c4e (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>
-rw-r--r--drivers/gpu/vga/vga_switcheroo.c3
-rw-r--r--drivers/video/console/fbcon.c11
-rw-r--r--drivers/video/fbmem.c2
3 files changed, 13 insertions, 3 deletions
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index fa60add0ff63..cf787e1d9322 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -25,6 +25,7 @@
25#include <linux/fb.h> 25#include <linux/fb.h>
26 26
27#include <linux/pci.h> 27#include <linux/pci.h>
28#include <linux/console.h>
28#include <linux/vga_switcheroo.h> 29#include <linux/vga_switcheroo.h>
29 30
30#include <linux/vgaarb.h> 31#include <linux/vgaarb.h>
@@ -337,8 +338,10 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
337 338
338 if (new_client->fb_info) { 339 if (new_client->fb_info) {
339 struct fb_event event; 340 struct fb_event event;
341 console_lock();
340 event.info = new_client->fb_info; 342 event.info = new_client->fb_info;
341 fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event); 343 fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event);
344 console_unlock();
342 } 345 }
343 346
344 ret = vgasr_priv.handler->switchto(new_client->id); 347 ret = vgasr_priv.handler->switchto(new_client->id);
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 */
846static int set_con2fb_map(int unit, int newidx, int user) 848static 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 */
3022static int fbcon_fb_unbind(int idx) 3023static 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 */
3048static int fbcon_fb_unregistered(struct fb_info *info) 3050static 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 */
3085static void fbcon_remap_all(int idx) 3088static 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 */
3129static int fbcon_fb_registered(struct fb_info *info) 3133static 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);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 070b9a13d892..dc61c12ecf8c 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1177,8 +1177,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
1177 event.data = &con2fb; 1177 event.data = &con2fb;
1178 if (!lock_fb_info(info)) 1178 if (!lock_fb_info(info))
1179 return -ENODEV; 1179 return -ENODEV;
1180 console_lock();
1180 event.info = info; 1181 event.info = info;
1181 ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); 1182 ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
1183 console_unlock();
1182 unlock_fb_info(info); 1184 unlock_fb_info(info);
1183 break; 1185 break;
1184 case FBIOBLANK: 1186 case FBIOBLANK: