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

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

tty: hvc: hvc_poll() break hv read loop



Avoid looping with the spinlock held while there is read data
being returned from the hv driver. Instead note if the entire
size returned by tty_buffer_request_room was read, and request
another read poll.

This limits the critical section lengths, and provides more
even service to other consoles in case there is a pathological
condition.

Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent a9bf5c8a
Loading
Loading
Loading
Loading
+45 −43
Original line number Diff line number Diff line
@@ -592,7 +592,7 @@ static u32 timeout = MIN_TIMEOUT;
int hvc_poll(struct hvc_struct *hp)
{
	struct tty_struct *tty;
	int i, n, poll_mask = 0;
	int i, n, count, poll_mask = 0;
	char buf[N_INBUF] __ALIGNED__;
	unsigned long flags;
	int read_total = 0;
@@ -618,7 +618,7 @@ int hvc_poll(struct hvc_struct *hp)

	/* Now check if we can get data (are we throttled ?) */
	if (tty_throttled(tty))
		goto throttled;
		goto out;

	/* If we aren't notifier driven and aren't throttled, we always
	 * request a reschedule
@@ -627,13 +627,13 @@ int hvc_poll(struct hvc_struct *hp)
		poll_mask |= HVC_POLL_READ;

	/* Read data if any */
	for (;;) {
		int count = tty_buffer_request_room(&hp->port, N_INBUF);

	count = tty_buffer_request_room(&hp->port, N_INBUF);

	/* If flip is full, just reschedule a later read */
	if (count == 0) {
		poll_mask |= HVC_POLL_READ;
			break;
		goto out;
	}

	n = hp->ops->get_chars(hp->vtermno, buf, count);
@@ -651,8 +651,9 @@ int hvc_poll(struct hvc_struct *hp)
			 */
			poll_mask |= HVC_POLL_READ;
		}
			break;
		goto out;
	}

	for (i = 0; i < n; ++i) {
#ifdef CONFIG_MAGIC_SYSRQ
		if (hp->index == hvc_console.index) {
@@ -673,10 +674,11 @@ int hvc_poll(struct hvc_struct *hp)
#endif /* CONFIG_MAGIC_SYSRQ */
		tty_insert_flip_char(&hp->port, buf[i], 0);
	}
	if (n == count)
		poll_mask |= HVC_POLL_READ;
	read_total = n;

		read_total += n;
	}
 throttled:
 out:
	/* Wakeup write queue if necessary */
	if (hp->do_wakeup) {
		hp->do_wakeup = 0;