xref: /linux-6.15/include/linux/iova.h (revision 2650073f)
155716d26SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
238717946SKay, Allen M /*
338717946SKay, Allen M  * Copyright (c) 2006, Intel Corporation.
438717946SKay, Allen M  *
538717946SKay, Allen M  * Copyright (C) 2006-2008 Intel Corporation
638717946SKay, Allen M  * Author: Anil S Keshavamurthy <[email protected]>
738717946SKay, Allen M  */
838717946SKay, Allen M 
938717946SKay, Allen M #ifndef _IOVA_H_
1038717946SKay, Allen M #define _IOVA_H_
1138717946SKay, Allen M 
1238717946SKay, Allen M #include <linux/types.h>
1338717946SKay, Allen M #include <linux/kernel.h>
1438717946SKay, Allen M #include <linux/rbtree.h>
15aade40b6SJoerg Roedel #include <linux/dma-mapping.h>
1638717946SKay, Allen M 
1738717946SKay, Allen M /* iova structure */
1838717946SKay, Allen M struct iova {
1938717946SKay, Allen M 	struct rb_node	node;
209257b4a2SOmer Peleg 	unsigned long	pfn_hi; /* Highest allocated pfn */
219257b4a2SOmer Peleg 	unsigned long	pfn_lo; /* Lowest allocated pfn */
229257b4a2SOmer Peleg };
239257b4a2SOmer Peleg 
249257b4a2SOmer Peleg 
2532e92d9fSJohn Garry struct iova_rcache;
2638717946SKay, Allen M 
2738717946SKay, Allen M /* holds all the iova translations for a domain */
2838717946SKay, Allen M struct iova_domain {
2938717946SKay, Allen M 	spinlock_t	iova_rbtree_lock; /* Lock to protect update of rbtree */
3038717946SKay, Allen M 	struct rb_root	rbroot;		/* iova domain rbtree root */
31e60aa7b5SRobin Murphy 	struct rb_node	*cached_node;	/* Save last alloced node */
32e60aa7b5SRobin Murphy 	struct rb_node	*cached32_node; /* Save last 32-bit alloced node */
330fb5fe87SRobin Murphy 	unsigned long	granule;	/* pfn granularity for this domain */
341b722500SRobin Murphy 	unsigned long	start_pfn;	/* Lower limit for this domain */
3538717946SKay, Allen M 	unsigned long	dma_32bit_pfn;
36bee60e94SGanapatrao Kulkarni 	unsigned long	max32_alloc_size; /* Size of last failed allocation */
37bb68b2fbSRobin Murphy 	struct iova	anchor;		/* rbtree lookup anchor */
38a17e3026SRobin Murphy 
3932e92d9fSJohn Garry 	struct iova_rcache	*rcaches;
40f598a497SJohn Garry 	struct hlist_node	cpuhp_dead;
4138717946SKay, Allen M };
4238717946SKay, Allen M 
iova_size(struct iova * iova)43a156ef99SJiang Liu static inline unsigned long iova_size(struct iova *iova)
44a156ef99SJiang Liu {
45a156ef99SJiang Liu 	return iova->pfn_hi - iova->pfn_lo + 1;
46a156ef99SJiang Liu }
47a156ef99SJiang Liu 
iova_shift(struct iova_domain * iovad)480fb5fe87SRobin Murphy static inline unsigned long iova_shift(struct iova_domain *iovad)
490fb5fe87SRobin Murphy {
500fb5fe87SRobin Murphy 	return __ffs(iovad->granule);
510fb5fe87SRobin Murphy }
520fb5fe87SRobin Murphy 
iova_mask(struct iova_domain * iovad)530fb5fe87SRobin Murphy static inline unsigned long iova_mask(struct iova_domain *iovad)
540fb5fe87SRobin Murphy {
550fb5fe87SRobin Murphy 	return iovad->granule - 1;
560fb5fe87SRobin Murphy }
570fb5fe87SRobin Murphy 
iova_offset(struct iova_domain * iovad,dma_addr_t iova)580fb5fe87SRobin Murphy static inline size_t iova_offset(struct iova_domain *iovad, dma_addr_t iova)
590fb5fe87SRobin Murphy {
600fb5fe87SRobin Murphy 	return iova & iova_mask(iovad);
610fb5fe87SRobin Murphy }
620fb5fe87SRobin Murphy 
iova_align(struct iova_domain * iovad,size_t size)630fb5fe87SRobin Murphy static inline size_t iova_align(struct iova_domain *iovad, size_t size)
640fb5fe87SRobin Murphy {
650fb5fe87SRobin Murphy 	return ALIGN(size, iovad->granule);
660fb5fe87SRobin Murphy }
670fb5fe87SRobin Murphy 
iova_align_down(struct iova_domain * iovad,size_t size)68*2650073fSMichael Kelley static inline size_t iova_align_down(struct iova_domain *iovad, size_t size)
69*2650073fSMichael Kelley {
70*2650073fSMichael Kelley 	return ALIGN_DOWN(size, iovad->granule);
71*2650073fSMichael Kelley }
72*2650073fSMichael Kelley 
iova_dma_addr(struct iova_domain * iovad,struct iova * iova)730fb5fe87SRobin Murphy static inline dma_addr_t iova_dma_addr(struct iova_domain *iovad, struct iova *iova)
740fb5fe87SRobin Murphy {
750fb5fe87SRobin Murphy 	return (dma_addr_t)iova->pfn_lo << iova_shift(iovad);
760fb5fe87SRobin Murphy }
770fb5fe87SRobin Murphy 
iova_pfn(struct iova_domain * iovad,dma_addr_t iova)780fb5fe87SRobin Murphy static inline unsigned long iova_pfn(struct iova_domain *iovad, dma_addr_t iova)
790fb5fe87SRobin Murphy {
800fb5fe87SRobin Murphy 	return iova >> iova_shift(iovad);
810fb5fe87SRobin Murphy }
820fb5fe87SRobin Murphy 
834f58330fSRobin Murphy #if IS_REACHABLE(CONFIG_IOMMU_IOVA)
84ae1ff3d6SSakari Ailus int iova_cache_get(void);
85ae1ff3d6SSakari Ailus void iova_cache_put(void);
8685b45456SRobin Murphy 
876d9870b7SJohn Garry unsigned long iova_rcache_range(void);
886d9870b7SJohn Garry 
8938717946SKay, Allen M void free_iova(struct iova_domain *iovad, unsigned long pfn);
9038717946SKay, Allen M void __free_iova(struct iova_domain *iovad, struct iova *iova);
9138717946SKay, Allen M struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
9238717946SKay, Allen M 	unsigned long limit_pfn,
9338717946SKay, Allen M 	bool size_aligned);
949257b4a2SOmer Peleg void free_iova_fast(struct iova_domain *iovad, unsigned long pfn,
959257b4a2SOmer Peleg 		    unsigned long size);
969257b4a2SOmer Peleg unsigned long alloc_iova_fast(struct iova_domain *iovad, unsigned long size,
97538d5b33STomasz Nowicki 			      unsigned long limit_pfn, bool flush_rcache);
9838717946SKay, Allen M struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
9938717946SKay, Allen M 	unsigned long pfn_hi);
1000fb5fe87SRobin Murphy void init_iova_domain(struct iova_domain *iovad, unsigned long granule,
101aa3ac946SZhen Lei 	unsigned long start_pfn);
10232e92d9fSJohn Garry int iova_domain_init_rcaches(struct iova_domain *iovad);
10338717946SKay, Allen M struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
10438717946SKay, Allen M void put_iova_domain(struct iova_domain *iovad);
10521aff52aSThierry Reding #else
iova_cache_get(void)10621aff52aSThierry Reding static inline int iova_cache_get(void)
10721aff52aSThierry Reding {
10821aff52aSThierry Reding 	return -ENOTSUPP;
10921aff52aSThierry Reding }
11021aff52aSThierry Reding 
iova_cache_put(void)11121aff52aSThierry Reding static inline void iova_cache_put(void)
11221aff52aSThierry Reding {
11321aff52aSThierry Reding }
11421aff52aSThierry Reding 
free_iova(struct iova_domain * iovad,unsigned long pfn)11521aff52aSThierry Reding static inline void free_iova(struct iova_domain *iovad, unsigned long pfn)
11621aff52aSThierry Reding {
11721aff52aSThierry Reding }
11821aff52aSThierry Reding 
__free_iova(struct iova_domain * iovad,struct iova * iova)11921aff52aSThierry Reding static inline void __free_iova(struct iova_domain *iovad, struct iova *iova)
12021aff52aSThierry Reding {
12121aff52aSThierry Reding }
12221aff52aSThierry Reding 
alloc_iova(struct iova_domain * iovad,unsigned long size,unsigned long limit_pfn,bool size_aligned)12321aff52aSThierry Reding static inline struct iova *alloc_iova(struct iova_domain *iovad,
12421aff52aSThierry Reding 				      unsigned long size,
12521aff52aSThierry Reding 				      unsigned long limit_pfn,
12621aff52aSThierry Reding 				      bool size_aligned)
12721aff52aSThierry Reding {
12821aff52aSThierry Reding 	return NULL;
12921aff52aSThierry Reding }
13021aff52aSThierry Reding 
free_iova_fast(struct iova_domain * iovad,unsigned long pfn,unsigned long size)13121aff52aSThierry Reding static inline void free_iova_fast(struct iova_domain *iovad,
13221aff52aSThierry Reding 				  unsigned long pfn,
13321aff52aSThierry Reding 				  unsigned long size)
13421aff52aSThierry Reding {
13521aff52aSThierry Reding }
13621aff52aSThierry Reding 
alloc_iova_fast(struct iova_domain * iovad,unsigned long size,unsigned long limit_pfn,bool flush_rcache)13721aff52aSThierry Reding static inline unsigned long alloc_iova_fast(struct iova_domain *iovad,
13821aff52aSThierry Reding 					    unsigned long size,
139538d5b33STomasz Nowicki 					    unsigned long limit_pfn,
140538d5b33STomasz Nowicki 					    bool flush_rcache)
14121aff52aSThierry Reding {
14221aff52aSThierry Reding 	return 0;
14321aff52aSThierry Reding }
14421aff52aSThierry Reding 
reserve_iova(struct iova_domain * iovad,unsigned long pfn_lo,unsigned long pfn_hi)14521aff52aSThierry Reding static inline struct iova *reserve_iova(struct iova_domain *iovad,
14621aff52aSThierry Reding 					unsigned long pfn_lo,
14721aff52aSThierry Reding 					unsigned long pfn_hi)
14821aff52aSThierry Reding {
14921aff52aSThierry Reding 	return NULL;
15021aff52aSThierry Reding }
15121aff52aSThierry Reding 
init_iova_domain(struct iova_domain * iovad,unsigned long granule,unsigned long start_pfn)15221aff52aSThierry Reding static inline void init_iova_domain(struct iova_domain *iovad,
15321aff52aSThierry Reding 				    unsigned long granule,
154aa3ac946SZhen Lei 				    unsigned long start_pfn)
15521aff52aSThierry Reding {
15621aff52aSThierry Reding }
15721aff52aSThierry Reding 
find_iova(struct iova_domain * iovad,unsigned long pfn)15821aff52aSThierry Reding static inline struct iova *find_iova(struct iova_domain *iovad,
15921aff52aSThierry Reding 				     unsigned long pfn)
16021aff52aSThierry Reding {
16121aff52aSThierry Reding 	return NULL;
16221aff52aSThierry Reding }
16321aff52aSThierry Reding 
put_iova_domain(struct iova_domain * iovad)16421aff52aSThierry Reding static inline void put_iova_domain(struct iova_domain *iovad)
16521aff52aSThierry Reding {
16621aff52aSThierry Reding }
16721aff52aSThierry Reding 
16821aff52aSThierry Reding #endif
16938717946SKay, Allen M 
17038717946SKay, Allen M #endif
171