Skip to content

Commit

Permalink
fbcon: fix locking harder
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
airlied committed Feb 8, 2013
1 parent e93a9a8 commit 054430e
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 3 deletions.
3 changes: 3 additions & 0 deletions drivers/gpu/vga/vga_switcheroo.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/fb.h>

#include <linux/pci.h>
#include <linux/console.h>
#include <linux/vga_switcheroo.h>

#include <linux/vgaarb.h>
Expand Down Expand Up @@ -337,8 +338,10 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)

if (new_client->fb_info) {
struct fb_event event;
console_lock();
event.info = new_client->fb_info;
fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event);
console_unlock();
}

ret = vgasr_priv.handler->switchto(new_client->id);
Expand Down
11 changes: 8 additions & 3 deletions drivers/video/console/fbcon.c
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,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)
{
Expand All @@ -859,15 +861,14 @@ 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)
oldinfo = registered_fb[oldidx];

found = search_fb_in_map(newidx);

console_lock();
con2fb_map[unit] = newidx;
if (!err && !found)
err = con2fb_acquire_newinfo(vc, info, unit, oldidx);
Expand All @@ -894,7 +895,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;
}

Expand Down Expand Up @@ -3019,6 +3019,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;
Expand All @@ -3045,6 +3046,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;
Expand Down Expand Up @@ -3082,6 +3084,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;
Expand Down Expand Up @@ -3126,6 +3129,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;
Expand Down Expand Up @@ -3278,6 +3282,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);
Expand Down
2 changes: 2 additions & 0 deletions drivers/video/fbmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1177,8 +1177,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:
Expand Down

0 comments on commit 054430e

Please sign in to comment.