Skip to content

Commit febb82c

Browse files
anadavjoergroedel
authored andcommitted
iommu: Factor iommu_iotlb_gather_is_disjoint() out
Refactor iommu_iotlb_gather_add_page() and factor out the logic that detects whether IOTLB gather range and a new range are disjoint. To be used by the next patch that implements different gathering logic for AMD. Note that updating gather->pgsize unconditionally does not affect correctness as the function had (and has) an invariant, in which gather->pgsize always represents the flushing granularity of its range. Arguably, “size" should never be zero, but lets assume for the matter of discussion that it might. If "size" equals to "gather->pgsize", then the assignment in question has no impact. Otherwise, if "size" is non-zero, then iommu_iotlb_sync() would initialize the size and range (see iommu_iotlb_gather_init()), and the invariant is kept. Otherwise, "size" is zero, and "gather" already holds a range, so gather->pgsize is non-zero and (gather->pgsize && gather->pgsize != size) is true. Therefore, again, iommu_iotlb_sync() would be called and initialize the size. Cc: Joerg Roedel <[email protected]> Cc: Jiajun Cao <[email protected]> Cc: Lu Baolu <[email protected]> Cc: [email protected] Cc: [email protected]> Reviewed-by: Robin Murphy <[email protected]> Acked-by: Will Deacon <[email protected]> Signed-off-by: Nadav Amit <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 3136895 commit febb82c

File tree

1 file changed

+26
-8
lines changed

1 file changed

+26
-8
lines changed

include/linux/iommu.h

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,28 @@ static inline void iommu_iotlb_sync(struct iommu_domain *domain,
497497
iommu_iotlb_gather_init(iotlb_gather);
498498
}
499499

500+
/**
501+
* iommu_iotlb_gather_is_disjoint - Checks whether a new range is disjoint
502+
*
503+
* @gather: TLB gather data
504+
* @iova: start of page to invalidate
505+
* @size: size of page to invalidate
506+
*
507+
* Helper for IOMMU drivers to check whether a new range and the gathered range
508+
* are disjoint. For many IOMMUs, flushing the IOMMU in this case is better
509+
* than merging the two, which might lead to unnecessary invalidations.
510+
*/
511+
static inline
512+
bool iommu_iotlb_gather_is_disjoint(struct iommu_iotlb_gather *gather,
513+
unsigned long iova, size_t size)
514+
{
515+
unsigned long start = iova, end = start + size - 1;
516+
517+
return gather->end != 0 &&
518+
(end + 1 < gather->start || start > gather->end + 1);
519+
}
520+
521+
500522
/**
501523
* iommu_iotlb_gather_add_range - Gather for address-based TLB invalidation
502524
* @gather: TLB gather data
@@ -533,20 +555,16 @@ static inline void iommu_iotlb_gather_add_page(struct iommu_domain *domain,
533555
struct iommu_iotlb_gather *gather,
534556
unsigned long iova, size_t size)
535557
{
536-
unsigned long start = iova, end = start + size - 1;
537-
538558
/*
539559
* If the new page is disjoint from the current range or is mapped at
540560
* a different granularity, then sync the TLB so that the gather
541561
* structure can be rewritten.
542562
*/
543-
if (gather->pgsize != size ||
544-
end + 1 < gather->start || start > gather->end + 1) {
545-
if (gather->pgsize)
546-
iommu_iotlb_sync(domain, gather);
547-
gather->pgsize = size;
548-
}
563+
if ((gather->pgsize && gather->pgsize != size) ||
564+
iommu_iotlb_gather_is_disjoint(gather, iova, size))
565+
iommu_iotlb_sync(domain, gather);
549566

567+
gather->pgsize = size;
550568
iommu_iotlb_gather_add_range(gather, iova, size);
551569
}
552570

0 commit comments

Comments
 (0)