aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/percpu.h3
-rw-r--r--include/linux/printk.h2
-rw-r--r--kernel/printk/printk.c38
3 files changed, 34 insertions, 9 deletions
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index a3aa63e47637..ba2e85a0ff5b 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -134,4 +134,7 @@ extern phys_addr_t per_cpu_ptr_to_phys(void *addr);
134 (typeof(type) __percpu *)__alloc_percpu(sizeof(type), \ 134 (typeof(type) __percpu *)__alloc_percpu(sizeof(type), \
135 __alignof__(type)) 135 __alignof__(type))
136 136
137/* To avoid include hell, as printk can not declare this, we declare it here */
138DECLARE_PER_CPU(printk_func_t, printk_func);
139
137#endif /* __LINUX_PERCPU_H */ 140#endif /* __LINUX_PERCPU_H */
diff --git a/include/linux/printk.h b/include/linux/printk.h
index d78125f73ac4..3bbd979d32fb 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -162,6 +162,8 @@ extern int kptr_restrict;
162 162
163extern void wake_up_klogd(void); 163extern void wake_up_klogd(void);
164 164
165typedef int(*printk_func_t)(const char *fmt, va_list args);
166
165void log_buf_kexec_setup(void); 167void log_buf_kexec_setup(void);
166void __init setup_log_buf(int early); 168void __init setup_log_buf(int early);
167void dump_stack_set_arch_desc(const char *fmt, ...); 169void dump_stack_set_arch_desc(const char *fmt, ...);
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index ced2b84b1cb7..f7b723f98cb9 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1807,6 +1807,30 @@ asmlinkage int printk_emit(int facility, int level,
1807} 1807}
1808EXPORT_SYMBOL(printk_emit); 1808EXPORT_SYMBOL(printk_emit);
1809 1809
1810int vprintk_default(const char *fmt, va_list args)
1811{
1812 int r;
1813
1814#ifdef CONFIG_KGDB_KDB
1815 if (unlikely(kdb_trap_printk)) {
1816 r = vkdb_printf(fmt, args);
1817 return r;
1818 }
1819#endif
1820 r = vprintk_emit(0, -1, NULL, 0, fmt, args);
1821
1822 return r;
1823}
1824EXPORT_SYMBOL_GPL(vprintk_default);
1825
1826/*
1827 * This allows printk to be diverted to another function per cpu.
1828 * This is useful for calling printk functions from within NMI
1829 * without worrying about race conditions that can lock up the
1830 * box.
1831 */
1832DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default;
1833
1810/** 1834/**
1811 * printk - print a kernel message 1835 * printk - print a kernel message
1812 * @fmt: format string 1836 * @fmt: format string
@@ -1830,19 +1854,15 @@ EXPORT_SYMBOL(printk_emit);
1830 */ 1854 */
1831asmlinkage __visible int printk(const char *fmt, ...) 1855asmlinkage __visible int printk(const char *fmt, ...)
1832{ 1856{
1857 printk_func_t vprintk_func;
1833 va_list args; 1858 va_list args;
1834 int r; 1859 int r;
1835 1860
1836#ifdef CONFIG_KGDB_KDB
1837 if (unlikely(kdb_trap_printk)) {
1838 va_start(args, fmt);
1839 r = vkdb_printf(fmt, args);
1840 va_end(args);
1841 return r;
1842 }
1843#endif
1844 va_start(args, fmt); 1861 va_start(args, fmt);
1845 r = vprintk_emit(0, -1, NULL, 0, fmt, args); 1862 preempt_disable();
1863 vprintk_func = this_cpu_read(printk_func);
1864 r = vprintk_func(fmt, args);
1865 preempt_enable();
1846 va_end(args); 1866 va_end(args);
1847 1867
1848 return r; 1868 return r;