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

From: Martin Schwidefsky (schwidefsky@de.ibm.com)
Date: Fri Oct 04 2002 - 09:40:51 EST


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/



This archive was generated by hypermail 2b29 : Mon Oct 07 2002 - 22:00:44 EST