Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter

2017-02-03 Thread Manuel Schölling
Hi Paul,

On Thu, 2017-02-02 at 15:07 -0500, Paul Gortmaker wrote:
> On Tue, Jan 10, 2017 at 4:28 PM, Manuel Schölling
> <manuel.schoell...@gmx.de> wrote:
> > The impact of the persistent scrollback feature on the code size is
> > rather small, so the config option is removed. The feature stays
> > disabled by default and can be enabled by using the boot command
> > line
> > parameter 'vgacon.scrollback_persistent=1' or by setting
> > VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> > 
> > Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
> > Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnier...@samsung.com>
> > ---
> 
> [...]
> 
> > +module_param_named(scrollback_persistent, scrollback_persistent,
> > bool, );
> > +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent
> > scrollback for all vga consoles");
> 
> Since this hasn't got widespread deployment yet and  only exists
> in Greg's tree, can we please fix the above to use setup_param or
> similar, since there is nothing modular about this code at all.
Not sure what you mean here.
If this is not the right may to declare it I'd be more than happy to
change this. But I could not find any function/macro named setup_param
[1].
It would be great if you could give me a hint what function to use
here!

Have a great weekend!

Manuel

[1] http://lxr.free-electrons.com/ident?i=setup_param


Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter

2017-02-03 Thread Manuel Schölling
Hi Paul,

On Thu, 2017-02-02 at 15:07 -0500, Paul Gortmaker wrote:
> On Tue, Jan 10, 2017 at 4:28 PM, Manuel Schölling
>  wrote:
> > The impact of the persistent scrollback feature on the code size is
> > rather small, so the config option is removed. The feature stays
> > disabled by default and can be enabled by using the boot command
> > line
> > parameter 'vgacon.scrollback_persistent=1' or by setting
> > VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> > 
> > Signed-off-by: Manuel Schölling 
> > Suggested-by: Bartlomiej Zolnierkiewicz 
> > ---
> 
> [...]
> 
> > +module_param_named(scrollback_persistent, scrollback_persistent,
> > bool, );
> > +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent
> > scrollback for all vga consoles");
> 
> Since this hasn't got widespread deployment yet and  only exists
> in Greg's tree, can we please fix the above to use setup_param or
> similar, since there is nothing modular about this code at all.
Not sure what you mean here.
If this is not the right may to declare it I'd be more than happy to
change this. But I could not find any function/macro named setup_param
[1].
It would be great if you could give me a hint what function to use
here!

Have a great weekend!

Manuel

[1] http://lxr.free-electrons.com/ident?i=setup_param


