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 <tao.zeng@amlogic.com>
This commit is contained in:
Tao Zeng
2019-06-05 16:04:24 +08:00
committed by Luke Go
parent 1965a80ac2
commit 1c6bee9686
4 changed files with 36 additions and 18 deletions

View 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:
@@ -138,12 +140,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();
@@ -154,17 +162,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);
}

View 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);
}

View 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;
}

View 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);