debug: improve ftrace_ramoops for io trace [2/2]
authorJianxin Pan <jianxin.pan@amlogic.com>
Wed, 3 Apr 2019 11:16:50 +0000 (19:16 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Wed, 17 Apr 2019 06:43:49 +0000 (23:43 -0700)
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>
21 files changed:
MAINTAINERS
arch/arm/include/asm/io.h
arch/arm64/include/asm/io.h
arch/arm64/kernel/io.c
drivers/amlogic/debug/Kconfig
drivers/amlogic/debug/Makefile
drivers/amlogic/debug/debug_ftrace_ramoops.c [new file with mode: 0644]
drivers/amlogic/iomap/iomap.c
drivers/amlogic/media/common/arch/registers/register_map.c
drivers/amlogic/media/common/arch/registers/register_ops_m8.c
drivers/amlogic/uart/meson_uart.c
drivers/irqchip/irq-gic.c
fs/pstore/ftrace.c
fs/pstore/inode.c
fs/pstore/internal.h
fs/pstore/ram.c
fs/pstore/ram_core.c
include/linux/amlogic/debug_ftrace_ramoops.h [new file with mode: 0644]
include/linux/amlogic/iomap.h
include/linux/pstore_ram.h
lib/ioremap.c

index aed10ba..754bd64 100644 (file)
@@ -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>
index 021692c..202cab5 100644 (file)
@@ -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)
 
index 0bba427..931f49b 100644 (file)
 #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;
 }
 
index 79b1738..b90a161 100644 (file)
 
 #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);
index 1bbc487..f8df94e 100644 (file)
@@ -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.
+
+
index 7576af9..9b2e3f1 100644 (file)
@@ -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 (file)
index 0000000..f67c59f
--- /dev/null
@@ -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);
+
index b5645c2..2998450 100644 (file)
@@ -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));
index e333b06..390d0db 100644 (file)
@@ -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) {
index 4f7e1a2..a0323e5 100644 (file)
        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},
index 3e1ee9f..3ce6eb1 100644 (file)
@@ -15,6 +15,7 @@
  *
  */
 
+#define SKIP_IO_TRACE
 #include <linux/clk.h>
 #include <linux/console.h>
 #include <linux/delay.h>
index d6c404b..43efc7e 100644 (file)
@@ -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>
index d488770..33fa139 100644 (file)
 #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);
 }
 
index 1781dc5..6f6f56c 100644 (file)
@@ -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;
 }
 
index e38a22b..cca4fef 100644 (file)
@@ -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)
 {
index 8e151fb..aa3f123 100644 (file)
@@ -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:
index e11672a..cf0e1b3 100644 (file)
@@ -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 (file)
index 0000000..51f4c88
--- /dev/null
@@ -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
index 41d885b..663ad76 100644 (file)
@@ -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);
index cb5edd6..6f82615 100644 (file)
@@ -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;
index 5323b59..0e192bb 100644 (file)
 #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);