Commit c9d286ac authored by Dave Airlie's avatar Dave Airlie Committed by Ben Hutchings

fbcon: fix locking harder

commit 054430e7 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: default avatarMaarten Lankhorst <maarten.lankhorst@canonical.com>
Tested-by: default avatarLu Hua <huax.lu@intel.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 095a3cac
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/console.h>
#include <linux/vga_switcheroo.h> #include <linux/vga_switcheroo.h>
struct vga_switcheroo_client { struct vga_switcheroo_client {
...@@ -256,8 +257,10 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) ...@@ -256,8 +257,10 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
if (new_client->fb_info) { if (new_client->fb_info) {
struct fb_event event; struct fb_event event;
console_lock();
event.info = new_client->fb_info; event.info = new_client->fb_info;
fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event); fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event);
console_unlock();
} }
ret = vgasr_priv.handler->switchto(new_client->id); ret = vgasr_priv.handler->switchto(new_client->id);
......
...@@ -843,6 +843,8 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, ...@@ -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 * Maps a virtual console @unit to a frame buffer device
* @newidx. * @newidx.
*
* This should be called with the console lock held.
*/ */
static int set_con2fb_map(int unit, int newidx, int user) 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) ...@@ -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)) { if (!search_for_mapped_con() || !con_is_bound(&fb_con)) {
info_idx = newidx; info_idx = newidx;
return fbcon_takeover(0); return do_fbcon_takeover(0);
} }
if (oldidx != -1) if (oldidx != -1)
...@@ -868,7 +870,6 @@ static int set_con2fb_map(int unit, int newidx, int user) ...@@ -868,7 +870,6 @@ static int set_con2fb_map(int unit, int newidx, int user)
found = search_fb_in_map(newidx); found = search_fb_in_map(newidx);
console_lock();
con2fb_map[unit] = newidx; con2fb_map[unit] = newidx;
if (!err && !found) if (!err && !found)
err = con2fb_acquire_newinfo(vc, info, unit, oldidx); err = con2fb_acquire_newinfo(vc, info, unit, oldidx);
...@@ -895,7 +896,6 @@ static int set_con2fb_map(int unit, int newidx, int user) ...@@ -895,7 +896,6 @@ static int set_con2fb_map(int unit, int newidx, int user)
if (!search_fb_in_map(info_idx)) if (!search_fb_in_map(info_idx))
info_idx = newidx; info_idx = newidx;
console_unlock();
return err; return err;
} }
...@@ -3026,6 +3026,7 @@ static inline int fbcon_unbind(void) ...@@ -3026,6 +3026,7 @@ static inline int fbcon_unbind(void)
} }
#endif /* CONFIG_VT_HW_CONSOLE_BINDING */ #endif /* CONFIG_VT_HW_CONSOLE_BINDING */
/* called with console_lock held */
static int fbcon_fb_unbind(int idx) static int fbcon_fb_unbind(int idx)
{ {
int i, new_idx = -1, ret = 0; int i, new_idx = -1, ret = 0;
...@@ -3052,6 +3053,7 @@ static int fbcon_fb_unbind(int idx) ...@@ -3052,6 +3053,7 @@ static int fbcon_fb_unbind(int idx)
return ret; return ret;
} }
/* called with console_lock held */
static int fbcon_fb_unregistered(struct fb_info *info) static int fbcon_fb_unregistered(struct fb_info *info)
{ {
int i, idx; int i, idx;
...@@ -3089,6 +3091,7 @@ static int fbcon_fb_unregistered(struct fb_info *info) ...@@ -3089,6 +3091,7 @@ static int fbcon_fb_unregistered(struct fb_info *info)
return 0; return 0;
} }
/* called with console_lock held */
static void fbcon_remap_all(int idx) static void fbcon_remap_all(int idx)
{ {
int i; int i;
...@@ -3133,6 +3136,7 @@ static inline void fbcon_select_primary(struct fb_info *info) ...@@ -3133,6 +3136,7 @@ static inline void fbcon_select_primary(struct fb_info *info)
} }
#endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */
/* called with console_lock held */
static int fbcon_fb_registered(struct fb_info *info) static int fbcon_fb_registered(struct fb_info *info)
{ {
int ret = 0, i, idx; int ret = 0, i, idx;
...@@ -3285,6 +3289,7 @@ static int fbcon_event_notify(struct notifier_block *self, ...@@ -3285,6 +3289,7 @@ static int fbcon_event_notify(struct notifier_block *self,
ret = fbcon_fb_unregistered(info); ret = fbcon_fb_unregistered(info);
break; break;
case FB_EVENT_SET_CONSOLE_MAP: case FB_EVENT_SET_CONSOLE_MAP:
/* called with console lock held */
con2fb = event->data; con2fb = event->data;
ret = set_con2fb_map(con2fb->console - 1, ret = set_con2fb_map(con2fb->console - 1,
con2fb->framebuffer, 1); con2fb->framebuffer, 1);
......
...@@ -1154,8 +1154,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, ...@@ -1154,8 +1154,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
event.data = &con2fb; event.data = &con2fb;
if (!lock_fb_info(info)) if (!lock_fb_info(info))
return -ENODEV; return -ENODEV;
console_lock();
event.info = info; event.info = info;
ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event);
console_unlock();
unlock_fb_info(info); unlock_fb_info(info);
break; break;
case FBIOBLANK: case FBIOBLANK:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment