[PATCH] 2.5.40 s390 (27/27): control characters.

Martin Schwidefsky (schwidefsky@de.ibm.com)
Fri, 4 Oct 2002 16:40:51 +0200


Replace IMMEDIATE_BH bottom half by tasklets in helper functions for
console control characters. Fix a race condition and make it look nicer.

diff -urN linux-2.5.40/drivers/s390/char/con3215.c linux-2.5.40-s390/drivers/s390/char/con3215.c
--- linux-2.5.40/drivers/s390/char/con3215.c Fri Oct 4 16:16:50 2002
+++ linux-2.5.40-s390/drivers/s390/char/con3215.c Fri Oct 4 16:17:01 2002
@@ -455,7 +455,7 @@
if ((raw = req->info) == NULL)
return; /* That shouldn't happen ... */
if (req->type == RAW3215_READ && raw->tty != NULL) {
- char *cchar;
+ unsigned int cchar;

tty = raw->tty;
count = 160 - req->residual;
@@ -467,14 +467,19 @@
if (count >= TTY_FLIPBUF_SIZE - tty->flip.count)
count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
EBCASC(raw->inbuf, count);
- if ((cchar = ctrlchar_handle(raw->inbuf, count, tty))) {
- if (cchar == (char *)-1)
- goto in_out;
+ cchar = ctrlchar_handle(raw->inbuf, count, tty);
+ switch (cchar & CTRLCHAR_MASK) {
+ case CTRLCHAR_SYSRQ:
+ break;
+
+ case CTRLCHAR_CTRL:
tty->flip.count++;
*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = *cchar;
+ *tty->flip.char_buf_ptr++ = cchar;
tty_flip_buffer_push(raw->tty);
- } else {
+ break;
+
+ case CTRLCHAR_NONE:
memcpy(tty->flip.char_buf_ptr,
raw->inbuf, count);
if (count < 2 ||
@@ -491,12 +496,13 @@
tty->flip.flag_buf_ptr += count;
tty->flip.count += count;
tty_flip_buffer_push(raw->tty);
+ break;
}
} else if (req->type == RAW3215_WRITE) {
raw->count -= req->len;
raw->written -= req->len;
}
-in_out:
+
raw->flags &= ~RAW3215_WORKING;
raw3215_free_req(req);
/* check for empty wait */
@@ -1095,8 +1101,6 @@
raw3215_freelist = req;
}

- ctrlchar_init();
-
#ifdef CONFIG_TN3215_CONSOLE
raw3215[0] = raw = (raw3215_info *)
alloc_bootmem_low(sizeof(raw3215_info));
diff -urN linux-2.5.40/drivers/s390/char/ctrlchar.c linux-2.5.40-s390/drivers/s390/char/ctrlchar.c
--- linux-2.5.40/drivers/s390/char/ctrlchar.c Fri Oct 4 16:14:52 2002
+++ linux-2.5.40-s390/drivers/s390/char/ctrlchar.c Fri Oct 4 16:17:01 2002
@@ -8,39 +8,27 @@
*/

#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/tty.h>
-#include <linux/interrupt.h>
-
+#include <linux/stddef.h>
#include <linux/sysrq.h>
+#include <linux/ctype.h>

-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#include <asm/cpcmd.h>
-#include <asm/irq.h>
+#include "ctrlchar.h"

#ifdef CONFIG_MAGIC_SYSRQ
static int ctrlchar_sysrq_key;
-static struct tq_struct ctrlchar_tq;

static void
-ctrlchar_handle_sysrq(struct tty_struct *tty) {
+ctrlchar_handle_sysrq(void *tty)
+{
handle_sysrq(ctrlchar_sysrq_key, NULL, tty);
}
-#endif
-
-void ctrlchar_init(void) {
-#ifdef CONFIG_MAGIC_SYSRQ
- static int init_done = 0;

- if (init_done++)
- return;
- INIT_LIST_HEAD(&ctrlchar_tq.list);
- ctrlchar_tq.sync = 0;
- ctrlchar_tq.routine = (void (*)(void *)) ctrlchar_handle_sysrq;
+static struct tq_struct ctrlchar_tq = {
+ .list = LIST_HEAD_INIT(ctrlchar_tq.list),
+ .routine = ctrlchar_handle_sysrq,
+};
#endif
-}
+

/**
* Check for special chars at start of input.
@@ -48,49 +36,42 @@
* @param buf Console input buffer.
* @param len Length of valid data in buffer.
* @param tty The tty struct for this console.
- * @return NULL, if nothing matched, (char *)-1, if buffer contents
- * should be ignored, otherwise pointer to char to be inserted.
+ * @return CTRLCHAR_NONE, if nothing matched,
+ * CTRLCHAR_SYSRQ, if sysrq was encountered
+ * otherwise char to be inserted logically or'ed
+ * with CTRLCHAR_CTRL
*/
-char *ctrlchar_handle(const char *buf, int len, struct tty_struct *tty) {
-
- static char ret;
-
+unsigned int
+ctrlchar_handle(const char *buf, int len, struct tty_struct *tty)
+{
if ((len < 2) || (len > 3))
- return NULL;
+ return CTRLCHAR_NONE;
+
/* hat is 0xb1 in codepage 037 (US etc.) and thus */
/* converted to 0x5e in ascii ('^') */
if ((buf[0] != '^') && (buf[0] != '\252'))
- return NULL;
- switch (buf[1]) {
+ return CTRLCHAR_NONE;
+
#ifdef CONFIG_MAGIC_SYSRQ
- case '-':
- if (len == 3) {
- ctrlchar_sysrq_key = buf[2];
- ctrlchar_tq.data = tty;
- queue_task(&ctrlchar_tq, &tq_immediate);
- mark_bh(IMMEDIATE_BH);
- return (char *)-1;
- }
- break;
+ /* racy */
+ if (len == 3 && buf[1] == '-') {
+ ctrlchar_sysrq_key = buf[2];
+ ctrlchar_tq.data = tty;
+ schedule_task(&ctrlchar_tq);
+ return CTRLCHAR_SYSRQ;
+ }
#endif
- case 'c':
- if (len == 2) {
- ret = INTR_CHAR(tty);
- return &ret;
- }
- break;
- case 'd':
- if (len == 2) {
- ret = EOF_CHAR(tty);
- return &ret;
- }
- break;
- case 'z':
- if (len == 2) {
- ret = SUSP_CHAR(tty);
- return &ret;
- }
- break;
+
+ if (len != 2)
+ return CTRLCHAR_NONE;
+
+ switch (tolower(buf[1])) {
+ case 'c':
+ return INTR_CHAR(tty) | CTRLCHAR_CTRL;
+ case 'd':
+ return EOF_CHAR(tty) | CTRLCHAR_CTRL;
+ case 'z':
+ return SUSP_CHAR(tty) | CTRLCHAR_CTRL;
}
- return NULL;
+ return CTRLCHAR_NONE;
}
diff -urN linux-2.5.40/drivers/s390/char/ctrlchar.h linux-2.5.40-s390/drivers/s390/char/ctrlchar.h
--- linux-2.5.40/drivers/s390/char/ctrlchar.h Tue Oct 1 09:07:44 2002
+++ linux-2.5.40-s390/drivers/s390/char/ctrlchar.h Fri Oct 4 16:17:01 2002
@@ -7,9 +7,14 @@
*
*/

-#include <linux/config.h>
-#include <linux/types.h>
#include <linux/tty.h>

-extern void ctrlchar_init(void);
-extern char *ctrlchar_handle(const char *buf, int len, struct tty_struct *tty);
+extern unsigned int
+ctrlchar_handle(const char *buf, int len, struct tty_struct *tty);
+
+
+#define CTRLCHAR_NONE (1 << 8)
+#define CTRLCHAR_CTRL (2 << 8)
+#define CTRLCHAR_SYSRQ (3 << 8)
+
+#define CTRLCHAR_MASK (~0xffu)
diff -urN linux-2.5.40/drivers/s390/char/hwc_tty.c linux-2.5.40-s390/drivers/s390/char/hwc_tty.c
--- linux-2.5.40/drivers/s390/char/hwc_tty.c Tue Oct 1 09:06:30 2002
+++ linux-2.5.40-s390/drivers/s390/char/hwc_tty.c Fri Oct 4 16:17:01 2002
@@ -188,15 +188,19 @@
struct tty_struct *tty = hwc_tty_data.tty;

if (tty != NULL) {
- char *cchar;
- if ((cchar = ctrlchar_handle (buf, count, tty))) {
- if (cchar == (char *) -1)
- return;
+ unsigned int cchar = ctrlchar_handle(buf, count, tty);
+
+ switch (cchar & CTRLCHAR_MASK) {
+ case CTRLCHAR_SYSRQ:
+ return;
+
+ case CTRLCHAR_CTRL:
tty->flip.count++;
*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
- *tty->flip.char_buf_ptr++ = *cchar;
- } else {
+ *tty->flip.char_buf_ptr++ = cchar;
+ break;

+ case CTRLCHAR_NONE:
memcpy (tty->flip.char_buf_ptr, buf, count);
if (count < 2 || (
strncmp (buf + count - 2, "^n", 2) ||
@@ -209,6 +213,7 @@
tty->flip.char_buf_ptr += count;
tty->flip.flag_buf_ptr += count;
tty->flip.count += count;
+ break;
}
tty_flip_buffer_push (tty);
hwc_tty_wake_up ();
@@ -221,8 +226,6 @@
if (!CONSOLE_IS_HWC)
return;

- ctrlchar_init ();
-
memset (&hwc_tty_driver, 0, sizeof (struct tty_driver));
memset (&hwc_tty_data, 0, sizeof (hwc_tty_data_struct));
hwc_tty_driver.magic = TTY_DRIVER_MAGIC;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/