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 <npig...@gmail.com>
---
 drivers/tty/hvc/hvc_console.c | 36 ++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 2abfc0b15fbb..6131d5084c42 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -493,23 +493,29 @@ static int hvc_write(struct tty_struct *tty, const 
unsigned char *buf, int count
        if (hp->port.count <= 0)
                return -EIO;
 
-       spin_lock_irqsave(&hp->lock, flags);
+       while (count > 0) {
+               spin_lock_irqsave(&hp->lock, flags);
 
-       /* Push pending writes */
-       if (hp->n_outbuf > 0)
-               hvc_push(hp);
-
-       while (count > 0 && (rsize = hp->outbuf_size - hp->n_outbuf) > 0) {
-               if (rsize > count)
-                       rsize = count;
-               memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
-               count -= rsize;
-               buf += rsize;
-               hp->n_outbuf += rsize;
-               written += rsize;
-               hvc_push(hp);
+               rsize = hp->outbuf_size - hp->n_outbuf;
+
+               if (rsize) {
+                       if (rsize > count)
+                               rsize = count;
+                       memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
+                       count -= rsize;
+                       buf += rsize;
+                       hp->n_outbuf += rsize;
+                       written += rsize;
+               }
+
+               if (hp->n_outbuf > 0)
+                       hvc_push(hp);
+
+               spin_unlock_irqrestore(&hp->lock, flags);
+
+               if (count)
+                       cond_resched();
        }
-       spin_unlock_irqrestore(&hp->lock, flags);
 
        /*
         * Racy, but harmless, kick thread if there is still pending data.
-- 
2.17.0

Reply via email to