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