msm: sde: Add EVTLOG and REG dump support for SDE rotator
EVTLOG is a memory logging method for reducing logging overhead. REG dump is used when a fatal error or SMMU fault is happening within the SDE rotator driver. Both tools are used for crash dump analysis in SDE rotator. CRs-Fixed: 1063582 Change-Id: I5ad406187ba590d2fa57d998e9ad79b8a32810ee Signed-off-by: Benjamin Chan <bkchan@codeaurora.org>
This commit is contained in:
parent
3dc7ca5e82
commit
0d6c14d893
7 changed files with 805 additions and 4 deletions
|
@ -5,4 +5,13 @@ config MSM_SDE_ROTATOR
|
|||
select VIDEOBUF2_CORE
|
||||
select SW_SYNC if SYNC
|
||||
---help---
|
||||
Enable support of V4L2 rotator driver.
|
||||
Enable support of V4L2 rotator driver.
|
||||
|
||||
config MSM_SDE_ROTATOR_EVTLOG_DEBUG
|
||||
depends on MSM_SDE_ROTATOR
|
||||
bool "Enable sde rotator debugging"
|
||||
---help---
|
||||
The SDE rotator debugging provides support to enable rotator debugging
|
||||
features to: Dump rotator registers during driver errors, panic
|
||||
driver during fatal errors and enable some rotator driver logging
|
||||
into an internal buffer (this avoids logging overhead).
|
||||
|
|
|
@ -92,6 +92,12 @@ enum sde_bus_clients {
|
|||
SDE_MAX_BUS_CLIENTS
|
||||
};
|
||||
|
||||
enum sde_rot_regdump_access {
|
||||
SDE_ROT_REGDUMP_READ,
|
||||
SDE_ROT_REGDUMP_WRITE,
|
||||
SDE_ROT_REGDUMP_MAX
|
||||
};
|
||||
|
||||
struct reg_bus_client {
|
||||
char name[MAX_CLIENT_NAME_LEN];
|
||||
short usecase_ndx;
|
||||
|
@ -107,6 +113,21 @@ struct sde_smmu_client {
|
|||
bool domain_attached;
|
||||
};
|
||||
|
||||
struct sde_rot_vbif_debug_bus {
|
||||
u32 disable_bus_addr;
|
||||
u32 block_bus_addr;
|
||||
u32 bit_offset;
|
||||
u32 block_cnt;
|
||||
u32 test_pnt_cnt;
|
||||
};
|
||||
|
||||
struct sde_rot_regdump {
|
||||
char *name;
|
||||
u32 offset;
|
||||
u32 len;
|
||||
enum sde_rot_regdump_access access;
|
||||
};
|
||||
|
||||
struct sde_rot_data_type {
|
||||
u32 mdss_version;
|
||||
|
||||
|
@ -140,6 +161,14 @@ struct sde_rot_data_type {
|
|||
|
||||
int iommu_attached;
|
||||
int iommu_ref_cnt;
|
||||
|
||||
struct sde_rot_vbif_debug_bus *nrt_vbif_dbg_bus;
|
||||
u32 nrt_vbif_dbg_bus_size;
|
||||
|
||||
struct sde_rot_regdump *regdump;
|
||||
u32 regdump_size;
|
||||
|
||||
void *sde_rot_hw;
|
||||
};
|
||||
|
||||
int sde_rotator_base_init(struct sde_rot_data_type **pmdata,
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "sde_rotator_r1.h"
|
||||
#include "sde_rotator_r3.h"
|
||||
#include "sde_rotator_trace.h"
|
||||
#include "sde_rotator_debug.h"
|
||||
|
||||
/* waiting for hw time out, 3 vsync for 30fps*/
|
||||
#define ROT_HW_ACQUIRE_TIMEOUT_IN_MS 100
|
||||
|
@ -127,6 +128,7 @@ static int sde_rotator_bus_scale_set_quota(struct sde_rot_bus_data_type *bus,
|
|||
bus->curr_bw_uc_idx = new_uc_idx;
|
||||
bus->curr_quota_val = quota;
|
||||
|
||||
SDEROT_EVTLOG(new_uc_idx, quota);
|
||||
SDEROT_DBG("uc_idx=%d quota=%llu\n", new_uc_idx, quota);
|
||||
ATRACE_BEGIN("msm_bus_scale_req_rot");
|
||||
ret = msm_bus_scale_client_update_request(bus->bus_hdl,
|
||||
|
@ -274,6 +276,7 @@ static void sde_rotator_footswitch_ctrl(struct sde_rot_mgr *mgr, bool on)
|
|||
return;
|
||||
}
|
||||
|
||||
SDEROT_EVTLOG(on);
|
||||
SDEROT_DBG("%s: rotator regulators", on ? "Enable" : "Disable");
|
||||
ret = sde_rot_enable_vreg(mgr->module_power.vreg_config,
|
||||
mgr->module_power.num_vreg, on);
|
||||
|
@ -307,6 +310,7 @@ static int sde_rotator_clk_ctrl(struct sde_rot_mgr *mgr, int enable)
|
|||
}
|
||||
|
||||
if (changed) {
|
||||
SDEROT_EVTLOG(enable);
|
||||
SDEROT_DBG("Rotator clk %s\n", enable ? "enable" : "disable");
|
||||
for (i = 0; i < mgr->num_rot_clk; i++) {
|
||||
clk = mgr->rot_clk[i].clk;
|
||||
|
@ -394,6 +398,7 @@ static bool sde_rotator_is_work_pending(struct sde_rot_mgr *mgr,
|
|||
static void sde_rotator_clear_fence(struct sde_rot_entry *entry)
|
||||
{
|
||||
if (entry->input_fence) {
|
||||
SDEROT_EVTLOG(entry->input_fence, 1111);
|
||||
SDEROT_DBG("sys_fence_put i:%p\n", entry->input_fence);
|
||||
sde_rotator_put_sync_fence(entry->input_fence);
|
||||
entry->input_fence = NULL;
|
||||
|
@ -404,6 +409,7 @@ static void sde_rotator_clear_fence(struct sde_rot_entry *entry)
|
|||
if (entry->fenceq && entry->fenceq->timeline)
|
||||
sde_rotator_resync_timeline(entry->fenceq->timeline);
|
||||
|
||||
SDEROT_EVTLOG(entry->output_fence, 2222);
|
||||
SDEROT_DBG("sys_fence_put o:%p\n", entry->output_fence);
|
||||
sde_rotator_put_sync_fence(entry->output_fence);
|
||||
entry->output_fence = NULL;
|
||||
|
@ -565,6 +571,7 @@ static struct sde_rot_perf *sde_rotator_find_session(
|
|||
|
||||
static void sde_rotator_release_data(struct sde_rot_entry *entry)
|
||||
{
|
||||
SDEROT_EVTLOG(entry->src_buf.p[0].addr, entry->dst_buf.p[0].addr);
|
||||
sde_mdp_data_free(&entry->src_buf, true, DMA_TO_DEVICE);
|
||||
sde_mdp_data_free(&entry->dst_buf, true, DMA_FROM_DEVICE);
|
||||
}
|
||||
|
@ -719,6 +726,10 @@ static struct sde_rot_hw_resource *sde_rotator_get_hw_resource(
|
|||
}
|
||||
}
|
||||
atomic_inc(&hw->num_active);
|
||||
SDEROT_EVTLOG(atomic_read(&hw->num_active), hw->pending_count,
|
||||
mgr->rdot_limit, entry->perf->rdot_limit,
|
||||
mgr->wrot_limit, entry->perf->wrot_limit,
|
||||
entry->item.session_id, entry->item.sequence_id);
|
||||
SDEROT_DBG("active=%d pending=%d rdot=%u/%u wrot=%u/%u s:%d.%d\n",
|
||||
atomic_read(&hw->num_active), hw->pending_count,
|
||||
mgr->rdot_limit, entry->perf->rdot_limit,
|
||||
|
@ -766,6 +777,8 @@ static void sde_rotator_put_hw_resource(struct sde_rot_queue *queue,
|
|||
if (hw_res)
|
||||
wake_up(&hw_res->wait_queue);
|
||||
}
|
||||
SDEROT_EVTLOG(atomic_read(&hw->num_active), hw->pending_count,
|
||||
entry->item.session_id, entry->item.sequence_id);
|
||||
SDEROT_DBG("active=%d pending=%d s:%d.%d\n",
|
||||
atomic_read(&hw->num_active), hw->pending_count,
|
||||
entry->item.session_id, entry->item.sequence_id);
|
||||
|
@ -1125,6 +1138,15 @@ static void sde_rotator_commit_handler(struct work_struct *work)
|
|||
|
||||
mgr = entry->private->mgr;
|
||||
|
||||
SDEROT_EVTLOG(
|
||||
entry->item.session_id, entry->item.sequence_id,
|
||||
entry->item.src_rect.x, entry->item.src_rect.y,
|
||||
entry->item.src_rect.w, entry->item.src_rect.h,
|
||||
entry->item.dst_rect.x, entry->item.dst_rect.y,
|
||||
entry->item.dst_rect.w, entry->item.dst_rect.h,
|
||||
entry->item.flags,
|
||||
entry->dnsc_factor_w, entry->dnsc_factor_h);
|
||||
|
||||
SDEDEV_DBG(mgr->device,
|
||||
"commit handler s:%d.%u src:(%d,%d,%d,%d) dst:(%d,%d,%d,%d) f:0x%x dnsc:%u/%u\n",
|
||||
entry->item.session_id, entry->item.sequence_id,
|
||||
|
@ -1233,11 +1255,13 @@ static void sde_rotator_done_handler(struct work_struct *work)
|
|||
entry->item.flags,
|
||||
entry->dnsc_factor_w, entry->dnsc_factor_h);
|
||||
|
||||
SDEROT_EVTLOG(entry->item.session_id, 0);
|
||||
ret = mgr->ops_wait_for_entry(hw, entry);
|
||||
if (ret) {
|
||||
SDEROT_ERR("fail to wait for completion %d\n", ret);
|
||||
atomic_inc(&request->failed_count);
|
||||
}
|
||||
SDEROT_EVTLOG(entry->item.session_id, 1);
|
||||
|
||||
if (entry->item.ts)
|
||||
entry->item.ts[SDE_ROTATOR_TS_DONE] = ktime_get();
|
||||
|
|
|
@ -22,6 +22,619 @@
|
|||
#include "sde_rotator_core.h"
|
||||
#include "sde_rotator_dev.h"
|
||||
|
||||
#ifdef CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG
|
||||
#define SDE_EVTLOG_DEFAULT_ENABLE 1
|
||||
#else
|
||||
#define SDE_EVTLOG_DEFAULT_ENABLE 0
|
||||
#endif
|
||||
#define SDE_EVTLOG_DEFAULT_PANIC 1
|
||||
#define SDE_EVTLOG_DEFAULT_REGDUMP SDE_ROT_DBG_DUMP_IN_MEM
|
||||
#define SDE_EVTLOG_DEFAULT_VBIF_DBGBUSDUMP SDE_ROT_DBG_DUMP_IN_MEM
|
||||
|
||||
/*
|
||||
* evtlog will print this number of entries when it is called through
|
||||
* sysfs node or panic. This prevents kernel log from evtlog message
|
||||
* flood.
|
||||
*/
|
||||
#define SDE_ROT_EVTLOG_PRINT_ENTRY 256
|
||||
|
||||
/*
|
||||
* evtlog keeps this number of entries in memory for debug purpose. This
|
||||
* number must be greater than print entry to prevent out of bound evtlog
|
||||
* entry array access.
|
||||
*/
|
||||
#define SDE_ROT_EVTLOG_ENTRY (SDE_ROT_EVTLOG_PRINT_ENTRY * 4)
|
||||
#define SDE_ROT_EVTLOG_MAX_DATA 15
|
||||
#define SDE_ROT_EVTLOG_BUF_MAX 512
|
||||
#define SDE_ROT_EVTLOG_BUF_ALIGN 32
|
||||
#define SDE_ROT_DEBUG_BASE_MAX 10
|
||||
|
||||
static DEFINE_SPINLOCK(sde_rot_xlock);
|
||||
|
||||
/*
|
||||
* tlog - EVTLOG entry structure
|
||||
* @counter - EVTLOG entriy counter
|
||||
* @time - timestamp of EVTLOG entry
|
||||
* @name - function name of EVTLOG entry
|
||||
* @line - line number of EVTLOG entry
|
||||
* @data - EVTLOG data contents
|
||||
* @data_cnt - number of data contents
|
||||
* @pid - pid of current calling thread
|
||||
*/
|
||||
struct tlog {
|
||||
u32 counter;
|
||||
s64 time;
|
||||
const char *name;
|
||||
int line;
|
||||
u32 data[SDE_ROT_EVTLOG_MAX_DATA];
|
||||
u32 data_cnt;
|
||||
int pid;
|
||||
};
|
||||
|
||||
/*
|
||||
* sde_rot_dbg_evtlog - EVTLOG debug data structure
|
||||
* @logs - EVTLOG entries
|
||||
* @first - first entry index in the EVTLOG
|
||||
* @last - last entry index in the EVTLOG
|
||||
* @curr - curr entry index in the EVTLOG
|
||||
* @evtlog - EVTLOG debugfs handle
|
||||
* @evtlog_enable - boolean indicates EVTLOG enable/disable
|
||||
* @panic_on_err - boolean indicates issue panic after EVTLOG dump
|
||||
* @enable_reg_dump - control in-log/memory dump for rotator registers
|
||||
* @enable_vbif_dbgbus_dump - control in-log/memory dump for VBIF debug bus
|
||||
* @evtlog_dump_work - schedule work strucutre for timeout handler
|
||||
* @work_dump_reg - storage for register dump control in schedule work
|
||||
* @work_panic - storage for panic control in schedule work
|
||||
* @work_vbif_dbgbus - storage for VBIF debug bus control in schedule work
|
||||
* @nrt_vbif_dbgbus_dump - memory buffer for VBIF debug bus dumping
|
||||
* @reg_dump_array - memory buffer for rotator registers dumping
|
||||
*/
|
||||
struct sde_rot_dbg_evtlog {
|
||||
struct tlog logs[SDE_ROT_EVTLOG_ENTRY];
|
||||
u32 first;
|
||||
u32 last;
|
||||
u32 curr;
|
||||
struct dentry *evtlog;
|
||||
u32 evtlog_enable;
|
||||
u32 panic_on_err;
|
||||
u32 enable_reg_dump;
|
||||
u32 enable_vbif_dbgbus_dump;
|
||||
struct work_struct evtlog_dump_work;
|
||||
bool work_dump_reg;
|
||||
bool work_panic;
|
||||
bool work_vbif_dbgbus;
|
||||
u32 *nrt_vbif_dbgbus_dump; /* address for the nrt vbif debug bus dump */
|
||||
u32 *reg_dump_array[SDE_ROT_DEBUG_BASE_MAX];
|
||||
} sde_rot_dbg_evtlog;
|
||||
|
||||
/*
|
||||
* sde_rot_evtlog_is_enabled - helper function for checking EVTLOG
|
||||
* enable/disable
|
||||
* @flag - EVTLOG option flag
|
||||
*/
|
||||
static inline bool sde_rot_evtlog_is_enabled(u32 flag)
|
||||
{
|
||||
return (flag & sde_rot_dbg_evtlog.evtlog_enable) ||
|
||||
(flag == SDE_ROT_EVTLOG_ALL &&
|
||||
sde_rot_dbg_evtlog.evtlog_enable);
|
||||
}
|
||||
|
||||
/*
|
||||
* __vbif_debug_bus - helper function for VBIF debug bus dump
|
||||
* @head - VBIF debug bus data structure
|
||||
* @vbif_base - VBIF IO mapped address
|
||||
* @dump_addr - output buffer for memory dump option
|
||||
* @in_log - boolean indicates in-log dump option
|
||||
*/
|
||||
static void __vbif_debug_bus(struct sde_rot_vbif_debug_bus *head,
|
||||
void __iomem *vbif_base, u32 *dump_addr, bool in_log)
|
||||
{
|
||||
int i, j;
|
||||
u32 val;
|
||||
|
||||
if (!dump_addr && !in_log)
|
||||
return;
|
||||
|
||||
for (i = 0; i < head->block_cnt; i++) {
|
||||
writel_relaxed(1 << (i + head->bit_offset),
|
||||
vbif_base + head->block_bus_addr);
|
||||
/* make sure that current bus blcok enable */
|
||||
wmb();
|
||||
for (j = 0; j < head->test_pnt_cnt; j++) {
|
||||
writel_relaxed(j, vbif_base + head->block_bus_addr + 4);
|
||||
/* make sure that test point is enabled */
|
||||
wmb();
|
||||
val = readl_relaxed(vbif_base + MMSS_VBIF_TEST_BUS_OUT);
|
||||
if (dump_addr) {
|
||||
*dump_addr++ = head->block_bus_addr;
|
||||
*dump_addr++ = i;
|
||||
*dump_addr++ = j;
|
||||
*dump_addr++ = val;
|
||||
}
|
||||
if (in_log)
|
||||
pr_err("testpoint:%x arb/xin id=%d index=%d val=0x%x\n",
|
||||
head->block_bus_addr, i, j, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_dump_vbif_debug_bus - VBIF debug bus dump
|
||||
* @bus_dump_flag - dump flag controlling in-log/memory dump option
|
||||
* @dump_mem - output buffer for memory dump location
|
||||
*/
|
||||
static void sde_rot_dump_vbif_debug_bus(u32 bus_dump_flag,
|
||||
u32 **dump_mem)
|
||||
{
|
||||
struct sde_rot_data_type *mdata = sde_rot_get_mdata();
|
||||
bool in_log, in_mem;
|
||||
u32 *dump_addr = NULL;
|
||||
u32 value;
|
||||
struct sde_rot_vbif_debug_bus *head;
|
||||
phys_addr_t phys = 0;
|
||||
int i, list_size = 0;
|
||||
void __iomem *vbif_base;
|
||||
struct sde_rot_vbif_debug_bus *dbg_bus;
|
||||
u32 bus_size;
|
||||
|
||||
pr_info("======== NRT VBIF Debug bus DUMP =========\n");
|
||||
vbif_base = mdata->vbif_nrt_io.base;
|
||||
dbg_bus = mdata->nrt_vbif_dbg_bus;
|
||||
bus_size = mdata->nrt_vbif_dbg_bus_size;
|
||||
|
||||
if (!vbif_base || !dbg_bus || !bus_size)
|
||||
return;
|
||||
|
||||
/* allocate memory for each test point */
|
||||
for (i = 0; i < bus_size; i++) {
|
||||
head = dbg_bus + i;
|
||||
list_size += (head->block_cnt * head->test_pnt_cnt);
|
||||
}
|
||||
|
||||
/* 4 bytes * 4 entries for each test point*/
|
||||
list_size *= 16;
|
||||
|
||||
in_log = (bus_dump_flag & SDE_ROT_DBG_DUMP_IN_LOG);
|
||||
in_mem = (bus_dump_flag & SDE_ROT_DBG_DUMP_IN_MEM);
|
||||
|
||||
if (in_mem) {
|
||||
if (!(*dump_mem))
|
||||
*dump_mem = dma_alloc_coherent(&mdata->pdev->dev,
|
||||
list_size, &phys, GFP_KERNEL);
|
||||
|
||||
if (*dump_mem) {
|
||||
dump_addr = *dump_mem;
|
||||
pr_info("%s: start_addr:0x%pK end_addr:0x%pK\n",
|
||||
__func__, dump_addr, dump_addr + list_size);
|
||||
} else {
|
||||
in_mem = false;
|
||||
pr_err("dump_mem: allocation fails\n");
|
||||
}
|
||||
}
|
||||
|
||||
sde_smmu_ctrl(1);
|
||||
|
||||
value = readl_relaxed(vbif_base + MMSS_VBIF_CLKON);
|
||||
writel_relaxed(value | BIT(1), vbif_base + MMSS_VBIF_CLKON);
|
||||
|
||||
/* make sure that vbif core is on */
|
||||
wmb();
|
||||
|
||||
for (i = 0; i < bus_size; i++) {
|
||||
head = dbg_bus + i;
|
||||
|
||||
writel_relaxed(0, vbif_base + head->disable_bus_addr);
|
||||
writel_relaxed(BIT(0), vbif_base + MMSS_VBIF_TEST_BUS_OUT_CTRL);
|
||||
/* make sure that other bus is off */
|
||||
wmb();
|
||||
|
||||
__vbif_debug_bus(head, vbif_base, dump_addr, in_log);
|
||||
if (dump_addr)
|
||||
dump_addr += (head->block_cnt * head->test_pnt_cnt * 4);
|
||||
}
|
||||
|
||||
sde_smmu_ctrl(0);
|
||||
|
||||
pr_info("========End VBIF Debug bus=========\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_dump_reg - helper function for dumping rotator register set content
|
||||
* @dump_name - register set name
|
||||
* @reg_dump_flag - dumping flag controlling in-log/memory dump location
|
||||
* @addr - starting address offset for dumping
|
||||
* @len - range of the register set
|
||||
* @dump_mem - output buffer for memory dump location option
|
||||
*/
|
||||
void sde_rot_dump_reg(const char *dump_name, u32 reg_dump_flag, u32 addr,
|
||||
int len, u32 **dump_mem)
|
||||
{
|
||||
struct sde_rot_data_type *mdata = sde_rot_get_mdata();
|
||||
bool in_log, in_mem;
|
||||
u32 *dump_addr = NULL;
|
||||
phys_addr_t phys = 0;
|
||||
int i;
|
||||
|
||||
in_log = (reg_dump_flag & SDE_ROT_DBG_DUMP_IN_LOG);
|
||||
in_mem = (reg_dump_flag & SDE_ROT_DBG_DUMP_IN_MEM);
|
||||
|
||||
pr_debug("reg_dump_flag=%d in_log=%d in_mem=%d\n",
|
||||
reg_dump_flag, in_log, in_mem);
|
||||
|
||||
if (len % 16)
|
||||
len += 16;
|
||||
len /= 16;
|
||||
|
||||
if (in_mem) {
|
||||
if (!(*dump_mem))
|
||||
*dump_mem = dma_alloc_coherent(&mdata->pdev->dev,
|
||||
len * 16, &phys, GFP_KERNEL);
|
||||
|
||||
if (*dump_mem) {
|
||||
dump_addr = *dump_mem;
|
||||
pr_info("%s: start_addr:0x%p end_addr:0x%p reg_addr=0x%X\n",
|
||||
dump_name, dump_addr, dump_addr + (u32)len * 16,
|
||||
addr);
|
||||
} else {
|
||||
in_mem = false;
|
||||
pr_err("dump_mem: kzalloc fails!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
u32 x0, x4, x8, xc;
|
||||
|
||||
x0 = readl_relaxed(mdata->sde_io.base + addr+0x0);
|
||||
x4 = readl_relaxed(mdata->sde_io.base + addr+0x4);
|
||||
x8 = readl_relaxed(mdata->sde_io.base + addr+0x8);
|
||||
xc = readl_relaxed(mdata->sde_io.base + addr+0xc);
|
||||
|
||||
if (in_log)
|
||||
pr_info("0x%08X : %08x %08x %08x %08x\n",
|
||||
addr, x0, x4, x8, xc);
|
||||
|
||||
if (dump_addr && in_mem) {
|
||||
dump_addr[i*4] = x0;
|
||||
dump_addr[i*4 + 1] = x4;
|
||||
dump_addr[i*4 + 2] = x8;
|
||||
dump_addr[i*4 + 3] = xc;
|
||||
}
|
||||
|
||||
addr += 16;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_dump_reg_all - dumping all SDE rotator registers
|
||||
*/
|
||||
static void sde_rot_dump_reg_all(void)
|
||||
{
|
||||
struct sde_rot_data_type *mdata = sde_rot_get_mdata();
|
||||
struct sde_rot_regdump *head, *regdump;
|
||||
u32 regdump_size;
|
||||
int i;
|
||||
|
||||
regdump = mdata->regdump;
|
||||
regdump_size = mdata->regdump_size;
|
||||
|
||||
if (!regdump || !regdump_size)
|
||||
return;
|
||||
|
||||
/* Enable clock to rotator if not yet enabled */
|
||||
sde_smmu_ctrl(1);
|
||||
|
||||
for (i = 0; (i < regdump_size) && (i < SDE_ROT_DEBUG_BASE_MAX); i++) {
|
||||
head = ®dump[i];
|
||||
|
||||
if (head->access == SDE_ROT_REGDUMP_WRITE) {
|
||||
writel_relaxed(1, mdata->sde_io.base + head->offset);
|
||||
/* Make sure write go through */
|
||||
wmb();
|
||||
} else {
|
||||
sde_rot_dump_reg(head->name,
|
||||
sde_rot_dbg_evtlog.enable_reg_dump,
|
||||
head->offset, head->len,
|
||||
&sde_rot_dbg_evtlog.reg_dump_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable rotator clock */
|
||||
sde_smmu_ctrl(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* __sde_rot_evtlog_dump_calc_range - calculate dump range for EVTLOG
|
||||
*/
|
||||
static bool __sde_rot_evtlog_dump_calc_range(void)
|
||||
{
|
||||
static u32 next;
|
||||
bool need_dump = true;
|
||||
unsigned long flags;
|
||||
struct sde_rot_dbg_evtlog *evtlog = &sde_rot_dbg_evtlog;
|
||||
|
||||
spin_lock_irqsave(&sde_rot_xlock, flags);
|
||||
|
||||
evtlog->first = next;
|
||||
|
||||
if (evtlog->last == evtlog->first) {
|
||||
need_dump = false;
|
||||
goto dump_exit;
|
||||
}
|
||||
|
||||
if (evtlog->last < evtlog->first) {
|
||||
evtlog->first %= SDE_ROT_EVTLOG_ENTRY;
|
||||
if (evtlog->last < evtlog->first)
|
||||
evtlog->last += SDE_ROT_EVTLOG_ENTRY;
|
||||
}
|
||||
|
||||
if ((evtlog->last - evtlog->first) > SDE_ROT_EVTLOG_PRINT_ENTRY) {
|
||||
pr_warn("evtlog buffer overflow before dump: %d\n",
|
||||
evtlog->last - evtlog->first);
|
||||
evtlog->first = evtlog->last - SDE_ROT_EVTLOG_PRINT_ENTRY;
|
||||
}
|
||||
next = evtlog->first + 1;
|
||||
|
||||
dump_exit:
|
||||
spin_unlock_irqrestore(&sde_rot_xlock, flags);
|
||||
|
||||
return need_dump;
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_evtlog_dump_entry - helper function for EVTLOG content dumping
|
||||
* @evtlog_buf: EVTLOG dump output buffer
|
||||
* @evtlog_buf_size: EVTLOG output buffer size
|
||||
*/
|
||||
static ssize_t sde_rot_evtlog_dump_entry(char *evtlog_buf,
|
||||
ssize_t evtlog_buf_size)
|
||||
{
|
||||
int i;
|
||||
ssize_t off = 0;
|
||||
struct tlog *log, *prev_log;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sde_rot_xlock, flags);
|
||||
|
||||
log = &sde_rot_dbg_evtlog.logs[sde_rot_dbg_evtlog.first %
|
||||
SDE_ROT_EVTLOG_ENTRY];
|
||||
|
||||
prev_log = &sde_rot_dbg_evtlog.logs[(sde_rot_dbg_evtlog.first - 1) %
|
||||
SDE_ROT_EVTLOG_ENTRY];
|
||||
|
||||
off = snprintf((evtlog_buf + off), (evtlog_buf_size - off), "%s:%-4d",
|
||||
log->name, log->line);
|
||||
|
||||
if (off < SDE_ROT_EVTLOG_BUF_ALIGN) {
|
||||
memset((evtlog_buf + off), 0x20,
|
||||
(SDE_ROT_EVTLOG_BUF_ALIGN - off));
|
||||
off = SDE_ROT_EVTLOG_BUF_ALIGN;
|
||||
}
|
||||
|
||||
off += snprintf((evtlog_buf + off), (evtlog_buf_size - off),
|
||||
"=>[%-8d:%-11llu:%9llu][%-4d]:", sde_rot_dbg_evtlog.first,
|
||||
log->time, (log->time - prev_log->time), log->pid);
|
||||
|
||||
for (i = 0; i < log->data_cnt; i++)
|
||||
off += snprintf((evtlog_buf + off), (evtlog_buf_size - off),
|
||||
"%x ", log->data[i]);
|
||||
|
||||
off += snprintf((evtlog_buf + off), (evtlog_buf_size - off), "\n");
|
||||
|
||||
spin_unlock_irqrestore(&sde_rot_xlock, flags);
|
||||
|
||||
return off;
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_evtlog_dump_all - Dumping all content in EVTLOG buffer
|
||||
*/
|
||||
static void sde_rot_evtlog_dump_all(void)
|
||||
{
|
||||
char evtlog_buf[SDE_ROT_EVTLOG_BUF_MAX];
|
||||
|
||||
while (__sde_rot_evtlog_dump_calc_range()) {
|
||||
sde_rot_evtlog_dump_entry(evtlog_buf, SDE_ROT_EVTLOG_BUF_MAX);
|
||||
pr_info("%s", evtlog_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_evtlog_dump_open - debugfs open handler for evtlog dump
|
||||
* @inode: debugfs inode
|
||||
* @file: file handler
|
||||
*/
|
||||
static int sde_rot_evtlog_dump_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
/* non-seekable */
|
||||
file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
|
||||
file->private_data = inode->i_private;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_evtlog_dump_read - debugfs read handler for evtlog dump
|
||||
* @file: file handler
|
||||
* @buff: user buffer content for debugfs
|
||||
* @count: size of user buffer
|
||||
* @ppos: position offset of user buffer
|
||||
*/
|
||||
static ssize_t sde_rot_evtlog_dump_read(struct file *file, char __user *buff,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
char evtlog_buf[SDE_ROT_EVTLOG_BUF_MAX];
|
||||
|
||||
if (__sde_rot_evtlog_dump_calc_range()) {
|
||||
len = sde_rot_evtlog_dump_entry(evtlog_buf,
|
||||
SDE_ROT_EVTLOG_BUF_MAX);
|
||||
if (copy_to_user(buff, evtlog_buf, len))
|
||||
return -EFAULT;
|
||||
*ppos += len;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_evtlog_dump_write - debugfs write handler for evtlog dump
|
||||
* @file: file handler
|
||||
* @user_buf: user buffer content from debugfs
|
||||
* @count: size of user buffer
|
||||
* @ppos: position offset of user buffer
|
||||
*/
|
||||
static ssize_t sde_rot_evtlog_dump_write(struct file *file,
|
||||
const char __user *user_buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
sde_rot_evtlog_dump_all();
|
||||
|
||||
sde_rot_dump_reg_all();
|
||||
|
||||
if (sde_rot_dbg_evtlog.panic_on_err)
|
||||
panic("evtlog_dump_write");
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_evtlog_dump_helper - helper function for evtlog dump
|
||||
* @dead: boolean indicates panic after dump
|
||||
* @panic_name: Panic signature name show up in log
|
||||
* @dump_rot: boolean indicates rotator register dump
|
||||
* @dump_vbif_debug_bus: boolean indicates VBIF debug bus dump
|
||||
*/
|
||||
static void sde_rot_evtlog_dump_helper(bool dead, const char *panic_name,
|
||||
bool dump_rot, bool dump_vbif_debug_bus)
|
||||
{
|
||||
sde_rot_evtlog_dump_all();
|
||||
|
||||
if (dump_rot)
|
||||
sde_rot_dump_reg_all();
|
||||
|
||||
if (dump_vbif_debug_bus)
|
||||
sde_rot_dump_vbif_debug_bus(
|
||||
sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump,
|
||||
&sde_rot_dbg_evtlog.nrt_vbif_dbgbus_dump);
|
||||
|
||||
if (dead)
|
||||
panic(panic_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_evtlog_debug_work - schedule work function for evtlog dump
|
||||
* @work: schedule work structure
|
||||
*/
|
||||
static void sde_rot_evtlog_debug_work(struct work_struct *work)
|
||||
{
|
||||
sde_rot_evtlog_dump_helper(
|
||||
sde_rot_dbg_evtlog.work_panic,
|
||||
"evtlog_workitem",
|
||||
sde_rot_dbg_evtlog.work_dump_reg,
|
||||
sde_rot_dbg_evtlog.work_vbif_dbgbus);
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_dump_panic - Issue evtlog dump and generic panic
|
||||
*/
|
||||
void sde_rot_dump_panic(void)
|
||||
{
|
||||
sde_rot_evtlog_dump_all();
|
||||
sde_rot_dump_reg_all();
|
||||
|
||||
panic("sde_rotator");
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_evtlog_tout_handler - log dump timeout handler
|
||||
* @queue: boolean indicate putting log dump into queue
|
||||
* @name: function name having timeout
|
||||
*/
|
||||
void sde_rot_evtlog_tout_handler(bool queue, const char *name, ...)
|
||||
{
|
||||
int i;
|
||||
bool dead = false;
|
||||
bool dump_rot = false;
|
||||
bool dump_vbif_dbgbus = false;
|
||||
char *blk_name = NULL;
|
||||
va_list args;
|
||||
|
||||
if (!sde_rot_evtlog_is_enabled(SDE_ROT_EVTLOG_DEFAULT))
|
||||
return;
|
||||
|
||||
if (queue && work_pending(&sde_rot_dbg_evtlog.evtlog_dump_work))
|
||||
return;
|
||||
|
||||
va_start(args, name);
|
||||
for (i = 0; i < SDE_ROT_EVTLOG_MAX_DATA; i++) {
|
||||
blk_name = va_arg(args, char*);
|
||||
if (IS_ERR_OR_NULL(blk_name))
|
||||
break;
|
||||
|
||||
if (!strcmp(blk_name, "rot"))
|
||||
dump_rot = true;
|
||||
|
||||
if (!strcmp(blk_name, "vbif_dbg_bus"))
|
||||
dump_vbif_dbgbus = true;
|
||||
|
||||
if (!strcmp(blk_name, "panic"))
|
||||
dead = true;
|
||||
}
|
||||
va_end(args);
|
||||
|
||||
if (queue) {
|
||||
/* schedule work to dump later */
|
||||
sde_rot_dbg_evtlog.work_panic = dead;
|
||||
sde_rot_dbg_evtlog.work_dump_reg = dump_rot;
|
||||
sde_rot_dbg_evtlog.work_vbif_dbgbus = dump_vbif_dbgbus;
|
||||
schedule_work(&sde_rot_dbg_evtlog.evtlog_dump_work);
|
||||
} else {
|
||||
sde_rot_evtlog_dump_helper(dead, name, dump_rot,
|
||||
dump_vbif_dbgbus);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rot_evtlog - log contents into memory for dump analysis
|
||||
* @name: Name of function calling evtlog
|
||||
* @line: line number of calling function
|
||||
* @flag: Log control flag
|
||||
*/
|
||||
void sde_rot_evtlog(const char *name, int line, int flag, ...)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i, val = 0;
|
||||
va_list args;
|
||||
struct tlog *log;
|
||||
|
||||
if (!sde_rot_evtlog_is_enabled(flag))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&sde_rot_xlock, flags);
|
||||
log = &sde_rot_dbg_evtlog.logs[sde_rot_dbg_evtlog.curr];
|
||||
log->time = ktime_to_us(ktime_get());
|
||||
log->name = name;
|
||||
log->line = line;
|
||||
log->data_cnt = 0;
|
||||
log->pid = current->pid;
|
||||
|
||||
va_start(args, flag);
|
||||
for (i = 0; i < SDE_ROT_EVTLOG_MAX_DATA; i++) {
|
||||
|
||||
val = va_arg(args, int);
|
||||
if (val == SDE_ROT_DATA_LIMITER)
|
||||
break;
|
||||
|
||||
log->data[i] = val;
|
||||
}
|
||||
va_end(args);
|
||||
log->data_cnt = i;
|
||||
sde_rot_dbg_evtlog.curr =
|
||||
(sde_rot_dbg_evtlog.curr + 1) % SDE_ROT_EVTLOG_ENTRY;
|
||||
sde_rot_dbg_evtlog.last++;
|
||||
|
||||
spin_unlock_irqrestore(&sde_rot_xlock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* sde_rotator_stat_show - Show statistics on read to this debugfs file
|
||||
* @s: Pointer to sequence file structure
|
||||
|
@ -249,6 +862,58 @@ static int sde_rotator_core_create_debugfs(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations sde_rot_evtlog_fops = {
|
||||
.open = sde_rot_evtlog_dump_open,
|
||||
.read = sde_rot_evtlog_dump_read,
|
||||
.write = sde_rot_evtlog_dump_write,
|
||||
};
|
||||
|
||||
static int sde_rotator_evtlog_create_debugfs(
|
||||
struct sde_rot_mgr *mgr,
|
||||
struct dentry *debugfs_root)
|
||||
{
|
||||
int i;
|
||||
|
||||
sde_rot_dbg_evtlog.evtlog = debugfs_create_dir("evtlog", debugfs_root);
|
||||
if (IS_ERR_OR_NULL(sde_rot_dbg_evtlog.evtlog)) {
|
||||
pr_err("debugfs_create_dir fail, error %ld\n",
|
||||
PTR_ERR(sde_rot_dbg_evtlog.evtlog));
|
||||
sde_rot_dbg_evtlog.evtlog = NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
INIT_WORK(&sde_rot_dbg_evtlog.evtlog_dump_work,
|
||||
sde_rot_evtlog_debug_work);
|
||||
sde_rot_dbg_evtlog.work_panic = false;
|
||||
|
||||
for (i = 0; i < SDE_ROT_EVTLOG_ENTRY; i++)
|
||||
sde_rot_dbg_evtlog.logs[i].counter = i;
|
||||
|
||||
debugfs_create_file("dump", 0644, sde_rot_dbg_evtlog.evtlog, NULL,
|
||||
&sde_rot_evtlog_fops);
|
||||
debugfs_create_u32("enable", 0644, sde_rot_dbg_evtlog.evtlog,
|
||||
&sde_rot_dbg_evtlog.evtlog_enable);
|
||||
debugfs_create_u32("panic", 0644, sde_rot_dbg_evtlog.evtlog,
|
||||
&sde_rot_dbg_evtlog.panic_on_err);
|
||||
debugfs_create_u32("reg_dump", 0644, sde_rot_dbg_evtlog.evtlog,
|
||||
&sde_rot_dbg_evtlog.enable_reg_dump);
|
||||
debugfs_create_u32("vbif_dbgbus_dump", 0644, sde_rot_dbg_evtlog.evtlog,
|
||||
&sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump);
|
||||
|
||||
sde_rot_dbg_evtlog.evtlog_enable = SDE_EVTLOG_DEFAULT_ENABLE;
|
||||
sde_rot_dbg_evtlog.panic_on_err = SDE_EVTLOG_DEFAULT_PANIC;
|
||||
sde_rot_dbg_evtlog.enable_reg_dump = SDE_EVTLOG_DEFAULT_REGDUMP;
|
||||
sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump =
|
||||
SDE_EVTLOG_DEFAULT_VBIF_DBGBUSDUMP;
|
||||
|
||||
pr_info("evtlog_status: enable:%d, panic:%d, dump:%d\n",
|
||||
sde_rot_dbg_evtlog.evtlog_enable,
|
||||
sde_rot_dbg_evtlog.panic_on_err,
|
||||
sde_rot_dbg_evtlog.enable_reg_dump);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* struct sde_rotator_stat_ops - processed statistics file operations
|
||||
*/
|
||||
|
@ -335,6 +1000,12 @@ struct dentry *sde_rotator_create_debugfs(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (sde_rotator_evtlog_create_debugfs(rot_dev->mgr, debugfs_root)) {
|
||||
SDEROT_ERR("fail create evtlog debugfs\n");
|
||||
debugfs_remove_recursive(debugfs_root);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return debugfs_root;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,32 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/dcache.h>
|
||||
|
||||
#define SDE_ROT_DATA_LIMITER (-1)
|
||||
#define SDE_ROT_EVTLOG_TOUT_DATA_LIMITER (NULL)
|
||||
|
||||
enum sde_rot_dbg_reg_dump_flag {
|
||||
SDE_ROT_DBG_DUMP_IN_LOG = BIT(0),
|
||||
SDE_ROT_DBG_DUMP_IN_MEM = BIT(1),
|
||||
};
|
||||
|
||||
enum sde_rot_dbg_evtlog_flag {
|
||||
SDE_ROT_EVTLOG_DEFAULT = BIT(0),
|
||||
SDE_ROT_EVTLOG_IOMMU = BIT(1),
|
||||
SDE_ROT_EVTLOG_DBG = BIT(6),
|
||||
SDE_ROT_EVTLOG_ALL = BIT(7)
|
||||
};
|
||||
|
||||
#define SDEROT_EVTLOG(...) sde_rot_evtlog(__func__, __LINE__, \
|
||||
SDE_ROT_EVTLOG_DEFAULT, ##__VA_ARGS__, SDE_ROT_DATA_LIMITER)
|
||||
|
||||
#define SDEROT_EVTLOG_TOUT_HANDLER(...) \
|
||||
sde_rot_evtlog_tout_handler(false, __func__, ##__VA_ARGS__, \
|
||||
SDE_ROT_EVTLOG_TOUT_DATA_LIMITER)
|
||||
|
||||
void sde_rot_evtlog(const char *name, int line, int flag, ...);
|
||||
void sde_rot_dump_panic(void);
|
||||
void sde_rot_evtlog_tout_handler(bool queue, const char *name, ...);
|
||||
|
||||
struct sde_rotator_device;
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "sde_rotator_r3_hwio.h"
|
||||
#include "sde_rotator_r3_debug.h"
|
||||
#include "sde_rotator_trace.h"
|
||||
#include "sde_rotator_debug.h"
|
||||
|
||||
/* XIN mapping */
|
||||
#define XIN_SSPP 0
|
||||
|
@ -198,6 +199,29 @@ static u32 sde_hw_rotator_output_pixfmts[] = {
|
|||
SDE_PIX_FMT_Y_CBCR_H2V2_TP10_UBWC,
|
||||
};
|
||||
|
||||
static struct sde_rot_vbif_debug_bus nrt_vbif_dbg_bus_r3[] = {
|
||||
{0x214, 0x21c, 16, 1, 0x10}, /* arb clients */
|
||||
{0x214, 0x21c, 0, 12, 0x13}, /* xin blocks - axi side */
|
||||
{0x21c, 0x214, 0, 12, 0xc}, /* xin blocks - clock side */
|
||||
};
|
||||
|
||||
static struct sde_rot_regdump sde_rot_r3_regdump[] = {
|
||||
{ "SDEROT_ROTTOP", SDE_ROT_ROTTOP_OFFSET, 0x100, SDE_ROT_REGDUMP_READ },
|
||||
{ "SDEROT_SSPP", SDE_ROT_SSPP_OFFSET, 0x200, SDE_ROT_REGDUMP_READ },
|
||||
{ "SDEROT_WB", SDE_ROT_WB_OFFSET, 0x300, SDE_ROT_REGDUMP_READ },
|
||||
{ "SDEROT_REGDMA_CSR", SDE_ROT_REGDMA_OFFSET, 0x100,
|
||||
SDE_ROT_REGDUMP_READ },
|
||||
/*
|
||||
* Need to perform a SW reset to REGDMA in order to access the
|
||||
* REGDMA RAM especially if REGDMA is waiting for Rotator IDLE.
|
||||
* REGDMA RAM should be dump at last.
|
||||
*/
|
||||
{ "SDEROT_REGDMA_RESET", ROTTOP_SW_RESET_OVERRIDE, 1,
|
||||
SDE_ROT_REGDUMP_WRITE },
|
||||
{ "SDEROT_REGDMA_RAM", SDE_ROT_REGDMA_RAM_OFFSET, 0x2000,
|
||||
SDE_ROT_REGDUMP_READ },
|
||||
};
|
||||
|
||||
/* Invalid software timestamp value for initialization */
|
||||
#define SDE_REGDMA_SWTS_INVALID (~0)
|
||||
|
||||
|
@ -332,6 +356,8 @@ static void sde_hw_rotator_dump_status(struct sde_hw_rotator *rot)
|
|||
REGDMA_CSR_REGDMA_INVALID_CMD_RAM_OFFSET),
|
||||
SDE_ROTREG_READ(rot->mdss_base,
|
||||
REGDMA_CSR_REGDMA_FSM_STATE));
|
||||
|
||||
SDEROT_EVTLOG_TOUT_HANDLER("rot", "vbif_dbg_bus", "panic");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1484,6 +1510,10 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw,
|
|||
&entry->dst_buf);
|
||||
}
|
||||
|
||||
SDEROT_EVTLOG(flags, item->input.width, item->input.height,
|
||||
item->output.width, item->output.height,
|
||||
entry->src_buf.p[0].addr, entry->dst_buf.p[0].addr);
|
||||
|
||||
if (mdata->default_ot_rd_limit) {
|
||||
struct sde_mdp_set_ot_params ot_params;
|
||||
|
||||
|
@ -1677,6 +1707,13 @@ static int sde_rotator_hw_rev_init(struct sde_hw_rotator *rot)
|
|||
set_bit(SDE_CAPS_R3_1P5_DOWNSCALE, mdata->sde_caps_map);
|
||||
}
|
||||
|
||||
mdata->nrt_vbif_dbg_bus = nrt_vbif_dbg_bus_r3;
|
||||
mdata->nrt_vbif_dbg_bus_size =
|
||||
ARRAY_SIZE(nrt_vbif_dbg_bus_r3);
|
||||
|
||||
mdata->regdump = sde_rot_r3_regdump;
|
||||
mdata->regdump_size = ARRAY_SIZE(sde_rot_r3_regdump);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2202,6 +2239,7 @@ int sde_rotator_r3_init(struct sde_rot_mgr *mgr)
|
|||
clk_set_flags(mgr->rot_clk[mgr->core_clk_idx].clk,
|
||||
CLKFLAG_NORETAIN_PERIPH);
|
||||
|
||||
mdata->sde_rot_hw = rot;
|
||||
return 0;
|
||||
error_hw_rev_init:
|
||||
if (rot->irq_num >= 0)
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "sde_rotator_util.h"
|
||||
#include "sde_rotator_io_util.h"
|
||||
#include "sde_rotator_smmu.h"
|
||||
#include "sde_rotator_debug.h"
|
||||
|
||||
#define SMMU_SDE_ROT_SEC "qcom,smmu_sde_rot_sec"
|
||||
#define SMMU_SDE_ROT_UNSEC "qcom,smmu_sde_rot_unsec"
|
||||
|
@ -332,6 +333,8 @@ int sde_smmu_ctrl(int enable)
|
|||
int rc = 0;
|
||||
|
||||
mutex_lock(&sde_smmu_ref_cnt_lock);
|
||||
SDEROT_EVTLOG(__builtin_return_address(0), enable, mdata->iommu_ref_cnt,
|
||||
mdata->iommu_attached);
|
||||
SDEROT_DBG("%pS: enable:%d ref_cnt:%d attach:%d\n",
|
||||
__builtin_return_address(0), enable, mdata->iommu_ref_cnt,
|
||||
mdata->iommu_attached);
|
||||
|
@ -407,9 +410,10 @@ static int sde_smmu_fault_handler(struct iommu_domain *domain,
|
|||
|
||||
sde_smmu = (struct sde_smmu_client *)token;
|
||||
|
||||
/* TODO: trigger rotator panic and dump */
|
||||
SDEROT_ERR("TODO: trigger rotator panic and dump, iova=0x%08lx\n",
|
||||
iova);
|
||||
/* trigger rotator panic and dump */
|
||||
SDEROT_ERR("trigger rotator panic and dump, iova=0x%08lx\n", iova);
|
||||
|
||||
sde_rot_dump_panic();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue