From 91db0733d7cf2c83053c5eef8403a2ea8bcfca32 Mon Sep 17 00:00:00 2001 From: Simon Xue Date: Tue, 25 Feb 2020 14:25:03 +0800 Subject: [PATCH] drm/rockchip: gem: add IOMMU_TLB_SHOT_ENTIRE when call iommu_map_sg Add IOMMU_TLB_SHOT_ENTIRE prot for iommu_map_sg, this shoot down entire iommu tlb one time after iommu_map_sg.This may save about 5ms when DRM mapping 12MB buffer. Change-Id: I618aff1b3928bd1ec1dd3d896db746e09e96acdc Signed-off-by: Simon Xue --- drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 4 ++++ drivers/iommu/iommu.c | 6 ++++++ drivers/iommu/rockchip-iommu.c | 12 ++++++++++++ include/linux/iommu.h | 7 +++++++ 4 files changed, 29 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index 73dadeb608b3..52e2c681faab 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -30,6 +30,10 @@ static int rockchip_gem_iommu_map(struct rockchip_gem_object *rk_obj) int prot = IOMMU_READ | IOMMU_WRITE; ssize_t ret; +#ifdef IOMMU_TLB_SHOT_ENTIRE + prot |= IOMMU_TLB_SHOT_ENTIRE; +#endif + mutex_lock(&private->mm_lock); ret = drm_mm_insert_node_generic(&private->mm, &rk_obj->mm, rk_obj->base.size, PAGE_SIZE, diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 4e0c8a9f8600..c8df6c10d2ff 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2636,6 +2636,12 @@ static size_t __iommu_map_sg(struct iommu_domain *domain, unsigned long iova, if (ops->iotlb_sync_map) ops->iotlb_sync_map(domain, iova, mapped); + +#ifdef IOMMU_TLB_SHOT_ENTIRE + if (domain->ops->flush_iotlb_all && (prot & IOMMU_TLB_SHOT_ENTIRE)) + domain->ops->flush_iotlb_all(domain); +#endif + return mapped; out_err: diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index d55e1e0fb6c8..a9c3f81f1229 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -993,7 +993,13 @@ 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. */ +#ifdef IOMMU_TLB_SHOT_ENTIRE + /* 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); +#else rk_iommu_zap_iova_first_last(rk_domain, iova, size); +#endif return 0; unwind: @@ -1038,7 +1044,13 @@ static int rk_iommu_map_iova_v2(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. */ +#ifdef IOMMU_TLB_SHOT_ENTIRE + /* 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); +#else rk_iommu_zap_iova_first_last(rk_domain, iova, size); +#endif return 0; unwind: diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 494609936795..8f83762c4ec4 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -45,6 +45,13 @@ */ #define IOMMU_SYS_CACHE_ONLY_NWA (1 << 7) +#ifdef CONFIG_NO_GKI + +/* For shoting entire IOMMU tlb once */ +#define IOMMU_TLB_SHOT_ENTIRE (1 << 8) + +#endif + struct iommu_ops; struct iommu_group; struct bus_type;