dmc: adding a data to identify violation stauts [1/1]
authorTao Zeng <tao.zeng@amlogic.com>
Wed, 5 Jun 2019 08:04:24 +0000 (16:04 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Tue, 11 Jun 2019 03:31:36 +0000 (20:31 -0700)
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 <tao.zeng@amlogic.com>
drivers/amlogic/ddr_tool/dmc_g12.c
drivers/amlogic/ddr_tool/dmc_gx.c
drivers/amlogic/ddr_tool/dmc_monitor.c
include/linux/amlogic/dmc_monitor.h

index 364dd64..3e5a735 100644 (file)
@@ -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);
 }
index 7871970..75a6552 100644 (file)
@@ -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);
 }
index d57ce49..61b38a0 100644 (file)
@@ -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;
 }
index 9fe2e34..c851cbb 100644 (file)
@@ -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);