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

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
...@@ -110,6 +110,29 @@ static struct hvc_struct *hvc_get_by_index(int index) ...@@ -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, ...@@ -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, ...@@ -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 ...@@ -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.
......
...@@ -54,6 +54,7 @@ struct hvc_struct { ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment