Patches to make bigger flipbufs possible

Pavel Machek (pavel@suse.cz)
Thu, 28 Oct 1999 17:19:59 +0200


Hi!

Current serials are limited to ~150kbps on HZ==100 systems. This is
patch which attempts to fix it. Tytso, please take a long look, and
try to include it - it is mostly cleanup.
Pavel

--- clean/drivers/char/tty_io.c Sat Oct 23 20:54:45 1999
+++ linux/drivers/char/tty_io.c Sat Oct 23 20:50:09 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 *);
@@ -798,10 +801,15 @@
tp = o_tp = NULL;
ltp = o_ltp = NULL;

- tty = (struct tty_struct*) get_zeroed_page(GFP_KERNEL);
+ tty = (struct tty_struct*) kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
+ memset(tty, 0, sizeof(struct tty_struct));
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;

@@ -824,10 +832,15 @@
}

if (driver->type == TTY_DRIVER_TYPE_PTY) {
- o_tty = (struct tty_struct *) get_zeroed_page(GFP_KERNEL);
+ o_tty = (struct tty_struct *) kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
+ memset(o_tty, 0, sizeof(struct tty_struct));
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;
@@ -943,13 +956,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;
@@ -980,7 +996,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;
@@ -991,7 +1008,8 @@
}
tty->magic = 0;
(*tty->driver.refcount)--;
- free_page((unsigned long) tty);
+ kfree(tty->flip.char_buf);
+ kfree(tty);
}

/*
@@ -1862,8 +1880,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();
@@ -1875,8 +1893,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;
@@ -1940,9 +1958,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;
@@ -1957,6 +1983,7 @@
tty->tq_hangup.data = tty;
sema_init(&tty->atomic_read, 1);
INIT_LIST_HEAD(&tty->tty_files);
+ return 0;
}

/*
@@ -1977,14 +2004,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/include/linux/tty.h Thu Oct 28 15:08:13 1999
+++ linux/include/linux/tty.h Thu Oct 28 15:19:05 1999
@@ -124,13 +124,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;
@@ -138,9 +139,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

-- 
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/