summaryrefslogtreecommitdiff
authorJianxin Pan <jianxin.pan@amlogic.com>2019-04-03 11:16:50 (GMT)
committer Jianxin Pan <jianxin.pan@amlogic.com>2019-04-17 06:43:49 (GMT)
commit715be69c3dc4d124970eb55860e7ae2cc41a2554 (patch)
tree4151af47a79360cb7f507a82d5347299915de978
parentc5801145d301e38f7f59e5edf79ca588ca14e882 (diff)
downloadcommon-715be69c3dc4d124970eb55860e7ae2cc41a2554.zip
common-715be69c3dc4d124970eb55860e7ae2cc41a2554.tar.gz
common-715be69c3dc4d124970eb55860e7ae2cc41a2554.tar.bz2
debug: improve ftrace_ramoops for io trace [2/2]
PD#SWPL-6028 Problem: improve ftrace_ramoops to debug bus hang Solution: 1. in uboot setenv initargs $initargs ramoops_io_en=1 loglevel=3;save;reset 2. in linux command line: cat /sys/module/kernel/parameters/ramoops_io_en to check if success. 3. after watchdog reboot, get trace data with: cat /sys/fs/pstore/ftrace-ramoops-0 Verify: TL1 x301 Change-Id: If1a2582b40a3ded31eedef5355eb0b8a5bf495c3 Signed-off-by: Jianxin Pan <jianxin.pan@amlogic.com>
Diffstat
-rw-r--r--MAINTAINERS1
-rw-r--r--arch/arm/include/asm/io.h57
-rw-r--r--arch/arm64/include/asm/io.h52
-rw-r--r--arch/arm64/kernel/io.c23
-rw-r--r--drivers/amlogic/debug/Kconfig12
-rw-r--r--drivers/amlogic/debug/Makefile1
-rw-r--r--drivers/amlogic/debug/debug_ftrace_ramoops.c149
-rw-r--r--drivers/amlogic/iomap/iomap.c4
-rw-r--r--drivers/amlogic/media/common/arch/registers/register_map.c4
-rw-r--r--drivers/amlogic/media/common/arch/registers/register_ops_m8.c14
-rw-r--r--drivers/amlogic/uart/meson_uart.c1
-rw-r--r--drivers/irqchip/irq-gic.c1
-rw-r--r--fs/pstore/ftrace.c11
-rw-r--r--fs/pstore/inode.c6
-rw-r--r--fs/pstore/internal.h14
-rw-r--r--fs/pstore/ram.c15
-rw-r--r--fs/pstore/ram_core.c16
-rw-r--r--include/linux/amlogic/debug_ftrace_ramoops.h62
-rw-r--r--include/linux/amlogic/iomap.h5
-rw-r--r--include/linux/pstore_ram.h1
-rw-r--r--lib/ioremap.c24
21 files changed, 445 insertions, 28 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index aed10ba..754bd64 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14509,6 +14509,7 @@ AMLOGIC DEBUG
M: Jianxin Pan <jianxin.pan@amlogic.com>
M: Tao Guo <tao.guo@amlogic.com>
F: drivers/amlogic/debug/*
+F: include/linux/amlogic/debug*.h
AMLOGIC G12A spdif channel status
M: xing wang<xing.wang@amlogic.com>
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 021692c..202cab5 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -31,6 +31,9 @@
#include <asm-generic/pci_iomap.h>
#include <xen/xen.h>
+#ifdef CONFIG_AMLOGIC_MODIFY
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#endif
/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
*/
@@ -73,17 +76,29 @@ void __raw_readsl(const volatile void __iomem *addr, void *data, int longlen);
#define __raw_writew __raw_writew
static inline void __raw_writew(u16 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("strh %1, %0"
: : "Q" (*(volatile u16 __force *)addr), "r" (val));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_readw __raw_readw
static inline u16 __raw_readw(const volatile void __iomem *addr)
{
u16 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile("ldrh %0, %1"
: "=r" (val)
: "Q" (*(volatile u16 __force *)addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
#endif
@@ -91,24 +106,42 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
#define __raw_writeb __raw_writeb
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("strb %1, %0"
: : "Qo" (*(volatile u8 __force *)addr), "r" (val));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_writel __raw_writel
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("str %1, %0"
: : "Qo" (*(volatile u32 __force *)addr), "r" (val));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile("ldrb %0, %1"
: "=r" (val)
: "Qo" (*(volatile u8 __force *)addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
@@ -116,9 +149,15 @@ static inline u8 __raw_readb(const volatile void __iomem *addr)
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile("ldr %0, %1"
: "=r" (val)
: "Qo" (*(volatile u32 __force *)addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
@@ -317,7 +356,13 @@ static inline void memset_io(volatile void __iomem *dst, unsigned c,
size_t count)
{
extern void mmioset(void *, unsigned int, size_t);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)dst, (unsigned long)count);
+#endif
mmioset((void __force *)dst, c, count);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)dst, (unsigned long)count);
+#endif
}
#define memset_io(dst,c,count) memset_io(dst,c,count)
@@ -325,7 +370,13 @@ static inline void memcpy_fromio(void *to, const volatile void __iomem *from,
size_t count)
{
extern void mmiocpy(void *, const void *, size_t);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)to, (unsigned long)count);
+#endif
mmiocpy(to, (const void __force *)from, count);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)to, (unsigned long)count);
+#endif
}
#define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count)
@@ -333,7 +384,13 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from,
size_t count)
{
extern void mmiocpy(void *, const void *, size_t);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)to, (unsigned long)count);
+#endif
mmiocpy((void __force *)to, from, count);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)to, (unsigned long)count);
+#endif
}
#define memcpy_toio(to,from,count) memcpy_toio(to,from,count)
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 0bba427..931f49b 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -33,42 +33,74 @@
#include <asm/cpufeature.h>
#include <xen/xen.h>
-
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#endif
/*
* Generic IO read/write. These perform native-endian accesses.
*/
#define __raw_writeb __raw_writeb
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("strb %w0, [%1]" : : "rZ" (val), "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_writew __raw_writew
static inline void __raw_writew(u16 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("strh %w0, [%1]" : : "rZ" (val), "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_writel __raw_writel
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_writeq __raw_writeq
static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("str %x0, [%1]" : : "rZ" (val), "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile(ALTERNATIVE("ldrb %w0, [%1]",
"ldarb %w0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
@@ -77,10 +109,16 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
{
u16 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile(ALTERNATIVE("ldrh %w0, [%1]",
"ldarh %w0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
@@ -88,10 +126,16 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile(ALTERNATIVE("ldr %w0, [%1]",
"ldar %w0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
@@ -99,10 +143,16 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
static inline u64 __raw_readq(const volatile void __iomem *addr)
{
u64 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile(ALTERNATIVE("ldr %0, [%1]",
"ldar %0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
diff --git a/arch/arm64/kernel/io.c b/arch/arm64/kernel/io.c
index 79b1738..b90a161 100644
--- a/arch/arm64/kernel/io.c
+++ b/arch/arm64/kernel/io.c
@@ -18,13 +18,21 @@
#include <linux/export.h>
#include <linux/types.h>
+#define SKIP_IO_TRACE
#include <linux/io.h>
+#undef SKIP_IO_TRACE
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#endif
/*
* Copy data from IO memory space to "real" memory space.
*/
void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
while (count && !IS_ALIGNED((unsigned long)from, 8)) {
*(u8 *)to = __raw_readb(from);
from++;
@@ -45,6 +53,9 @@ void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
to++;
count--;
}
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
}
EXPORT_SYMBOL(__memcpy_fromio);
@@ -53,6 +64,9 @@ EXPORT_SYMBOL(__memcpy_fromio);
*/
void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, 0x1234);
+#endif
while (count && !IS_ALIGNED((unsigned long)to, 8)) {
__raw_writeb(*(u8 *)from, to);
from++;
@@ -73,6 +87,9 @@ void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
to++;
count--;
}
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, 0x1234);
+#endif
}
EXPORT_SYMBOL(__memcpy_toio);
@@ -83,6 +100,9 @@ void __memset_io(volatile void __iomem *dst, int c, size_t count)
{
u64 qc = (u8)c;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, 0xabcd);
+#endif
qc |= qc << 8;
qc |= qc << 16;
qc |= qc << 32;
@@ -104,5 +124,8 @@ void __memset_io(volatile void __iomem *dst, int c, size_t count)
dst++;
count--;
}
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, 0xabcd);
+#endif
}
EXPORT_SYMBOL(__memset_io);
diff --git a/drivers/amlogic/debug/Kconfig b/drivers/amlogic/debug/Kconfig
index 1bbc487..f8df94e 100644
--- a/drivers/amlogic/debug/Kconfig
+++ b/drivers/amlogic/debug/Kconfig
@@ -19,3 +19,15 @@ config AMLOGIC_DEBUG_ATRACE
default y
help
Add android atrace compatible function
+
+config AMLOGIC_DEBUG_FTRACE_PSTORE
+ bool "Amlogic ftrace pstore debug"
+ depends on AMLOGIC_DEBUG
+ depends on PSTORE_FTRACE
+ default y
+ help
+ Dump function call and register access to ramoops after watchdog
+ reboot.
+ Enable if doubt.
+
+
diff --git a/drivers/amlogic/debug/Makefile b/drivers/amlogic/debug/Makefile
index 7576af9..9b2e3f1 100644
--- a/drivers/amlogic/debug/Makefile
+++ b/drivers/amlogic/debug/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_AMLOGIC_DEBUG_LOCKUP) += debug_lockup.o
obj-$(CONFIG_AMLOGIC_DEBUG_ATRACE) += meson_atrace.o
+obj-$(CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE)+= debug_ftrace_ramoops.o
diff --git a/drivers/amlogic/debug/debug_ftrace_ramoops.c b/drivers/amlogic/debug/debug_ftrace_ramoops.c
new file mode 100644
index 0000000..f67c59f
--- a/dev/null
+++ b/drivers/amlogic/debug/debug_ftrace_ramoops.c
@@ -0,0 +1,149 @@
+/*
+ * drivers/amlogic/debug/debug_ftrace_ramoops.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/irqflags.h>
+#include <linux/percpu.h>
+#include <linux/smp.h>
+#include <linux/atomic.h>
+#include <linux/types.h>
+#include <linux/ftrace.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#include <../../../fs/pstore/internal.h>
+#include <linux/trace_clock.h>
+#include <linux/percpu.h>
+#include <linux/moduleparam.h>
+
+static DEFINE_PER_CPU(int, en);
+static DEFINE_PER_CPU(unsigned long, irq_flag);
+
+#define IRQ_D 1
+
+unsigned int dump_iomap;
+core_param(dump_iomap, dump_iomap, uint, 0664);
+
+unsigned int ramoops_ftrace_en;
+EXPORT_SYMBOL(ramoops_ftrace_en);
+
+int ramoops_io_en;
+EXPORT_SYMBOL(ramoops_io_en);
+core_param(ramoops_io_en, ramoops_io_en, int, 0664);
+
+const char *record_name[PSTORE_FLAG_IO_MAX] = {
+ "NULL",
+ "FUNC",
+ "IO-R",
+ "IO-W",
+ "IO-R-E",
+ "IO-W-E",
+};
+
+void notrace pstore_ftrace_save(struct pstore_ftrace_record *rec)
+{
+ int cpu = raw_smp_processor_id();
+
+ if (unlikely(oops_in_progress) || unlikely(per_cpu(en, cpu)))
+ return;
+ per_cpu(en, cpu) = 1;
+ pstore_ftrace_encode_cpu(rec, cpu);
+ strlcpy(rec->comm, current->comm, sizeof(rec->comm) - 1);
+ rec->pid = current->pid;
+ rec->time = trace_clock_local();
+ psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)rec,
+ 0, sizeof(*rec), psinfo);
+ per_cpu(en, cpu) = 0;
+}
+EXPORT_SYMBOL(pstore_ftrace_save);
+
+static void notrace pstore_function_dump(struct pstore_ftrace_record *rec,
+ struct seq_file *s)
+{
+ unsigned long sec = 0, ms = 0;
+ unsigned long long time = rec->time;
+
+ do_div(time, 1000000);
+ sec = (unsigned long)time / 1000;
+ ms = (unsigned long)time % 1000;
+ seq_printf(s, "[%04ld.%03ld@%d] <%5d-%s> <%pf <- %pF>\n",
+ sec, ms, pstore_ftrace_decode_cpu(rec), rec->pid, rec->comm,
+ (void *)rec->ip, (void *)rec->parent_ip);
+}
+
+void notrace pstore_io_rw_dump(struct pstore_ftrace_record *rec,
+ struct seq_file *s)
+{
+ unsigned long sec = 0, ms = 0;
+ unsigned long long time = rec->time;
+ unsigned int cpu = pstore_ftrace_decode_cpu(rec);
+
+ do_div(time, 1000000);
+ sec = (unsigned long)time / 1000;
+ ms = (unsigned long)time % 1000;
+ seq_printf(s, "[%04ld.%03ld@%d] <%5d-%6s> <%6s %08lx-%8lx> <%pf <- %pF>\n",
+ sec, ms, cpu, rec->pid, rec->comm, record_name[rec->flag],
+ rec->val1, (rec->flag == PSTORE_FLAG_IO_W) ? rec->val2 : 0,
+ (void *)rec->ip, (void *)rec->parent_ip);
+}
+
+void notrace pstore_ftrace_dump(struct pstore_ftrace_record *rec,
+ struct seq_file *s)
+{
+ switch (rec->flag & PSTORE_FLAG_MASK) {
+ case PSTORE_FLAG_FUNC:
+ pstore_function_dump(rec, s);
+ break;
+ case PSTORE_FLAG_IO_R:
+ case PSTORE_FLAG_IO_W:
+ case PSTORE_FLAG_IO_W_END:
+ case PSTORE_FLAG_IO_R_END:
+ pstore_io_rw_dump(rec, s);
+ break;
+ default:
+ seq_printf(s, "Unknown Msg:%x\n", rec->flag);
+ }
+}
+
+void notrace pstore_io_save(unsigned long reg, unsigned long val,
+ unsigned long parant, unsigned int flag)
+{
+ struct pstore_ftrace_record rec;
+ int cpu = get_cpu();
+
+ put_cpu();
+ if (!ramoops_ftrace_en || !ramoops_io_en)
+ return;
+
+ if ((flag == PSTORE_FLAG_IO_R || flag == PSTORE_FLAG_IO_W) && IRQ_D)
+ local_irq_save(per_cpu(irq_flag, cpu));
+
+ rec.ip = CALLER_ADDR0;
+ rec.parent_ip = parant;
+ rec.flag = flag;
+ rec.val1 = reg;
+ rec.val2 = val;
+ pstore_ftrace_save(&rec);
+
+ if ((flag == PSTORE_FLAG_IO_R_END || flag == PSTORE_FLAG_IO_W_END)
+ && IRQ_D)
+ local_irq_restore(per_cpu(irq_flag, cpu));
+}
+EXPORT_SYMBOL(pstore_io_save);
+
diff --git a/drivers/amlogic/iomap/iomap.c b/drivers/amlogic/iomap/iomap.c
index b5645c2..2998450 100644
--- a/drivers/amlogic/iomap/iomap.c
+++ b/drivers/amlogic/iomap/iomap.c
@@ -39,7 +39,7 @@ static const struct of_device_id iomap_dt_match[] = {
static void __iomem *meson_reg_map[IO_BUS_MAX] = { NULL };
-int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
+inline int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
{
if (bus_type < IO_BUS_MAX && (meson_reg_map[bus_type] != NULL)) {
*val = readl((meson_reg_map[bus_type]+reg));
@@ -49,7 +49,7 @@ int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
}
EXPORT_SYMBOL(aml_reg_read);
-int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val)
+inline int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val)
{
if (bus_type < IO_BUS_MAX && (meson_reg_map[bus_type] != NULL)) {
writel(val, (meson_reg_map[bus_type]+reg));
diff --git a/drivers/amlogic/media/common/arch/registers/register_map.c b/drivers/amlogic/media/common/arch/registers/register_map.c
index e333b06..390d0db 100644
--- a/drivers/amlogic/media/common/arch/registers/register_map.c
+++ b/drivers/amlogic/media/common/arch/registers/register_map.c
@@ -51,7 +51,7 @@ enum {
static void __iomem *codecio_reg_map[CODECIO_BUS_MAX];
-static int codecio_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
+static inline int codecio_reg_read(u32 bus_type, u32 reg, u32 *val)
{
if (bus_type < CODECIO_BUS_MAX) {
if (codecio_reg_map[bus_type] == NULL) {
@@ -65,7 +65,7 @@ static int codecio_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
return -1;
}
-static int codecio_reg_write(u32 bus_type, unsigned int reg, unsigned int val)
+static inline int codecio_reg_write(u32 bus_type, u32 reg, u32 val)
{
if (bus_type < CODECIO_BUS_MAX) {
if (codecio_reg_map[bus_type] == NULL) {
diff --git a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c
index 4f7e1a2ba..a0323e5 100644
--- a/drivers/amlogic/media/common/arch/registers/register_ops_m8.c
+++ b/drivers/amlogic/media/common/arch/registers/register_ops_m8.c
@@ -49,20 +49,6 @@
MESON_CPU_MAJOR_ID_SM1, \
MESON_CPU_MAJOR_ID_TM2, \
0}
-int codec_apb_read(unsigned int reg)
-{
- unsigned int val = 0;
-
- aml_reg_read(IO_APB_BUS_BASE, reg << 2, &val);
- return val;
-}
-EXPORT_SYMBOL(codec_apb_read);
-
-void codec_apb_write(unsigned int reg, unsigned int val)
-{
- aml_reg_write(IO_APB_BUS_BASE, reg << 2, val);
-}
-EXPORT_SYMBOL(codec_apb_write);
static struct chip_register_ops m8_ops[] __initdata = {
{IO_DOS_BUS, 0, codecio_read_dosbus, codecio_write_dosbus},
diff --git a/drivers/amlogic/uart/meson_uart.c b/drivers/amlogic/uart/meson_uart.c
index 3e1ee9f..3ce6eb1 100644
--- a/drivers/amlogic/uart/meson_uart.c
+++ b/drivers/amlogic/uart/meson_uart.c
@@ -15,6 +15,7 @@
*
*/
+#define SKIP_IO_TRACE
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/delay.h>
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index d6c404b..43efc7e 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -20,6 +20,7 @@
* As such, the enable set/clear, pending set/clear and active bit
* registers are banked per-cpu for these sources.
*/
+#define SKIP_IO_TRACE
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/err.h>
diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c
index d488770..33fa139 100644
--- a/fs/pstore/ftrace.c
+++ b/fs/pstore/ftrace.c
@@ -27,6 +27,10 @@
#include <asm/barrier.h>
#include "internal.h"
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#endif
+
static void notrace pstore_ftrace_call(unsigned long ip,
unsigned long parent_ip,
struct ftrace_ops *op,
@@ -39,13 +43,16 @@ static void notrace pstore_ftrace_call(unsigned long ip,
return;
local_irq_save(flags);
-
rec.ip = ip;
rec.parent_ip = parent_ip;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ rec.flag = PSTORE_FLAG_FUNC;
+ pstore_ftrace_save(&rec);
+#else
pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id());
psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec,
0, sizeof(rec), psinfo);
-
+#endif
local_irq_restore(flags);
}
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 1781dc5..6f6f56c 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -37,6 +37,7 @@
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/syslog.h>
+#include <linux/amlogic/debug_ftrace_ramoops.h>
#include "internal.h"
@@ -107,10 +108,13 @@ static int pstore_ftrace_seq_show(struct seq_file *s, void *v)
struct pstore_ftrace_seq_data *data = v;
struct pstore_ftrace_record *rec = (void *)(ps->data + data->off);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_dump(rec, s);
+#else
seq_printf(s, "%d %08lx %08lx %pf <- %pF\n",
pstore_ftrace_decode_cpu(rec), rec->ip, rec->parent_ip,
(void *)rec->ip, (void *)rec->parent_ip);
-
+#endif
return 0;
}
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index e38a22b..cca4fef 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -17,8 +17,22 @@ struct pstore_ftrace_record {
#ifndef PSTORE_CPU_IN_IP
unsigned int cpu;
#endif
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ int pid;
+ unsigned long val1;
+ unsigned long val2;
+ unsigned long long time;
+ unsigned char comm[8];
+ unsigned int flag;
+#endif
};
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+void notrace pstore_ftrace_save(struct pstore_ftrace_record *rec);
+void notrace pstore_ftrace_dump(struct pstore_ftrace_record *rec,
+ struct seq_file *s);
+#endif
+
static inline void
pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu)
{
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 8e151fb..aa3f123 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -602,6 +602,9 @@ static int ramoops_probe(struct platform_device *pdev)
cxt->size = pdata->mem_size;
cxt->phys_addr = pdata->mem_address;
cxt->memtype = pdata->mem_type;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ cxt->memtype |= (!!ramoops_io_en);
+#endif
cxt->record_size = pdata->record_size;
cxt->console_size = pdata->console_size;
cxt->ftrace_size = pdata->ftrace_size;
@@ -621,7 +624,6 @@ static int ramoops_probe(struct platform_device *pdev)
cxt->console_size, 0);
if (err)
goto fail_init_cprz;
-
err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size,
LINUX_VERSION_CODE);
if (err)
@@ -679,6 +681,17 @@ static int ramoops_probe(struct platform_device *pdev)
cxt->size, (unsigned long long)cxt->phys_addr,
cxt->ecc_info.ecc_size, cxt->ecc_info.block_size);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ if (ramoops_ftrace_size) {
+ cxt->fprz->flags |= (PRZ_FLAG_NO_LOCK | PRZ_FLAG_BIG_LOCK);
+ ramoops_ftrace_en = !persistent_ram_old_size(cxt->fprz);
+ }
+ pr_info("ramoops_io_en:%d %d old:0x%lx ftrace_size:0x%lx",
+ ramoops_io_en, ramoops_ftrace_en,
+ (unsigned long)persistent_ram_old_size(cxt->fprz),
+ ramoops_ftrace_size);
+#endif
+
return 0;
fail_buf:
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index e11672a..cf0e1b3 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -12,6 +12,7 @@
*
*/
+#define SKIP_IO_TRACE
#define pr_fmt(fmt) "persistent_ram: " fmt
#include <linux/device.h>
@@ -49,7 +50,8 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz)
}
/* increase and wrap the start pointer, returning the old value */
-static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
+static size_t notrace buffer_start_add(struct persistent_ram_zone *prz,
+ size_t a)
{
int old;
int new;
@@ -71,7 +73,7 @@ static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
}
/* increase the size counter until it hits the max size */
-static void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
+static void notrace buffer_size_add(struct persistent_ram_zone *prz, size_t a)
{
size_t old;
size_t new;
@@ -310,6 +312,12 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz,
int c = count;
size_t start;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ unsigned long flags = 0;
+
+ if (prz->flags & PRZ_FLAG_BIG_LOCK)
+ raw_spin_lock_irqsave(&prz->buffer_lock, flags);
+#endif
if (unlikely(c > prz->buffer_size)) {
s += c - prz->buffer_size;
c = prz->buffer_size;
@@ -330,6 +338,10 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz,
persistent_ram_update_header_ecc(prz);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ if (prz->flags & PRZ_FLAG_BIG_LOCK)
+ raw_spin_unlock_irqrestore(&prz->buffer_lock, flags);
+#endif
return count;
}
diff --git a/include/linux/amlogic/debug_ftrace_ramoops.h b/include/linux/amlogic/debug_ftrace_ramoops.h
new file mode 100644
index 0000000..51f4c88
--- a/dev/null
+++ b/include/linux/amlogic/debug_ftrace_ramoops.h
@@ -0,0 +1,62 @@
+/*
+ * include/linux/amlogic/debug_ftrace_ramoops.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __DEBUG_FTRACE_RAMOOPS_H__
+#define __DEBUG_FTRACE_RAMOOPS_H__
+#define __DEBUG_FTRACE_RAMOOPS_H__
+#include <linux/ftrace.h>
+
+extern unsigned int ramoops_ftrace_en;
+extern int ramoops_io_en;
+extern unsigned int dump_iomap;
+
+#define PSTORE_FLAG_FUNC 0x1
+#define PSTORE_FLAG_IO_R 0x2
+#define PSTORE_FLAG_IO_W 0x3
+#define PSTORE_FLAG_IO_R_END 0x4
+#define PSTORE_FLAG_IO_W_END 0x5
+#define PSTORE_FLAG_IO_MAX 0x6
+#define PSTORE_FLAG_MASK 0xF
+
+void notrace pstore_io_save(unsigned long reg, unsigned long val,
+ unsigned long parant, unsigned int flag);
+
+//#define SKIP_IO_TRACE
+#if (defined CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE) && (!defined SKIP_IO_TRACE)
+#define pstore_ftrace_io_wr(reg, val) \
+pstore_io_save(reg, val, CALLER_ADDR0, PSTORE_FLAG_IO_W)
+
+#define pstore_ftrace_io_wr_end(reg, val) \
+pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_W_END)
+
+#define pstore_ftrace_io_rd(reg) \
+pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R)
+#define pstore_ftrace_io_rd_end(reg) \
+pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R_END)
+
+#define need_dump_iomap() (ramoops_io_en | dump_iomap)
+
+#else
+#define pstore_ftrace_io_wr(reg, val) do { } while (0)
+#define pstore_ftrace_io_rd(reg) do { } while (0)
+#define need_dump_iomap() 0
+#define pstore_ftrace_io_wr_end(reg, val) do { } while (0)
+#define pstore_ftrace_io_rd_end(reg) do { } while (0)
+
+#endif
+
+#endif
diff --git a/include/linux/amlogic/iomap.h b/include/linux/amlogic/iomap.h
index 41d885b..663ad76 100644
--- a/include/linux/amlogic/iomap.h
+++ b/include/linux/amlogic/iomap.h
@@ -26,8 +26,9 @@ enum{
IO_HIUBUS_BASE,
IO_BUS_MAX,
};
-extern int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val);
-extern int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val);
+
+extern inline int aml_reg_read(u32 bus_type, u32 reg, u32 *val);
+extern inline int aml_reg_write(u32 bus_type, u32 reg, u32 val);
extern int aml_regmap_update_bits(u32 bus_type,
unsigned int reg, unsigned int mask,
unsigned int val);
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index cb5edd6..6f82615 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -30,6 +30,7 @@
* PRZ_FLAG_NO_LOCK is used. For all other cases, locking is required.
*/
#define PRZ_FLAG_NO_LOCK BIT(0)
+#define PRZ_FLAG_BIG_LOCK BIT(7)
struct persistent_ram_buffer;
struct rs_control;
diff --git a/lib/ioremap.c b/lib/ioremap.c
index 5323b59..0e192bb0 100644
--- a/lib/ioremap.c
+++ b/lib/ioremap.c
@@ -12,6 +12,10 @@
#include <linux/export.h>
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+#include <linux/moduleparam.h>
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#endif
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
static int __read_mostly ioremap_pud_capable;
@@ -122,6 +126,19 @@ static inline int ioremap_pud_range(pgd_t *pgd, unsigned long addr,
return 0;
}
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+bool is_normal_memory(pgprot_t p)
+{
+#if defined(CONFIG_ARM)
+ return ((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC);
+#elif defined(CONFIG_ARM64)
+ return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL);
+#else
+#error "Unuspported architecture"
+#endif
+}
+#endif
+
int ioremap_page_range(unsigned long addr,
unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
{
@@ -143,7 +160,12 @@ int ioremap_page_range(unsigned long addr,
} while (pgd++, addr = next, addr != end);
flush_cache_vmap(start, end);
-
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ if (need_dump_iomap() && !is_normal_memory(prot))
+ pr_err("io__map <va:0x%08lx-0x%08lx> pa:0x%lx,port:0x%lx\n",
+ start, end, (unsigned long)phys_addr,
+ (unsigned long)pgprot_val(prot));
+#endif
return err;
}
EXPORT_SYMBOL_GPL(ioremap_page_range);