diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index 622ac6ae4d4c..dbd08eb94fd6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -37,7 +37,7 @@ static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj) { struct drm_device *drm = rk_obj->base.dev; struct rockchip_drm_private *private = drm->dev_private; - int prot = IOMMU_READ | IOMMU_WRITE; + int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_TLB_SHOT_ENTIRE; ssize_t ret; mutex_lock(&private->mm_lock); diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 3dd56f149178..88cad7db1bf2 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1717,6 +1717,9 @@ size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova, mapped += s->length; } + if (domain->ops->flush_iotlb_all && (prot & IOMMU_TLB_SHOT_ENTIRE)) + domain->ops->flush_iotlb_all(domain); + return mapped; out_err: diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index 2747dffe69c9..d5e52aabb8b0 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -771,7 +771,10 @@ static int rk_iommu_map_iova(struct rk_iommu_domain *rk_domain, u32 *pte_addr, * We only zap the first and last iova, since only they could have * dte or pte shared with an existing mapping. */ - rk_iommu_zap_iova_first_last(rk_domain, iova, size); + + /* Do not zap tlb cache line if IOMMU_TLB_SHOT_ENTIRE set */ + if (!(prot & IOMMU_TLB_SHOT_ENTIRE)) + rk_iommu_zap_iova_first_last(rk_domain, iova, size); return 0; unwind: diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 87994c265bf5..f76d47368d78 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -42,6 +42,9 @@ */ #define IOMMU_PRIV (1 << 5) +/* For shoting entire IOMMU tlb once */ +#define IOMMU_TLB_SHOT_ENTIRE (1 << 6) + struct iommu_ops; struct iommu_group; struct bus_type;