[PATCH] vgacon/vt: clear buffer attributes when we load a 512 character font (v2)

2013-01-24 Thread Dave Airlie
From: Dave Airlie 

When we switch from 256->512 byte font rendering mode, it means the
current contents of the screen is being reinterpreted. The bit that holds
the high bit of the 9-bit font, may have been previously set, and thus
the new font misrenders.

The problem case we see is grub2 writes spaces with the bit set, so it
ends up with data like 0x820, which gets reinterpreted into 0x120 char
which the font translates into G with a circumflex. This flashes up on
screen at boot and is quite ugly.

A current side effect of this patch though is that any rendering on the
screen changes color to a slightly darker color, but at least the screen
no longer corrupts.

v2: as suggested by hpa, always clear the attribute space, whether we
are are going to or from 512 chars.

Signed-off-by: Dave Airlie 

f
---
 drivers/tty/vt/vt.c|  2 +-
 drivers/video/console/vgacon.c | 22 +++---
 include/linux/vt_kern.h|  1 +
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 8fd8968..c8067ae 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -638,7 +638,7 @@ static inline void save_screen(struct vc_data *vc)
  * Redrawing of screen
  */
 
-static void clear_buffer_attributes(struct vc_data *vc)
+void clear_buffer_attributes(struct vc_data *vc)
 {
unsigned short *p = (unsigned short *)vc->vc_origin;
int count = vc->vc_screenbuf_size / 2;
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index d449a74..5855d17 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -1064,7 +1064,7 @@ static int vgacon_do_font_op(struct vgastate *state,char 
*arg,int set,int ch512)
unsigned short video_port_status = vga_video_port_reg + 6;
int font_select = 0x00, beg, i;
char *charmap;
-   
+   bool clear_attribs = false;
if (vga_video_type != VIDEO_TYPE_EGAM) {
charmap = (char *) VGA_MAP_MEM(colourmap, 0);
beg = 0x0e;
@@ -1169,12 +1169,6 @@ static int vgacon_do_font_op(struct vgastate *state,char 
*arg,int set,int ch512)
 
/* if 512 char mode is already enabled don't re-enable it. */
if ((set) && (ch512 != vga_512_chars)) {
-   /* attribute controller */
-   for (i = 0; i < MAX_NR_CONSOLES; i++) {
-   struct vc_data *c = vc_cons[i].d;
-   if (c && c->vc_sw == &vga_con)
-   c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
-   }
vga_512_chars = ch512;
/* 256-char: enable intensity bit
   512-char: disable intensity bit */
@@ -1185,8 +1179,22 @@ static int vgacon_do_font_op(struct vgastate *state,char 
*arg,int set,int ch512)
   it means, but it works, and it appears necessary */
inb_p(video_port_status);
vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
+   clear_attribs = true;
}
raw_spin_unlock_irq(&vga_lock);
+
+   if (clear_attribs) {
+   for (i = 0; i < MAX_NR_CONSOLES; i++) {
+   struct vc_data *c = vc_cons[i].d;
+   if (c && c->vc_sw == &vga_con) {
+   /* force hi font mask to 0, so we always clear
+  the bit on either transition */
+   c->vc_hi_font_mask = 0x00;
+   clear_buffer_attributes(c);
+   c->vc_hi_font_mask = ch512 ? 0x0800 : 0;
+   }
+   }
+   }
return 0;
 }
 
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 50ae7d0..1f55665 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -47,6 +47,7 @@ int con_set_cmap(unsigned char __user *cmap);
 int con_get_cmap(unsigned char __user *cmap);
 void scrollback(struct vc_data *vc, int lines);
 void scrollfront(struct vc_data *vc, int lines);
+void clear_buffer_attributes(struct vc_data *vc);
 void update_region(struct vc_data *vc, unsigned long start, int count);
 void redraw_screen(struct vc_data *vc, int is_switch);
 #define update_screen(x) redraw_screen(x, 0)
-- 
1.8.1


--
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. ON SALE this month only -- learn more at:
http://p.sf.net/sfu/learnnow-d2d
--
___
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel


[PATCH] fbcon: fix locking harder

2013-01-24 Thread Dave Airlie
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.

Signed-off-by: Dave Airlie 
---
 drivers/gpu/vga/vga_switcheroo.c |  3 +++
 drivers/video/console/fbcon.c| 11 ---
 drivers/video/fbmem.c|  2 ++
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index fa60add..cf787e1 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -25,6 +25,7 @@
 #include 
 
 #include 
+#include 
 #include 
 
 #include 
@@ -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);
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 2aef9ca..2e2d959 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,
  *
  * 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)
 {
@@ -859,7 +861,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)
@@ -867,7 +869,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);
@@ -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;
 }
 
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 070b9a1..dc61c12 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,
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:
-- 
1.8.1


--
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. ON SALE this month only -- learn more at:
http://p.sf.net/sfu/learnnow-d2d
--
___
Dri-dev