printk: ipipe: defer printk() from head domain
authorPhilippe Gerum <rpm@xenomai.org>
Sun, 3 Dec 2017 11:03:03 +0000 (12:03 +0100)
committerMarek Szyprowski <m.szyprowski@samsung.com>
Fri, 27 Apr 2018 09:21:34 +0000 (11:21 +0200)
drivers/base/core.c
kernel/printk/printk.c

index 12ebd055724cd6cdc01edff013583f38979fe92a..b757056c2f4bd1007b7f468573f40bc5190607f1 100644 (file)
@@ -2915,6 +2915,17 @@ EXPORT_SYMBOL(dev_printk_emit);
 static void __dev_printk(const char *level, const struct device *dev,
                        struct va_format *vaf)
 {
+#ifdef CONFIG_IPIPE
+       /*
+        * Console logging only if hard locked, or over the head
+        * stage.
+        */
+       if (hard_irqs_disabled() || !ipipe_root_p) {
+               __ipipe_log_printk(vaf->fmt, *vaf->va);
+               return;
+       }
+#endif
+           
        if (dev)
                dev_printk_emit(level[1] - '0', dev, "%s %s: %pV",
                                dev_driver_string(dev), dev_name(dev), vaf);
index 512f7c2baedd59bef5300e361c22e92b7a4845a0..651265f21c1c567c9980243eef53329b0bd1dd75 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/kmsg_dump.h>
 #include <linux/syslog.h>
 #include <linux/cpu.h>
+#include <linux/ipipe.h>
 #include <linux/notifier.h>
 #include <linux/rculist.h>
 #include <linux/poll.h>
@@ -1799,6 +1800,65 @@ int vprintk_default(const char *fmt, va_list args)
 }
 EXPORT_SYMBOL_GPL(vprintk_default);
 
+#ifdef CONFIG_IPIPE
+
+extern int __ipipe_printk_bypass;
+
+static IPIPE_DEFINE_SPINLOCK(__ipipe_printk_lock);
+
+static int __ipipe_printk_fill;
+
+static char __ipipe_printk_buf[__LOG_BUF_LEN];
+
+int __ipipe_log_printk(const char *fmt, va_list args)
+{
+       int ret = 0, fbytes, oldcount;
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&__ipipe_printk_lock, flags);
+
+       oldcount = __ipipe_printk_fill;
+       fbytes = __LOG_BUF_LEN - oldcount;
+       if (fbytes > 1) {
+               ret = vscnprintf(__ipipe_printk_buf + __ipipe_printk_fill,
+                                fbytes, fmt, args) + 1;
+               __ipipe_printk_fill += ret;
+       }
+
+       raw_spin_unlock_irqrestore(&__ipipe_printk_lock, flags);
+
+       if (oldcount == 0)
+               ipipe_raise_irq(__ipipe_printk_virq);
+
+       return ret;
+}
+
+void __ipipe_flush_printk (unsigned virq, void *cookie)
+{
+       char *p = __ipipe_printk_buf;
+       int len, lmax, out = 0;
+       unsigned long flags;
+
+       goto start;
+       do {
+       raw_spin_unlock_irqrestore(&__ipipe_printk_lock, flags);
+start:
+               lmax = __ipipe_printk_fill;
+               while (out < lmax) {
+                       len = strlen(p) + 1;
+                       printk("%s",p);
+                       p += len;
+                       out += len;
+               }
+               raw_spin_lock_irqsave(&__ipipe_printk_lock, flags);
+       }
+       while (__ipipe_printk_fill != lmax);
+
+       __ipipe_printk_fill = 0;
+
+       raw_spin_unlock_irqrestore(&__ipipe_printk_lock, flags);
+}
+
 /**
  * printk - print a kernel message
  * @fmt: format string
@@ -1820,6 +1880,44 @@ EXPORT_SYMBOL_GPL(vprintk_default);
  *
  * See the vsnprintf() documentation for format string extensions over C99.
  */
+
+asmlinkage __visible int printk(const char *fmt, ...)
+{
+       int sprintk = 1, cs = -1;
+       unsigned long flags;
+       va_list args;
+       int ret;
+
+       va_start(args, fmt);
+
+       flags = hard_local_irq_save();
+
+       if (__ipipe_printk_bypass || oops_in_progress)
+               cs = ipipe_disable_context_check();
+       else if (__ipipe_current_domain == ipipe_root_domain) {
+               if (ipipe_head_domain != ipipe_root_domain && 
+                   (raw_irqs_disabled_flags(flags) ||
+                    test_bit(IPIPE_STALL_FLAG, &__ipipe_head_status)))
+                       sprintk = 0;
+       } else
+               sprintk = 0;
+
+       hard_local_irq_restore(flags);
+
+       if (sprintk) {
+               ret = vprintk_func(fmt, args);
+               if (cs != -1)
+                       ipipe_restore_context_check(cs);
+       } else
+               ret = __ipipe_log_printk(fmt, args);
+
+       va_end(args);
+
+       return ret;
+}
+
+#else /* !CONFIG_IPIPE */
+
 asmlinkage __visible int printk(const char *fmt, ...)
 {
        va_list args;
@@ -1831,6 +1929,9 @@ asmlinkage __visible int printk(const char *fmt, ...)
 
        return r;
 }
+
+#endif /* CONFIG_IPIPE */
+
 EXPORT_SYMBOL(printk);
 
 #else /* CONFIG_PRINTK */
@@ -3128,6 +3229,9 @@ void dump_stack_print_info(const char *log_lvl)
                printk("%sHardware name: %s\n",
                       log_lvl, dump_stack_arch_desc_str);
 
+#ifdef CONFIG_IPIPE
+       printk("I-pipe domain: %s\n", ipipe_current_domain->name);
+#endif
        print_worker_info(log_lvl, current);
 }