Repost: patch for 2.1.112 n_tty.c

Bill Hawes (whawes@transmeta.com)
Fri, 31 Jul 1998 12:59:33 -0700


This is a multi-part message in MIME format.
--------------80ED899E5CC44F9FB760C34F
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The attached patch for drivers/char/n_tty.c fixes a couple of bugs in
the n_tty code, and might help with some of the fb console problems
people are seeing. One of the bugs is that the opost_block doesn't check
for error returns from the low level driver, and bad things will happen
if the return value is an error rather than a count.

The other changes are to make the tty code not block for a 0-length
read, and some code cleanup that's pretty much self-explanatory.

I've been using the patch since 2.1.103 or thereabouts, so it's pretty
well tested.

Regards,
Bill

--------------80ED899E5CC44F9FB760C34F
Content-Type: text/plain; charset=us-ascii; name="n_tty112-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="n_tty112-patch"

--- linux-2.1.112/drivers/char/n_tty.c.old Wed Mar 11 17:37:13 1998
+++ linux-2.1.112/drivers/char/n_tty.c Tue Jul 28 16:25:28 1998
@@ -190,7 +190,7 @@
* opost_block --- to speed up block console writes, among other
* things.
*/
-static int opost_block(struct tty_struct * tty,
+static ssize_t opost_block(struct tty_struct * tty,
const unsigned char * inbuf, unsigned int nr)
{
char buf[80];
@@ -863,9 +863,9 @@
static ssize_t read_chan(struct tty_struct *tty, struct file *file,
unsigned char *buf, size_t nr)
{
+ unsigned char *b = buf;
struct wait_queue wait = { current, NULL };
int c;
- unsigned char *b = buf;
int minimum, time;
ssize_t retval = 0;
ssize_t size;
@@ -896,25 +896,23 @@
}
}

- if (tty->icanon) {
- minimum = time = 0;
- current->timeout = (unsigned long) -1;
- } else {
+ minimum = time = 0;
+ current->timeout = (unsigned long) -1;
+ if (!tty->icanon) {
time = (HZ / 10) * TIME_CHAR(tty);
minimum = MIN_CHAR(tty);
if (minimum) {
- current->timeout = (unsigned long) -1;
if (time)
tty->minimum_to_wake = 1;
else if (!waitqueue_active(&tty->read_wait) ||
(tty->minimum_to_wake > minimum))
tty->minimum_to_wake = minimum;
} else {
+ current->timeout = 0;
if (time) {
current->timeout = time + jiffies;
time = 0;
- } else
- current->timeout = 0;
+ }
tty->minimum_to_wake = minimum = 1;
}
}
@@ -922,10 +920,10 @@
add_wait_queue(&tty->read_wait, &wait);

disable_bh(TQUEUE_BH);
- while (1) {
+ while (nr) {
/* First test for status change. */
if (tty->packet && tty->link->ctrl_status) {
- if (b != buf || !nr)
+ if (b != buf)
break;
put_user(tty->link->ctrl_status, b++);
nr--;
@@ -966,7 +964,7 @@
current->state = TASK_RUNNING;

/* Deal with packet mode. */
- if (tty->packet && b == buf && nr) {
+ if (tty->packet && b == buf) {
put_user(TIOCPKT_DATA, b++);
nr--;
}
@@ -1013,7 +1011,7 @@
if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE)
check_unthrottle(tty);

- if (b - buf >= minimum || !nr)
+ if (b - buf >= minimum)
break;
if (time)
current->timeout = time + jiffies;
@@ -1027,25 +1025,27 @@
current->state = TASK_RUNNING;
current->timeout = 0;
size = b - buf;
- if (size && nr)
- clear_bit(TTY_PUSH, &tty->flags);
- if (!size && test_and_clear_bit(TTY_PUSH, &tty->flags))
- goto do_it_again;
- if (!size && !retval)
- clear_bit(TTY_PUSH, &tty->flags);
- return (size ? size : retval);
+ if (size) {
+ retval = size;
+ if (nr)
+ clear_bit(TTY_PUSH, &tty->flags);
+ } else if (test_and_clear_bit(TTY_PUSH, &tty->flags))
+ goto do_it_again;
+
+ return retval;
}

static ssize_t write_chan(struct tty_struct * tty, struct file * file,
const unsigned char * buf, size_t nr)
{
+ const unsigned char *b = buf;
struct wait_queue wait = { current, NULL };
int c;
- const unsigned char *b = buf;
- ssize_t retval = 0, num;
+ ssize_t retval = 0;

/* Job control check -- must be done at start (POSIX.1 7.1.1.4). */
- if (L_TOSTOP(tty) && file->f_dentry->d_inode->i_rdev != CONSOLE_DEV &&
+ if (L_TOSTOP(tty) &&
+ file->f_dentry->d_inode->i_rdev != CONSOLE_DEV &&
file->f_dentry->d_inode->i_rdev != SYSCONS_DEV) {
retval = tty_check_change(tty);
if (retval)
@@ -1065,7 +1065,11 @@
}
if (O_OPOST(tty) && !(test_bit(TTY_HW_COOK_OUT, &tty->flags))) {
while (nr > 0) {
- num = opost_block(tty, b, nr);
+ ssize_t num = opost_block(tty, b, nr);
+ if (num < 0) {
+ retval = num;
+ goto break_out;
+ }
b += num;
nr -= num;
if (nr == 0)
@@ -1081,7 +1085,7 @@
c = tty->driver.write(tty, 1, b, nr);
if (c < 0) {
retval = c;
- break;
+ goto break_out;
}
b += c;
nr -= c;
@@ -1094,6 +1098,7 @@
}
schedule();
}
+break_out:
current->state = TASK_RUNNING;
remove_wait_queue(&tty->write_wait, &wait);
return (b - buf) ? b - buf : retval;

--------------80ED899E5CC44F9FB760C34F--

-
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.altern.org/andrebalsa/doc/lkml-faq.html