Messages in this thread Patch in this message | | | Date | Wed, 2 Jun 1999 14:13:19 +0200 | From | Pavel Machek <> | Subject | Flip changes done right |
| |
Hi!
My previous patch was totally bogus. (I thought I tried it!!!) I spend two hours fixing it. Ok, here it is, this time it should work. Please apply, Pavel
--- clean/include/linux/tty.h Fri May 14 20:42:58 1999 +++ linux/include/linux/tty.h Wed Jun 2 13:45:36 1999 @@ -125,13 +125,14 @@ */ #define __DISABLED_CHAR '\0' +/* HACK for old drivers, don't include this constant in new code */ +#define TTY_FLIPBUF_SIZE 512 + /* * This is the flip buffer used for the tty driver. The buffer is - * located in the tty structure, and is used as a high speed interface - * between the tty driver and the tty line discipline. + * kmalloced, and is used as a high speed interface between tty driver + * and the line discipline. */ -#define TTY_FLIPBUF_SIZE 512 - struct tty_flip_buffer { struct tq_struct tqueue; struct semaphore pty_sem; @@ -139,9 +140,9 @@ unsigned char *flag_buf_ptr; int count; int buf_num; - unsigned char char_buf[2*TTY_FLIPBUF_SIZE]; - char flag_buf[2*TTY_FLIPBUF_SIZE]; - unsigned char slop[4]; /* N.B. bug overwrites buffer by 1 */ + int flipbuf_size; + unsigned char *char_buf; + char *flag_buf; }; /* * The pty uses char_buf and flag_buf as a contiguous buffer --- clean/include/linux/tty_flip.h Wed Sep 10 04:41:41 1997 +++ linux/include/linux/tty_flip.h Sun May 30 21:08:21 1999 @@ -10,7 +10,7 @@ _INLINE_ void tty_insert_flip_char(struct tty_struct *tty, unsigned char ch, char flag) { - if (tty->flip.count < TTY_FLIPBUF_SIZE) { + if (tty->flip.count < tty->flip.flipbuf_size) { tty->flip.count++; *tty->flip.flag_buf_ptr++ = flag; *tty->flip.char_buf_ptr++ = ch; --- clean/include/linux/tty_driver.h Sun Aug 16 22:34:51 1998 +++ linux/include/linux/tty_driver.h Wed Jun 2 13:24:01 1999 @@ -132,6 +132,7 @@ int *refcount; /* for loadable tty drivers */ struct proc_dir_entry *proc_entry; /* /proc fs entry */ struct tty_driver *other; /* only used for the PTY driver */ + int flip_size; /* requested size of flip buffer */ /* * Pointer to the tty data structures @@ -197,10 +198,13 @@ * optimize for this case if this flag is set. (Note that there * is also a promise, if the above case is true, not to signal * overruns, either.) + * + * TTY_DRIVER_SPECIAL_FLIPSIZE --- we want non-512 bytes flip buffer */ #define TTY_DRIVER_INSTALLED 0x0001 #define TTY_DRIVER_RESET_TERMIOS 0x0002 #define TTY_DRIVER_REAL_RAW 0x0004 +#define TTY_DRIVER_SPECIAL_FLIPSIZE 0x0008 /* tty driver types */ #define TTY_DRIVER_TYPE_SYSTEM 0x0001 --- clean/drivers/char/tty_io.c Fri May 14 20:42:29 1999 +++ linux/drivers/char/tty_io.c Wed Jun 2 14:11:00 1999 @@ -54,6 +54,9 @@ * * Added support for a Unix98-style ptmx device. * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998 + * + * Added support for bigger flipbuf sizes + * -- Pavel Machek <pavel@ucw.cz>, June 99 */ #include <linux/config.h> @@ -115,7 +118,7 @@ */ struct tty_struct * redirect = NULL; -static void initialize_tty_struct(struct tty_struct *tty); +static int initialize_tty_struct(struct tty_struct *tty, int); static ssize_t tty_read(struct file *, char *, size_t, loff_t *); static ssize_t tty_write(struct file *, const char *, size_t, loff_t *); @@ -786,10 +789,14 @@ tp = o_tp = NULL; ltp = o_ltp = NULL; - tty = (struct tty_struct*) get_free_page(GFP_KERNEL); + tty = (struct tty_struct*) kmalloc(sizeof(struct tty_struct), GFP_KERNEL); if(!tty) goto fail_no_mem; - initialize_tty_struct(tty); + + if (initialize_tty_struct(tty, driver->flip_size)) { + kfree(tty); + goto fail_no_mem; + } tty->device = device; tty->driver = *driver; @@ -812,10 +819,14 @@ } if (driver->type == TTY_DRIVER_TYPE_PTY) { - o_tty = (struct tty_struct *) get_free_page(GFP_KERNEL); + o_tty = (struct tty_struct *) kmalloc(sizeof(struct tty_struct), GFP_KERNEL); if (!o_tty) goto free_mem_out; - initialize_tty_struct(o_tty); + if (initialize_tty_struct(o_tty, 512)) { + kfree(o_tty); + o_tty = NULL; + goto free_mem_out; + } o_tty->device = (kdev_t) MKDEV(driver->other->major, driver->other->minor_start + idx); o_tty->driver = *driver->other; @@ -931,13 +942,16 @@ free_mem_out: if (o_tp) kfree_s(o_tp, sizeof(struct termios)); - if (o_tty) - free_page((unsigned long) o_tty); + if (o_tty) { + kfree(o_tty->flip.char_buf); + kfree(o_tty); + } if (ltp) kfree_s(ltp, sizeof(struct termios)); if (tp) kfree_s(tp, sizeof(struct termios)); - free_page((unsigned long) tty); + kfree(tty->flip.char_buf); + kfree(tty); fail_no_mem: retval = -ENOMEM; @@ -968,7 +982,8 @@ } o_tty->magic = 0; (*o_tty->driver.refcount)--; - free_page((unsigned long) o_tty); + kfree(o_tty->flip.char_buf); + kfree(o_tty); } tty->driver.table[idx] = NULL; @@ -979,7 +994,8 @@ } tty->magic = 0; (*tty->driver.refcount)--; - free_page((unsigned long) tty); + kfree(tty->flip.char_buf); + kfree(tty); } /* @@ -1842,8 +1858,8 @@ return; } if (tty->flip.buf_num) { - cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE; - fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE; + cp = tty->flip.char_buf + tty->flip.flipbuf_size; + fp = tty->flip.flag_buf + tty->flip.flipbuf_size; tty->flip.buf_num = 0; save_flags(flags); cli(); @@ -1855,8 +1871,8 @@ tty->flip.buf_num = 1; save_flags(flags); cli(); - tty->flip.char_buf_ptr = tty->flip.char_buf + TTY_FLIPBUF_SIZE; - tty->flip.flag_buf_ptr = tty->flip.flag_buf + TTY_FLIPBUF_SIZE; + tty->flip.char_buf_ptr = tty->flip.char_buf + tty->flip.flipbuf_size; + tty->flip.flag_buf_ptr = tty->flip.flag_buf + tty->flip.flipbuf_size; } count = tty->flip.count; tty->flip.count = 0; @@ -1920,9 +1936,17 @@ /* * This subroutine initializes a tty structure. */ -static void initialize_tty_struct(struct tty_struct *tty) +static int initialize_tty_struct(struct tty_struct *tty, int flip_size) { memset(tty, 0, sizeof(struct tty_struct)); + + /* there was notice about buffer overrun in original code -- that's why I do +4 */ + tty->flip.char_buf = kmalloc(flip_size*4 +4, GFP_KERNEL); + if (!tty->flip.char_buf) + return -ENOMEM; + + tty->flip.flag_buf = tty->flip.char_buf + flip_size*2; + tty->flip.flipbuf_size = flip_size; tty->magic = TTY_MAGIC; tty->ldisc = ldiscs[N_TTY]; tty->pgrp = -1; @@ -1936,6 +1960,7 @@ tty->tq_hangup.routine = do_tty_hangup; tty->tq_hangup.data = tty; sema_init(&tty->atomic_read, 1); + return 0; } /* @@ -1956,14 +1981,19 @@ if (driver->flags & TTY_DRIVER_INSTALLED) return 0; + if (!(driver->flags & TTY_DRIVER_SPECIAL_FLIPSIZE)) + driver->flip_size = 512; + error = register_chrdev(driver->major, driver->name, &tty_fops); - if (error < 0) + if (error < 0) { return error; + } else if(driver->major == 0) driver->major = error; if (!driver->put_char) driver->put_char = tty_default_put_char; + driver->prev = 0; driver->next = tty_drivers; --- clean/drivers/char/pty.c Fri May 14 20:42:27 1999 +++ linux/drivers/char/pty.c Wed Jun 2 12:08:15 1999 @@ -150,7 +150,7 @@ n = MIN(count, to->ldisc.receive_room(to)); if (!n) break; - n = MIN(n, PTY_BUF_SIZE); + n = MIN(n, tty->flip.flipbuf_size); n -= copy_from_user(temp_buffer, buf, n); if (!n) { if (!c) --- clean/drivers/char/serial.c Fri May 14 20:42:29 1999 +++ linux/drivers/char/serial.c Wed Jun 2 12:09:51 1999 @@ -385,7 +389,7 @@ icount = &info->state->icount; do { ch = serial_inp(info, UART_RX); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) + if (tty->flip.count >= tty->flip.flipbuf_size) break; *tty->flip.char_buf_ptr = ch; icount->rx++; @@ -438,7 +442,7 @@ * reported immediately, and doesn't * affect the current character */ - if (tty->flip.count < TTY_FLIPBUF_SIZE) { + if (tty->flip.count < tty->flip.flipbuf_size) { tty->flip.count++; tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; -- I'm really pavel@ucw.cz. Look at http://195.113.31.123/~pavel. Pavel Hi! I'm a .signature virus! Copy me into your ~/.signature, please! - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |