> On Jun 1, 2021, at 10:27 AM, Robin Murphy <robin.mur...@arm.com> wrote: > > On 2021-06-01 17:39, Nadav Amit wrote: >>> On Jun 1, 2021, at 8:59 AM, Robin Murphy <robin.mur...@arm.com> wrote: >>> >>> On 2021-05-02 07:59, Nadav Amit wrote: >>>> From: Nadav Amit <na...@vmware.com> >>>> Some IOMMU architectures perform invalidations regardless of the page >>>> size. In such architectures there is no need to sync when the page size >>>> changes or to regard pgsize when making interim flush in >>>> iommu_iotlb_gather_add_page(). >>>> Add a "ignore_gather_pgsize" property for each IOMMU-ops to decide >>>> whether gather's pgsize is tracked and triggers a flush. >>> >>> I've objected before[1], and I'll readily object again ;) >>> >>> I still think it's very silly to add a bunch of indirection all over the >>> place to make a helper function not do the main thing it's intended to help >>> with. If you only need trivial address gathering then it's far simpler to >>> just implement trivial address gathering. I suppose if you really want to >>> you could factor out another helper to share the 5 lines of code which >>> ended up in mtk-iommu (see commit f21ae3b10084). >> Thanks, Robin. >> I read your comments but I cannot fully understand the alternative that you >> propose, although I do understand your objection to the indirection >> “ignore_gather_pgsize”. Would it be ok if “ignore_gather_pgsize" was >> provided as an argument for iommu_iotlb_gather_add_page()? > > No, I mean if iommu_iotlb_gather_add_page() doesn't have the behaviour your > driver wants, just don't call it. Write or factor out a suitable helper that > *does* do what you want and call that, or just implement the logic directly > inline. Indirect argument or not, it just doesn't make much sense to have a > helper function call which says "do this except don't do most of it". > >> In general, I can live without this patch. It probably would have negligent >> impact on performance anyhow. > > As I implied, it sounds like your needs are the same as the Mediatek driver > had, so you could readily factor out a new page-size-agnostic gather helper > from that. I fully support making the functional change to amd-iommu > *somehow* - nobody likes unnecessary syncs - just not with this particular > implementation :)
Hm… avoid code duplication I need to extract some common code to another function. Is the following resembles what you had in mind (untested)? -- >8 -- Subject: [PATCH] iommu: add iommu_iotlb_gather_add_page_ignore_pgsize() --- drivers/iommu/mtk_iommu.c | 7 ++--- include/linux/iommu.h | 55 ++++++++++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index e168a682806a..5890e745bed3 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -520,12 +520,9 @@ static size_t mtk_iommu_unmap(struct iommu_domain *domain, struct iommu_iotlb_gather *gather) { struct mtk_iommu_domain *dom = to_mtk_domain(domain); - unsigned long end = iova + size - 1; - if (gather->start > iova) - gather->start = iova; - if (gather->end < end) - gather->end = end; + iommu_iotlb_gather_update_range(gather, iova, size); + return dom->iop->unmap(dom->iop, iova, size, gather); } diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 9ca6e6b8084d..037434b6eb4c 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -535,29 +535,58 @@ static inline void iommu_iotlb_sync(struct iommu_domain *domain, iommu_iotlb_gather_init(iotlb_gather); } -static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain, +static inline +void iommu_iotlb_gather_update_range(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t size) +{ + unsigned long start = iova, end = start + size - 1; + + if (gather->end < end) + gather->end = end; + + if (gather->start > start) + gather->start = start; + + gather->pgsize = size; +} + +static inline +bool iommu_iotlb_gather_is_disjoint(struct iommu_iotlb_gather *gather, + unsigned long iova, size_t size) +{ + return iova + size < gather->start || iova > gather->end + 1; +} + +static inline +void iommu_iotlb_gather_add_page_ignore_pgsize(struct iommu_domain *domain, struct iommu_iotlb_gather *gather, unsigned long iova, size_t size) { - unsigned long start = iova, end = start + size - 1; + /* + * Only if the new page is disjoint from the current range, then sync + * the TLB so that the gather structure can be rewritten. + */ + if (iommu_iotlb_gather_is_disjoint(gather, iova, size) && gather->pgsize) + iommu_iotlb_sync(domain, gather); + + iommu_iotlb_gather_update_range(gather, iova, size); +} +static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain, + struct iommu_iotlb_gather *gather, + unsigned long iova, size_t size) +{ /* * If the new page is disjoint from the current range or is mapped at * a different granularity, then sync the TLB so that the gather * structure can be rewritten. */ - if (gather->pgsize != size || - end + 1 < gather->start || start > gather->end + 1) { - if (gather->pgsize) - iommu_iotlb_sync(domain, gather); - gather->pgsize = size; - } - - if (gather->end < end) - gather->end = end; + if ((gather->pgsize != size || + iommu_iotlb_gather_is_disjoint(gather, iova, size)) && + gather->pgsize) + iommu_iotlb_sync(domain, gather); - if (gather->start > start) - gather->start = start; + iommu_iotlb_gather_update_range(gather, iova, size); } /* PCI device grouping function */ -- 2.25.1
signature.asc
Description: Message signed with OpenPGP
_______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu