From 715be69c3dc4d124970eb55860e7ae2cc41a2554 Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Wed, 3 Apr 2019 19:16:50 +0800 Subject: [PATCH] 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 --- MAINTAINERS | 1 + arch/arm/include/asm/io.h | 57 ++++++++ arch/arm64/include/asm/io.h | 52 ++++++- arch/arm64/kernel/io.c | 23 ++++ drivers/amlogic/debug/Kconfig | 12 ++ drivers/amlogic/debug/Makefile | 1 + drivers/amlogic/debug/debug_ftrace_ramoops.c | 149 +++++++++++++++++++++ drivers/amlogic/iomap/iomap.c | 4 +- .../media/common/arch/registers/register_map.c | 4 +- .../media/common/arch/registers/register_ops_m8.c | 14 -- drivers/amlogic/uart/meson_uart.c | 1 + drivers/irqchip/irq-gic.c | 1 + fs/pstore/ftrace.c | 11 +- fs/pstore/inode.c | 6 +- fs/pstore/internal.h | 14 ++ fs/pstore/ram.c | 15 ++- fs/pstore/ram_core.c | 16 ++- include/linux/amlogic/debug_ftrace_ramoops.h | 62 +++++++++ include/linux/amlogic/iomap.h | 5 +- include/linux/pstore_ram.h | 1 + lib/ioremap.c | 24 +++- 21 files changed, 445 insertions(+), 28 deletions(-) create mode 100644 drivers/amlogic/debug/debug_ftrace_ramoops.c create mode 100644 include/linux/amlogic/debug_ftrace_ramoops.h diff --git a/MAINTAINERS b/MAINTAINERS index aed10ba..754bd64 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14509,6 +14509,7 @@ AMLOGIC DEBUG M: Jianxin Pan M: Tao Guo F: drivers/amlogic/debug/* +F: include/linux/amlogic/debug*.h AMLOGIC G12A spdif channel status M: xing wang 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 #include +#ifdef CONFIG_AMLOGIC_MODIFY +#include +#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 #include - +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#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 #include +#define SKIP_IO_TRACE #include +#undef SKIP_IO_TRACE +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#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 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include <../../../fs/pstore/internal.h> +#include +#include +#include + +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 #include #include 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 #include #include 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 #include "internal.h" +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#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 #include #include +#include #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 @@ -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 --- /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 + +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 #include #include +#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE +#include +#include +#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 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); -- 2.7.4