From bafc97155a8465e50d80ad26af89bfaf595a97f8 Mon Sep 17 00:00:00 2001 From: hjc Date: Thu, 14 May 2015 15:42:41 +0800 Subject: [PATCH] rk fb: add for iommu pagefault debug Signed-off-by: hjc --- drivers/video/rockchip/rk_fb.c | 188 +++++++++++++++++++++++++-------- include/linux/rk_fb.h | 11 ++ 2 files changed, 156 insertions(+), 43 deletions(-) diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c index 390506936b05..2b75541a84c6 100755 --- a/drivers/video/rockchip/rk_fb.c +++ b/drivers/video/rockchip/rk_fb.c @@ -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); diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h index 2b8fc3ab5d8f..28516107d55c 100755 --- a/include/linux/rk_fb.h +++ b/include/linux/rk_fb.h @@ -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 { -- 2.34.1