[PATCH OLK-5.10 0/4] Backport kunpeng920G to OLK-5.10
Cong Wang (1): iommu: avoid taking iova_rbtree_lock twice Xiang Chen (3): iommu/arm-smmu-v3: Add a check to avoid invalid iotlb sync dma-mapping: benchmark: Add support for multi-pages map/unmap iommu/iova: Put free_iova_mem() outside of spinlock iova_rbtree_lock drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 +++ drivers/iommu/iova.c | 24 ++++++++++++------- kernel/dma/map_benchmark.c | 21 ++++++++++------ .../testing/selftests/dma/dma_map_benchmark.c | 20 ++++++++++++---- 4 files changed, 49 insertions(+), 19 deletions(-) -- 2.34.1
From: Xiang Chen <chenxiang66@hisilicon.com> mainline inclusion from mainline-v5.13-rc1 commit 6cc7e5a9c6b02507b9be5a99b51e970afa91c85f category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ID5X4C Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... ---------------------------------------- It may send a invalid tlb sync for smmuv3 if iotlb_gather is not valid (iotlb_gather->pgsize = 0). So add a check to avoid invalid iotlb sync for it. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Link: https://lore.kernel.org/r/1617109106-121844-1-git-send-email-chenxiang66@his... Signed-off-by: Will Deacon <will@kernel.org> Conflicts: drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c [fix context conflicts] Signed-off-by: Lin Yujun <linyujun809@h-partners.com> --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 12b418ed65be..e67c1feeca5f 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -2958,10 +2958,13 @@ static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) static void arm_smmu_iotlb_sync(struct iommu_domain *domain, struct iommu_iotlb_gather *gather) { struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); + if (!gather->pgsize) + return; + arm_smmu_tlb_inv_range_domain(gather->start, gather->end - gather->start + 1, gather->pgsize, true, smmu_domain); } #ifdef CONFIG_HISILICON_ERRATUM_162100602 -- 2.34.1
From: Xiang Chen <chenxiang66@hisilicon.com> mainline inclusion from mainline-v5.13-rc1 commit ca947482b0b30443e6da1f0f5ba7244e34a4f65a category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ID5X4C Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... ---------------------------------------- Currently it only support one page map/unmap once a time for dma-map benchmark, but there are some other scenaries which need to support for multi-page map/unmap: for those multi-pages interfaces such as dma_alloc_coherent() and dma_map_sg(), the time spent on multi-pages map/unmap is not the time of a single page * npages (not linear) as it may use block description instead of page description when it is satified with the size such as 2M/1G, and also it can send a single TLB invalidation command to invalidate multi-pages instead of multi-times when RIL is enabled (which will short the time of unmap). So it is necessary to add support for multi-pages map/unmap. Add a parameter "-g" to support multi-pages map/unmap. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Acked-by: Barry Song <song.bao.hua@hisilicon.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Conflicts: kernel/dma/map_benchmark.c [fix context conflicts] Signed-off-by: Lin Yujun <linyujun809@h-partners.com> --- kernel/dma/map_benchmark.c | 21 ++++++++++++------- .../testing/selftests/dma/dma_map_benchmark.c | 20 ++++++++++++++---- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/kernel/dma/map_benchmark.c b/kernel/dma/map_benchmark.c index 5c13c9352bb5..a0e86a73daeb 100644 --- a/kernel/dma/map_benchmark.c +++ b/kernel/dma/map_benchmark.c @@ -36,11 +36,12 @@ struct map_benchmark { __u32 seconds; /* how long the test will last */ __s32 node; /* which numa node this benchmark will run on */ __u32 dma_bits; /* DMA addressing capability */ __u32 dma_dir; /* DMA data direction */ __u32 dma_trans_ns; /* time for DMA transmission in ns */ - __u8 expansion[80]; /* For future use */ + __u32 granule; /* how many PAGE_SIZE will do map/unmap once a time */ + __u8 expansion[76]; /* For future use */ }; struct map_benchmark_data { struct map_benchmark bparam; struct device *dev; @@ -56,13 +57,15 @@ struct map_benchmark_data { static int map_benchmark_thread(void *data) { void *buf; dma_addr_t dma_addr; struct map_benchmark_data *map = data; + int npages = map->bparam.granule; + u64 size = npages * PAGE_SIZE; int ret = 0; - buf = (void *)__get_free_page(GFP_KERNEL); + buf = alloc_pages_exact(size, GFP_KERNEL); if (!buf) return -ENOMEM; while (!kthread_should_stop()) { u64 map_100ns, unmap_100ns, map_sq, unmap_sq; @@ -74,14 +77,14 @@ static int map_benchmark_thread(void *data) * cache, this will give an underestimate of the real-world * overhead of BIDIRECTIONAL or TO_DEVICE mappings; * 66 means evertything goes well! 66 is lucky. */ if (map->dir != DMA_FROM_DEVICE) - memset(buf, 0x66, PAGE_SIZE); + memset(buf, 0x66, size); map_stime = ktime_get(); - dma_addr = dma_map_single(map->dev, buf, PAGE_SIZE, map->dir); + dma_addr = dma_map_single(map->dev, buf, size, map->dir); if (unlikely(dma_mapping_error(map->dev, dma_addr))) { pr_err("dma_map_single failed on %s\n", dev_name(map->dev)); ret = -ENOMEM; goto out; @@ -91,11 +94,11 @@ static int map_benchmark_thread(void *data) /* Pretend DMA is transmitting */ ndelay(map->bparam.dma_trans_ns); unmap_stime = ktime_get(); - dma_unmap_single(map->dev, dma_addr, PAGE_SIZE, map->dir); + dma_unmap_single(map->dev, dma_addr, size, map->dir); unmap_etime = ktime_get(); unmap_delta = ktime_sub(unmap_etime, unmap_stime); /* calculate sum and sum of squares */ @@ -110,11 +113,11 @@ static int map_benchmark_thread(void *data) atomic64_add(unmap_sq, &map->sum_sq_unmap); atomic64_inc(&map->loops); } out: - free_page((unsigned long)buf); + free_pages_exact(buf, size); return ret; } static int do_map_benchmark(struct map_benchmark_data *map) { @@ -200,11 +203,10 @@ static long map_benchmark_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct map_benchmark_data *map = file->private_data; void __user *argp = (void __user *)arg; u64 old_dma_mask; - int ret; if (copy_from_user(&map->bparam, argp, sizeof(map->bparam))) return -EFAULT; @@ -232,10 +234,15 @@ static long map_benchmark_ioctl(struct file *file, unsigned int cmd, !node_possible(map->bparam.node))) { pr_err("invalid numa node\n"); return -EINVAL; } + if (map->bparam.granule < 1 || map->bparam.granule > 1024) { + pr_err("invalid granule size\n"); + return -EINVAL; + } + switch (map->bparam.dma_dir) { case DMA_MAP_BIDIRECTIONAL: map->dir = DMA_BIDIRECTIONAL; break; case DMA_MAP_FROM_DEVICE: diff --git a/tools/testing/selftests/dma/dma_map_benchmark.c b/tools/testing/selftests/dma/dma_map_benchmark.c index fb23ce9617ea..6f2caa6c50f7 100644 --- a/tools/testing/selftests/dma/dma_map_benchmark.c +++ b/tools/testing/selftests/dma/dma_map_benchmark.c @@ -38,26 +38,29 @@ struct map_benchmark { __u32 seconds; /* how long the test will last */ __s32 node; /* which numa node this benchmark will run on */ __u32 dma_bits; /* DMA addressing capability */ __u32 dma_dir; /* DMA data direction */ __u32 dma_trans_ns; /* time for DMA transmission in ns */ - __u8 expansion[80]; /* For future use */ + __u32 granule; /* how many PAGE_SIZE will do map/unmap once a time */ + __u8 expansion[76]; /* For future use */ }; int main(int argc, char **argv) { struct map_benchmark map; int fd, opt; /* default single thread, run 20 seconds on NUMA_NO_NODE */ int threads = 1, seconds = 20, node = -1; /* default dma mask 32bit, bidirectional DMA */ int bits = 32, xdelay = 0, dir = DMA_MAP_BIDIRECTIONAL; + /* default granule 1 PAGESIZE */ + int granule = 1; int cmd = DMA_MAP_BENCHMARK; char *p; - while ((opt = getopt(argc, argv, "t:s:n:b:d:x:")) != -1) { + while ((opt = getopt(argc, argv, "t:s:n:b:d:x:g:")) != -1) { switch (opt) { case 't': threads = atoi(optarg); break; case 's': @@ -73,10 +76,13 @@ int main(int argc, char **argv) dir = atoi(optarg); break; case 'x': xdelay = atoi(optarg); break; + case 'g': + granule = atoi(optarg); + break; default: return -1; } } @@ -108,10 +114,15 @@ int main(int argc, char **argv) dir != DMA_MAP_FROM_DEVICE) { fprintf(stderr, "invalid dma direction\n"); exit(1); } + if (granule < 1 || granule > 1024) { + fprintf(stderr, "invalid granule size\n"); + exit(1); + } + fd = open("/sys/kernel/debug/dma_map_benchmark", O_RDWR); if (fd == -1) { perror("open"); exit(1); } @@ -121,18 +132,19 @@ int main(int argc, char **argv) map.threads = threads; map.node = node; map.dma_bits = bits; map.dma_dir = dir; map.dma_trans_ns = xdelay; + map.granule = granule; if (ioctl(fd, cmd, &map)) { perror("ioctl"); exit(1); } - printf("dma mapping benchmark: threads:%d seconds:%d node:%d dir:%s\n", - threads, seconds, node, dir[directions]); + printf("dma mapping benchmark: threads:%d seconds:%d node:%d dir:%s granule: %d\n", + threads, seconds, node, dir[directions], granule); printf("average map latency(us):%.1f standard deviation:%.1f\n", map.avg_map_100ns/10.0, map.map_stddev/10.0); printf("average unmap latency(us):%.1f standard deviation:%.1f\n", map.avg_unmap_100ns/10.0, map.unmap_stddev/10.0); -- 2.34.1
From: Cong Wang <xiyou.wangcong@gmail.com> mainline inclusion from mainline-v5.11-rc1 commit 3a651b3a27a1ee35879499ead3942dc854a20968 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ID5X4C Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... ---------------------------------------- Both find_iova() and __free_iova() take iova_rbtree_lock, there is no reason to take and release it twice inside free_iova(). Fold them into one critical section by calling the unlock versions instead. Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: John Garry <john.garry@huawei.com> Link: https://lore.kernel.org/r/1605608734-84416-5-git-send-email-john.garry@huawe... Signed-off-by: Will Deacon <will@kernel.org> Signed-off-by: Lin Yujun <linyujun809@h-partners.com> --- drivers/iommu/iova.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index 99d5e942aff6..7e4a5cfe49ae 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -410,14 +410,18 @@ EXPORT_SYMBOL_GPL(__free_iova); * frees the iova from that domain. */ void free_iova(struct iova_domain *iovad, unsigned long pfn) { - struct iova *iova = find_iova(iovad, pfn); + unsigned long flags; + struct iova *iova; + spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); + iova = private_find_iova(iovad, pfn); if (iova) - __free_iova(iovad, iova); + private_free_iova(iovad, iova); + spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); } EXPORT_SYMBOL_GPL(free_iova); /** -- 2.34.1
From: Xiang Chen <chenxiang66@hisilicon.com> mainline inclusion from mainline-v5.14-rc1 commit 7978724f399ae7eba5b6d36ae5a7224d5bf3859a category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ID5X4C Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... ---------------------------------------- It is not necessary to put free_iova_mem() inside of spinlock/unlock iova_rbtree_lock which only leads to more completion for the spinlock. It has a small promote on the performance after the change. And also rename private_free_iova() as remove_iova() because the function will not free iova after that change. Signed-off-by: Xiang Chen <chenxiang66@hisilicon.com> Reviewed-by: John Garry <john.garry@huawei.com> Acked-by: Robin Murphy <robin.murphy@arm.com> Link: https://lore.kernel.org/r/1620647582-194621-1-git-send-email-chenxiang66@his... Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Lin Yujun <linyujun809@h-partners.com> --- drivers/iommu/iova.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index 7e4a5cfe49ae..5e4d536c01a6 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -355,16 +355,15 @@ private_find_iova(struct iova_domain *iovad, unsigned long pfn) } return NULL; } -static void private_free_iova(struct iova_domain *iovad, struct iova *iova) +static void remove_iova(struct iova_domain *iovad, struct iova *iova) { assert_spin_locked(&iovad->iova_rbtree_lock); __cached_rbnode_delete_update(iovad, iova); rb_erase(&iova->node, &iovad->rbroot); - free_iova_mem(iova); } /** * find_iova - finds an iova for a given pfn * @iovad: - iova domain in question. @@ -395,12 +394,13 @@ void __free_iova(struct iova_domain *iovad, struct iova *iova) { unsigned long flags; spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); - private_free_iova(iovad, iova); + remove_iova(iovad, iova); spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); + free_iova_mem(iova); } EXPORT_SYMBOL_GPL(__free_iova); /** * free_iova - finds and frees the iova for a given pfn @@ -415,14 +415,17 @@ free_iova(struct iova_domain *iovad, unsigned long pfn) unsigned long flags; struct iova *iova; spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); iova = private_find_iova(iovad, pfn); - if (iova) - private_free_iova(iovad, iova); + if (!iova) { + spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); + return; + } + remove_iova(iovad, iova); spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); - + free_iova_mem(iova); } EXPORT_SYMBOL_GPL(free_iova); /** * alloc_iova_fast - allocates an iova from rcache @@ -856,11 +859,12 @@ iova_magazine_free_pfns(struct iova_magazine *mag, struct iova_domain *iovad) struct iova *iova = private_find_iova(iovad, mag->pfns[i]); if (WARN_ON(!iova)) continue; - private_free_iova(iovad, iova); + remove_iova(iovad, iova); + free_iova_mem(iova); } spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); mag->size = 0; -- 2.34.1
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/18951 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/AB2... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/18951 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/AB2...
participants (2)
-
Lin Yujun -
patchwork bot