tty: make receive_buf() return the amout of bytes received
it makes it simpler to keep track of the amount of bytes received and simplifies how flush_to_ldisc counts the remaining bytes. It also fixes a bug of lost bytes on n_tty when flushing too many bytes via the USB serial gadget driver. Tested-by: Stefan Bigler <stefan.bigler@keymile.com> Tested-by: Toby Gray <toby.gray@realvnc.com> Signed-off-by: Felipe Balbi <balbi@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
e9a470f445
commit
b1c43f82c5
@ -81,38 +81,6 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
|
||||
return put_user(x, ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* n_tty_set__room - receive space
|
||||
* @tty: terminal
|
||||
*
|
||||
* Called by the driver to find out how much data it is
|
||||
* permitted to feed to the line discipline without any being lost
|
||||
* and thus to manage flow control. Not serialized. Answers for the
|
||||
* "instant".
|
||||
*/
|
||||
|
||||
static void n_tty_set_room(struct tty_struct *tty)
|
||||
{
|
||||
/* tty->read_cnt is not read locked ? */
|
||||
int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
|
||||
int old_left;
|
||||
|
||||
/*
|
||||
* If we are doing input canonicalization, and there are no
|
||||
* pending newlines, let characters through without limit, so
|
||||
* that erase characters will be handled. Other excess
|
||||
* characters will be beeped.
|
||||
*/
|
||||
if (left <= 0)
|
||||
left = tty->icanon && !tty->canon_data;
|
||||
old_left = tty->receive_room;
|
||||
tty->receive_room = left;
|
||||
|
||||
/* Did this open up the receive buffer? We may need to flip */
|
||||
if (left && !old_left)
|
||||
schedule_work(&tty->buf.work);
|
||||
}
|
||||
|
||||
static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
|
||||
{
|
||||
if (tty->read_cnt < N_TTY_BUF_SIZE) {
|
||||
@ -184,7 +152,6 @@ static void reset_buffer_flags(struct tty_struct *tty)
|
||||
|
||||
tty->canon_head = tty->canon_data = tty->erasing = 0;
|
||||
memset(&tty->read_flags, 0, sizeof tty->read_flags);
|
||||
n_tty_set_room(tty);
|
||||
check_unthrottle(tty);
|
||||
}
|
||||
|
||||
@ -1360,17 +1327,19 @@ static void n_tty_write_wakeup(struct tty_struct *tty)
|
||||
* calls one at a time and in order (or using flush_to_ldisc)
|
||||
*/
|
||||
|
||||
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
char *fp, int count)
|
||||
static unsigned int n_tty_receive_buf(struct tty_struct *tty,
|
||||
const unsigned char *cp, char *fp, int count)
|
||||
{
|
||||
const unsigned char *p;
|
||||
char *f, flags = TTY_NORMAL;
|
||||
int i;
|
||||
char buf[64];
|
||||
unsigned long cpuflags;
|
||||
int left;
|
||||
int ret = 0;
|
||||
|
||||
if (!tty->read_buf)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (tty->real_raw) {
|
||||
spin_lock_irqsave(&tty->read_lock, cpuflags);
|
||||
@ -1380,6 +1349,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
memcpy(tty->read_buf + tty->read_head, cp, i);
|
||||
tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
|
||||
tty->read_cnt += i;
|
||||
ret += i;
|
||||
cp += i;
|
||||
count -= i;
|
||||
|
||||
@ -1389,8 +1359,10 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
memcpy(tty->read_buf + tty->read_head, cp, i);
|
||||
tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
|
||||
tty->read_cnt += i;
|
||||
ret += i;
|
||||
spin_unlock_irqrestore(&tty->read_lock, cpuflags);
|
||||
} else {
|
||||
ret = count;
|
||||
for (i = count, p = cp, f = fp; i; i--, p++) {
|
||||
if (f)
|
||||
flags = *f++;
|
||||
@ -1418,8 +1390,6 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
tty->ops->flush_chars(tty);
|
||||
}
|
||||
|
||||
n_tty_set_room(tty);
|
||||
|
||||
if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||
|
||||
L_EXTPROC(tty)) {
|
||||
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
|
||||
@ -1432,8 +1402,12 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
|
||||
* mode. We don't want to throttle the driver if we're in
|
||||
* canonical mode and don't have a newline yet!
|
||||
*/
|
||||
if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
|
||||
left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
|
||||
|
||||
if (left < TTY_THRESHOLD_THROTTLE)
|
||||
tty_throttle(tty);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int is_ignored(int sig)
|
||||
@ -1477,7 +1451,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
|
||||
if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
|
||||
tty->raw = 1;
|
||||
tty->real_raw = 1;
|
||||
n_tty_set_room(tty);
|
||||
return;
|
||||
}
|
||||
if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) ||
|
||||
@ -1530,7 +1503,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
|
||||
else
|
||||
tty->real_raw = 0;
|
||||
}
|
||||
n_tty_set_room(tty);
|
||||
/* The termios change make the tty ready for I/O */
|
||||
wake_up_interruptible(&tty->write_wait);
|
||||
wake_up_interruptible(&tty->read_wait);
|
||||
@ -1812,8 +1784,6 @@ do_it_again:
|
||||
retval = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
/* FIXME: does n_tty_set_room need locking ? */
|
||||
n_tty_set_room(tty);
|
||||
timeout = schedule_timeout(timeout);
|
||||
continue;
|
||||
}
|
||||
@ -1885,10 +1855,8 @@ do_it_again:
|
||||
* longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
|
||||
* we won't get any more characters.
|
||||
*/
|
||||
if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) {
|
||||
n_tty_set_room(tty);
|
||||
if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE)
|
||||
check_unthrottle(tty);
|
||||
}
|
||||
|
||||
if (b - buf >= minimum)
|
||||
break;
|
||||
@ -1910,7 +1878,6 @@ do_it_again:
|
||||
} else if (test_and_clear_bit(TTY_PUSH, &tty->flags))
|
||||
goto do_it_again;
|
||||
|
||||
n_tty_set_room(tty);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user