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>
This commit is contained in:
Hendrik Brueckner 2015-08-17 16:13:41 +02:00 коммит произвёл Martin Schwidefsky
Родитель ab7373bf23
Коммит 1d3f9094c6
1 изменённых файлов: 51 добавлений и 1 удалений

Просмотреть файл

@ -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;
}