summaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-22 12:17:25 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-22 12:17:25 -0800
commit37c85961c3f87f2141c84e53df31e59db072fd2e (patch)
treeff020df86c8c893e4524dda9205254be202560cc /drivers/video
parentcaa59428971d5ad81d19512365c9ba580d83268c (diff)
parentd8a4995bcea168dfac8ee41c28c79109907e4fba (diff)
downloadlinux-37c85961c3f87f2141c84e53df31e59db072fd2e.tar.bz2
Merge tag 'tty-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH: "Here is the big tty/serial driver patchset for 4.11-rc1. Not much here, but a lot of little fixes and individual serial driver updates all over the subsystem. Majority are for the sh-sci driver and platform (the arch-specific changes have acks from the maintainer). The start of the "serial bus" code is here as well, but nothing is converted to use it yet. That work is still ongoing, hopefully will start to show up across different subsystems for 4.12 (bluetooth is one major place that will be used.) All of these have been in linux-next for a while with no reported issues" * tag 'tty-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (109 commits) tty: pl011: Work around QDF2400 E44 stuck BUSY bit atmel_serial: Use the fractional divider when possible tty: Remove extra include in HVC console tty framework serial: exar: Enable MSI support serial: exar: Move register defines from uapi header to consumer site serial: pci: Remove unused pci_boards entries serial: exar: Move Commtech adapters to 8250_exar as well serial: exar: Fix feature control register constants serial: exar: Fix initialization of EXAR registers for ports > 0 serial: exar: Fix mapping of port I/O resources serial: sh-sci: fix hardware RX trigger level setting tty/serial: atmel: ensure state is restored after suspending serial: 8250_dw: Avoid "too much work" from bogus rx timeout interrupt serdev: ttyport: check whether tty_init_dev() fails serial: 8250_pci: make pciserial_detach_ports() static ARM: dts: STiH410-b2260: Enable HW flow-control ARM: dts: STiH407-family: Use new Pinctrl groups ARM: dts: STiH407-pinctrl: Add Pinctrl group for HW flow-control ARM: dts: STiH410-b2260: Identify the UART RTS line dt-bindings: serial: Update 'uart-has-rtscts' description ...
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/console/Kconfig27
-rw-r--r--drivers/video/console/vgacon.c164
2 files changed, 136 insertions, 55 deletions
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index c3f1fb9ee820..5b71bd905a60 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -43,9 +43,30 @@ 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_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 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)
+ 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 c22a56232b7c..dc06cb6a15dc 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -162,70 +162,118 @@ 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 void vgacon_scrollback_init(int pitch)
+struct vgacon_scrollback_info {
+ void *data;
+ int tail;
+ int size;
+ int rows;
+ int cnt;
+ int cur;
+ int save;
+ int restore;
+};
+
+static struct vgacon_scrollback_info *vgacon_scrollback_cur;
+static struct vgacon_scrollback_info vgacon_scrollbacks[MAX_NR_CONSOLES];
+static bool scrollback_persistent = \
+ IS_ENABLED(CONFIG_VGACON_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT);
+module_param_named(scrollback_persistent, scrollback_persistent, bool, 0000);
+MODULE_PARM_DESC(scrollback_persistent, "Enable persistent scrollback for all vga consoles");
+
+static void vgacon_scrollback_reset(int vc_num, size_t reset_size)
+{
+ struct vgacon_scrollback_info *scrollback = &vgacon_scrollbacks[vc_num];
+
+ if (scrollback->data && reset_size > 0)
+ memset(scrollback->data, 0, reset_size);
+
+ scrollback->cnt = 0;
+ scrollback->tail = 0;
+ scrollback->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 = &vgacon_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)
{
- 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 (!scrollback_persistent)
+ vc_num = 0;
+
+ if (!vgacon_scrollbacks[vc_num].data) {
+ vgacon_scrollback_init(vc_num);
+ } else {
+ if (scrollback_persistent) {
+ vgacon_scrollback_cur = &vgacon_scrollbacks[vc_num];
+ } else {
+ size_t size = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024;
+
+ vgacon_scrollback_reset(vc_num, size);
+ }
}
}
static void vgacon_scrollback_startup(void)
{
- vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT);
- vgacon_scrollback_init(vga_video_num_columns * 2);
+ vgacon_scrollback_cur = &vgacon_scrollbacks[0];
+ vgacon_scrollback_init(0);
}
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_cur->data || !vgacon_scrollback_cur->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_cur->data +
+ vgacon_scrollback_cur->tail,
p, c->vc_size_row);
- vgacon_scrollback_cnt++;
+
+ vgacon_scrollback_cur->cnt++;
p += c->vc_size_row;
- vgacon_scrollback_tail += c->vc_size_row;
+ vgacon_scrollback_cur->tail += c->vc_size_row;
- if (vgacon_scrollback_tail >= vgacon_scrollback_size)
- vgacon_scrollback_tail = 0;
+ if (vgacon_scrollback_cur->tail >= vgacon_scrollback_cur->size)
+ vgacon_scrollback_cur->tail = 0;
- if (vgacon_scrollback_cnt > vgacon_scrollback_rows)
- vgacon_scrollback_cnt = vgacon_scrollback_rows;
+ if (vgacon_scrollback_cur->cnt > vgacon_scrollback_cur->rows)
+ vgacon_scrollback_cur->cnt = vgacon_scrollback_cur->rows;
- vgacon_scrollback_cur = vgacon_scrollback_cnt;
+ vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
}
}
static void vgacon_restore_screen(struct vc_data *c)
{
- vgacon_scrollback_save = 0;
+ vgacon_scrollback_cur->save = 0;
- if (!vga_is_gfx && !vgacon_scrollback_restore) {
+ if (!vga_is_gfx && !vgacon_scrollback_cur->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_cur->restore = 1;
+ vgacon_scrollback_cur->cur = vgacon_scrollback_cur->cnt;
}
}
@@ -239,41 +287,41 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
return;
}
- if (!vgacon_scrollback)
+ if (!vgacon_scrollback_cur->data)
return;
- if (!vgacon_scrollback_save) {
+ if (!vgacon_scrollback_cur->save) {
vgacon_cursor(c, CM_ERASE);
vgacon_save_screen(c);
- vgacon_scrollback_save = 1;
+ vgacon_scrollback_cur->save = 1;
}
- vgacon_scrollback_restore = 0;
- start = vgacon_scrollback_cur + lines;
+ vgacon_scrollback_cur->restore = 0;
+ start = vgacon_scrollback_cur->cur + lines;
end = start + abs(lines);
if (start < 0)
start = 0;
- if (start > vgacon_scrollback_cnt)
- start = vgacon_scrollback_cnt;
+ if (start > vgacon_scrollback_cur->cnt)
+ start = vgacon_scrollback_cur->cnt;
if (end < 0)
end = 0;
- if (end > vgacon_scrollback_cnt)
- end = vgacon_scrollback_cnt;
+ if (end > vgacon_scrollback_cur->cnt)
+ end = vgacon_scrollback_cur->cnt;
- vgacon_scrollback_cur = start;
+ vgacon_scrollback_cur->cur = start;
count = end - start;
- soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) *
- c->vc_size_row);
+ soff = vgacon_scrollback_cur->tail -
+ ((vgacon_scrollback_cur->cnt - end) * c->vc_size_row);
soff -= count * c->vc_size_row;
if (soff < 0)
- soff += vgacon_scrollback_size;
+ soff += vgacon_scrollback_cur->size;
- count = vgacon_scrollback_cnt - start;
+ count = vgacon_scrollback_cur->cnt - start;
if (count > c->vc_rows)
count = c->vc_rows;
@@ -287,13 +335,13 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
count *= c->vc_size_row;
/* how much memory to end of buffer left? */
- copysize = min(count, vgacon_scrollback_size - soff);
- scr_memcpyw(d, vgacon_scrollback + soff, copysize);
+ copysize = min(count, vgacon_scrollback_cur->size - soff);
+ scr_memcpyw(d, vgacon_scrollback_cur->data + soff, copysize);
d += copysize;
count -= copysize;
if (count) {
- scr_memcpyw(d, vgacon_scrollback, count);
+ scr_memcpyw(d, vgacon_scrollback_cur->data, count);
d += count;
}
@@ -302,10 +350,18 @@ 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;
+
+ vgacon_scrollback_reset(c->vc_num, size);
+}
#else
#define vgacon_scrollback_startup(...) do { } while (0)
#define vgacon_scrollback_init(...) do { } while (0)
#define vgacon_scrollback_update(...) do { } while (0)
+#define vgacon_scrollback_switch(...) do { } while (0)
static void vgacon_restore_screen(struct vc_data *c)
{
@@ -319,6 +375,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)
@@ -780,7 +840,7 @@ static int vgacon_switch(struct vc_data *c)
vgacon_doresize(c, c->vc_cols, c->vc_rows);
}
- vgacon_scrollback_init(c->vc_size_row);
+ vgacon_scrollback_switch(c->vc_num);
return 0; /* Redrawing not needed */
}
@@ -1326,7 +1386,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
*/
@@ -1359,6 +1418,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);