static int fimg2d_sysmmu_fault_handler(enum S5P_SYSMMU_INTERRUPT_TYPE itype, unsigned long pgtable_base, unsigned long fault_addr) { struct fimg2d_bltcmd *cmd; if (itype == SYSMMU_PAGEFAULT) { printk(KERN_ERR "[%s] sysmmu page fault(0x%lx), pgd(0x%lx)\n", __func__, fault_addr, pgtable_base); } else { printk(KERN_ERR "[%s] sysmmu interrupt " "type(%d) pgd(0x%lx) addr(0x%lx)\n", __func__, itype, pgtable_base, fault_addr); } cmd = fimg2d_get_first_command(info); if (!cmd) { printk(KERN_ERR "[%s] null command\n", __func__); goto next; } if (cmd->ctx->mm->pgd != phys_to_virt(pgtable_base)) { printk(KERN_ERR "[%s] pgtable base is different from current command\n", __func__); goto next; } fimg2d_dump_command(cmd); next: fimg2d_clk_dump(info); info->dump(info); BUG(); return 0; }
struct fimg2d_bltcmd *fimg2d_get_command(struct fimg2d_control *ctrl) { unsigned long flags; struct fimg2d_bltcmd *cmd; g2d_spin_lock(&ctrl->bltlock, flags); cmd = fimg2d_get_first_command(ctrl); g2d_spin_unlock(&ctrl->bltlock, flags); return cmd; }
void fimg2d4x_bitblt(struct fimg2d_control *info) { struct fimg2d_context *ctx; struct fimg2d_bltcmd *cmd; unsigned long *pgd; fimg2d_debug("enter blitter\n"); #ifdef CONFIG_PM_RUNTIME pm_runtime_get_sync(info->dev); fimg2d_debug("pm_runtime_get_sync\n"); #endif fimg2d_clk_on(info); while ((cmd = fimg2d_get_first_command(info))) { ctx = cmd->ctx; if (info->err) { printk(KERN_ERR "[%s] device error\n", __func__); goto blitend; } atomic_set(&info->busy, 1); info->configure(info, cmd); if (cmd->image[IDST].addr.type != ADDR_PHYS) { pgd = (unsigned long *)ctx->mm->pgd; s5p_sysmmu_enable(info->dev, (unsigned long)virt_to_phys(pgd)); fimg2d_debug("sysmmu enable: pgd %p ctx %p seq_no(%u)\n", pgd, ctx, cmd->seq_no); } fimg2d4x_pre_bitblt(info, cmd); #ifdef PERF_PROFILE perf_start(cmd->ctx, PERF_BLIT); #endif /* start blit */ info->run(info); fimg2d4x_blit_wait(info, cmd); #ifdef PERF_PROFILE perf_end(cmd->ctx, PERF_BLIT); #endif if (cmd->image[IDST].addr.type != ADDR_PHYS) { s5p_sysmmu_disable(info->dev); fimg2d_debug("sysmmu disable\n"); } blitend: spin_lock(&info->bltlock); fimg2d_dequeue(&cmd->node); kfree(cmd); atomic_dec(&ctx->ncmd); /* wake up context */ if (!atomic_read(&ctx->ncmd)) wake_up(&ctx->wait_q); spin_unlock(&info->bltlock); } atomic_set(&info->active, 0); fimg2d_clk_off(info); #ifdef CONFIG_PM_RUNTIME pm_runtime_put_sync(info->dev); fimg2d_debug("pm_runtime_put_sync\n"); #endif fimg2d_debug("exit blitter\n"); }