Commit 084bd9dd authored by Philippe Gerum's avatar Philippe Gerum

ipipe: printk: enable dev_printk() from the head stage

Calling dev_{info,warn,err}() is currently invalid, as vprintk_emit()
eventually operates on regular kernel resources.

If called from the head stage, or with hard irqs disabled in presence
of a head stage, route all dev_printk() requests to our deferred
logging mechanism already used for printk() instead. This means that
we won't syslog the output in such a case, but at least we will have a
feedback on the console device, without doing anything silly in the
meantime.
parent 1dc516b0
......@@ -2785,6 +2785,19 @@ 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 over the head stage, or if hard locked
* over the root stage.
*/
if (__ipipe_current_domain != ipipe_root_domain ||
(ipipe_head_domain != ipipe_root_domain &&
hard_irqs_disabled())) {
__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);
......
......@@ -47,6 +47,7 @@ void ipipe_restore_root(unsigned long x);
#include <asm/ipipe_base.h>
#include <linux/compiler.h>
#include <linux/linkage.h>
#include <stdarg.h>
#ifndef IPIPE_NR_ROOT_IRQS
#define IPIPE_NR_ROOT_IRQS NR_IRQS
......@@ -169,6 +170,7 @@ static inline void __ipipe_sync_stage(void)
#define __ipipe_run_irqtail(irq) do { } while(0)
#endif
int __ipipe_log_printk(const char *fmt, va_list args);
void __ipipe_flush_printk(unsigned int irq, void *cookie);
#define __ipipe_get_cpu(flags) ({ (flags) = hard_preempt_disable(); ipipe_processor_id(); })
......
......@@ -1823,6 +1823,29 @@ 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;
......@@ -1870,12 +1893,13 @@ start:
*
* See the vsnprintf() documentation for format string extensions over C99.
*/
asmlinkage __visible int printk(const char *fmt, ...)
{
int sprintk = 1, cs = -1;
int r, fbytes, oldcount;
unsigned long flags;
va_list args;
int ret;
va_start(args, fmt);
......@@ -1894,31 +1918,15 @@ asmlinkage __visible int printk(const char *fmt, ...)
hard_local_irq_restore(flags);
if (sprintk) {
r = vprintk_func(fmt, args);
ret = vprintk_func(fmt, args);
if (cs != -1)
ipipe_restore_context_check(cs);
goto out;
}
raw_spin_lock_irqsave(&__ipipe_printk_lock, flags);
oldcount = __ipipe_printk_fill;
fbytes = __LOG_BUF_LEN - oldcount;
if (fbytes > 1) {
r = vscnprintf(__ipipe_printk_buf + __ipipe_printk_fill,
fbytes, fmt, args) + 1;
__ipipe_printk_fill += r;
} else
r = 0;
raw_spin_unlock_irqrestore(&__ipipe_printk_lock, flags);
ret = __ipipe_log_printk(fmt, args);
if (oldcount == 0)
ipipe_raise_irq(__ipipe_printk_virq);
out:
va_end(args);
return r;
return ret;
}
#else /* !CONFIG_IPIPE */
......
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