Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+21 −15
Original line number Original line Diff line number Diff line
@@ -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.
	 */
	 */