| From bfd8d8fe98b8792f362cd210a7873969f8d2fc04 Mon Sep 17 00:00:00 2001 |
| From: Nicolas Pitre <nicolas.pitre@linaro.org> |
| Date: Thu, 10 Jan 2019 16:33:55 -0500 |
| Subject: vgacon: unconfuse vc_origin when using soft scrollback |
| |
| From: Nicolas Pitre <nicolas.pitre@linaro.org> |
| |
| commit bfd8d8fe98b8792f362cd210a7873969f8d2fc04 upstream. |
| |
| When CONFIG_VGACON_SOFT_SCROLLBACK is selected, the VGA display memory |
| index and vc_visible_origin don't change when scrollback is activated. |
| The actual screen content is saved away and the scrollbackdata is copied |
| over it. However the vt code, and /dev/vcs devices in particular, still |
| expect vc_origin to always point at the actual screen content not the |
| displayed scrollback content. |
| |
| So adjust vc_origin to point at the saved screen content when scrollback |
| is active and set it back to vc_visible_origin when restoring the screen. |
| |
| This fixes /dev/vcsa<n> that return scrollback content when they |
| shouldn't (onli /dev/vcsa without a number should), and also fixes |
| /dev/vcsu that should return scrollback content when scrollback is |
| active but currently doesn't. |
| |
| An unnecessary call to vga_set_mem_top() is also removed. |
| |
| Signed-off-by: Nicolas Pitre <nico@linaro.org> |
| Cc: stable@vger.kernel.org # v4.19+ |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/video/console/vgacon.c | 7 ++++--- |
| 1 file changed, 4 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/video/console/vgacon.c |
| +++ b/drivers/video/console/vgacon.c |
| @@ -271,6 +271,7 @@ static void vgacon_scrollback_update(str |
| |
| static void vgacon_restore_screen(struct vc_data *c) |
| { |
| + c->vc_origin = c->vc_visible_origin; |
| vgacon_scrollback_cur->save = 0; |
| |
| if (!vga_is_gfx && !vgacon_scrollback_cur->restore) { |
| @@ -287,8 +288,7 @@ static void vgacon_scrolldelta(struct vc |
| int start, end, count, soff; |
| |
| if (!lines) { |
| - c->vc_visible_origin = c->vc_origin; |
| - vga_set_mem_top(c); |
| + vgacon_restore_screen(c); |
| return; |
| } |
| |
| @@ -298,6 +298,7 @@ static void vgacon_scrolldelta(struct vc |
| if (!vgacon_scrollback_cur->save) { |
| vgacon_cursor(c, CM_ERASE); |
| vgacon_save_screen(c); |
| + c->vc_origin = (unsigned long)c->vc_screenbuf; |
| vgacon_scrollback_cur->save = 1; |
| } |
| |
| @@ -335,7 +336,7 @@ static void vgacon_scrolldelta(struct vc |
| int copysize; |
| |
| int diff = c->vc_rows - count; |
| - void *d = (void *) c->vc_origin; |
| + void *d = (void *) c->vc_visible_origin; |
| void *s = (void *) c->vc_screenbuf; |
| |
| count *= c->vc_size_row; |