Skip to contentSkip to conversation

hvc: provide a flush operation, implement for opal console, and use in hvc console

RFC PATCH New Nicholas Piggin 1 participant 1 message Apr 9, 2018

Subsystems (3)
lore
Share & tools
lore

Nicholas Piggin

author reviewer
#0 lore raw

RFC PATCH 1/1 hvc: provide a flush operation, implement for opal console, and use in hvc console

This patch is not quite polished and needs to be split out, but the idea is to move busy waits in hvc console drivers out from under locks and into the main hvc driver where it can sleep.

The flush op allows for a 0 timeout which reverts to spin wait behaviour to cater for polling cases. A default operation is used for drivers that don't supply one, and they should get some benefit too just from sleeping outside locks.

This applies on top of the recent series of opal console patches.

Before this patch it is possible to see large interrupts off delays caused by hvc_push->opal_put_chars_nonatomic->opal_flush_console despite the previous series moved the flush from under the opal driver's output lock, because hvc_push is called with the hvc lock.

This is an irqsoff trace collected after running dmesg from the OpenBMC console:

   dmesg-8334   12d...    0us : _raw_spin_lock_irqsave
   dmesg-8334   12d...    0us : hvc_push <-hvc_write
   dmesg-8334   12d...    1us : opal_put_chars_nonatomic <-hvc_push
   dmesg-8334   12d...    1us : __opal_put_chars <-hvc_push
   dmesg-8334   12d...    2us : opal_flush_console <-__opal_put_chars
   dmesg-8334   12d...    4us!: udelay <-opal_flush_console
   dmesg-8334   12d...  787us : soft_nmi_interrupt <-soft_nmi_common
   dmesg-8334   12d...  787us : printk_nmi_enter <-soft_nmi_interrupt
   dmesg-8334   12d.Z.  788us : rcu_nmi_enter <-soft_nmi_interrupt
   dmesg-8334   12d.Z.  788us : rcu_nmi_exit <-soft_nmi_interrupt
   dmesg-8334   12d...  788us#: printk_nmi_exit <-soft_nmi_interrupt
   dmesg-8334   12d... 10005us*: udelay <-opal_flush_console
   dmesg-8334   12d... 20007us*: udelay <-opal_flush_console
   dmesg-8334   12d... 30020us*: udelay <-opal_flush_console
   dmesg-8334   12d... 40022us*: udelay <-opal_flush_console
   dmesg-8334   12d... 50023us*: udelay <-opal_flush_console
   dmesg-8334   12d... 60024us : opal_error_code <-opal_flush_console
   dmesg-8334   12d... 60025us : _raw_spin_unlock_irqrestore <-hvc_write
   dmesg-8334   12d... 60025us : _raw_spin_unlock_irqrestore
   dmesg-8334   12d... 60025us : trace_hardirqs_on <-_raw_spin_unlock_irqrestore
   dmesg-8334   12d... 60027us : <stack trace>

After this patch, the same operation does not show latency above the noise of an idle system (~400us).

Impossible to tell the responsiveness difference with my ping 200-400ms to the BMC. It's not noticably worse.

---
 arch/powerpc/include/asm/opal.h       |   1 +
 arch/powerpc/platforms/powernv/opal.c |  74 ++++++++++--------
 drivers/tty/hvc/hvc_console.c         | 106 ++++++++++++++++++++------
 drivers/tty/hvc/hvc_console.h         |   1 +
 drivers/tty/hvc/hvc_opal.c            |   2 +
 5 files changed, 129 insertions(+), 55 deletions(-)
arch/powerpc/include/asm/opal.h +1 -0
index 66954d671831..115c8a5a0bfd 100644
@@ -304,6 +304,7 @@ extern void opal_configure_cores(void);
 extern int opal_get_chars(uint32_t vtermno, char *buf, int count);
 extern int opal_put_chars(uint32_t vtermno, const char *buf, int total_len);
 extern int opal_put_chars_nonatomic(uint32_t vtermno, const char *buf, int total_len);
+extern int opal_flush_chars(uint32_t vtermno, long timeout);
 extern int opal_flush_console(uint32_t vtermno);
 
 extern void hvc_opal_init_early(void);
arch/powerpc/platforms/powernv/opal.c +42 -32

109 lines not on this page · raw message

drivers/tty/hvc/hvc_console.c +83 -23

146 lines not on this page · raw message

drivers/tty/hvc/hvc_console.h +1 -0
index ea63090e013f..6ae9e0c3b06f 100644
@@ -54,6 +54,7 @@ struct hvc_struct {
 struct hv_ops {
 	int (*get_chars)(uint32_t vtermno, char *buf, int count);
 	int (*put_chars)(uint32_t vtermno, const char *buf, int count);
+	int (*flush)(uint32_t vtermno, long timeout);
 
 	/* Callbacks for notification. Called in open, close and hangup */
 	int (*notifier_add)(struct hvc_struct *hp, int irq);
drivers/tty/hvc/hvc_opal.c +2 -0
index 436b98258e60..782895c659d7 100644
@@ -52,6 +52,7 @@ static u32 hvc_opal_boot_termno;
 static const struct hv_ops hvc_opal_raw_ops = {
 	.get_chars = opal_get_chars,
 	.put_chars = opal_put_chars_nonatomic,
+	.flush = opal_flush_chars,
 	.notifier_add = notifier_add_irq,
 	.notifier_del = notifier_del_irq,
 	.notifier_hangup = notifier_hangup_irq,
@@ -141,6 +142,7 @@ static int hvc_opal_hvsi_tiocmset(struct hvc_struct *hp, unsigned int set,
 static const struct hv_ops hvc_opal_hvsi_ops = {
 	.get_chars = hvc_opal_hvsi_get_chars,
 	.put_chars = hvc_opal_hvsi_put_chars,
+	.flush = opal_flush_chars,
 	.notifier_add = hvc_opal_hvsi_open,
 	.notifier_del = hvc_opal_hvsi_close,
 	.notifier_hangup = hvc_opal_hvsi_hangup,
Signature · 1 line
2.17.0