Commit 550ddadc authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman

tty: hvc: hvc_write() may sleep

Rework the hvc_write loop to drop and re-take the spinlock on each
iteration, add a cond_resched. Don't bother with an initial hvc_push
initially, which makes the logic simpler -- just do a hvc_push on
each time around the loop.
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent cfb5946b
...@@ -493,13 +493,12 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count ...@@ -493,13 +493,12 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count
if (hp->port.count <= 0) if (hp->port.count <= 0)
return -EIO; return -EIO;
while (count > 0) {
spin_lock_irqsave(&hp->lock, flags); spin_lock_irqsave(&hp->lock, flags);
/* Push pending writes */ rsize = hp->outbuf_size - hp->n_outbuf;
if (hp->n_outbuf > 0)
hvc_push(hp);
while (count > 0 && (rsize = hp->outbuf_size - hp->n_outbuf) > 0) { if (rsize) {
if (rsize > count) if (rsize > count)
rsize = count; rsize = count;
memcpy(hp->outbuf + hp->n_outbuf, buf, rsize); memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
...@@ -507,10 +506,17 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count ...@@ -507,10 +506,17 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count
buf += rsize; buf += rsize;
hp->n_outbuf += rsize; hp->n_outbuf += rsize;
written += rsize; written += rsize;
hvc_push(hp);
} }
if (hp->n_outbuf > 0)
hvc_push(hp);
spin_unlock_irqrestore(&hp->lock, flags); spin_unlock_irqrestore(&hp->lock, flags);
if (count)
cond_resched();
}
/* /*
* Racy, but harmless, kick thread if there is still pending data. * Racy, but harmless, kick thread if there is still pending data.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment