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: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
cfb5946b55
commit
550ddadcc7
@ -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
|
|||||||
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.
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user