static int fimg2d_check_dma_sync(struct fimg2d_bltcmd *cmd) { struct mm_struct *mm = cmd->ctx->mm; fimg2d_calc_dma_size(cmd); if (fimg2d_check_address(cmd)) return -EINVAL; if (fimg2d_check_pgd(mm, cmd)) return -EFAULT; #ifndef CCI_SNOOP fimg2d_debug("cache flush\n"); perf_start(cmd, PERF_CACHE); if (is_inner_flushall(cmd->dma_all)) { inner_touch_range(cmd); flush_all_cpu_caches(); } else { inner_flush_clip_range(cmd); } #ifdef CONFIG_OUTER_CACHE if (is_outer_flushall(cmd->dma_all)) outer_flush_all(); else outer_flush_clip_range(cmd); #endif perf_end(cmd, PERF_CACHE); #endif return 0; }
int fimg2d4x_bitblt(struct fimg2d_control *ctrl) { int ret = 0; enum addr_space addr_type; struct fimg2d_context *ctx; struct fimg2d_bltcmd *cmd; unsigned long *pgd; fimg2d_debug("%s : enter blitter\n", __func__); while (1) { cmd = fimg2d_get_command(ctrl); if (!cmd) break; ctx = cmd->ctx; ctx->state = CTX_READY; #ifdef CONFIG_PM_RUNTIME if (fimg2d4x_get_clk_cnt(ctrl->clock) == false) fimg2d_err("2D clock is not set\n"); #endif atomic_set(&ctrl->busy, 1); perf_start(cmd, PERF_SFR); ret = ctrl->configure(ctrl, cmd); perf_end(cmd, PERF_SFR); if (IS_ERR_VALUE(ret)) { fimg2d_err("failed to configure\n"); ctx->state = CTX_ERROR; goto fail_n_del; } addr_type = cmd->image[IDST].addr.type; ctx->vma_lock = vma_lock_mapping(ctx->mm, prefbuf, MAX_IMAGES - 1); if (fimg2d_check_pgd(ctx->mm, cmd)) { ret = -EFAULT; goto fail_n_del; } if (addr_type == ADDR_USER || addr_type == ADDR_USER_CONTIG) { if (!ctx->mm || !ctx->mm->pgd) { atomic_set(&ctrl->busy, 0); fimg2d_err("ctx->mm:0x%p or ctx->mm->pgd:0x%p\n", ctx->mm, (ctx->mm) ? ctx->mm->pgd : NULL); ret = -EPERM; goto fail_n_del; } pgd = (unsigned long *)ctx->mm->pgd; #ifdef CONFIG_EXYNOS7_IOMMU if (iovmm_activate(ctrl->dev)) { fimg2d_err("failed to iovmm activate\n"); ret = -EPERM; goto fail_n_del; } #else if (exynos_sysmmu_enable(ctrl->dev, (unsigned long)virt_to_phys(pgd))) { fimg2d_err("failed to sysmme enable\n"); ret = -EPERM; goto fail_n_del; } #endif fimg2d_debug("%s : sysmmu enable: pgd %p ctx %p seq_no(%u)\n", __func__, pgd, ctx, cmd->blt.seq_no); //exynos_sysmmu_set_pbuf(ctrl->dev, nbufs, prefbuf); fimg2d_debug("%s : set smmu prefbuf\n", __func__); } fimg2d4x_pre_bitblt(ctrl, cmd); perf_start(cmd, PERF_BLIT); /* start blit */ fimg2d_debug("%s : start blit\n", __func__); ctrl->run(ctrl); ret = fimg2d4x_blit_wait(ctrl, cmd); perf_end(cmd, PERF_BLIT); perf_start(cmd, PERF_UNMAP); if (addr_type == ADDR_USER || addr_type == ADDR_USER_CONTIG) { #ifdef CONFIG_EXYNOS7_IOMMU iovmm_deactivate(ctrl->dev); if (cmd->dma[ISRC].base.size > 0) { exynos_sysmmu_unmap_user_pages(ctrl->dev, ctx->mm, cmd->dma[ISRC].base.addr, cmd->dma[ISRC].base.size); } if (cmd->dma[ISRC].plane2.size > 0) { exynos_sysmmu_unmap_user_pages(ctrl->dev, ctx->mm, cmd->dma[ISRC].plane2.addr, cmd->dma[ISRC].plane2.size); } if (cmd->dma[IMSK].base.size > 0) { exynos_sysmmu_unmap_user_pages(ctrl->dev, ctx->mm, cmd->dma[IMSK].base.addr, cmd->dma[IMSK].base.size); } if (cmd->dma[IDST].base.size > 0) { exynos_sysmmu_unmap_user_pages(ctrl->dev, ctx->mm, cmd->dma[IDST].base.addr, cmd->dma[IDST].base.size); } if (cmd->dma[IDST].plane2.size > 0) { exynos_sysmmu_unmap_user_pages(ctrl->dev, ctx->mm, cmd->dma[IDST].plane2.addr, cmd->dma[IDST].plane2.size); } #else exynos_sysmmu_disable(ctrl->dev); #endif fimg2d_debug("sysmmu disable\n"); } perf_end(cmd, PERF_UNMAP); fail_n_del: vma_unlock_mapping(ctx->vma_lock); fimg2d_del_command(ctrl, cmd); } fimg2d_debug("%s : exit blitter\n", __func__); return ret; }