1  /* SPDX-License-Identifier: GPL-2.0-only */
2  /*
3   * Copyright (c) 2006, Intel Corporation.
4   *
5   * Copyright (C) 2006-2008 Intel Corporation
6   * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
7   */
8  
9  #ifndef _IOVA_H_
10  #define _IOVA_H_
11  
12  #include <linux/types.h>
13  #include <linux/kernel.h>
14  #include <linux/rbtree.h>
15  #include <linux/dma-mapping.h>
16  
17  /* iova structure */
18  struct iova {
19  	struct rb_node	node;
20  	unsigned long	pfn_hi; /* Highest allocated pfn */
21  	unsigned long	pfn_lo; /* Lowest allocated pfn */
22  };
23  
24  
25  struct iova_rcache;
26  
27  /* holds all the iova translations for a domain */
28  struct iova_domain {
29  	spinlock_t	iova_rbtree_lock; /* Lock to protect update of rbtree */
30  	struct rb_root	rbroot;		/* iova domain rbtree root */
31  	struct rb_node	*cached_node;	/* Save last alloced node */
32  	struct rb_node	*cached32_node; /* Save last 32-bit alloced node */
33  	unsigned long	granule;	/* pfn granularity for this domain */
34  	unsigned long	start_pfn;	/* Lower limit for this domain */
35  	unsigned long	dma_32bit_pfn;
36  	unsigned long	max32_alloc_size; /* Size of last failed allocation */
37  	struct iova	anchor;		/* rbtree lookup anchor */
38  
39  	struct iova_rcache	*rcaches;
40  	struct hlist_node	cpuhp_dead;
41  };
42  
iova_size(struct iova * iova)43  static inline unsigned long iova_size(struct iova *iova)
44  {
45  	return iova->pfn_hi - iova->pfn_lo + 1;
46  }
47  
iova_shift(struct iova_domain * iovad)48  static inline unsigned long iova_shift(struct iova_domain *iovad)
49  {
50  	return __ffs(iovad->granule);
51  }
52  
iova_mask(struct iova_domain * iovad)53  static inline unsigned long iova_mask(struct iova_domain *iovad)
54  {
55  	return iovad->granule - 1;
56  }
57  
iova_offset(struct iova_domain * iovad,dma_addr_t iova)58  static inline size_t iova_offset(struct iova_domain *iovad, dma_addr_t iova)
59  {
60  	return iova & iova_mask(iovad);
61  }
62  
iova_align(struct iova_domain * iovad,size_t size)63  static inline size_t iova_align(struct iova_domain *iovad, size_t size)
64  {
65  	return ALIGN(size, iovad->granule);
66  }
67  
iova_align_down(struct iova_domain * iovad,size_t size)68  static inline size_t iova_align_down(struct iova_domain *iovad, size_t size)
69  {
70  	return ALIGN_DOWN(size, iovad->granule);
71  }
72  
iova_dma_addr(struct iova_domain * iovad,struct iova * iova)73  static inline dma_addr_t iova_dma_addr(struct iova_domain *iovad, struct iova *iova)
74  {
75  	return (dma_addr_t)iova->pfn_lo << iova_shift(iovad);
76  }
77  
iova_pfn(struct iova_domain * iovad,dma_addr_t iova)78  static inline unsigned long iova_pfn(struct iova_domain *iovad, dma_addr_t iova)
79  {
80  	return iova >> iova_shift(iovad);
81  }
82  
83  #if IS_REACHABLE(CONFIG_IOMMU_IOVA)
84  int iova_cache_get(void);
85  void iova_cache_put(void);
86  
87  unsigned long iova_rcache_range(void);
88  
89  void free_iova(struct iova_domain *iovad, unsigned long pfn);
90  void __free_iova(struct iova_domain *iovad, struct iova *iova);
91  struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size,
92  	unsigned long limit_pfn,
93  	bool size_aligned);
94  void free_iova_fast(struct iova_domain *iovad, unsigned long pfn,
95  		    unsigned long size);
96  unsigned long alloc_iova_fast(struct iova_domain *iovad, unsigned long size,
97  			      unsigned long limit_pfn, bool flush_rcache);
98  struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo,
99  	unsigned long pfn_hi);
100  void init_iova_domain(struct iova_domain *iovad, unsigned long granule,
101  	unsigned long start_pfn);
102  int iova_domain_init_rcaches(struct iova_domain *iovad);
103  struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn);
104  void put_iova_domain(struct iova_domain *iovad);
105  #else
iova_cache_get(void)106  static inline int iova_cache_get(void)
107  {
108  	return -ENOTSUPP;
109  }
110  
iova_cache_put(void)111  static inline void iova_cache_put(void)
112  {
113  }
114  
free_iova(struct iova_domain * iovad,unsigned long pfn)115  static inline void free_iova(struct iova_domain *iovad, unsigned long pfn)
116  {
117  }
118  
__free_iova(struct iova_domain * iovad,struct iova * iova)119  static inline void __free_iova(struct iova_domain *iovad, struct iova *iova)
120  {
121  }
122  
alloc_iova(struct iova_domain * iovad,unsigned long size,unsigned long limit_pfn,bool size_aligned)123  static inline struct iova *alloc_iova(struct iova_domain *iovad,
124  				      unsigned long size,
125  				      unsigned long limit_pfn,
126  				      bool size_aligned)
127  {
128  	return NULL;
129  }
130  
free_iova_fast(struct iova_domain * iovad,unsigned long pfn,unsigned long size)131  static inline void free_iova_fast(struct iova_domain *iovad,
132  				  unsigned long pfn,
133  				  unsigned long size)
134  {
135  }
136  
alloc_iova_fast(struct iova_domain * iovad,unsigned long size,unsigned long limit_pfn,bool flush_rcache)137  static inline unsigned long alloc_iova_fast(struct iova_domain *iovad,
138  					    unsigned long size,
139  					    unsigned long limit_pfn,
140  					    bool flush_rcache)
141  {
142  	return 0;
143  }
144  
reserve_iova(struct iova_domain * iovad,unsigned long pfn_lo,unsigned long pfn_hi)145  static inline struct iova *reserve_iova(struct iova_domain *iovad,
146  					unsigned long pfn_lo,
147  					unsigned long pfn_hi)
148  {
149  	return NULL;
150  }
151  
init_iova_domain(struct iova_domain * iovad,unsigned long granule,unsigned long start_pfn)152  static inline void init_iova_domain(struct iova_domain *iovad,
153  				    unsigned long granule,
154  				    unsigned long start_pfn)
155  {
156  }
157  
find_iova(struct iova_domain * iovad,unsigned long pfn)158  static inline struct iova *find_iova(struct iova_domain *iovad,
159  				     unsigned long pfn)
160  {
161  	return NULL;
162  }
163  
put_iova_domain(struct iova_domain * iovad)164  static inline void put_iova_domain(struct iova_domain *iovad)
165  {
166  }
167  
168  #endif
169  
170  #endif
171