From e9fd8597f446d6ff8e42b8d963b6ca2ece5c3d91 Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Wed, 5 Jun 2019 16:04:24 +0800 Subject: [PATCH] dmc: adding a data to identify violation stauts [1/1] PD#TV-5802 Problem: irq of dmc violation happens very qiuckly, which may have some wrong report if violation print in workqueu. Solution: Add a data to identify it. If data is null, then it's a fake violation Verify: txhd Change-Id: I402763fa2d20cfae3dc2d9647f7b2c2fb29ce966 Signed-off-by: Tao Zeng --- drivers/amlogic/ddr_tool/dmc_g12.c | 25 +++++++++++++++++-------- drivers/amlogic/ddr_tool/dmc_gx.c | 25 +++++++++++++++++-------- drivers/amlogic/ddr_tool/dmc_monitor.c | 2 +- include/linux/amlogic/dmc_monitor.h | 2 +- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/drivers/amlogic/ddr_tool/dmc_g12.c b/drivers/amlogic/ddr_tool/dmc_g12.c index 364dd64..3e5a735 100644 --- a/drivers/amlogic/ddr_tool/dmc_g12.c +++ b/drivers/amlogic/ddr_tool/dmc_g12.c @@ -98,12 +98,14 @@ static void show_violation_mem(unsigned long addr) kunmap_atomic(p); } -static void check_violation(struct dmc_monitor *mon) +static void check_violation(struct dmc_monitor *mon, void *data) { int i, port, subport; unsigned long addr, status; char id_str[4]; char off1, off2; + struct page *page; + struct page_trace *trace; switch (mon->chip) { case MESON_CPU_MAJOR_ID_G12B: @@ -140,12 +142,18 @@ static void check_violation(struct dmc_monitor *mon) mon->same_page++; continue; } + /* ignore cma driver pages */ + page = phys_to_page(addr); + trace = find_page_base(page); + if (!trace || trace->migrate_type == MIGRATE_CMA) + continue; port = (status >> off2) & 0x1f; subport = (status >> 6) & 0xf; - pr_info(DMC_TAG", addr:%08lx, s:%08lx, ID:%s, sub:%s, c:%ld\n", + pr_info(DMC_TAG", addr:%08lx, s:%08lx, ID:%s, sub:%s, c:%ld, d:%p\n", addr, status, to_ports(port), - to_sub_ports(port, subport, id_str), mon->same_page); + to_sub_ports(port, subport, id_str), + mon->same_page, data); show_violation_mem(addr); if (!port) /* dump stack for CPU write */ dump_stack(); @@ -156,17 +164,18 @@ static void check_violation(struct dmc_monitor *mon) } } -static void g12_dmc_mon_irq(struct dmc_monitor *mon) +static void g12_dmc_mon_irq(struct dmc_monitor *mon, void *data) { unsigned long value; value = dmc_rw(DMC_SEC_STATUS, 0, DMC_READ); - if (value & DMC_WRITE_VIOLATION) - check_violation(mon); + if (in_interrupt()) { + if (value & DMC_WRITE_VIOLATION) + check_violation(mon, data); - /* check irq flags just after IRQ handler */ - if (in_interrupt()) + /* check irq flags just after IRQ handler */ mod_delayed_work(system_wq, &mon->work, 0); + } /* clear irq */ dmc_rw(DMC_SEC_STATUS, value, DMC_WRITE); } diff --git a/drivers/amlogic/ddr_tool/dmc_gx.c b/drivers/amlogic/ddr_tool/dmc_gx.c index 7871970..75a6552 100644 --- a/drivers/amlogic/ddr_tool/dmc_gx.c +++ b/drivers/amlogic/ddr_tool/dmc_gx.c @@ -102,11 +102,13 @@ static void show_violation_mem(unsigned long addr) kunmap_atomic(p); } -static void check_violation(struct dmc_monitor *mon) +static void check_violation(struct dmc_monitor *mon, void *data) { int i, port, subport; unsigned long addr, status; char id_str[4]; + struct page *page; + struct page_trace *trace; for (i = 1; i < 8; i += 2) { status = dmc_rw(DMC_VIO_ADDR0 + (i << 2), 0, DMC_READ); @@ -123,12 +125,18 @@ static void check_violation(struct dmc_monitor *mon) mon->same_page++; continue; } + /* ignore cma driver pages */ + page = phys_to_page(addr); + trace = find_page_base(page); + if (!trace || trace->migrate_type == MIGRATE_CMA) + continue; port = (status >> 10) & 0xf; subport = (status >> 6) & 0xf; - pr_info(DMC_TAG", addr:%08lx, s:%08lx, ID:%s, sub:%s, c:%ld\n", + pr_info(DMC_TAG", addr:%08lx, s:%08lx, ID:%s, sub:%s, c:%ld, d:%p\n", addr, status, to_ports(port), - to_sub_ports(port, subport, id_str), mon->same_page); + to_sub_ports(port, subport, id_str), + mon->same_page, data); show_violation_mem(addr); if (!port) /* dump stack for CPU write */ dump_stack(); @@ -139,17 +147,18 @@ static void check_violation(struct dmc_monitor *mon) } } -static void gx_dmc_mon_irq(struct dmc_monitor *mon) +static void gx_dmc_mon_irq(struct dmc_monitor *mon, void *data) { unsigned long value; value = dmc_rw(DMC_SEC_STATUS, 0, DMC_READ); - if (value & DMC_WRITE_VIOLATION) - check_violation(mon); + if (in_interrupt()) { + if (value & DMC_WRITE_VIOLATION) + check_violation(mon, data); - /* check irq flags just after IRQ handler */ - if (in_interrupt()) + /* check irq flags just after IRQ handler */ mod_delayed_work(system_wq, &mon->work, 0); + } /* clear irq */ dmc_rw(DMC_SEC_STATUS, value, DMC_WRITE); } diff --git a/drivers/amlogic/ddr_tool/dmc_monitor.c b/drivers/amlogic/ddr_tool/dmc_monitor.c index d57ce49..61b38a0 100644 --- a/drivers/amlogic/ddr_tool/dmc_monitor.c +++ b/drivers/amlogic/ddr_tool/dmc_monitor.c @@ -154,7 +154,7 @@ static size_t dump_reg(char *buf) static irqreturn_t dmc_monitor_irq_handler(int irq, void *dev_instance) { if (dmc_mon->ops && dmc_mon->ops->handle_irq) - dmc_mon->ops->handle_irq(dmc_mon); + dmc_mon->ops->handle_irq(dmc_mon, dev_instance); return IRQ_HANDLED; } diff --git a/include/linux/amlogic/dmc_monitor.h b/include/linux/amlogic/dmc_monitor.h index 9fe2e34..c851cbbc 100644 --- a/include/linux/amlogic/dmc_monitor.h +++ b/include/linux/amlogic/dmc_monitor.h @@ -36,7 +36,7 @@ struct dmc_monitor; struct dmc_mon_ops { - void (*handle_irq)(struct dmc_monitor *mon); + void (*handle_irq)(struct dmc_monitor *mon, void *data); int (*set_montor)(struct dmc_monitor *mon); void (*disable)(struct dmc_monitor *mon); size_t (*dump_reg)(char *buf); -- 2.7.4