Commit 81732c3b authored by Jean-François Moine's avatar Jean-François Moine Committed by Greg Kroah-Hartman

tty vt: Fix line garbage in virtual console on command line edition

On some machines using a specific hardware for console screen output,
the update of the pixel frame buffer does not work correctly when
using command line edition. This may be due to a memory cache bug
in the machine on which the problem has been found, but an other
solution is possible.

This patch proposes to avoid touching directly the pixel frame buffer
and to rebuild each character using the standard putc() function
on command line edition.

The resulting code is smaller and not obviously slower (no read
access to the pixel frame buffer).

Tested on a Cubox (ARM Marvell Dove 88AP510 SoC).
Signed-off-by: default avatarJean-François Moine <moinejf@free.fr>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7b6031a7
...@@ -537,45 +537,27 @@ void complement_pos(struct vc_data *vc, int offset) ...@@ -537,45 +537,27 @@ void complement_pos(struct vc_data *vc, int offset)
static void insert_char(struct vc_data *vc, unsigned int nr) static void insert_char(struct vc_data *vc, unsigned int nr)
{ {
unsigned short *p, *q = (unsigned short *)vc->vc_pos; unsigned short *p = (unsigned short *) vc->vc_pos;
p = q + vc->vc_cols - nr - vc->vc_x; scr_memmovew(p + nr, p, vc->vc_cols - vc->vc_x);
while (--p >= q) scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
scr_writew(scr_readw(p), p + nr);
scr_memsetw(q, vc->vc_video_erase_char, nr * 2);
vc->vc_need_wrap = 0; vc->vc_need_wrap = 0;
if (DO_UPDATE(vc)) { if (DO_UPDATE(vc))
unsigned short oldattr = vc->vc_attr; do_update_region(vc, (unsigned long) p,
vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x, vc->vc_y, vc->vc_x + nr, 1, (vc->vc_cols - vc->vc_x) / 2 + 1);
vc->vc_cols - vc->vc_x - nr);
vc->vc_attr = vc->vc_video_erase_char >> 8;
while (nr--)
vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y, vc->vc_x + nr);
vc->vc_attr = oldattr;
}
} }
static void delete_char(struct vc_data *vc, unsigned int nr) static void delete_char(struct vc_data *vc, unsigned int nr)
{ {
unsigned int i = vc->vc_x; unsigned short *p = (unsigned short *) vc->vc_pos;
unsigned short *p = (unsigned short *)vc->vc_pos;
while (++i <= vc->vc_cols - nr) { scr_memcpyw(p, p + nr, vc->vc_cols - vc->vc_x - nr);
scr_writew(scr_readw(p+nr), p); scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char,
p++; nr * 2);
}
scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
vc->vc_need_wrap = 0; vc->vc_need_wrap = 0;
if (DO_UPDATE(vc)) { if (DO_UPDATE(vc))
unsigned short oldattr = vc->vc_attr; do_update_region(vc, (unsigned long) p,
vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x + nr, vc->vc_y, vc->vc_x, 1, (vc->vc_cols - vc->vc_x) / 2);
vc->vc_cols - vc->vc_x - nr);
vc->vc_attr = vc->vc_video_erase_char >> 8;
while (nr--)
vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y,
vc->vc_cols - 1 - nr);
vc->vc_attr = oldattr;
}
} }
static int softcursor_original; static int softcursor_original;
...@@ -1172,45 +1154,26 @@ static void csi_J(struct vc_data *vc, int vpar) ...@@ -1172,45 +1154,26 @@ static void csi_J(struct vc_data *vc, int vpar)
case 0: /* erase from cursor to end of display */ case 0: /* erase from cursor to end of display */
count = (vc->vc_scr_end - vc->vc_pos) >> 1; count = (vc->vc_scr_end - vc->vc_pos) >> 1;
start = (unsigned short *)vc->vc_pos; start = (unsigned short *)vc->vc_pos;
if (DO_UPDATE(vc)) {
/* do in two stages */
vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
vc->vc_cols - vc->vc_x);
vc->vc_sw->con_clear(vc, vc->vc_y + 1, 0,
vc->vc_rows - vc->vc_y - 1,
vc->vc_cols);
}
break; break;
case 1: /* erase from start to cursor */ case 1: /* erase from start to cursor */
count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1; count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
start = (unsigned short *)vc->vc_origin; start = (unsigned short *)vc->vc_origin;
if (DO_UPDATE(vc)) {
/* do in two stages */
vc->vc_sw->con_clear(vc, 0, 0, vc->vc_y,
vc->vc_cols);
vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
vc->vc_x + 1);
}
break; break;
case 3: /* erase scroll-back buffer (and whole display) */ case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char, scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size >> 1); vc->vc_screenbuf_size >> 1);
set_origin(vc); set_origin(vc);
if (CON_IS_VISIBLE(vc))
update_screen(vc);
/* fall through */ /* fall through */
case 2: /* erase whole display */ case 2: /* erase whole display */
count = vc->vc_cols * vc->vc_rows; count = vc->vc_cols * vc->vc_rows;
start = (unsigned short *)vc->vc_origin; start = (unsigned short *)vc->vc_origin;
if (DO_UPDATE(vc))
vc->vc_sw->con_clear(vc, 0, 0,
vc->vc_rows,
vc->vc_cols);
break; break;
default: default:
return; return;
} }
scr_memsetw(start, vc->vc_video_erase_char, 2 * count); scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
if (DO_UPDATE(vc))
do_update_region(vc, (unsigned long) start, count);
vc->vc_need_wrap = 0; vc->vc_need_wrap = 0;
} }
...@@ -1223,29 +1186,22 @@ static void csi_K(struct vc_data *vc, int vpar) ...@@ -1223,29 +1186,22 @@ static void csi_K(struct vc_data *vc, int vpar)
case 0: /* erase from cursor to end of line */ case 0: /* erase from cursor to end of line */
count = vc->vc_cols - vc->vc_x; count = vc->vc_cols - vc->vc_x;
start = (unsigned short *)vc->vc_pos; start = (unsigned short *)vc->vc_pos;
if (DO_UPDATE(vc))
vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
vc->vc_cols - vc->vc_x);
break; break;
case 1: /* erase from start of line to cursor */ case 1: /* erase from start of line to cursor */
start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1)); start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
count = vc->vc_x + 1; count = vc->vc_x + 1;
if (DO_UPDATE(vc))
vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
vc->vc_x + 1);
break; break;
case 2: /* erase whole line */ case 2: /* erase whole line */
start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1)); start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
count = vc->vc_cols; count = vc->vc_cols;
if (DO_UPDATE(vc))
vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
vc->vc_cols);
break; break;
default: default:
return; return;
} }
scr_memsetw(start, vc->vc_video_erase_char, 2 * count); scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
vc->vc_need_wrap = 0; vc->vc_need_wrap = 0;
if (DO_UPDATE(vc))
do_update_region(vc, (unsigned long) start, count);
} }
static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */ static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */
......
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