mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user