summaryrefslogtreecommitdiff
path: root/drivers/s390/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/con3270.c4
-rw-r--r--drivers/s390/char/ctrlchar.c16
-rw-r--r--drivers/s390/char/ctrlchar.h12
-rw-r--r--drivers/s390/char/diag_ftp.c4
-rw-r--r--drivers/s390/char/monreader.c2
-rw-r--r--drivers/s390/char/sclp.c6
-rw-r--r--drivers/s390/char/sclp_cmd.c18
-rw-r--r--drivers/s390/char/sclp_vt220.c52
-rw-r--r--drivers/s390/char/tty3270.c4
9 files changed, 99 insertions, 19 deletions
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index 75ffe9980..7c511add5 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -413,6 +413,10 @@ con3270_irq(struct con3270 *cp, struct raw3270_request *rq, struct irb *irb)
else
/* Normal end. Copy residual count. */
rq->rescnt = irb->scsw.cmd.count;
+ } else if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
+ /* Interrupt without an outstanding request -> update all */
+ cp->update_flags = CON_UPDATE_ALL;
+ con3270_set_timer(cp, 1);
}
return RAW3270_IO_DONE;
}
diff --git a/drivers/s390/char/ctrlchar.c b/drivers/s390/char/ctrlchar.c
index 8de2deb17..f7d92584b 100644
--- a/drivers/s390/char/ctrlchar.c
+++ b/drivers/s390/char/ctrlchar.c
@@ -14,15 +14,21 @@
#include "ctrlchar.h"
#ifdef CONFIG_MAGIC_SYSRQ
-static int ctrlchar_sysrq_key;
+static struct sysrq_work ctrlchar_sysrq;
static void
ctrlchar_handle_sysrq(struct work_struct *work)
{
- handle_sysrq(ctrlchar_sysrq_key);
+ struct sysrq_work *sysrq = container_of(work, struct sysrq_work, work);
+
+ handle_sysrq(sysrq->key);
}
-static DECLARE_WORK(ctrlchar_work, ctrlchar_handle_sysrq);
+void schedule_sysrq_work(struct sysrq_work *sw)
+{
+ INIT_WORK(&sw->work, ctrlchar_handle_sysrq);
+ schedule_work(&sw->work);
+}
#endif
@@ -51,8 +57,8 @@ ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty)
#ifdef CONFIG_MAGIC_SYSRQ
/* racy */
if (len == 3 && buf[1] == '-') {
- ctrlchar_sysrq_key = buf[2];
- schedule_work(&ctrlchar_work);
+ ctrlchar_sysrq.key = buf[2];
+ schedule_sysrq_work(&ctrlchar_sysrq);
return CTRLCHAR_SYSRQ;
}
#endif
diff --git a/drivers/s390/char/ctrlchar.h b/drivers/s390/char/ctrlchar.h
index 1a53552f4..59c2d6e55 100644
--- a/drivers/s390/char/ctrlchar.h
+++ b/drivers/s390/char/ctrlchar.h
@@ -7,6 +7,8 @@
*/
#include <linux/tty.h>
+#include <linux/sysrq.h>
+#include <linux/workqueue.h>
extern unsigned int
ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty);
@@ -17,3 +19,13 @@ ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty);
#define CTRLCHAR_SYSRQ (3 << 8)
#define CTRLCHAR_MASK (~0xffu)
+
+
+#ifdef CONFIG_MAGIC_SYSRQ
+struct sysrq_work {
+ int key;
+ struct work_struct work;
+};
+
+void schedule_sysrq_work(struct sysrq_work *sw);
+#endif
diff --git a/drivers/s390/char/diag_ftp.c b/drivers/s390/char/diag_ftp.c
index 93889632f..12db8db04 100644
--- a/drivers/s390/char/diag_ftp.c
+++ b/drivers/s390/char/diag_ftp.c
@@ -223,7 +223,7 @@ int diag_ftp_startup(void)
if (rc)
return rc;
- ctl_set_bit(0, 63 - 22);
+ irq_subclass_register(IRQ_SUBCLASS_SERVICE_SIGNAL);
return 0;
}
@@ -232,6 +232,6 @@ int diag_ftp_startup(void)
*/
void diag_ftp_shutdown(void)
{
- ctl_clear_bit(0, 63 - 22);
+ irq_subclass_unregister(IRQ_SUBCLASS_SERVICE_SIGNAL);
unregister_external_irq(EXT_IRQ_CP_SERVICE, diag_ftp_handler);
}
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 0da3ae3cd..b7d60306b 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -95,7 +95,7 @@ static void dcss_mkname(char *ascii_name, char *ebcdic_name)
if (ascii_name[i] == '\0')
break;
ebcdic_name[i] = toupper(ascii_name[i]);
- };
+ }
for (; i < 8; i++)
ebcdic_name[i] = ' ';
ASCEBC(ebcdic_name, 8);
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 5e20513c0..f58bf4c6c 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -53,7 +53,7 @@ static DECLARE_COMPLETION(sclp_request_queue_flushed);
/* Number of console pages to allocate, used by sclp_con.c and sclp_vt220.c */
int sclp_console_pages = SCLP_CONSOLE_PAGES;
/* Flag to indicate if buffer pages are dropped on buffer full condition */
-int sclp_console_drop = 0;
+int sclp_console_drop = 1;
/* Number of times the console dropped buffer pages */
unsigned long sclp_console_full;
@@ -79,8 +79,8 @@ static int __init sclp_setup_console_drop(char *str)
int drop, rc;
rc = kstrtoint(str, 0, &drop);
- if (!rc && drop)
- sclp_console_drop = 1;
+ if (!rc)
+ sclp_console_drop = drop;
return 1;
}
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index e9485fbbb..806239c2c 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -25,6 +25,7 @@
#include <asm/setup.h>
#include <asm/page.h>
#include <asm/sclp.h>
+#include <asm/numa.h>
#include "sclp.h"
@@ -388,11 +389,11 @@ static struct notifier_block sclp_mem_nb = {
};
static void __init align_to_block_size(unsigned long long *start,
- unsigned long long *size)
+ unsigned long long *size,
+ unsigned long long alignment)
{
- unsigned long long start_align, size_align, alignment;
+ unsigned long long start_align, size_align;
- alignment = memory_block_size_bytes();
start_align = roundup(*start, alignment);
size_align = rounddown(*start + *size, alignment) - start_align;
@@ -404,8 +405,8 @@ static void __init align_to_block_size(unsigned long long *start,
static void __init add_memory_merged(u16 rn)
{
+ unsigned long long start, size, addr, block_size;
static u16 first_rn, num;
- unsigned long long start, size;
if (rn && first_rn && (first_rn + num == rn)) {
num++;
@@ -423,9 +424,12 @@ static void __init add_memory_merged(u16 rn)
goto skip_add;
if (memory_end_set && (start + size > memory_end))
size = memory_end - start;
- align_to_block_size(&start, &size);
- if (size)
- add_memory(0, start, size);
+ block_size = memory_block_size_bytes();
+ align_to_block_size(&start, &size, block_size);
+ if (!size)
+ goto skip_add;
+ for (addr = start; addr < start + size; addr += block_size)
+ add_memory(numa_pfn_to_nid(PFN_DOWN(addr)), addr, block_size);
skip_add:
first_rn = rn;
num = 1;
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
index ae67386c0..68d6ee7ae 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;
}
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index e91b89dc6..e96fc7fd9 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -659,6 +659,10 @@ tty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb)
else
/* Normal end. Copy residual count. */
rq->rescnt = irb->scsw.cmd.count;
+ } else if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END) {
+ /* Interrupt without an outstanding request -> update all */
+ tp->update_flags = TTY_UPDATE_ALL;
+ tty3270_set_timer(tp, 1);
}
return RAW3270_IO_DONE;
}