Re: [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles

2017-01-19 Thread Manuel Schölling
On Thu, 2017-01-19 at 14:23 +0100, Greg KH wrote:
> On Fri, Jan 13, 2017 at 09:07:57PM +0100, Manuel Schölling wrote:
> > Add a scrollback buffers for each VGA console. The benefit is that
> > the scrollback history is not flushed when switching between
> > consoles
> > but is persistent.
> > The buffers are allocated on demand when a new console is opened.
> > 
> > This breaks tools like clear_console that rely on flushing the
> > scrollback history by switching back and forth between consoles
> > which is why this feature is disabled by default.
> > Use the escape sequence \e[3J instead for flushing the buffer.
> > 
> > Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
> > Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
> > Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
> > Tested-by: Adam Borowski <kilob...@angband.pl>
> > ---
> >  drivers/video/console/Kconfig  |  25 +++-
> >  drivers/video/console/vgacon.c | 142 ++---
> > 
> >  2 files changed, 111 insertions(+), 56 deletions(-)
> > 
> > diff --git a/drivers/video/console/Kconfig
> > b/drivers/video/console/Kconfig
> > index c3f1fb9ee820..f500e58f7636 100644
> > --- a/drivers/video/console/Kconfig
> > +++ b/drivers/video/console/Kconfig
> > @@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
> > range 1 1024
> > default "64"
> > help
> > - Enter the amount of System RAM to allocate for the
> > scrollback
> > -    buffer.  Each 64KB will give you approximately 16 80x25
> > -    screenfuls of scrollback buffer
> > +     Enter the amount of System RAM to allocate for
> > scrollback
> > +     buffers of VGA consoles. Each 64KB will give you
> > approximately
> > +     16 80x25 screenfuls of scrollback buffer.
> > +
> > +config VGACON_SOFT_SCROLLBACK_PERSISTENT
> > +   bool "Persistent Scrollback History for each console"
> > +   depends on VGACON_SOFT_SCROLLBACK
> > +   default n
> > +   help
> > +     Say Y here if the scrollback history should persist when
> > switching
> > +     between consoles. Otherwise, the scrollback history will
> > be flushed
> > +     each time the console is switched.
> > +
> > +     This feature might break your tool of choice to flush
> > the scrollback
> > +     buffer, e.g. clear(1) will work fine but Debian's
> > clear_console(1)
> > +     will be broken, which might cause security issues.
> > +     You can use the escape sequence \e[3J instead if this
> > feature is
> > +     activated.
> 
> This issue is the one that makes me the most worried.  Why doesn't
> clear_console() work anymore?  Why doesn't it use \e[3J ?

Well, clear_console() just switches from one console to another and
back again. It just assumes that the scrollback buffer is flushed when
switching.
My plan is to make a patch for clear_console() as soon as these patches
are in the kernel - it's chicken-and-egg problem.

Bye,

Manuel



Re: [PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles

2017-01-19 Thread Manuel Schölling
On Thu, 2017-01-19 at 14:23 +0100, Greg KH wrote:
> On Fri, Jan 13, 2017 at 09:07:57PM +0100, Manuel Schölling wrote:
> > Add a scrollback buffers for each VGA console. The benefit is that
> > the scrollback history is not flushed when switching between
> > consoles
> > but is persistent.
> > The buffers are allocated on demand when a new console is opened.
> > 
> > This breaks tools like clear_console that rely on flushing the
> > scrollback history by switching back and forth between consoles
> > which is why this feature is disabled by default.
> > Use the escape sequence \e[3J instead for flushing the buffer.
> > 
> > Signed-off-by: Manuel Schölling 
> > Reviewed-by: Andrey Utkin 
> > Tested-by: Andrey Utkin 
> > Tested-by: Adam Borowski 
> > ---
> >  drivers/video/console/Kconfig  |  25 +++-
> >  drivers/video/console/vgacon.c | 142 ++---
> > 
> >  2 files changed, 111 insertions(+), 56 deletions(-)
> > 
> > diff --git a/drivers/video/console/Kconfig
> > b/drivers/video/console/Kconfig
> > index c3f1fb9ee820..f500e58f7636 100644
> > --- a/drivers/video/console/Kconfig
> > +++ b/drivers/video/console/Kconfig
> > @@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
> > range 1 1024
> > default "64"
> > help
> > - Enter the amount of System RAM to allocate for the
> > scrollback
> > -    buffer.  Each 64KB will give you approximately 16 80x25
> > -    screenfuls of scrollback buffer
> > +     Enter the amount of System RAM to allocate for
> > scrollback
> > +     buffers of VGA consoles. Each 64KB will give you
> > approximately
> > +     16 80x25 screenfuls of scrollback buffer.
> > +
> > +config VGACON_SOFT_SCROLLBACK_PERSISTENT
> > +   bool "Persistent Scrollback History for each console"
> > +   depends on VGACON_SOFT_SCROLLBACK
> > +   default n
> > +   help
> > +     Say Y here if the scrollback history should persist when
> > switching
> > +     between consoles. Otherwise, the scrollback history will
> > be flushed
> > +     each time the console is switched.
> > +
> > +     This feature might break your tool of choice to flush
> > the scrollback
> > +     buffer, e.g. clear(1) will work fine but Debian's
> > clear_console(1)
> > +     will be broken, which might cause security issues.
> > +     You can use the escape sequence \e[3J instead if this
> > feature is
> > +     activated.
> 
> This issue is the one that makes me the most worried.  Why doesn't
> clear_console() work anymore?  Why doesn't it use \e[3J ?

Well, clear_console() just switches from one console to another and
back again. It just assumes that the scrollback buffer is flushed when
switching.
My plan is to make a patch for clear_console() as soon as these patches
are in the kernel - it's chicken-and-egg problem.

Bye,

Manuel



[PATCH v10 0/4] console: Add persistent scrollback buffers for all VGA consoles

2017-01-13 Thread Manuel Schölling
Changes in v10:
  - Fix compilation error if CONFIG_VGACON_SOFT_SCROLLBACK=n
Changes in v9:
  - Make persistent scrollback feature a boot parameter
Changes in v8:
  - Add Reviewed-by/Tested-By statements
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (4):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles
  console: Make persistent scrollback a boot parameter

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  27 ++-
 drivers/video/console/vgacon.c | 164 -
 include/linux/console.h|   4 +
 4 files changed, 149 insertions(+), 55 deletions(-)

-- 
2.11.0



[PATCH v10 0/4] console: Add persistent scrollback buffers for all VGA consoles

2017-01-13 Thread Manuel Schölling
Changes in v10:
  - Fix compilation error if CONFIG_VGACON_SOFT_SCROLLBACK=n
Changes in v9:
  - Make persistent scrollback feature a boot parameter
Changes in v8:
  - Add Reviewed-by/Tested-By statements
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (4):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles
  console: Make persistent scrollback a boot parameter

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  27 ++-
 drivers/video/console/vgacon.c | 164 -
 include/linux/console.h|   4 +
 4 files changed, 149 insertions(+), 55 deletions(-)

-- 
2.11.0



[PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles

2017-01-13 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index c3f1fb9ee820..f500e58f7636 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bbc5326..ca23d222e029 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;

[PATCH v10 3/4] console: Add persistent scrollback buffers for all VGA consoles

2017-01-13 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index c3f1fb9ee820..f500e58f7636 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bbc5326..ca23d222e029 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+

[PATCH v10 4/4] console: Make persistent scrollback a boot parameter

2017-01-13 Thread Manuel Schölling
The impact of the persistent scrollback feature on the code size is
rather small, so the config option is removed. The feature stays
disabled by default and can be enabled by using the boot command line
parameter 'vgacon.scrollback_persistent=1' or by setting
VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnier...@samsung.com>
---
 drivers/video/console/Kconfig  | 12 +++-
 drivers/video/console/vgacon.c | 25 -
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index f500e58f7636..5b71bd905a60 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -47,14 +47,16 @@ config VGACON_SOFT_SCROLLBACK_SIZE
  buffers of VGA consoles. Each 64KB will give you approximately
  16 80x25 screenfuls of scrollback buffer.
 
-config VGACON_SOFT_SCROLLBACK_PERSISTENT
-   bool "Persistent Scrollback History for each console"
+config VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+   bool "Persistent Scrollback History for each console by default"
depends on VGACON_SOFT_SCROLLBACK
default n
help
- Say Y here if the scrollback history should persist when switching
- between consoles. Otherwise, the scrollback history will be flushed
- each time the console is switched.
+ Say Y here if the scrollback history should persist by default when
+ switching between consoles. Otherwise, the scrollback history will be
+ flushed each time the console is switched. This feature can also be
+ enabled using the boot command line parameter
+ 'vgacon.scrollback_persistent=1'.
 
  This feature might break your tool of choice to flush the scrollback
  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index ca23d222e029..dc06cb6a15dc 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -174,11 +174,11 @@ struct vgacon_scrollback_info {
 };
 
 static struct vgacon_scrollback_info *vgacon_scrollback_cur;
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
 static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
-#else
-static struct vgacon_scrollback_info vgacon_scrollbacks[1];
-#endif
+static bool scrollback_persistent = \
+   IS_ENABLED(CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT);
+module_param_named(scrollback_persistent, scrollback_persistent, bool, );
+MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all 
vga consoles");
 
 static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
@@ -213,20 +213,19 @@ static void vgacon_scrollback_init(int vc_num)
 
 static void vgacon_scrollback_switch(int vc_num)
 {
-#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-   vc_num = 0;
-#endif
+   if (!scrollback_persistent)
+   vc_num = 0;
 
if (!vgacon_scrollbacks[vc_num].data) {
vgacon_scrollback_init(vc_num);
} else {
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-   vgacon_scrollback_cur = _scrollbacks[vc_num];
-#else
-   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   if (scrollback_persistent) {
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+   } else {
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-   vgacon_scrollback_reset(vc_num, size);
-#endif
+   vgacon_scrollback_reset(vc_num, size);
+   }
}
 }
 
-- 
2.11.0



[PATCH v10 4/4] console: Make persistent scrollback a boot parameter

2017-01-13 Thread Manuel Schölling
The impact of the persistent scrollback feature on the code size is
rather small, so the config option is removed. The feature stays
disabled by default and can be enabled by using the boot command line
parameter 'vgacon.scrollback_persistent=1' or by setting
VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.

Signed-off-by: Manuel Schölling 
Suggested-by: Bartlomiej Zolnierkiewicz 
---
 drivers/video/console/Kconfig  | 12 +++-
 drivers/video/console/vgacon.c | 25 -
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index f500e58f7636..5b71bd905a60 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -47,14 +47,16 @@ config VGACON_SOFT_SCROLLBACK_SIZE
  buffers of VGA consoles. Each 64KB will give you approximately
  16 80x25 screenfuls of scrollback buffer.
 
-config VGACON_SOFT_SCROLLBACK_PERSISTENT
-   bool "Persistent Scrollback History for each console"
+config VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+   bool "Persistent Scrollback History for each console by default"
depends on VGACON_SOFT_SCROLLBACK
default n
help
- Say Y here if the scrollback history should persist when switching
- between consoles. Otherwise, the scrollback history will be flushed
- each time the console is switched.
+ Say Y here if the scrollback history should persist by default when
+ switching between consoles. Otherwise, the scrollback history will be
+ flushed each time the console is switched. This feature can also be
+ enabled using the boot command line parameter
+ 'vgacon.scrollback_persistent=1'.
 
  This feature might break your tool of choice to flush the scrollback
  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index ca23d222e029..dc06cb6a15dc 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -174,11 +174,11 @@ struct vgacon_scrollback_info {
 };
 
 static struct vgacon_scrollback_info *vgacon_scrollback_cur;
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
 static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
-#else
-static struct vgacon_scrollback_info vgacon_scrollbacks[1];
-#endif
+static bool scrollback_persistent = \
+   IS_ENABLED(CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT);
+module_param_named(scrollback_persistent, scrollback_persistent, bool, );
+MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all 
vga consoles");
 
 static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
@@ -213,20 +213,19 @@ static void vgacon_scrollback_init(int vc_num)
 
 static void vgacon_scrollback_switch(int vc_num)
 {
-#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-   vc_num = 0;
-#endif
+   if (!scrollback_persistent)
+   vc_num = 0;
 
if (!vgacon_scrollbacks[vc_num].data) {
vgacon_scrollback_init(vc_num);
} else {
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-   vgacon_scrollback_cur = _scrollbacks[vc_num];
-#else
-   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   if (scrollback_persistent) {
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+   } else {
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-   vgacon_scrollback_reset(vc_num, size);
-#endif
+   vgacon_scrollback_reset(vc_num, size);
+   }
}
 }
 
-- 
2.11.0



[PATCH v10 1/4] console: Move scrollback data into its own struct

2017-01-13 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a56232b7c..48b97648d4af 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
 

[PATCH v10 1/4] console: Move scrollback data into its own struct

2017-01-13 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a56232b7c..48b97648d4af 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   sta

[PATCH v10 2/4] console: Add callback to flush scrollback buffer to consw struct

2017-01-13 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>
---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9df3b91..9d3ce505e7ab 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b97648d4af..9a7c2bbc5326 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c6685587..5949d1855589 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.11.0



[PATCH v10 2/4] console: Add callback to flush scrollback buffer to consw struct

2017-01-13 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 
---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9df3b91..9d3ce505e7ab 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b97648d4af..9a7c2bbc5326 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c6685587..5949d1855589 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.11.0



Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter

2017-01-13 Thread Manuel Schölling
On Tue, 2017-01-10 at 23:58 +0100, Adam Borowski wrote:
> On Tue, Jan 10, 2017 at 10:28:38PM +0100, Manuel Schölling wrote:
> > The impact of the persistent scrollback feature on the code size is
> > rather small, so the config option is removed. The feature stays
> > disabled by default and can be enabled by using the boot command
> > line
> > parameter 'vgacon.scrollback_persistent=1' or by setting
> > VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> > 
> > Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
> > Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnier...@samsung.com>
> > +module_param_named(scrollback_persistent, scrollback_persistent,
> > bool, );
> > +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent
> > scrollback for all vga consoles");
> 
> A command-line knob settable by the end-user is something more
> persistent
> than a config option.  As you're going to extend this code beyond
> vgacon in
> the near future, perhaps it'd be better to have a shared setting for
> all
> console drivers?
According to the guys at #kernelnewbies on IRC everybody hates new
command line options.
I'd rather stick to the module parameter for now and maybe introduce a 
new cmd line option later, once this feature has been implemented in
several console drivers.

Bye,

Manuel



Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter

2017-01-13 Thread Manuel Schölling
On Tue, 2017-01-10 at 23:58 +0100, Adam Borowski wrote:
> On Tue, Jan 10, 2017 at 10:28:38PM +0100, Manuel Schölling wrote:
> > The impact of the persistent scrollback feature on the code size is
> > rather small, so the config option is removed. The feature stays
> > disabled by default and can be enabled by using the boot command
> > line
> > parameter 'vgacon.scrollback_persistent=1' or by setting
> > VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> > 
> > Signed-off-by: Manuel Schölling 
> > Suggested-by: Bartlomiej Zolnierkiewicz 
> > +module_param_named(scrollback_persistent, scrollback_persistent,
> > bool, );
> > +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent
> > scrollback for all vga consoles");
> 
> A command-line knob settable by the end-user is something more
> persistent
> than a config option.  As you're going to extend this code beyond
> vgacon in
> the near future, perhaps it'd be better to have a shared setting for
> all
> console drivers?
According to the guys at #kernelnewbies on IRC everybody hates new
command line options.
I'd rather stick to the module parameter for now and maybe introduce a 
new cmd line option later, once this feature has been implemented in
several console drivers.

Bye,

Manuel



Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter

2017-01-11 Thread Manuel Schölling
On Tue, 2017-01-10 at 23:58 +0100, Adam Borowski wrote:
> On Tue, Jan 10, 2017 at 10:28:38PM +0100, Manuel Schölling wrote:
> > The impact of the persistent scrollback feature on the code size is
> > rather small, so the config option is removed. The feature stays
> > disabled by default and can be enabled by using the boot command
> > line
> > parameter 'vgacon.scrollback_persistent=1' or by setting
> > VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> > 
> > Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
> > Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnier...@samsung.com>
> > +module_param_named(scrollback_persistent, scrollback_persistent,
> > bool, );
> > +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent
> > scrollback for all vga consoles");
> 
> A command-line knob settable by the end-user is something more
> persistent
> than a config option.  As you're going to extend this code beyond
> vgacon in
> the near future, perhaps it'd be better to have a shared setting for
> all
> console drivers?
Probably a good idea, but I'm struggling with the implementation a bit:

I tried to run 

  if (strstr(boot_command_line, "nopersistentscrollback")) {...}

in vgacon_scrollback_startup() but I am getting 

  WARNING: modpost: Found 2 section mismatch(es).

when compiling. Probably because vgacon_scrollback_startup() is
executed after init.

I tried to find another way to implement a boot cmd line parameter but
had no luck.
If you/somebody could point me in the right direction, it would be very
much appreciated.

Thanks!

Manuel



Re: [PATCH v9 4/4] console: Make persistent scrollback a boot parameter

2017-01-11 Thread Manuel Schölling
On Tue, 2017-01-10 at 23:58 +0100, Adam Borowski wrote:
> On Tue, Jan 10, 2017 at 10:28:38PM +0100, Manuel Schölling wrote:
> > The impact of the persistent scrollback feature on the code size is
> > rather small, so the config option is removed. The feature stays
> > disabled by default and can be enabled by using the boot command
> > line
> > parameter 'vgacon.scrollback_persistent=1' or by setting
> > VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.
> > 
> > Signed-off-by: Manuel Schölling 
> > Suggested-by: Bartlomiej Zolnierkiewicz 
> > +module_param_named(scrollback_persistent, scrollback_persistent,
> > bool, );
> > +MODULE_PARM_DESC(scrollback_persistent, "Enable persistent
> > scrollback for all vga consoles");
> 
> A command-line knob settable by the end-user is something more
> persistent
> than a config option.  As you're going to extend this code beyond
> vgacon in
> the near future, perhaps it'd be better to have a shared setting for
> all
> console drivers?
Probably a good idea, but I'm struggling with the implementation a bit:

I tried to run 

  if (strstr(boot_command_line, "nopersistentscrollback")) {...}

in vgacon_scrollback_startup() but I am getting 

  WARNING: modpost: Found 2 section mismatch(es).

when compiling. Probably because vgacon_scrollback_startup() is
executed after init.

I tried to find another way to implement a boot cmd line parameter but
had no luck.
If you/somebody could point me in the right direction, it would be very
much appreciated.

Thanks!

Manuel



[PATCH v9 2/4] console: Add callback to flush scrollback buffer to consw struct

2017-01-10 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>
---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9df3b91..9d3ce505e7ab 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b97648d4af..9a7c2bbc5326 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c6685587..5949d1855589 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.11.0



[PATCH v9 0/4] console: Add persistent scrollback buffers for all VGA consoles

2017-01-10 Thread Manuel Schölling
--
Changes in v9:
  - Make persistent scrollback feature a boot parameter
Changes in v8:
  - Add Reviewed-by/Tested-By statements
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.11.0



[PATCH v9 2/4] console: Add callback to flush scrollback buffer to consw struct

2017-01-10 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 
---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9df3b91..9d3ce505e7ab 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b97648d4af..9a7c2bbc5326 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c6685587..5949d1855589 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.11.0



[PATCH v9 0/4] console: Add persistent scrollback buffers for all VGA consoles

2017-01-10 Thread Manuel Schölling
--
Changes in v9:
  - Make persistent scrollback feature a boot parameter
Changes in v8:
  - Add Reviewed-by/Tested-By statements
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.11.0



[PATCH v9 3/4] console: Add persistent scrollback buffers for all VGA consoles

2017-01-10 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index c3f1fb9ee820..f500e58f7636 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bbc5326..ca23d222e029 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;

[PATCH v9 4/4] console: Make persistent scrollback a boot parameter

2017-01-10 Thread Manuel Schölling
The impact of the persistent scrollback feature on the code size is
rather small, so the config option is removed. The feature stays
disabled by default and can be enabled by using the boot command line
parameter 'vgacon.scrollback_persistent=1' or by setting
VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Suggested-by: Bartlomiej Zolnierkiewicz <b.zolnier...@samsung.com>
---
 drivers/video/console/Kconfig  | 12 +++-
 drivers/video/console/vgacon.c | 25 -
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index f500e58f7636..5b71bd905a60 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -47,14 +47,16 @@ config VGACON_SOFT_SCROLLBACK_SIZE
  buffers of VGA consoles. Each 64KB will give you approximately
  16 80x25 screenfuls of scrollback buffer.
 
-config VGACON_SOFT_SCROLLBACK_PERSISTENT
-   bool "Persistent Scrollback History for each console"
+config VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+   bool "Persistent Scrollback History for each console by default"
depends on VGACON_SOFT_SCROLLBACK
default n
help
- Say Y here if the scrollback history should persist when switching
- between consoles. Otherwise, the scrollback history will be flushed
- each time the console is switched.
+ Say Y here if the scrollback history should persist by default when
+ switching between consoles. Otherwise, the scrollback history will be
+ flushed each time the console is switched. This feature can also be
+ enabled using the boot command line parameter
+ 'vgacon.scrollback_persistent=1'.
 
  This feature might break your tool of choice to flush the scrollback
  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index ca23d222e029..45a76972495b 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -174,11 +174,9 @@ struct vgacon_scrollback_info {
 };
 
 static struct vgacon_scrollback_info *vgacon_scrollback_cur;
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
 static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
-#else
-static struct vgacon_scrollback_info vgacon_scrollbacks[1];
-#endif
+static bool scrollback_persistent = \
+   IS_ENABLED(CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT);
 
 static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
@@ -213,20 +211,19 @@ static void vgacon_scrollback_init(int vc_num)
 
 static void vgacon_scrollback_switch(int vc_num)
 {
-#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-   vc_num = 0;
-#endif
+   if (!scrollback_persistent)
+   vc_num = 0;
 
if (!vgacon_scrollbacks[vc_num].data) {
vgacon_scrollback_init(vc_num);
} else {
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-   vgacon_scrollback_cur = _scrollbacks[vc_num];
-#else
-   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   if (scrollback_persistent) {
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+   } else {
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-   vgacon_scrollback_reset(vc_num, size);
-#endif
+   vgacon_scrollback_reset(vc_num, size);
+   }
}
 }
 
@@ -1423,4 +1420,6 @@ const struct consw vga_con = {
 };
 EXPORT_SYMBOL(vga_con);
 
+module_param_named(scrollback_persistent, scrollback_persistent, bool, );
+MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all 
vga consoles");
 MODULE_LICENSE("GPL");
-- 
2.11.0



[PATCH v9 1/4] console: Move scrollback data into its own struct

2017-01-10 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a56232b7c..48b97648d4af 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
 

[PATCH v9 3/4] console: Add persistent scrollback buffers for all VGA consoles

2017-01-10 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index c3f1fb9ee820..f500e58f7636 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bbc5326..ca23d222e029 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+

[PATCH v9 4/4] console: Make persistent scrollback a boot parameter

2017-01-10 Thread Manuel Schölling
The impact of the persistent scrollback feature on the code size is
rather small, so the config option is removed. The feature stays
disabled by default and can be enabled by using the boot command line
parameter 'vgacon.scrollback_persistent=1' or by setting
VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT=y.

Signed-off-by: Manuel Schölling 
Suggested-by: Bartlomiej Zolnierkiewicz 
---
 drivers/video/console/Kconfig  | 12 +++-
 drivers/video/console/vgacon.c | 25 -
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index f500e58f7636..5b71bd905a60 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -47,14 +47,16 @@ config VGACON_SOFT_SCROLLBACK_SIZE
  buffers of VGA consoles. Each 64KB will give you approximately
  16 80x25 screenfuls of scrollback buffer.
 
-config VGACON_SOFT_SCROLLBACK_PERSISTENT
-   bool "Persistent Scrollback History for each console"
+config VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+   bool "Persistent Scrollback History for each console by default"
depends on VGACON_SOFT_SCROLLBACK
default n
help
- Say Y here if the scrollback history should persist when switching
- between consoles. Otherwise, the scrollback history will be flushed
- each time the console is switched.
+ Say Y here if the scrollback history should persist by default when
+ switching between consoles. Otherwise, the scrollback history will be
+ flushed each time the console is switched. This feature can also be
+ enabled using the boot command line parameter
+ 'vgacon.scrollback_persistent=1'.
 
  This feature might break your tool of choice to flush the scrollback
  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index ca23d222e029..45a76972495b 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -174,11 +174,9 @@ struct vgacon_scrollback_info {
 };
 
 static struct vgacon_scrollback_info *vgacon_scrollback_cur;
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
 static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
-#else
-static struct vgacon_scrollback_info vgacon_scrollbacks[1];
-#endif
+static bool scrollback_persistent = \
+   IS_ENABLED(CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT);
 
 static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
@@ -213,20 +211,19 @@ static void vgacon_scrollback_init(int vc_num)
 
 static void vgacon_scrollback_switch(int vc_num)
 {
-#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-   vc_num = 0;
-#endif
+   if (!scrollback_persistent)
+   vc_num = 0;
 
if (!vgacon_scrollbacks[vc_num].data) {
vgacon_scrollback_init(vc_num);
} else {
-#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
-   vgacon_scrollback_cur = _scrollbacks[vc_num];
-#else
-   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   if (scrollback_persistent) {
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+   } else {
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
 
-   vgacon_scrollback_reset(vc_num, size);
-#endif
+   vgacon_scrollback_reset(vc_num, size);
+   }
}
 }
 
@@ -1423,4 +1420,6 @@ const struct consw vga_con = {
 };
 EXPORT_SYMBOL(vga_con);
 
+module_param_named(scrollback_persistent, scrollback_persistent, bool, );
+MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all 
vga consoles");
 MODULE_LICENSE("GPL");
-- 
2.11.0



[PATCH v9 1/4] console: Move scrollback data into its own struct

2017-01-10 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a56232b7c..48b97648d4af 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   sta

Re: [PATCH v8 3/3] console: Add persistent scrollback buffers for all VGA consoles

2017-01-10 Thread Manuel Schölling
Hi Bartlomiej,

First of all thank you for you feedback!

On Tue, 2017-01-10 at 17:44 +0100, Bartlomiej Zolnierkiewicz wrote:
> On Tuesday, January 10, 2017 05:22:22 PM Bartlomiej Zolnierkiewicz
> wrote:
> > 
> > Hi,
> > 
> > The patchset generally looks fine to me but I have a question
> > regarding new VGACON_SOFT_SCROLLBACK_PERSISTENT config option.
> > 
> > Since the code size impact to support the persistent scrollback
> > feature is minimal wouldn't it be better to always include it?
> > 
> > The feature would be disabled by default and could be enabled
> > by using the new kernel command line parameter (you may also add
> > a new config option for enabling it by default if desired).
> 
> Something like:
> 
> #ifdef VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
> static bool scrollback_persistent = 1;
> #else
> static bool scrollback_persistent;
> #endif
> 
> module_param_named(scrollback_persistent, scrollback_persistent,
> bool, 0);
> MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback
> feature");
> 
> and then use scrollback_persistent variable in
> vgacon_scrollback_switch()
> to control the actual behavior instead of ifdefs.
Sounds pretty good to me. You are right: The code size impact is rather
small. I will apply your suggestions and send you another patch as soon
as I find the time to implement it (should be any time this week).

Thanks again!

Manuel



> Best regards,
> --
> Bartlomiej Zolnierkiewicz
> Samsung R Institute Poland
> Samsung Electronics
> 
> > Best regards,
> > --
> > Bartlomiej Zolnierkiewicz
> > Samsung R Institute Poland
> > Samsung Electronics
> > 
> > On Thursday, January 05, 2017 12:33:20 PM Manuel Schölling wrote:
> > > Add a scrollback buffers for each VGA console. The benefit is
> > > that
> > > the scrollback history is not flushed when switching between
> > > consoles
> > > but is persistent.
> > > The buffers are allocated on demand when a new console is opened.
> > > 
> > > This breaks tools like clear_console that rely on flushing the
> > > scrollback history by switching back and forth between consoles
> > > which is why this feature is disabled by default.
> > > Use the escape sequence \e[3J instead for flushing the buffer.
> > > 
> > > Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
> > > Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
> > > Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
> > > Tested-by: Adam Borowski <kilob...@angband.pl>
> > > ---
> > >  drivers/video/console/Kconfig  |  25 +++-
> > >  drivers/video/console/vgacon.c | 142 ++-
> > > --
> > >  2 files changed, 111 insertions(+), 56 deletions(-)
> > > 
> > > diff --git a/drivers/video/console/Kconfig
> > > b/drivers/video/console/Kconfig
> > > index c3f1fb9ee820..f500e58f7636 100644
> > > --- a/drivers/video/console/Kconfig
> > > +++ b/drivers/video/console/Kconfig
> > > @@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
> > > range 1 1024
> > > default "64"
> > > help
> > > - Enter the amount of System RAM to allocate for the
> > > scrollback
> > > -  buffer.  Each 64KB will give you approximately 16 80x25
> > > -  screenfuls of scrollback buffer
> > > +   Enter the amount of System RAM to allocate for
> > > scrollback
> > > +   buffers of VGA consoles. Each 64KB will give you
> > > approximately
> > > +   16 80x25 screenfuls of scrollback buffer.
> > > +
> > > +config VGACON_SOFT_SCROLLBACK_PERSISTENT
> > > + bool "Persistent Scrollback History for each console"
> > > + depends on VGACON_SOFT_SCROLLBACK
> > > + default n
> > > + help
> > > +   Say Y here if the scrollback history should persist
> > > when switching
> > > +   between consoles. Otherwise, the scrollback history
> > > will be flushed
> > > +   each time the console is switched.
> > > +
> > > +   This feature might break your tool of choice to flush
> > > the scrollback
> > > +   buffer, e.g. clear(1) will work fine but Debian's
> > > clear_console(1)
> > > +   will be broken, which might cause security issues.
> > > +   You can use the escape sequence \e[3J instead if this
> > > feature is
> > > +   activated.
> > > +
> > 

Re: [PATCH v8 3/3] console: Add persistent scrollback buffers for all VGA consoles

2017-01-10 Thread Manuel Schölling
Hi Bartlomiej,

First of all thank you for you feedback!

On Tue, 2017-01-10 at 17:44 +0100, Bartlomiej Zolnierkiewicz wrote:
> On Tuesday, January 10, 2017 05:22:22 PM Bartlomiej Zolnierkiewicz
> wrote:
> > 
> > Hi,
> > 
> > The patchset generally looks fine to me but I have a question
> > regarding new VGACON_SOFT_SCROLLBACK_PERSISTENT config option.
> > 
> > Since the code size impact to support the persistent scrollback
> > feature is minimal wouldn't it be better to always include it?
> > 
> > The feature would be disabled by default and could be enabled
> > by using the new kernel command line parameter (you may also add
> > a new config option for enabling it by default if desired).
> 
> Something like:
> 
> #ifdef VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
> static bool scrollback_persistent = 1;
> #else
> static bool scrollback_persistent;
> #endif
> 
> module_param_named(scrollback_persistent, scrollback_persistent,
> bool, 0);
> MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback
> feature");
> 
> and then use scrollback_persistent variable in
> vgacon_scrollback_switch()
> to control the actual behavior instead of ifdefs.
Sounds pretty good to me. You are right: The code size impact is rather
small. I will apply your suggestions and send you another patch as soon
as I find the time to implement it (should be any time this week).

Thanks again!

Manuel



> Best regards,
> --
> Bartlomiej Zolnierkiewicz
> Samsung R Institute Poland
> Samsung Electronics
> 
> > Best regards,
> > --
> > Bartlomiej Zolnierkiewicz
> > Samsung R Institute Poland
> > Samsung Electronics
> > 
> > On Thursday, January 05, 2017 12:33:20 PM Manuel Schölling wrote:
> > > Add a scrollback buffers for each VGA console. The benefit is
> > > that
> > > the scrollback history is not flushed when switching between
> > > consoles
> > > but is persistent.
> > > The buffers are allocated on demand when a new console is opened.
> > > 
> > > This breaks tools like clear_console that rely on flushing the
> > > scrollback history by switching back and forth between consoles
> > > which is why this feature is disabled by default.
> > > Use the escape sequence \e[3J instead for flushing the buffer.
> > > 
> > > Signed-off-by: Manuel Schölling 
> > > Reviewed-by: Andrey Utkin 
> > > Tested-by: Andrey Utkin 
> > > Tested-by: Adam Borowski 
> > > ---
> > >  drivers/video/console/Kconfig  |  25 +++-
> > >  drivers/video/console/vgacon.c | 142 ++-
> > > --
> > >  2 files changed, 111 insertions(+), 56 deletions(-)
> > > 
> > > diff --git a/drivers/video/console/Kconfig
> > > b/drivers/video/console/Kconfig
> > > index c3f1fb9ee820..f500e58f7636 100644
> > > --- a/drivers/video/console/Kconfig
> > > +++ b/drivers/video/console/Kconfig
> > > @@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
> > > range 1 1024
> > > default "64"
> > > help
> > > - Enter the amount of System RAM to allocate for the
> > > scrollback
> > > -  buffer.  Each 64KB will give you approximately 16 80x25
> > > -  screenfuls of scrollback buffer
> > > +   Enter the amount of System RAM to allocate for
> > > scrollback
> > > +   buffers of VGA consoles. Each 64KB will give you
> > > approximately
> > > +   16 80x25 screenfuls of scrollback buffer.
> > > +
> > > +config VGACON_SOFT_SCROLLBACK_PERSISTENT
> > > + bool "Persistent Scrollback History for each console"
> > > + depends on VGACON_SOFT_SCROLLBACK
> > > + default n
> > > + help
> > > +   Say Y here if the scrollback history should persist
> > > when switching
> > > +   between consoles. Otherwise, the scrollback history
> > > will be flushed
> > > +   each time the console is switched.
> > > +
> > > +   This feature might break your tool of choice to flush
> > > the scrollback
> > > +   buffer, e.g. clear(1) will work fine but Debian's
> > > clear_console(1)
> > > +   will be broken, which might cause security issues.
> > > +   You can use the escape sequence \e[3J instead if this
> > > feature is
> > > +   activated.
> > > +
> > > +   Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is
> > > taken for each
> > > +   created tty

[PATCH v8 0/3] console: Add persistent scrollback buffers for all VGA consoles

2017-01-05 Thread Manuel Schölling
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

--
Changes in v8:
  - Add Reviewed-by/Tested-By statements
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.11.0



[PATCH v8 0/3] console: Add persistent scrollback buffers for all VGA consoles

2017-01-05 Thread Manuel Schölling
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

--
Changes in v8:
  - Add Reviewed-by/Tested-By statements
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.11.0



[PATCH v8 1/3] console: Move scrollback data into its own struct

2017-01-05 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a56232b7c..48b97648d4af 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
 

[PATCH v8 1/3] console: Move scrollback data into its own struct

2017-01-05 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a56232b7c..48b97648d4af 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   sta

[PATCH v8 2/3] console: Add callback to flush scrollback buffer to consw struct

2017-01-05 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>
---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9df3b91..9d3ce505e7ab 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b97648d4af..9a7c2bbc5326 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c6685587..5949d1855589 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.11.0



[PATCH v8 2/3] console: Add callback to flush scrollback buffer to consw struct

2017-01-05 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 
---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9df3b91..9d3ce505e7ab 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b97648d4af..9a7c2bbc5326 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c6685587..5949d1855589 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.11.0



[PATCH v8 3/3] console: Add persistent scrollback buffers for all VGA consoles

2017-01-05 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index c3f1fb9ee820..f500e58f7636 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bbc5326..ca23d222e029 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;

[PATCH v8 3/3] console: Add persistent scrollback buffers for all VGA consoles

2017-01-05 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index c3f1fb9ee820..f500e58f7636 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bbc5326..ca23d222e029 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+

[PATCH RESEND v7 1/3] console: Move scrollback data into its own struct

2017-01-02 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
 

[PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct

2017-01-02 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9d..9d3ce50 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..9a7c2bb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c66..5949d18 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.1.4



[PATCH RESEND v7 1/3] console: Move scrollback data into its own struct

2017-01-02 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   sta

[PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct

2017-01-02 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9d..9d3ce50 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..9a7c2bb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c66..5949d18 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.1.4



[PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2017-01-02 Thread Manuel Schölling
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

--
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.1.4



[PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles

2017-01-02 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bb..ca23d22 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vg

[PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2017-01-02 Thread Manuel Schölling
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

--
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.1.4



[PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles

2017-01-02 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bb..ca23d22 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_

[PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct

2016-12-21 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9d..9d3ce50 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..9a7c2bb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c66..5949d18 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.1.4



[PATCH RESEND v7 2/3] console: Add callback to flush scrollback buffer to consw struct

2016-12-21 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9d..9d3ce50 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..9a7c2bb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c66..5949d18 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.1.4



[PATCH RESEND v7 1/3] console: Move scrollback data into its own struct

2016-12-21 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
 

[PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-21 Thread Manuel Schölling
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

--
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.1.4



[PATCH RESEND v7 1/3] console: Move scrollback data into its own struct

2016-12-21 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   sta

[PATCH RESEND v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-21 Thread Manuel Schölling
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

--
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.1.4



[PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-21 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bb..ca23d22 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vg

[PATCH RESEND v7 3/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-21 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bb..ca23d22 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_

Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-06 Thread Manuel Schölling
Hi Greg,

On Di, 2016-12-06 at 11:02 +0100, Greg KH wrote:
> On Sun, Dec 04, 2016 at 11:53:53AM +0100, Manuel Schölling wrote:
> > Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
> > Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
> > Tested-by: Adam Borowski <kilob...@angband.pl>
> > 
> > --
> > Changes in v7:
> >   - Add new callback to consw struct for flushing video console driver's
> > scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
> > by Adam Borowski (kilob...@angband.pl).
> >   - Fix style issues
> 
> But this is now v8, right?  I see two v7 patch series in my inbox :(
> 
> confused,
Sorry for causing confusion. I wasn't sure about the workflow so asked
on #kernelnewbies a few days ago but apparently I misunderstood the
advice I got there:

This is just the same patch (v7) as I sent before, but I added the
Tested-By/Reviewed-By tags.




Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-06 Thread Manuel Schölling
Hi Greg,

On Di, 2016-12-06 at 11:02 +0100, Greg KH wrote:
> On Sun, Dec 04, 2016 at 11:53:53AM +0100, Manuel Schölling wrote:
> > Reviewed-by: Andrey Utkin 
> > Tested-by: Andrey Utkin 
> > Tested-by: Adam Borowski 
> > 
> > --
> > Changes in v7:
> >   - Add new callback to consw struct for flushing video console driver's
> > scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
> > by Adam Borowski (kilob...@angband.pl).
> >   - Fix style issues
> 
> But this is now v8, right?  I see two v7 patch series in my inbox :(
> 
> confused,
Sorry for causing confusion. I wasn't sure about the workflow so asked
on #kernelnewbies a few days ago but apparently I misunderstood the
advice I got there:

This is just the same patch (v7) as I sent before, but I added the
Tested-By/Reviewed-By tags.




[PATCH v7 3/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-04 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bb..ca23d22 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vg

[PATCH v7 3/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-04 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bb..ca23d22 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_

[PATCH v7 2/3] console: Add callback to flush scrollback buffer to consw struct

2016-12-04 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9d..9d3ce50 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..9a7c2bb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c66..5949d18 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.1.4



[PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-04 Thread Manuel Schölling
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

--
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.1.4



[PATCH v7 1/3] console: Move scrollback data into its own struct

2016-12-04 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
Reviewed-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Andrey Utkin <andrey_ut...@fastmail.com>
Tested-by: Adam Borowski <kilob...@angband.pl>

---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
 

[PATCH v7 2/3] console: Add callback to flush scrollback buffer to consw struct

2016-12-04 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9d..9d3ce50 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..9a7c2bb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c66..5949d18 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.1.4



[PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-04 Thread Manuel Schölling
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

--
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.1.4



[PATCH v7 1/3] console: Move scrollback data into its own struct

2016-12-04 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling 
Reviewed-by: Andrey Utkin 
Tested-by: Andrey Utkin 
Tested-by: Adam Borowski 

---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   sta

Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-01 Thread Manuel Schölling
Hi Andrey,

On Di, 2016-11-29 at 10:01 +, Andrey Utkin wrote:
> On Mon, Nov 28, 2016 at 10:28:19PM +0100, Manuel Schölling wrote:
> Regarding logout scrollback clearing not working for me. ncurses-6.0-rc1
> which I tested it with is the latest available in Gentoo portage, please
> confirm whether I need any newer version, or should I tune something
> else. I'd appreciate if you also tested your patch with gentoo setup.

I finally setup gentoo running agetty (util-linux-2.26.2) and patching
the file term-utils/agetty.c with

static void termio_clear(int fd)
{
/*
 * Do not write a full reset (ESC c) because this destroys
 * the unicode mode again if the terminal was in unicode
 * mode.  Also it clears the CONSOLE_MAGIC features which
 * are required for some languages/console-fonts.
 * Just put the cursor to the home position (ESC [ H),
 * erase everything below the cursor (ESC [ J), and set the
 * scrolling region to the full window (ESC [ r)
 */
-   write_all(fd, "\033[r\033[H\033[J", 9);
+   write_all(fd, "\033[3J\033[r\033[H\033[J", 13);
}

solves the issue with the scrollback buffer after log out.
Let me know if you agree that this is the right way to go and I will
send a patch to the maintainer of util-linux.

Thanks again for spending all this time to test the patch!

Have a good weekend!

Manuel




Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-12-01 Thread Manuel Schölling
Hi Andrey,

On Di, 2016-11-29 at 10:01 +, Andrey Utkin wrote:
> On Mon, Nov 28, 2016 at 10:28:19PM +0100, Manuel Schölling wrote:
> Regarding logout scrollback clearing not working for me. ncurses-6.0-rc1
> which I tested it with is the latest available in Gentoo portage, please
> confirm whether I need any newer version, or should I tune something
> else. I'd appreciate if you also tested your patch with gentoo setup.

I finally setup gentoo running agetty (util-linux-2.26.2) and patching
the file term-utils/agetty.c with

static void termio_clear(int fd)
{
/*
 * Do not write a full reset (ESC c) because this destroys
 * the unicode mode again if the terminal was in unicode
 * mode.  Also it clears the CONSOLE_MAGIC features which
 * are required for some languages/console-fonts.
 * Just put the cursor to the home position (ESC [ H),
 * erase everything below the cursor (ESC [ J), and set the
 * scrolling region to the full window (ESC [ r)
 */
-   write_all(fd, "\033[r\033[H\033[J", 9);
+   write_all(fd, "\033[3J\033[r\033[H\033[J", 13);
}

solves the issue with the scrollback buffer after log out.
Let me know if you agree that this is the right way to go and I will
send a patch to the maintainer of util-linux.

Thanks again for spending all this time to test the patch!

Have a good weekend!

Manuel




Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-11-29 Thread Manuel Schölling
Hi Andrey,

On Di, 2016-11-29 at 10:01 +, Andrey Utkin wrote:
> Regarding logout scrollback clearing not working for me. ncurses-6.0-rc1
> which I tested it with is the latest available in Gentoo portage, please
> confirm whether I need any newer version, or should I tune something
> else. I'd appreciate if you also tested your patch with gentoo setup.
Are you sure ncurses is involved at all?
My Debian agetty(8) manpage says:

   -J,--noclear
  Do not clear the screen before prompting for the login name (the
  screen is normally cleared).

And digging into the source code of agetty shows these lines [1]:

static void termio_clear(int fd)
{
/*
 * Do not write a full reset (ESC c) because this destroys
 * the unicode mode again if the terminal was in unicode
 * mode.  Also it clears the CONSOLE_MAGIC features which
 * are required for some languages/console-fonts.
 * Just put the cursor to the home position (ESC [ H),
 * erase everything below the cursor (ESC [ J), and set the
 * scrolling region to the full window (ESC [ r)
 */
write_all(fd, "\033[r\033[H\033[J", 9);
}

So I guess that agetty relies on on switching the console for flushing
the scrollback buffer and we'd had to add the \E[3J sequence here.

Note that up until now I just had a look at the theory (manpage and
source code). I'd need some days to find time to show at runtime that
this really is the reason why the buffer is not flushed.

Bye,

Manuel

[1] https://github.com/karelzak/util-linux/blob/master/term-utils/agetty.c#L1175




Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-11-29 Thread Manuel Schölling
Hi Andrey,

On Di, 2016-11-29 at 10:01 +, Andrey Utkin wrote:
> Regarding logout scrollback clearing not working for me. ncurses-6.0-rc1
> which I tested it with is the latest available in Gentoo portage, please
> confirm whether I need any newer version, or should I tune something
> else. I'd appreciate if you also tested your patch with gentoo setup.
Are you sure ncurses is involved at all?
My Debian agetty(8) manpage says:

   -J,--noclear
  Do not clear the screen before prompting for the login name (the
  screen is normally cleared).

And digging into the source code of agetty shows these lines [1]:

static void termio_clear(int fd)
{
/*
 * Do not write a full reset (ESC c) because this destroys
 * the unicode mode again if the terminal was in unicode
 * mode.  Also it clears the CONSOLE_MAGIC features which
 * are required for some languages/console-fonts.
 * Just put the cursor to the home position (ESC [ H),
 * erase everything below the cursor (ESC [ J), and set the
 * scrolling region to the full window (ESC [ r)
 */
write_all(fd, "\033[r\033[H\033[J", 9);
}

So I guess that agetty relies on on switching the console for flushing
the scrollback buffer and we'd had to add the \E[3J sequence here.

Note that up until now I just had a look at the theory (manpage and
source code). I'd need some days to find time to show at runtime that
this really is the reason why the buffer is not flushed.

Bye,

Manuel

[1] https://github.com/karelzak/util-linux/blob/master/term-utils/agetty.c#L1175




Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-11-28 Thread Manuel Schölling
Hi Andrey,

Adam already discussed some of your notes, but I want to catch up one
this one:

On So, 2016-11-27 at 21:37 +, Andrey Utkin wrote:
> I see the user experience is subpar to what I'm accustomed to (I use
> Konsole and "Clear Scrollback and Reset" action, default shortcut is
> Ctrl+Shift+K). The strange behaviour moments have nothing to do with
> current patchset but are properties of vgacon, though. (I compared it
> with another PC which runs without this patchset, and it looks like it
> runs vgacon, too, however, I'm not sure how to ensure this at runtime.)
I'm not sure what you mean with 'subpar'. Ctrl+Shift+K would probably be
nice - but it might interfere with some shortcuts of programs.
Are you missing any other features?
(I am working on persistent scrollback for framebuffer consoles in the
mean time...)

Bye,

Manuel



Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-11-28 Thread Manuel Schölling
Hi Andrey,

Adam already discussed some of your notes, but I want to catch up one
this one:

On So, 2016-11-27 at 21:37 +, Andrey Utkin wrote:
> I see the user experience is subpar to what I'm accustomed to (I use
> Konsole and "Clear Scrollback and Reset" action, default shortcut is
> Ctrl+Shift+K). The strange behaviour moments have nothing to do with
> current patchset but are properties of vgacon, though. (I compared it
> with another PC which runs without this patchset, and it looks like it
> runs vgacon, too, however, I'm not sure how to ensure this at runtime.)
I'm not sure what you mean with 'subpar'. Ctrl+Shift+K would probably be
nice - but it might interfere with some shortcuts of programs.
Are you missing any other features?
(I am working on persistent scrollback for framebuffer consoles in the
mean time...)

Bye,

Manuel



Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-11-28 Thread Manuel Schölling
On Mo, 2016-11-28 at 00:53 +0100, Adam Borowski wrote:
> \e[3J works well now, thanks!
Great to hear that!

> Tested-by: Adam Borowski 
Thanks, Adam, for spending all this time testing the patches!




Re: [PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-11-28 Thread Manuel Schölling
On Mo, 2016-11-28 at 00:53 +0100, Adam Borowski wrote:
> \e[3J works well now, thanks!
Great to hear that!

> Tested-by: Adam Borowski 
Thanks, Adam, for spending all this time testing the patches!




[PATCH v7 2/3] console: Add callback to flush scrollback buffer to consw struct

2016-11-27 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9d..9d3ce50 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..9a7c2bb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c66..5949d18 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.1.4



[PATCH v7 1/3] console: Move scrollback data into its own struct

2016-11-27 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   start = vgacon_scrollback.cur + lines;
end

[PATCH v7 1/3] console: Move scrollback data into its own struct

2016-11-27 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling 
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   start = vgacon_scrollback.cur + lines;
end = start + abs(lines);
 
  

[PATCH v7 2/3] console: Add callback to flush scrollback buffer to consw struct

2016-11-27 Thread Manuel Schölling
This new callback is in preparation for persistent scrollback buffer
support for VGA consoles.
With a single scrollback buffer for all consoles, we could flush the
buffer just by invocating consw->con_switch(). But when each VGA console
has its own scrollback buffer, we need a new callback to tell the
video console driver which buffer to flush.

Signed-off-by: Manuel Schölling 
---
 drivers/tty/vt/vt.c|  9 +
 drivers/video/console/vgacon.c | 24 +++-
 include/linux/console.h|  4 
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4c10a9d..9d3ce50 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -625,6 +625,14 @@ static void save_screen(struct vc_data *vc)
vc->vc_sw->con_save_screen(vc);
 }
 
+static void flush_scrollback(struct vc_data *vc)
+{
+   WARN_CONSOLE_UNLOCKED();
+
+   if (vc->vc_sw->con_flush_scrollback)
+   vc->vc_sw->con_flush_scrollback(vc);
+}
+
 /*
  * Redrawing of screen
  */
@@ -1171,6 +1179,7 @@ static void csi_J(struct vc_data *vc, int vpar)
case 3: /* erase scroll-back buffer (and whole display) */
scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
vc->vc_screenbuf_size);
+   flush_scrollback(vc);
set_origin(vc);
if (con_is_visible(vc))
update_screen(vc);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..9a7c2bb 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -173,6 +173,16 @@ static struct vgacon_scrollback_info {
int restore;
 } vgacon_scrollback;
 
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback.data && reset_size > 0)
+   memset(vgacon_scrollback.data, 0, reset_size);
+
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+}
+
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
@@ -305,6 +315,14 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
} else
vgacon_cursor(c, CM_MOVE);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   if (c->vc_num == fg_console)
+   vgacon_scrollback_reset(size);
+}
 #else
 #define vgacon_scrollback_startup(...) do { } while (0)
 #define vgacon_scrollback_init(...)do { } while (0)
@@ -322,6 +340,10 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
vga_vram_size);
vga_set_mem_top(c);
 }
+
+static void vgacon_flush_scrollback(struct vc_data *c)
+{
+}
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
 static const char *vgacon_startup(void)
@@ -1329,7 +1351,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int 
t, unsigned int b,
return true;
 }
 
-
 /*
  *  The console `switch' structure for the VGA based console
  */
@@ -1362,6 +1383,7 @@ const struct consw vga_con = {
.con_save_screen = vgacon_save_screen,
.con_build_attr = vgacon_build_attr,
.con_invert_region = vgacon_invert_region,
+   .con_flush_scrollback = vgacon_flush_scrollback,
 };
 EXPORT_SYMBOL(vga_con);
 
diff --git a/include/linux/console.h b/include/linux/console.h
index 9c26c66..5949d18 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -73,6 +73,10 @@ struct consw {
u16*(*con_screen_pos)(struct vc_data *, int);
unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int 
*);
/*
+* Flush the video console driver's scrollback buffer
+*/
+   void(*con_flush_scrollback)(struct vc_data *);
+   /*
 * Prepare the console for the debugger.  This includes, but is not
 * limited to, unblanking the console, loading an appropriate
 * palette, and allowing debugger generated output.
-- 
2.1.4



[PATCH v7 3/3] console: Add persistent scrollback buffers for all VGA consoles

2016-11-27 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bb..ca23d22 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+   vc_num = 0;
+#endif
+
+   

[PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-11-27 Thread Manuel Schölling
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.1.4



[PATCH v7 3/3] console: Add persistent scrollback buffers for all VGA consoles

2016-11-27 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling 
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 142 ++---
 2 files changed, 111 insertions(+), 56 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 9a7c2bb..ca23d22 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,74 +171,110 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_reset(size_t reset_size)
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
 {
-   if (vgacon_scrollback.data && reset_size > 0)
-   memset(vgacon_scrollback.data, 0, reset_size);
+   struct vgacon_scrollback_info *scrollback = _scrollbacks[vc_num];
+
+   if (scrollback->data && reset_size > 0)
+   memset(scrollback->data, 0, reset_size);
 
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
+   scrollback->cnt  = 0;
+   scrollback->tail = 0;
+   scrollback->cur  = 0;
 }
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size / pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(vc_num, size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+   vc_num = 0;
+#endif
+
+   if (!vgacon_scrollbacks[vc_num].d

[PATCH v7 0/3] console: Add persistent scrollback buffers for all VGA consoles

2016-11-27 Thread Manuel Schölling
Changes in v7:
  - Add new callback to consw struct for flushing video console driver's
scrollback buffer. Fixes issues with escape sequence '\e[3J' reported
by Adam Borowski (kilob...@angband.pl).
  - Fix style issues
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (3):
  console: Move scrollback data into its own struct
  console: Add callback to flush scrollback buffer to consw struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/tty/vt/vt.c|   9 +++
 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 165 -
 include/linux/console.h|   4 +
 4 files changed, 148 insertions(+), 55 deletions(-)

-- 
2.1.4



Re: [PATCH v5 2/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-23 Thread Manuel Schölling
On Mo, 2016-11-21 at 21:17 +0100, Adam Borowski wrote:
> On Sun, Nov 20, 2016 at 10:58:08PM +0100, Manuel Schölling wrote:
> > Add a scrollback buffers for each VGA console. The benefit is that
> > the scrollback history is not flushed when switching between consoles
> > but is persistent.
> > The buffers are allocated on demand when a new console is opened.
> > 
> > This breaks tools like clear_console that rely on flushing the
> > scrollback history by switching back and forth between consoles
> > which is why this feature is disabled by default.
> > Use the escape sequence \e[3J instead for flushing the buffer.
> > 
> > Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
> > ---

> But alas, this commit breaks that very \e[3J.  It does only a \e[2J, leaving
> the scrollback uncleared.  For comparison, both mainline and with just your
> preparatory commit, \e[3J works as expected.
Thanks again for reporting this issue. I was finally able to reproduce
it.
Looks like the same problem arises when implementing persistent
scrollback buffers for framebuffer consoles. I will have to think about
the underlying issue a bit more, but I guess that the consw struct needs
another field for a function that flushes the scrollback buffer.
Before this was just done by switching the console, which is fine if you
just have one buffer. But now each console has its own buffer, so simply
calling vc_data's vc_sw->con_switch() won't be sufficient anymore.




Re: [PATCH v5 2/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-23 Thread Manuel Schölling
On Mo, 2016-11-21 at 21:17 +0100, Adam Borowski wrote:
> On Sun, Nov 20, 2016 at 10:58:08PM +0100, Manuel Schölling wrote:
> > Add a scrollback buffers for each VGA console. The benefit is that
> > the scrollback history is not flushed when switching between consoles
> > but is persistent.
> > The buffers are allocated on demand when a new console is opened.
> > 
> > This breaks tools like clear_console that rely on flushing the
> > scrollback history by switching back and forth between consoles
> > which is why this feature is disabled by default.
> > Use the escape sequence \e[3J instead for flushing the buffer.
> > 
> > Signed-off-by: Manuel Schölling 
> > ---

> But alas, this commit breaks that very \e[3J.  It does only a \e[2J, leaving
> the scrollback uncleared.  For comparison, both mainline and with just your
> preparatory commit, \e[3J works as expected.
Thanks again for reporting this issue. I was finally able to reproduce
it.
Looks like the same problem arises when implementing persistent
scrollback buffers for framebuffer consoles. I will have to think about
the underlying issue a bit more, but I guess that the consw struct needs
another field for a function that flushes the scrollback buffer.
Before this was just done by switching the console, which is fine if you
just have one buffer. But now each console has its own buffer, so simply
calling vc_data's vc_sw->con_switch() won't be sufficient anymore.




Re: [PATCH v6 2/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-23 Thread Manuel Schölling
On Di, 2016-11-22 at 19:31 +, Andrey Utkin wrote:
> I'm not sure my emails with review of previous submission reached you, but in
> them I meant to mention that there are some style nits which are easy to
> eliminate.
I am afraid I did not get it. I will fix these style issues in the next
patch: Adam Borowski found another issue with clearing the scrollback
buffer, which I am finally able to reproduce.

> P. S. Manuel, please fix your git-send-email workflow or apply some
> workaround (check locale settings and such). Again your References
> header contains illegal symbol:
> 
> References: <201611210615.PPE1zXiO??ngguang...@intel.com>
I finally found out where the issue came from: Evolution somehow
reinterprets the Message-Id when you are copying it to the clipboard.



Re: [PATCH v6 2/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-23 Thread Manuel Schölling
On Di, 2016-11-22 at 19:31 +, Andrey Utkin wrote:
> I'm not sure my emails with review of previous submission reached you, but in
> them I meant to mention that there are some style nits which are easy to
> eliminate.
I am afraid I did not get it. I will fix these style issues in the next
patch: Adam Borowski found another issue with clearing the scrollback
buffer, which I am finally able to reproduce.

> P. S. Manuel, please fix your git-send-email workflow or apply some
> workaround (check locale settings and such). Again your References
> header contains illegal symbol:
> 
> References: <201611210615.PPE1zXiO??ngguang...@intel.com>
I finally found out where the issue came from: Evolution somehow
reinterprets the Message-Id when you are copying it to the clipboard.



Re: [PATCH v5 2/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-22 Thread Manuel Schölling
Hi Adam,

On Mo, 2016-11-21 at 21:17 +0100, Adam Borowski wrote:
> On Sun, Nov 20, 2016 at 10:58:08PM +0100, Manuel Schölling wrote:
> > Add a scrollback buffers for each VGA console. The benefit is that
> > the scrollback history is not flushed when switching between consoles
> > but is persistent.
> > The buffers are allocated on demand when a new console is opened.
> > 
> > This breaks tools like clear_console that rely on flushing the
> > scrollback history by switching back and forth between consoles
> > which is why this feature is disabled by default.
> > Use the escape sequence \e[3J instead for flushing the buffer.

> First, big thanks for this fix, it's something that greatly annoyed me
> since forever!
Yeah, me too! ;)

> The thing about clear_console is unfortunate: they abused the bug you're
> fixing.  I've asked to use \e[3J (https://bugs.debian.org/845177) so there's
> hope it'll be applied in stretch; with Debian configuring its glibc to
> support only kernels from two releases before (in jessie that's 2.6.32, in
> stretch 3.2)[1] there's hope we can flip the default in several years.
> 
> Do you suspect any other program relies on VT switch to clear the
> scrollback?
Not, AFAIK. Although I do not have a complete list of programs that are
suppose to do that.

> But alas, this commit breaks that very \e[3J.  It does only a \e[2J, leaving
> the scrollback uncleared.  For comparison, both mainline and with just your
> preparatory commit, \e[3J works as expected.
Really? All my tests worked fine: I compiled the kernel with the latest 
patches, started the kernel in QEMU and then did

  $ openvt /bin/sh
  $ echo -e '\e[3J' # scrollback buffer was flushed correctly
  $ chvt 2
  $ echo -e '\e[3J' # scrollback buffer was flushed correctly

Can you tell me how you tested it? Maybe I can reproduce the bug.

Thanks for spending the time to test it!

Bye,

Manuel




Re: [PATCH v5 2/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-22 Thread Manuel Schölling
Hi Adam,

On Mo, 2016-11-21 at 21:17 +0100, Adam Borowski wrote:
> On Sun, Nov 20, 2016 at 10:58:08PM +0100, Manuel Schölling wrote:
> > Add a scrollback buffers for each VGA console. The benefit is that
> > the scrollback history is not flushed when switching between consoles
> > but is persistent.
> > The buffers are allocated on demand when a new console is opened.
> > 
> > This breaks tools like clear_console that rely on flushing the
> > scrollback history by switching back and forth between consoles
> > which is why this feature is disabled by default.
> > Use the escape sequence \e[3J instead for flushing the buffer.

> First, big thanks for this fix, it's something that greatly annoyed me
> since forever!
Yeah, me too! ;)

> The thing about clear_console is unfortunate: they abused the bug you're
> fixing.  I've asked to use \e[3J (https://bugs.debian.org/845177) so there's
> hope it'll be applied in stretch; with Debian configuring its glibc to
> support only kernels from two releases before (in jessie that's 2.6.32, in
> stretch 3.2)[1] there's hope we can flip the default in several years.
> 
> Do you suspect any other program relies on VT switch to clear the
> scrollback?
Not, AFAIK. Although I do not have a complete list of programs that are
suppose to do that.

> But alas, this commit breaks that very \e[3J.  It does only a \e[2J, leaving
> the scrollback uncleared.  For comparison, both mainline and with just your
> preparatory commit, \e[3J works as expected.
Really? All my tests worked fine: I compiled the kernel with the latest 
patches, started the kernel in QEMU and then did

  $ openvt /bin/sh
  $ echo -e '\e[3J' # scrollback buffer was flushed correctly
  $ chvt 2
  $ echo -e '\e[3J' # scrollback buffer was flushed correctly

Can you tell me how you tested it? Maybe I can reproduce the bug.

Thanks for spending the time to test it!

Bye,

Manuel




[PATCH v6 2/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-22 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 134 +++--
 2 files changed, 111 insertions(+), 48 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..896d02b 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,64 +171,107 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_reset(size_t reset_size)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   if (vgacon_scrollback_cur->data && reset_size > 0)
+   memset(vgacon_scrollback_cur->data, 0, reset_size);
+
+   vgacon_scrollback_cur->cnt  = 0;
+   vgacon_scrollback_cur->tail = 0;
+   vgacon_scrollback_cur->cur  = 0;
+}
+
+static void vgacon_scrollback_init(int vc_num)
+{
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size/pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+   GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+   vc_num = 0;
+#endif
+
+   if (!vgacon_scrollbacks[vc_num].data)
+   vgacon_scrollback_init(vc_num);
+   else {
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+#else
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   vgacon_scrollback_reset

[PATCH v6 2/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-22 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling 
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 134 +++--
 2 files changed, 111 insertions(+), 48 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..896d02b 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,64 +171,107 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
 
-static void vgacon_scrollback_init(int pitch)
+static void vgacon_scrollback_reset(size_t reset_size)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   if (vgacon_scrollback_cur->data && reset_size > 0)
+   memset(vgacon_scrollback_cur->data, 0, reset_size);
+
+   vgacon_scrollback_cur->cnt  = 0;
+   vgacon_scrollback_cur->tail = 0;
+   vgacon_scrollback_cur->cur  = 0;
+}
+
+static void vgacon_scrollback_init(int vc_num)
+{
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size/pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+   GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+#ifndef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+   vc_num = 0;
+#endif
+
+   if (!vgacon_scrollbacks[vc_num].data)
+   vgacon_scrollback_init(vc_num);
+   else {
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+#else
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+   vgacon_scrollback_reset(size);
+#endif
}
 }
 
 static vo

[PATCH v6 0/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-22 Thread Manuel Schölling
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (2):
  console: Move scrollback data into its own struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 149 +++--
 2 files changed, 120 insertions(+), 54 deletions(-)

-- 
2.1.4



[PATCH v6 0/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-22 Thread Manuel Schölling
Changes in v6:
  - Change of check if feature is enabled in 
vgacon_scrollback_switch()
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (2):
  console: Move scrollback data into its own struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 149 +++--
 2 files changed, 120 insertions(+), 54 deletions(-)

-- 
2.1.4



[PATCH v6 1/2] console: Move scrollback data into its own struct

2016-11-22 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   start = vgacon_scrollback.cur + lines;
end

[PATCH v6 1/2] console: Move scrollback data into its own struct

2016-11-22 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling 
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   start = vgacon_scrollback.cur + lines;
end = start + abs(lines);
 
  

[PATCH v5 0/2] console: Add persistent scrollback buffers for all VGA console

2016-11-20 Thread Manuel Schölling
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1 to v4.2:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (2):
  console: Move scrollback data into its own struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 146 +++--
 2 files changed, 117 insertions(+), 54 deletions(-)

-- 
2.1.4



[PATCH v5 2/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-20 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 131 +++--
 2 files changed, 108 insertions(+), 48 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..4d7845a 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,64 +171,104 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
+
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback_cur->data && reset_size > 0)
+   memset(vgacon_scrollback_cur->data, 0, reset_size);
 
-static void vgacon_scrollback_init(int pitch)
+   vgacon_scrollback_cur->cnt  = 0;
+   vgacon_scrollback_cur->tail = 0;
+   vgacon_scrollback_cur->cur  = 0;
+}
+
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size/pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+   GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+   vc_num = CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT ? vc_num : 0;
+
+   if (!vgacon_scrollbacks[vc_num].data)
+   vgacon_scrollback_init(vc_num);
+   else {
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+#else
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   vgacon_scrollback_reset

[PATCH v5 0/2] console: Add persistent scrollback buffers for all VGA console

2016-11-20 Thread Manuel Schölling
Changes in v5:
  - Clearify documentation
  - Skip superfluous array initialization
  - Disable scrollback if buffer allocation fails
  - Refactor vgacon_switch_scrollback()
  - Rename vgacon_switch_scrollback() to vgacon_scrollback_switch()
  - Add check for fg_console in vgacon_scrollback_update
Changes in v4.1 to v4.2:
  - Fix compiler error
Changes in v4:
  - Rename from VGACON_SOFT_SCROLLBACK_FOR_EACH_CONSOLE to
VGACON_SOFT_SCROLLBACK_PERSISTENT
  - Split into two patches
  - Rework documentation
  - Remove cosmetic changes in comments (postponed)
Changes in v3:
  - Add config option for this feature
  - Fallback to old scrollback buffer if kcalloc() fails
  - Remove ioctl() call again and add documentation about existing
escape sequence to flush the scrollback buffer
Changes in v2:
  - Add ioctl() call to flush scrollback buffer
  - (Patch v2 was not labeled as such, sorry)

Manuel Schölling (2):
  console: Move scrollback data into its own struct
  console: Add persistent scrollback buffers for all VGA consoles

 drivers/video/console/Kconfig  |  25 ++-
 drivers/video/console/vgacon.c | 146 +++--
 2 files changed, 117 insertions(+), 54 deletions(-)

-- 
2.1.4



[PATCH v5 2/2] console: Add persistent scrollback buffers for all VGA consoles

2016-11-20 Thread Manuel Schölling
Add a scrollback buffers for each VGA console. The benefit is that
the scrollback history is not flushed when switching between consoles
but is persistent.
The buffers are allocated on demand when a new console is opened.

This breaks tools like clear_console that rely on flushing the
scrollback history by switching back and forth between consoles
which is why this feature is disabled by default.
Use the escape sequence \e[3J instead for flushing the buffer.

Signed-off-by: Manuel Schölling 
---
 drivers/video/console/Kconfig  |  25 +++-
 drivers/video/console/vgacon.c | 131 +++--
 2 files changed, 108 insertions(+), 48 deletions(-)

diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index 38da6e2..c5742d2 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,28 @@ config VGACON_SOFT_SCROLLBACK_SIZE
range 1 1024
default "64"
help
- Enter the amount of System RAM to allocate for the scrollback
-buffer.  Each 64KB will give you approximately 16 80x25
-screenfuls of scrollback buffer
+ Enter the amount of System RAM to allocate for scrollback
+ buffers of VGA consoles. Each 64KB will give you approximately
+ 16 80x25 screenfuls of scrollback buffer.
+
+config VGACON_SOFT_SCROLLBACK_PERSISTENT
+   bool "Persistent Scrollback History for each console"
+   depends on VGACON_SOFT_SCROLLBACK
+   default n
+   help
+ Say Y here if the scrollback history should persist when switching
+ between consoles. Otherwise, the scrollback history will be flushed
+ each time the console is switched.
+
+ This feature might break your tool of choice to flush the scrollback
+ buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+ will be broken, which might cause security issues.
+ You can use the escape sequence \e[3J instead if this feature is
+ activated.
+
+ Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+ created tty device.
+ So if you use a RAM-constrained system, say N here.
 
 config MDA_CONSOLE
depends on !M68K && !PARISC && ISA
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 48b9764..4d7845a 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,7 +162,7 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static struct vgacon_scrollback_info {
+struct vgacon_scrollback_info {
void *data;
int tail;
int size;
@@ -171,64 +171,104 @@ static struct vgacon_scrollback_info {
int cur;
int save;
int restore;
-} vgacon_scrollback;
+};
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+#else
+static struct vgacon_scrollback_info vgacon_scrollbacks[1];
+#endif
+
+static void vgacon_scrollback_reset(size_t reset_size)
+{
+   if (vgacon_scrollback_cur->data && reset_size > 0)
+   memset(vgacon_scrollback_cur->data, 0, reset_size);
 
-static void vgacon_scrollback_init(int pitch)
+   vgacon_scrollback_cur->cnt  = 0;
+   vgacon_scrollback_cur->tail = 0;
+   vgacon_scrollback_cur->cur  = 0;
+}
+
+static void vgacon_scrollback_init(int vc_num)
 {
-   int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
-
-   if (vgacon_scrollback.data) {
-   vgacon_scrollback.cnt  = 0;
-   vgacon_scrollback.tail = 0;
-   vgacon_scrollback.cur  = 0;
-   vgacon_scrollback.rows = rows - 1;
-   vgacon_scrollback.size = rows * pitch;
+   int pitch = vga_video_num_columns * 2;
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   int rows = size/pitch;
+   void *data;
+
+   data = kmalloc_array(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024,
+   GFP_NOWAIT);
+
+   vgacon_scrollbacks[vc_num].data = data;
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+
+   vgacon_scrollback_cur->rows = rows - 1;
+   vgacon_scrollback_cur->size = rows * pitch;
+
+   vgacon_scrollback_reset(size);
+}
+
+static void vgacon_scrollback_switch(int vc_num)
+{
+   vc_num = CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT ? vc_num : 0;
+
+   if (!vgacon_scrollbacks[vc_num].data)
+   vgacon_scrollback_init(vc_num);
+   else {
+#ifdef CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT
+   vgacon_scrollback_cur = _scrollbacks[vc_num];
+#else
+   size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+   vgacon_scrollback_reset(size);
+#endif
}
 }
 
 static void vgacon_

[PATCH v5 1/2] console: Move scrollback data into its own struct

2016-11-20 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   start = vgacon_scrollback.cur + lines;
end

[PATCH v5 1/2] console: Move scrollback data into its own struct

2016-11-20 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling 
---
 drivers/video/console/vgacon.c | 91 ++
 1 file changed, 47 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..48b9764 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,34 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE,
+   1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +197,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +242,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   start = vgacon_scrollback.cur + lines;
end = start + abs(lines);
 
  

[PATCH v4.1 1/2] console: Move scrollback data into its own struct

2016-11-16 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling <manuel.schoell...@gmx.de>
---
 drivers/video/console/vgacon.c | 90 +-
 1 file changed, 46 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..1fee18f 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,33 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 
1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +196,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +241,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   start = vgacon_scrollback.cur + lines;
end = start + abs(lines)

[PATCH v4.1 1/2] console: Move scrollback data into its own struct

2016-11-16 Thread Manuel Schölling
This refactoring is in preparation for persistent scrollback
support for VGA console.

Signed-off-by: Manuel Schölling 
---
 drivers/video/console/vgacon.c | 90 +-
 1 file changed, 46 insertions(+), 44 deletions(-)

diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index c22a562..1fee18f 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,31 +162,33 @@ static inline void vga_set_mem_top(struct vc_data *c)
 
 #ifdef CONFIG_VGACON_SOFT_SCROLLBACK
 /* software scrollback */
-static void *vgacon_scrollback;
-static int vgacon_scrollback_tail;
-static int vgacon_scrollback_size;
-static int vgacon_scrollback_rows;
-static int vgacon_scrollback_cnt;
-static int vgacon_scrollback_cur;
-static int vgacon_scrollback_save;
-static int vgacon_scrollback_restore;
+static struct vgacon_scrollback_info {
+   void *data;
+   int tail;
+   int size;
+   int rows;
+   int cnt;
+   int cur;
+   int save;
+   int restore;
+} vgacon_scrollback;
 
 static void vgacon_scrollback_init(int pitch)
 {
int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch;
 
-   if (vgacon_scrollback) {
-   vgacon_scrollback_cnt  = 0;
-   vgacon_scrollback_tail = 0;
-   vgacon_scrollback_cur  = 0;
-   vgacon_scrollback_rows = rows - 1;
-   vgacon_scrollback_size = rows * pitch;
+   if (vgacon_scrollback.data) {
+   vgacon_scrollback.cnt  = 0;
+   vgacon_scrollback.tail = 0;
+   vgacon_scrollback.cur  = 0;
+   vgacon_scrollback.rows = rows - 1;
+   vgacon_scrollback.size = rows * pitch;
}
 }
 
 static void vgacon_scrollback_startup(void)
 {
-   vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, 
GFP_NOWAIT);
+   vgacon_scrollback.data = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 
1024, GFP_NOWAIT);
vgacon_scrollback_init(vga_video_num_columns * 2);
 }
 
@@ -194,38 +196,38 @@ static void vgacon_scrollback_update(struct vc_data *c, 
int t, int count)
 {
void *p;
 
-   if (!vgacon_scrollback_size || c->vc_num != fg_console)
+   if (!vgacon_scrollback.size || c->vc_num != fg_console)
return;
 
p = (void *) (c->vc_origin + t * c->vc_size_row);
 
while (count--) {
-   scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail,
+   scr_memcpyw(vgacon_scrollback.data + vgacon_scrollback.tail,
p, c->vc_size_row);
-   vgacon_scrollback_cnt++;
+   vgacon_scrollback.cnt++;
p += c->vc_size_row;
-   vgacon_scrollback_tail += c->vc_size_row;
+   vgacon_scrollback.tail += c->vc_size_row;
 
-   if (vgacon_scrollback_tail >= vgacon_scrollback_size)
-   vgacon_scrollback_tail = 0;
+   if (vgacon_scrollback.tail >= vgacon_scrollback.size)
+   vgacon_scrollback.tail = 0;
 
-   if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
-   vgacon_scrollback_cnt = vgacon_scrollback_rows;
+   if (vgacon_scrollback.cnt > vgacon_scrollback.rows)
+   vgacon_scrollback.cnt = vgacon_scrollback.rows;
 
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
-   vgacon_scrollback_save = 0;
+   vgacon_scrollback.save = 0;
 
-   if (!vga_is_gfx && !vgacon_scrollback_restore) {
+   if (!vga_is_gfx && !vgacon_scrollback.restore) {
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
c->vc_screenbuf_size > vga_vram_size ?
vga_vram_size : c->vc_screenbuf_size);
-   vgacon_scrollback_restore = 1;
-   vgacon_scrollback_cur = vgacon_scrollback_cnt;
+   vgacon_scrollback.restore = 1;
+   vgacon_scrollback.cur = vgacon_scrollback.cnt;
}
 }
 
@@ -239,41 +241,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int 
lines)
return;
}
 
-   if (!vgacon_scrollback)
+   if (!vgacon_scrollback.data)
return;
 
-   if (!vgacon_scrollback_save) {
+   if (!vgacon_scrollback.save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
-   vgacon_scrollback_save = 1;
+   vgacon_scrollback.save = 1;
}
 
-   vgacon_scrollback_restore = 0;
-   start = vgacon_scrollback_cur + lines;
+   vgacon_scrollback.restore = 0;
+   start = vgacon_scrollback.cur + lines;
end = start + abs(lines);
 
if (start < 0)

  1   2   3   >