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

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

tty: hvc: introduce the hv_ops.flush operation for hvc drivers



Use .flush to wait for drivers to flush their console outside of
the spinlock, to reduce lock/irq latencies.

Flush the hvc console driver after each write, which can help
messages make it out to the console after a crash.

Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 550ddadc
Loading
Loading
Loading
Loading
+33 −2
Original line number Original line Diff line number Diff line
@@ -110,6 +110,29 @@ static struct hvc_struct *hvc_get_by_index(int index)
	return hp;
	return hp;
}
}


static int __hvc_flush(const struct hv_ops *ops, uint32_t vtermno, bool wait)
{
	if (wait)
		might_sleep();

	if (ops->flush)
		return ops->flush(vtermno, wait);
	return 0;
}

static int hvc_console_flush(const struct hv_ops *ops, uint32_t vtermno)
{
	return __hvc_flush(ops, vtermno, false);
}

/*
 * Wait for the console to flush before writing more to it. This sleeps.
 */
static int hvc_flush(struct hvc_struct *hp)
{
	return __hvc_flush(hp->ops, hp->vtermno, true);
}

/*
/*
 * Initial console vtermnos for console API usage prior to full console
 * Initial console vtermnos for console API usage prior to full console
 * initialization.  Any vty adapter outside this range will not have usable
 * initialization.  Any vty adapter outside this range will not have usable
@@ -155,8 +178,12 @@ static void hvc_console_print(struct console *co, const char *b,
			if (r <= 0) {
			if (r <= 0) {
				/* throw away characters on error
				/* throw away characters on error
				 * but spin in case of -EAGAIN */
				 * but spin in case of -EAGAIN */
				if (r != -EAGAIN)
				if (r != -EAGAIN) {
					i = 0;
					i = 0;
				} else {
					hvc_console_flush(cons_ops[index],
						      vtermnos[index]);
				}
			} else if (r > 0) {
			} else if (r > 0) {
				i -= r;
				i -= r;
				if (i > 0)
				if (i > 0)
@@ -164,6 +191,7 @@ static void hvc_console_print(struct console *co, const char *b,
			}
			}
		}
		}
	}
	}
	hvc_console_flush(cons_ops[index], vtermnos[index]);
}
}


static struct tty_driver *hvc_console_device(struct console *c, int *index)
static struct tty_driver *hvc_console_device(struct console *c, int *index)
@@ -513,9 +541,12 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count


		spin_unlock_irqrestore(&hp->lock, flags);
		spin_unlock_irqrestore(&hp->lock, flags);


		if (count)
		if (count) {
			if (hp->n_outbuf > 0)
				hvc_flush(hp);
			cond_resched();
			cond_resched();
		}
		}
	}


	/*
	/*
	 * Racy, but harmless, kick thread if there is still pending data.
	 * Racy, but harmless, kick thread if there is still pending data.
+1 −0
Original line number Original line Diff line number Diff line
@@ -54,6 +54,7 @@ struct hvc_struct {
struct hv_ops {
struct hv_ops {
	int (*get_chars)(uint32_t vtermno, char *buf, int count);
	int (*get_chars)(uint32_t vtermno, char *buf, int count);
	int (*put_chars)(uint32_t vtermno, const char *buf, int count);
	int (*put_chars)(uint32_t vtermno, const char *buf, int count);
	int (*flush)(uint32_t vtermno, bool wait);


	/* Callbacks for notification. Called in open, close and hangup */
	/* Callbacks for notification. Called in open, close and hangup */
	int (*notifier_add)(struct hvc_struct *hp, int irq);
	int (*notifier_add)(struct hvc_struct *hp, int irq);