summaryrefslogtreecommitdiff
path: root/drivers/s390
diff options
context:
space:
mode:
authorHendrik Brueckner <brueckner@linux.vnet.ibm.com>2015-08-17 16:13:41 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2015-08-26 17:20:45 +0200
commit1d3f9094c6fdb5680fd3b19a5b153308d53a70ee (patch)
treea3d5dfab22fde888559db8c872c4739db14b9752 /drivers/s390
parentab7373bf235ede864a72f0d2f8f9a21a1748c4a2 (diff)
s390/sclp_vt220: support magic sysrequests
Implement magic sysrequest handling for the VT220 terminal (also known as the Integrated ASCII console on the HMC/SE). To invoke a "magic sysrequest" function, press "Ctrl+o" followed by a second character that designates the debugging function. The handling of the sysrq is scheduled away from the SCLP IRQ context; because large amounts of sysrq output might fill up the console buffers. The console might deadlock because it cannot empty the buffers while still in the receiving IRQ context. This behavior is the same as for the SCLP console. Reported-by: Horst Weber <hweber@de.ibm.com> Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/char/sclp_vt220.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index ae67386c03d3..68d6ee7ae504 100644
--- a/drivers/s390/char/sclp_vt220.c
+++ b/drivers/s390/char/sclp_vt220.c
@@ -12,6 +12,7 @@
#include <linux/wait.h>
#include <linux/timer.h>
#include <linux/kernel.h>
+#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
@@ -27,6 +28,7 @@
#include <asm/uaccess.h>
#include "sclp.h"
+#include "ctrlchar.h"
#define SCLP_VT220_MAJOR TTY_MAJOR
#define SCLP_VT220_MINOR 65
@@ -477,6 +479,53 @@ sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
#define SCLP_VT220_SESSION_STARTED 0x80
#define SCLP_VT220_SESSION_DATA 0x00
+#ifdef CONFIG_MAGIC_SYSRQ
+
+static int sysrq_pressed;
+static struct sysrq_work sysrq;
+
+static void sclp_vt220_reset_session(void)
+{
+ sysrq_pressed = 0;
+}
+
+static void sclp_vt220_handle_input(const char *buffer, unsigned int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ /* Handle magic sys request */
+ if (buffer[i] == ('O' ^ 0100)) { /* CTRL-O */
+ /*
+ * If pressed again, reset sysrq_pressed
+ * and flip CTRL-O character
+ */
+ sysrq_pressed = !sysrq_pressed;
+ if (sysrq_pressed)
+ continue;
+ } else if (sysrq_pressed) {
+ sysrq.key = buffer[i];
+ schedule_sysrq_work(&sysrq);
+ sysrq_pressed = 0;
+ continue;
+ }
+ tty_insert_flip_char(&sclp_vt220_port, buffer[i], 0);
+ }
+}
+
+#else
+
+static void sclp_vt220_reset_session(void)
+{
+}
+
+static void sclp_vt220_handle_input(const char *buffer, unsigned int count)
+{
+ tty_insert_flip_string(&sclp_vt220_port, buffer, count);
+}
+
+#endif
+
/*
* Called by the SCLP to report incoming event buffers.
*/
@@ -492,12 +541,13 @@ sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
switch (*buffer) {
case SCLP_VT220_SESSION_ENDED:
case SCLP_VT220_SESSION_STARTED:
+ sclp_vt220_reset_session();
break;
case SCLP_VT220_SESSION_DATA:
/* Send input to line discipline */
buffer++;
count--;
- tty_insert_flip_string(&sclp_vt220_port, buffer, count);
+ sclp_vt220_handle_input(buffer, count);
tty_flip_buffer_push(&sclp_vt220_port);
break;
}