]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/iommu/iova.c
a3dbba8caa19f8a77d3031624b7d4f76a0674b7d
[karo-tx-linux.git] / drivers / iommu / iova.c
1 /*
2  * Copyright © 2006-2009, Intel Corporation.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15  * Place - Suite 330, Boston, MA 02111-1307 USA.
16  *
17  * Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
18  */
19
20 #include <linux/iova.h>
21 #include <linux/slab.h>
22
23 static struct kmem_cache *iommu_iova_cache;
24
25 int iommu_iova_cache_init(void)
26 {
27         int ret = 0;
28
29         iommu_iova_cache = kmem_cache_create("iommu_iova",
30                                          sizeof(struct iova),
31                                          0,
32                                          SLAB_HWCACHE_ALIGN,
33                                          NULL);
34         if (!iommu_iova_cache) {
35                 pr_err("Couldn't create iova cache\n");
36                 ret = -ENOMEM;
37         }
38
39         return ret;
40 }
41
42 void iommu_iova_cache_destroy(void)
43 {
44         kmem_cache_destroy(iommu_iova_cache);
45 }
46
47 struct iova *alloc_iova_mem(void)
48 {
49         return kmem_cache_alloc(iommu_iova_cache, GFP_ATOMIC);
50 }
51
52 void free_iova_mem(struct iova *iova)
53 {
54         kmem_cache_free(iommu_iova_cache, iova);
55 }
56
57 void
58 init_iova_domain(struct iova_domain *iovad, unsigned long start_pfn,
59         unsigned long pfn_32bit)
60 {
61         spin_lock_init(&iovad->iova_rbtree_lock);
62         iovad->rbroot = RB_ROOT;
63         iovad->cached32_node = NULL;
64         iovad->start_pfn = start_pfn;
65         iovad->dma_32bit_pfn = pfn_32bit;
66 }
67
68 static struct rb_node *
69 __get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
70 {
71         if ((*limit_pfn != iovad->dma_32bit_pfn) ||
72                 (iovad->cached32_node == NULL))
73                 return rb_last(&iovad->rbroot);
74         else {
75                 struct rb_node *prev_node = rb_prev(iovad->cached32_node);
76                 struct iova *curr_iova =
77                         container_of(iovad->cached32_node, struct iova, node);
78                 *limit_pfn = curr_iova->pfn_lo - 1;
79                 return prev_node;
80         }
81 }
82
83 static void
84 __cached_rbnode_insert_update(struct iova_domain *iovad,
85         unsigned long limit_pfn, struct iova *new)
86 {
87         if (limit_pfn != iovad->dma_32bit_pfn)
88                 return;
89         iovad->cached32_node = &new->node;
90 }
91
92 static void
93 __cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
94 {
95         struct iova *cached_iova;
96         struct rb_node *curr;
97
98         if (!iovad->cached32_node)
99                 return;
100         curr = iovad->cached32_node;
101         cached_iova = container_of(curr, struct iova, node);
102
103         if (free->pfn_lo >= cached_iova->pfn_lo) {
104                 struct rb_node *node = rb_next(&free->node);
105                 struct iova *iova = container_of(node, struct iova, node);
106
107                 /* only cache if it's below 32bit pfn */
108                 if (node && iova->pfn_lo < iovad->dma_32bit_pfn)
109                         iovad->cached32_node = node;
110                 else
111                         iovad->cached32_node = NULL;
112         }
113 }
114
115 /* Computes the padding size required, to make the
116  * the start address naturally aligned on its size
117  */
118 static int
119 iova_get_pad_size(int size, unsigned int limit_pfn)
120 {
121         unsigned int pad_size = 0;
122         unsigned int order = ilog2(size);
123
124         if (order)
125                 pad_size = (limit_pfn + 1) % (1 << order);
126
127         return pad_size;
128 }
129
130 static int __alloc_and_insert_iova_range(struct iova_domain *iovad,
131                 unsigned long size, unsigned long limit_pfn,
132                         struct iova *new, bool size_aligned)
133 {
134         struct rb_node *prev, *curr = NULL;
135         unsigned long flags;
136         unsigned long saved_pfn;
137         unsigned int pad_size = 0;
138
139         /* Walk the tree backwards */
140         spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
141         saved_pfn = limit_pfn;
142         curr = __get_cached_rbnode(iovad, &limit_pfn);
143         prev = curr;
144         while (curr) {
145                 struct iova *curr_iova = container_of(curr, struct iova, node);
146
147                 if (limit_pfn < curr_iova->pfn_lo)
148                         goto move_left;
149                 else if (limit_pfn < curr_iova->pfn_hi)
150                         goto adjust_limit_pfn;
151                 else {
152                         if (size_aligned)
153                                 pad_size = iova_get_pad_size(size, limit_pfn);
154                         if ((curr_iova->pfn_hi + size + pad_size) <= limit_pfn)
155                                 break;  /* found a free slot */
156                 }
157 adjust_limit_pfn:
158                 limit_pfn = curr_iova->pfn_lo - 1;
159 move_left:
160                 prev = curr;
161                 curr = rb_prev(curr);
162         }
163
164         if (!curr) {
165                 if (size_aligned)
166                         pad_size = iova_get_pad_size(size, limit_pfn);
167                 if ((iovad->start_pfn + size + pad_size) > limit_pfn) {
168                         spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
169                         return -ENOMEM;
170                 }
171         }
172
173         /* pfn_lo will point to size aligned address if size_aligned is set */
174         new->pfn_lo = limit_pfn - (size + pad_size) + 1;
175         new->pfn_hi = new->pfn_lo + size - 1;
176
177         /* Insert the new_iova into domain rbtree by holding writer lock */
178         /* Add new node and rebalance tree. */
179         {
180                 struct rb_node **entry, *parent = NULL;
181
182                 /* If we have 'prev', it's a valid place to start the
183                    insertion. Otherwise, start from the root. */
184                 if (prev)
185                         entry = &prev;
186                 else
187                         entry = &iovad->rbroot.rb_node;
188
189                 /* Figure out where to put new node */
190                 while (*entry) {
191                         struct iova *this = container_of(*entry,
192                                                         struct iova, node);
193                         parent = *entry;
194
195                         if (new->pfn_lo < this->pfn_lo)
196                                 entry = &((*entry)->rb_left);
197                         else if (new->pfn_lo > this->pfn_lo)
198                                 entry = &((*entry)->rb_right);
199                         else
200                                 BUG(); /* this should not happen */
201                 }
202
203                 /* Add new node and rebalance tree. */
204                 rb_link_node(&new->node, parent, entry);
205                 rb_insert_color(&new->node, &iovad->rbroot);
206         }
207         __cached_rbnode_insert_update(iovad, saved_pfn, new);
208
209         spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
210
211
212         return 0;
213 }
214
215 static void
216 iova_insert_rbtree(struct rb_root *root, struct iova *iova)
217 {
218         struct rb_node **new = &(root->rb_node), *parent = NULL;
219         /* Figure out where to put new node */
220         while (*new) {
221                 struct iova *this = container_of(*new, struct iova, node);
222                 parent = *new;
223
224                 if (iova->pfn_lo < this->pfn_lo)
225                         new = &((*new)->rb_left);
226                 else if (iova->pfn_lo > this->pfn_lo)
227                         new = &((*new)->rb_right);
228                 else
229                         BUG(); /* this should not happen */
230         }
231         /* Add new node and rebalance tree. */
232         rb_link_node(&iova->node, parent, new);
233         rb_insert_color(&iova->node, root);
234 }
235
236 /**
237  * alloc_iova - allocates an iova
238  * @iovad: - iova domain in question
239  * @size: - size of page frames to allocate
240  * @limit_pfn: - max limit address
241  * @size_aligned: - set if size_aligned address range is required
242  * This function allocates an iova in the range iovad->start_pfn to limit_pfn,
243  * searching top-down from limit_pfn to iovad->start_pfn. If the size_aligned
244  * flag is set then the allocated address iova->pfn_lo will be naturally
245  * aligned on roundup_power_of_two(size).
246  */
247 struct iova *
248 alloc_iova(struct iova_domain *iovad, unsigned long size,
249         unsigned long limit_pfn,
250         bool size_aligned)
251 {
252         struct iova *new_iova;
253         int ret;
254
255         new_iova = alloc_iova_mem();
256         if (!new_iova)
257                 return NULL;
258
259         /* If size aligned is set then round the size to
260          * to next power of two.
261          */
262         if (size_aligned)
263                 size = __roundup_pow_of_two(size);
264
265         ret = __alloc_and_insert_iova_range(iovad, size, limit_pfn,
266                         new_iova, size_aligned);
267
268         if (ret) {
269                 free_iova_mem(new_iova);
270                 return NULL;
271         }
272
273         return new_iova;
274 }
275
276 /**
277  * find_iova - find's an iova for a given pfn
278  * @iovad: - iova domain in question.
279  * @pfn: - page frame number
280  * This function finds and returns an iova belonging to the
281  * given doamin which matches the given pfn.
282  */
283 struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn)
284 {
285         unsigned long flags;
286         struct rb_node *node;
287
288         /* Take the lock so that no other thread is manipulating the rbtree */
289         spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
290         node = iovad->rbroot.rb_node;
291         while (node) {
292                 struct iova *iova = container_of(node, struct iova, node);
293
294                 /* If pfn falls within iova's range, return iova */
295                 if ((pfn >= iova->pfn_lo) && (pfn <= iova->pfn_hi)) {
296                         spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
297                         /* We are not holding the lock while this iova
298                          * is referenced by the caller as the same thread
299                          * which called this function also calls __free_iova()
300                          * and it is by design that only one thread can possibly
301                          * reference a particular iova and hence no conflict.
302                          */
303                         return iova;
304                 }
305
306                 if (pfn < iova->pfn_lo)
307                         node = node->rb_left;
308                 else if (pfn > iova->pfn_lo)
309                         node = node->rb_right;
310         }
311
312         spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
313         return NULL;
314 }
315
316 /**
317  * __free_iova - frees the given iova
318  * @iovad: iova domain in question.
319  * @iova: iova in question.
320  * Frees the given iova belonging to the giving domain
321  */
322 void
323 __free_iova(struct iova_domain *iovad, struct iova *iova)
324 {
325         unsigned long flags;
326
327         spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
328         __cached_rbnode_delete_update(iovad, iova);
329         rb_erase(&iova->node, &iovad->rbroot);
330         spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
331         free_iova_mem(iova);
332 }
333
334 /**
335  * free_iova - finds and frees the iova for a given pfn
336  * @iovad: - iova domain in question.
337  * @pfn: - pfn that is allocated previously
338  * This functions finds an iova for a given pfn and then
339  * frees the iova from that domain.
340  */
341 void
342 free_iova(struct iova_domain *iovad, unsigned long pfn)
343 {
344         struct iova *iova = find_iova(iovad, pfn);
345         if (iova)
346                 __free_iova(iovad, iova);
347
348 }
349
350 /**
351  * put_iova_domain - destroys the iova doamin
352  * @iovad: - iova domain in question.
353  * All the iova's in that domain are destroyed.
354  */
355 void put_iova_domain(struct iova_domain *iovad)
356 {
357         struct rb_node *node;
358         unsigned long flags;
359
360         spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
361         node = rb_first(&iovad->rbroot);
362         while (node) {
363                 struct iova *iova = container_of(node, struct iova, node);
364                 rb_erase(node, &iovad->rbroot);
365                 free_iova_mem(iova);
366                 node = rb_first(&iovad->rbroot);
367         }
368         spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
369 }
370
371 static int
372 __is_range_overlap(struct rb_node *node,
373         unsigned long pfn_lo, unsigned long pfn_hi)
374 {
375         struct iova *iova = container_of(node, struct iova, node);
376
377         if ((pfn_lo <= iova->pfn_hi) && (pfn_hi >= iova->pfn_lo))
378                 return 1;
379         return 0;
380 }
381
382 static inline struct iova *
383 alloc_and_init_iova(unsigned long pfn_lo, unsigned long pfn_hi)
384 {
385         struct iova *iova;
386
387         iova = alloc_iova_mem();
388         if (iova) {
389                 iova->pfn_lo = pfn_lo;
390                 iova->pfn_hi = pfn_hi;
391         }
392
393         return iova;
394 }
395
396 static struct iova *
397 __insert_new_range(struct iova_domain *iovad,
398         unsigned long pfn_lo, unsigned long pfn_hi)
399 {
400         struct iova *iova;
401
402         iova = alloc_and_init_iova(pfn_lo, pfn_hi);
403         if (iova)
404                 iova_insert_rbtree(&iovad->rbroot, iova);
405
406         return iova;
407 }
408
409 static void
410 __adjust_overlap_range(struct iova *iova,
411         unsigned long *pfn_lo, unsigned long *pfn_hi)
412 {
413         if (*pfn_lo < iova->pfn_lo)
414                 iova->pfn_lo = *pfn_lo;
415         if (*pfn_hi > iova->pfn_hi)
416                 *pfn_lo = iova->pfn_hi + 1;
417 }
418
419 /**
420  * reserve_iova - reserves an iova in the given range
421  * @iovad: - iova domain pointer
422  * @pfn_lo: - lower page frame address
423  * @pfn_hi:- higher pfn adderss
424  * This function allocates reserves the address range from pfn_lo to pfn_hi so
425  * that this address is not dished out as part of alloc_iova.
426  */
427 struct iova *
428 reserve_iova(struct iova_domain *iovad,
429         unsigned long pfn_lo, unsigned long pfn_hi)
430 {
431         struct rb_node *node;
432         unsigned long flags;
433         struct iova *iova;
434         unsigned int overlap = 0;
435
436         spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
437         for (node = rb_first(&iovad->rbroot); node; node = rb_next(node)) {
438                 if (__is_range_overlap(node, pfn_lo, pfn_hi)) {
439                         iova = container_of(node, struct iova, node);
440                         __adjust_overlap_range(iova, &pfn_lo, &pfn_hi);
441                         if ((pfn_lo >= iova->pfn_lo) &&
442                                 (pfn_hi <= iova->pfn_hi))
443                                 goto finish;
444                         overlap = 1;
445
446                 } else if (overlap)
447                                 break;
448         }
449
450         /* We are here either because this is the first reserver node
451          * or need to insert remaining non overlap addr range
452          */
453         iova = __insert_new_range(iovad, pfn_lo, pfn_hi);
454 finish:
455
456         spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
457         return iova;
458 }
459
460 /**
461  * copy_reserved_iova - copies the reserved between domains
462  * @from: - source doamin from where to copy
463  * @to: - destination domin where to copy
464  * This function copies reserved iova's from one doamin to
465  * other.
466  */
467 void
468 copy_reserved_iova(struct iova_domain *from, struct iova_domain *to)
469 {
470         unsigned long flags;
471         struct rb_node *node;
472
473         spin_lock_irqsave(&from->iova_rbtree_lock, flags);
474         for (node = rb_first(&from->rbroot); node; node = rb_next(node)) {
475                 struct iova *iova = container_of(node, struct iova, node);
476                 struct iova *new_iova;
477                 new_iova = reserve_iova(to, iova->pfn_lo, iova->pfn_hi);
478                 if (!new_iova)
479                         printk(KERN_ERR "Reserve iova range %lx@%lx failed\n",
480                                 iova->pfn_lo, iova->pfn_lo);
481         }
482         spin_unlock_irqrestore(&from->iova_rbtree_lock, flags);
483 }
484
485 struct iova *
486 split_and_remove_iova(struct iova_domain *iovad, struct iova *iova,
487                       unsigned long pfn_lo, unsigned long pfn_hi)
488 {
489         unsigned long flags;
490         struct iova *prev = NULL, *next = NULL;
491
492         spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
493         if (iova->pfn_lo < pfn_lo) {
494                 prev = alloc_and_init_iova(iova->pfn_lo, pfn_lo - 1);
495                 if (prev == NULL)
496                         goto error;
497         }
498         if (iova->pfn_hi > pfn_hi) {
499                 next = alloc_and_init_iova(pfn_hi + 1, iova->pfn_hi);
500                 if (next == NULL)
501                         goto error;
502         }
503
504         __cached_rbnode_delete_update(iovad, iova);
505         rb_erase(&iova->node, &iovad->rbroot);
506
507         if (prev) {
508                 iova_insert_rbtree(&iovad->rbroot, prev);
509                 iova->pfn_lo = pfn_lo;
510         }
511         if (next) {
512                 iova_insert_rbtree(&iovad->rbroot, next);
513                 iova->pfn_hi = pfn_hi;
514         }
515         spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
516
517         return iova;
518
519 error:
520         spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags);
521         if (prev)
522                 free_iova_mem(prev);
523         return NULL;
524 }