diff options
| author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2002-10-03 21:51:19 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2002-10-03 21:51:19 -0700 |
| commit | 5cc974f558b45f35422eb53f1f8f56808fa69114 (patch) | |
| tree | d438eaad1715fe32a33ecbfc6b5ef9a1c3044415 | |
| parent | 2b46c62781bf2a0d7dd73d4a2b884343f65a38b8 (diff) | |
[PATCH] s390 update (27/27): control characters.
Replace IMMEDIATE_BH bottom half by tasklets in helper functions for
console control characters. Fix a race condition and make it look nicer.
| -rw-r--r-- | drivers/s390/char/con3215.c | 22 | ||||
| -rw-r--r-- | drivers/s390/char/ctrlchar.c | 99 | ||||
| -rw-r--r-- | drivers/s390/char/ctrlchar.h | 13 | ||||
| -rw-r--r-- | drivers/s390/char/hwc_tty.c | 19 |
4 files changed, 73 insertions, 80 deletions
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 18a66f4503b1..1372edd33a45 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -455,7 +455,7 @@ static void raw3215_irq(int irq, void *int_parm, struct pt_regs *regs) 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 @@ static void raw3215_irq(int irq, void *int_parm, struct pt_regs *regs) 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 @@ static void raw3215_irq(int irq, void *int_parm, struct pt_regs *regs) 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 @@ void __init con3215_init(void) raw3215_freelist = req; } - ctrlchar_init(); - #ifdef CONFIG_TN3215_CONSOLE raw3215[0] = raw = (raw3215_info *) alloc_bootmem_low(sizeof(raw3215_info)); diff --git a/drivers/s390/char/ctrlchar.c b/drivers/s390/char/ctrlchar.c index 8a48a583a2c4..6f6b28dc6b12 100644 --- a/drivers/s390/char/ctrlchar.c +++ b/drivers/s390/char/ctrlchar.c @@ -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 @@ void ctrlchar_init(void) { * @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 --git a/drivers/s390/char/ctrlchar.h b/drivers/s390/char/ctrlchar.h index 8a10bbd8340d..a03f0d270c00 100644 --- a/drivers/s390/char/ctrlchar.h +++ b/drivers/s390/char/ctrlchar.h @@ -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 --git a/drivers/s390/char/hwc_tty.c b/drivers/s390/char/hwc_tty.c index e64ec6e7d9dc..5bff78021485 100644 --- a/drivers/s390/char/hwc_tty.c +++ b/drivers/s390/char/hwc_tty.c @@ -188,15 +188,19 @@ hwc_tty_input (unsigned char *buf, unsigned int count) 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 @@ hwc_tty_input (unsigned char *buf, unsigned int count) 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 @@ hwc_tty_init (void) 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; |
