mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
rk fb: add for iommu pagefault debug
Signed-off-by: hjc <hjc@rock-chips.com>
This commit is contained in:
@@ -78,13 +78,17 @@ static struct rk_fb_trsm_ops *trsm_mipi_ops;
|
||||
static int uboot_logo_on;
|
||||
|
||||
static int rk_fb_debug_lvl;
|
||||
static int rk_fb_iommu_debug = 1;
|
||||
module_param(rk_fb_debug_lvl, int, S_IRUGO | S_IWUSR);
|
||||
module_param(rk_fb_iommu_debug, int, S_IRUGO | S_IWUSR);
|
||||
|
||||
#define fb_dbg(level, x...) do { \
|
||||
if (unlikely(rk_fb_debug_lvl >= level)) \
|
||||
printk(KERN_DEBUG x); \
|
||||
printk(KERN_INFO x); \
|
||||
} while (0)
|
||||
|
||||
static int rk_fb_config_debug(struct rk_lcdc_driver *dev_drv,
|
||||
struct rk_fb_win_cfg_data *win_data,
|
||||
struct rk_fb_reg_data *regs, u32 cmd);
|
||||
int support_uboot_display(void)
|
||||
{
|
||||
return uboot_logo_on;
|
||||
@@ -1451,7 +1455,10 @@ static int rk_fb_copy_from_loader(struct fb_info *info)
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_ROCKCHIP_IOMMU
|
||||
static int g_last_addr[4][4];
|
||||
static int g_last_addr[5][4];
|
||||
static int g_now_config_addr[5][4];
|
||||
static int g_last_state[5][4];
|
||||
static int g_now_config_state[5][4];
|
||||
int g_last_timeout;
|
||||
u32 freed_addr[10];
|
||||
u32 freed_index;
|
||||
@@ -1642,15 +1649,20 @@ static void rk_fb_update_win(struct rk_lcdc_driver *dev_drv,
|
||||
reg_win_data->reg_area_data[i].y_vir_stride;
|
||||
win->area[i].state = 1;
|
||||
#if defined(CONFIG_ROCKCHIP_IOMMU)
|
||||
if (dev_drv->iommu_enabled)
|
||||
g_last_addr[win->id][i] = win->area[i].smem_start +
|
||||
if (dev_drv->iommu_enabled) {
|
||||
g_now_config_addr[win->id][i] =
|
||||
win->area[i].smem_start +
|
||||
win->area[i].y_offset;
|
||||
g_now_config_state[win->id][i] = 1;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
win->area[i].state = 0;
|
||||
#if defined(CONFIG_ROCKCHIP_IOMMU)
|
||||
if (dev_drv->iommu_enabled)
|
||||
g_last_addr[win->id][i] = -1;
|
||||
if (dev_drv->iommu_enabled) {
|
||||
g_now_config_addr[win->id][i] = 0;
|
||||
g_now_config_state[win->id][i] = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1679,22 +1691,18 @@ static int rk_fb_reg_effect(struct rk_lcdc_driver *dev_drv,
|
||||
struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
|
||||
int i, j, wait_for_vsync = false;
|
||||
unsigned int dsp_addr[5][4];
|
||||
unsigned int area_support[5] = {1, 1, 1, 1, 1};
|
||||
int win_status = 0;
|
||||
|
||||
if (dev_drv->ops->get_dsp_addr)
|
||||
dev_drv->ops->get_dsp_addr(dev_drv, dsp_addr);
|
||||
|
||||
if (dev_drv->ops->area_support_num)
|
||||
dev_drv->ops->area_support_num(dev_drv, area_support);
|
||||
|
||||
for (i = 0; i < dev_drv->lcdc_win_num; i++) {
|
||||
if (rk_fb->disp_policy == DISPLAY_POLICY_BOX &&
|
||||
(!strcmp(dev_drv->win[i]->name, "hwc")))
|
||||
continue;
|
||||
|
||||
for (j = 0;j < RK_WIN_MAX_AREA; j++) {
|
||||
if ((j > 0) && (area_support[i] == 1)) {
|
||||
if ((j > 0) && (dev_drv->area_support[i] == 1)) {
|
||||
continue;
|
||||
}
|
||||
if (dev_drv->win[i]->area[j].state == 1) {
|
||||
@@ -1730,6 +1738,67 @@ static int rk_fb_reg_effect(struct rk_lcdc_driver *dev_drv,
|
||||
return wait_for_vsync;
|
||||
}
|
||||
|
||||
static int rk_fb_iommu_page_fault_dump(struct rk_lcdc_driver *dev_drv)
|
||||
{
|
||||
int i, j, state, page_fault = 0;
|
||||
unsigned int dsp_addr[5][4];
|
||||
|
||||
if (dev_drv->ops->extern_func) {
|
||||
dev_drv->ops->extern_func(dev_drv, UNMASK_PAGE_FAULT);
|
||||
page_fault = dev_drv->ops->extern_func(dev_drv, GET_PAGE_FAULT);
|
||||
}
|
||||
if (page_fault) {
|
||||
pr_info("last config:\n");
|
||||
for(i = 0; i < dev_drv->lcdc_win_num; i++) {
|
||||
for(j = 0; j < RK_WIN_MAX_AREA; j++) {
|
||||
if ((j > 0) && (dev_drv->area_support[i] == 1))
|
||||
continue;
|
||||
pr_info("win[%d]area[%d],state=%d,addr=0x%08x\n",
|
||||
i, j, g_last_state[i][j], g_last_addr[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("last freed buffer:\n");
|
||||
for (i = 0; (freed_addr[i] != 0xfefefefe) && freed_addr[i]; i++)
|
||||
pr_info("%d:0x%08x\n", i, freed_addr[i]);
|
||||
|
||||
dev_drv->ops->get_dsp_addr(dev_drv, dsp_addr);
|
||||
pr_info("vop now state:\n");
|
||||
for(i = 0; i < dev_drv->lcdc_win_num; i++) {
|
||||
for(j = 0; j < RK_WIN_MAX_AREA; j++) {
|
||||
if ((j > 0) && (dev_drv->area_support[i] == 1))
|
||||
continue;
|
||||
state = dev_drv->ops->get_win_state(dev_drv, i, j);
|
||||
pr_info("win[%d]area[%d],state=%d,addr=0x%08x\n",
|
||||
i, j, state, dsp_addr[i][j]);
|
||||
}
|
||||
}
|
||||
pr_info("now config:\n");
|
||||
for(i = 0; i < dev_drv->lcdc_win_num; i++) {
|
||||
for(j = 0; j < RK_WIN_MAX_AREA; j++) {
|
||||
if ((j > 0) && (dev_drv->area_support[i] == 1))
|
||||
continue;
|
||||
pr_info("win[%d]area[%d],state=%d,addr=0x%08x\n",
|
||||
i, j, g_now_config_state[i][j],
|
||||
g_now_config_addr[i][j]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < DUMP_FRAME_NUM; i++)
|
||||
rk_fb_config_debug(dev_drv, &(dev_drv->tmp_win_cfg[i]),
|
||||
&(dev_drv->tmp_regs[i]), 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < dev_drv->lcdc_win_num; i++) {
|
||||
for (j = 0; j < RK_WIN_MAX_AREA; j++) {
|
||||
if ((j > 0) && (dev_drv->area_support[i] == 1))
|
||||
continue;
|
||||
g_last_addr[i][j] = g_now_config_addr[i][j];
|
||||
g_last_state[i][j] = g_now_config_state[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
return page_fault;
|
||||
}
|
||||
static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv,
|
||||
struct rk_fb_reg_data *regs)
|
||||
{
|
||||
@@ -1741,7 +1810,7 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv,
|
||||
bool wait_for_vsync;
|
||||
int count = 100;
|
||||
long timeout;
|
||||
|
||||
int pagefault = 0;
|
||||
/* acq_fence wait */
|
||||
for (i = 0; i < regs->win_num; i++) {
|
||||
win_data = ®s->reg_win_data[i];
|
||||
@@ -1774,13 +1843,22 @@ static void rk_fb_update_reg(struct rk_lcdc_driver *dev_drv,
|
||||
#if defined(CONFIG_ROCKCHIP_IOMMU)
|
||||
if (dev_drv->iommu_enabled) {
|
||||
for (j = 0; j < 4; j++)
|
||||
g_last_addr[i][j] = -1;
|
||||
g_now_config_addr[i][j] = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
dev_drv->ops->ovl_mgr(dev_drv, 0, 1);
|
||||
dev_drv->ops->cfg_done(dev_drv);
|
||||
|
||||
if (rk_fb_iommu_debug > 0) {
|
||||
pagefault = rk_fb_iommu_page_fault_dump(dev_drv);
|
||||
}
|
||||
|
||||
if (pagefault == 0) {
|
||||
dev_drv->ops->cfg_done(dev_drv);
|
||||
} else {
|
||||
sw_sync_timeline_inc(dev_drv->timeline, 1);
|
||||
}
|
||||
|
||||
do {
|
||||
timestamp = dev_drv->vsync_info.timestamp;
|
||||
@@ -1875,8 +1953,8 @@ static int rk_fb_check_config_var(struct rk_fb_area_par *area_par,
|
||||
}
|
||||
|
||||
static int rk_fb_config_debug(struct rk_lcdc_driver *dev_drv,
|
||||
struct rk_fb_win_cfg_data *win_data,
|
||||
struct rk_fb_reg_data *regs, u32 cmd)
|
||||
struct rk_fb_win_cfg_data *win_data,
|
||||
struct rk_fb_reg_data *regs, u32 cmd)
|
||||
{
|
||||
int i, j;
|
||||
struct rk_fb_win_par *win_par;
|
||||
@@ -1884,71 +1962,88 @@ static int rk_fb_config_debug(struct rk_lcdc_driver *dev_drv,
|
||||
struct rk_fb_reg_win_data *reg_win_data;
|
||||
struct rk_fb_reg_area_data *area_data;
|
||||
|
||||
unsigned int area_support[5] = {1, 1, 1, 1, 1};
|
||||
if (dev_drv->ops->area_support_num)
|
||||
dev_drv->ops->area_support_num(dev_drv, area_support);
|
||||
|
||||
mutex_lock(&dev_drv->output_lock);
|
||||
fb_dbg(1, "-------------frame start-------------\n");
|
||||
fb_dbg(1, "user config:\n");
|
||||
fb_dbg(cmd, "-------------frame start-------------\n");
|
||||
fb_dbg(cmd, "user config:\n");
|
||||
for (i = 0; i < dev_drv->lcdc_win_num; i++) {
|
||||
win_par = &(win_data->win_par[i]);
|
||||
if ((win_par->area_par[0].ion_fd <= 0) &&
|
||||
(win_par->area_par[0].phy_addr <= 0))
|
||||
continue;
|
||||
fb_dbg(1, "win[%d]:z_order=%d,galhpa_v=%d\n",
|
||||
fb_dbg(cmd, "win[%d]:z_order=%d,galhpa_v=%d\n",
|
||||
win_par->win_id, win_par->z_order,
|
||||
win_par->g_alpha_val);
|
||||
for (j = 0; j < RK_WIN_MAX_AREA; j++) {
|
||||
area_par = &(win_par->area_par[j]);
|
||||
if (((j > 0) && (area_support[i] == 1)) ||
|
||||
if (((j > 0) && (dev_drv->area_support[i] == 1)) ||
|
||||
((win_par->area_par[j].ion_fd <= 0) &&
|
||||
(win_par->area_par[j].phy_addr <= 0)))
|
||||
continue;
|
||||
fb_dbg(1, " area[%d]:fmt=%d,ion_fd=%d,phy_add=0x%x,xoff=%d,yoff=%d\n",
|
||||
fb_dbg(cmd, " area[%d]:fmt=%d,ion_fd=%d,phy_add=0x%x,xoff=%d,yoff=%d\n",
|
||||
j, area_par->data_format, area_par->ion_fd,
|
||||
area_par->phy_addr, area_par->x_offset,
|
||||
area_par->y_offset);
|
||||
fb_dbg(1, " xpos=%d,ypos=%d,xsize=%d,ysize=%d\n",
|
||||
fb_dbg(cmd, " xpos=%d,ypos=%d,xsize=%d,ysize=%d\n",
|
||||
area_par->xpos, area_par->ypos,
|
||||
area_par->xsize, area_par->ysize);
|
||||
fb_dbg(1, " xact=%d,yact=%d,xvir=%d,yvir=%d\n",
|
||||
fb_dbg(cmd, " xact=%d,yact=%d,xvir=%d,yvir=%d\n",
|
||||
area_par->xact, area_par->yact,
|
||||
area_par->xvir, area_par->yvir);
|
||||
}
|
||||
}
|
||||
|
||||
fb_dbg(2, "regs data:\n");
|
||||
fb_dbg(2, "win_num=%d,buf_num=%d\n",
|
||||
fb_dbg(cmd, "regs data:\n");
|
||||
fb_dbg(cmd, "win_num=%d,buf_num=%d\n",
|
||||
regs->win_num, regs->buf_num);
|
||||
for (i = 0; i < dev_drv->lcdc_win_num; i++) {
|
||||
reg_win_data = &(regs->reg_win_data[i]);
|
||||
if (reg_win_data->reg_area_data[0].smem_start <= 0)
|
||||
continue;
|
||||
fb_dbg(2, "win[%d]:z_order=%d,area_num=%d,area_buf_num=%d\n",
|
||||
fb_dbg(cmd, "win[%d]:z_order=%d,area_num=%d,area_buf_num=%d\n",
|
||||
reg_win_data->win_id, reg_win_data->z_order,
|
||||
reg_win_data->area_num, reg_win_data->area_buf_num);
|
||||
for (j = 0; j < RK_WIN_MAX_AREA; j++) {
|
||||
area_data = &(reg_win_data->reg_area_data[j]);
|
||||
if (((j > 0) && (area_support[i] == 1)) ||
|
||||
if (((j > 0) && (dev_drv->area_support[i] == 1)) ||
|
||||
(area_data->smem_start <= 0))
|
||||
continue;
|
||||
fb_dbg(2, " area[%d]:fmt=%d,ion=%p,smem_star=0x%lx,cbr_star=0x%lx\n",
|
||||
fb_dbg(cmd, " area[%d]:fmt=%d,ion=%p,smem_star=0x%lx,cbr_star=0x%lx\n",
|
||||
j, area_data->data_format, area_data->ion_handle,
|
||||
area_data->smem_start, area_data->cbr_start);
|
||||
fb_dbg(2, " yoff=0x%x,coff=0x%x,area_data->buff_len=%x\n",
|
||||
fb_dbg(cmd, " yoff=0x%x,coff=0x%x,area_data->buff_len=%x\n",
|
||||
area_data->y_offset, area_data->c_offset,area_data->buff_len);
|
||||
fb_dbg(2, " xpos=%d,ypos=%d,xsize=%d,ysize=%d\n",
|
||||
fb_dbg(cmd, " xpos=%d,ypos=%d,xsize=%d,ysize=%d\n",
|
||||
area_data->xpos, area_data->ypos,
|
||||
area_data->xsize, area_data->ysize);
|
||||
fb_dbg(2, " xact=%d,yact=%d,xvir=%d,yvir=%d\n",
|
||||
fb_dbg(cmd, " xact=%d,yact=%d,xvir=%d,yvir=%d\n",
|
||||
area_data->xact, area_data->yact,
|
||||
area_data->xvir, area_data->yvir);
|
||||
}
|
||||
}
|
||||
fb_dbg(1, "-------------frame end---------------\n");
|
||||
fb_dbg(cmd, "-------------frame end---------------\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int rk_fb_config_backup(struct rk_lcdc_driver *dev_drv,
|
||||
struct rk_fb_win_cfg_data *win_cfg,
|
||||
struct rk_fb_reg_data *regs)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*2->1->0: 0 is newest*/
|
||||
for (i = 0; i < DUMP_FRAME_NUM - 1; i++) {
|
||||
memcpy(&(dev_drv->tmp_win_cfg[DUMP_FRAME_NUM-1-i]),
|
||||
&(dev_drv->tmp_win_cfg[DUMP_FRAME_NUM-2-i]),
|
||||
sizeof(struct rk_fb_win_cfg_data));
|
||||
memcpy(&(dev_drv->tmp_regs[DUMP_FRAME_NUM-1-i]),
|
||||
&(dev_drv->tmp_regs[DUMP_FRAME_NUM-2-i]),
|
||||
sizeof(struct rk_fb_reg_data));
|
||||
}
|
||||
|
||||
memcpy(&(dev_drv->tmp_win_cfg[0]), win_cfg,
|
||||
sizeof(struct rk_fb_win_cfg_data));
|
||||
memcpy(&(dev_drv->tmp_regs[0]), regs,
|
||||
sizeof(struct rk_fb_reg_data));
|
||||
|
||||
mutex_unlock(&dev_drv->output_lock);
|
||||
return 0;
|
||||
}
|
||||
static int rk_fb_set_win_buffer(struct fb_info *info,
|
||||
@@ -1996,7 +2091,7 @@ static int rk_fb_set_win_buffer(struct fb_info *info,
|
||||
if (IS_ERR(hdl)) {
|
||||
pr_info("%s: Could not import handle:"
|
||||
" %ld\n", __func__, (long)hdl);
|
||||
/*return -EINVAL; */
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
reg_win_data->reg_area_data[i].ion_handle = hdl;
|
||||
@@ -2307,6 +2402,7 @@ static int rk_fb_set_win_config(struct fb_info *info,
|
||||
if (rk_fb_set_win_buffer(info, &win_data->win_par[i],
|
||||
®s->reg_win_data[j])) {
|
||||
ret = -ENOMEM;
|
||||
pr_info("error:%s[%d]\n", __func__,__LINE__);
|
||||
goto err2;
|
||||
}
|
||||
if (regs->reg_win_data[j].area_num > 0) {
|
||||
@@ -2389,11 +2485,12 @@ static int rk_fb_set_win_config(struct fb_info *info,
|
||||
rk_fb_update_reg(dev_drv, regs);
|
||||
}
|
||||
}
|
||||
|
||||
if (rk_fb_debug_lvl > 0)
|
||||
rk_fb_config_debug(dev_drv, win_data, regs, rk_fb_debug_lvl);
|
||||
if (rk_fb_iommu_debug > 0)
|
||||
rk_fb_config_backup(dev_drv, win_data, regs);
|
||||
err:
|
||||
mutex_unlock(&dev_drv->output_lock);
|
||||
if (rk_fb_debug_lvl > 0)
|
||||
rk_fb_config_debug(dev_drv,win_data, regs, 0);
|
||||
return ret;
|
||||
err_null_frame:
|
||||
for (j = 0; j < RK_MAX_BUF_NUM; j++)
|
||||
@@ -3688,6 +3785,7 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb,
|
||||
struct rk_screen *screen = devm_kzalloc(dev_drv->dev,
|
||||
sizeof(struct rk_screen),
|
||||
GFP_KERNEL);
|
||||
int i = 0;
|
||||
|
||||
if (!screen) {
|
||||
dev_err(dev_drv->dev, "malloc screen for lcdc%d fail!",
|
||||
@@ -3736,6 +3834,10 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb,
|
||||
dev_drv->overscan.top = 100;
|
||||
dev_drv->overscan.right = 100;
|
||||
dev_drv->overscan.bottom = 100;
|
||||
for (i = 0; i < RK30_MAX_LAYER_SUPPORT; i++)
|
||||
dev_drv->area_support[i] = 1;
|
||||
if (dev_drv->ops->area_support_num)
|
||||
dev_drv->ops->area_support_num(dev_drv, dev_drv->area_support);
|
||||
rk_disp_pwr_ctr_parse_dt(dev_drv);
|
||||
if (dev_drv->prop == PRMRY) {
|
||||
rk_fb_set_prmry_screen(screen);
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
#define ALIGN_ODD_TIMES(x, align) (((x) % ((align) * 2) == 0) ? ((x) + (align)) : (x))
|
||||
#define ALIGN_64BYTE_ODD_TIMES(x, align) ALIGN_ODD_TIMES(ALIGN_N_TIMES(x, align), align)
|
||||
|
||||
#define DUMP_FRAME_NUM 3
|
||||
|
||||
//#define USE_ION_MMU 1
|
||||
#if defined(CONFIG_ION_ROCKCHIP)
|
||||
@@ -246,6 +247,12 @@ typedef enum {
|
||||
SCREEN_UNPREPARE_DDR_CHANGE,
|
||||
} screen_status;
|
||||
|
||||
typedef enum {
|
||||
GET_PAGE_FAULT = 0x0,
|
||||
CLR_PAGE_FAULT = 0x1,
|
||||
UNMASK_PAGE_FAULT = 0x2
|
||||
} extern_func;
|
||||
|
||||
struct rk_fb_rgb {
|
||||
struct fb_bitfield red;
|
||||
struct fb_bitfield green;
|
||||
@@ -475,6 +482,7 @@ struct rk_lcdc_drv_ops {
|
||||
int (*dsp_black) (struct rk_lcdc_driver *dev_drv, int enable);
|
||||
int (*backlight_close)(struct rk_lcdc_driver *dev_drv, int enable);
|
||||
int (*area_support_num)(struct rk_lcdc_driver *dev_drv, unsigned int *area_support);
|
||||
int (*extern_func)(struct rk_lcdc_driver *dev_drv, int cmd);
|
||||
};
|
||||
|
||||
struct rk_fb_area_par {
|
||||
@@ -654,6 +662,9 @@ struct rk_lcdc_driver {
|
||||
/*1:hdmi switch uncomplete,0:complete*/
|
||||
bool hdmi_switch;
|
||||
void *trace_buf;
|
||||
struct rk_fb_win_cfg_data tmp_win_cfg[DUMP_FRAME_NUM];
|
||||
struct rk_fb_reg_data tmp_regs[DUMP_FRAME_NUM];
|
||||
unsigned int area_support[RK30_MAX_LAYER_SUPPORT];
|
||||
};
|
||||
|
||||
struct rk_fb_par {
|
||||
|
||||
Reference in New Issue
Block a user