From: Hendrik Brueckner Date: Mon, 17 Aug 2015 14:13:41 +0000 (+0200) Subject: s390/sclp_vt220: support magic sysrequests X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=1d3f9094c6fdb5680fd3b19a5b153308d53a70ee;p=linux-beck.git 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 Signed-off-by: Hendrik Brueckner Reviewed-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- 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 #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include #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; }