aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-16 13:06:39 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-16 13:06:39 -0500
commit9cfc86249f32d984339c6d1f8a1fd1326989b3b8 (patch)
tree56428d319483f54949de8d9d0a5b3f715287ed91 /lib
parentf42647acc4eab1befa9e290691ed7a40f9a7d3cc (diff)
parent243797f59b748f679ab88d456fcc4f92236d724b (diff)
Merge branch 'akpm'
* akpm: (173 commits) genalloc: use bitmap_find_next_zero_area ia64: use bitmap_find_next_zero_area sparc: use bitmap_find_next_zero_area mlx4: use bitmap_find_next_zero_area isp1362-hcd: use bitmap_find_next_zero_area iommu-helper: use bitmap library bitmap: introduce bitmap_set, bitmap_clear, bitmap_find_next_zero_area qnx4: use hweight8 qnx4fs: remove remains of the (defunct) write support resource: constify arg to resource_size() and resource_type() gru: send cross partition interrupts using the gru gru: function to generate chipset IPI values gru: update driver version number gru: improve GRU TLB dropin statistics gru: fix GRU interrupt race at deallocate gru: add hugepage support gru: fix bug in allocation of kernel contexts gru: update GRU structures to match latest hardware spec gru: check for correct GRU chiplet assignment gru: remove stray local_irq_enable ...
Diffstat (limited to 'lib')
-rw-r--r--lib/bitmap.c81
-rw-r--r--lib/genalloc.c33
-rw-r--r--lib/iommu-helper.c59
-rw-r--r--lib/swiotlb.c4
4 files changed, 104 insertions, 73 deletions
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 702565821c99..11bf49750583 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -271,6 +271,87 @@ int __bitmap_weight(const unsigned long *bitmap, int bits)
271} 271}
272EXPORT_SYMBOL(__bitmap_weight); 272EXPORT_SYMBOL(__bitmap_weight);
273 273
274#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
275
276void bitmap_set(unsigned long *map, int start, int nr)
277{
278 unsigned long *p = map + BIT_WORD(start);
279 const int size = start + nr;
280 int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
281 unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
282
283 while (nr - bits_to_set >= 0) {
284 *p |= mask_to_set;
285 nr -= bits_to_set;
286 bits_to_set = BITS_PER_LONG;
287 mask_to_set = ~0UL;
288 p++;
289 }
290 if (nr) {
291 mask_to_set &= BITMAP_LAST_WORD_MASK(size);
292 *p |= mask_to_set;
293 }
294}
295EXPORT_SYMBOL(bitmap_set);
296
297void bitmap_clear(unsigned long *map, int start, int nr)
298{
299 unsigned long *p = map + BIT_WORD(start);
300 const int size = start + nr;
301 int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
302 unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
303
304 while (nr - bits_to_clear >= 0) {
305 *p &= ~mask_to_clear;
306 nr -= bits_to_clear;
307 bits_to_clear = BITS_PER_LONG;
308 mask_to_clear = ~0UL;
309 p++;
310 }
311 if (nr) {
312 mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
313 *p &= ~mask_to_clear;
314 }
315}
316EXPORT_SYMBOL(bitmap_clear);
317
318/*
319 * bitmap_find_next_zero_area - find a contiguous aligned zero area
320 * @map: The address to base the search on
321 * @size: The bitmap size in bits
322 * @start: The bitnumber to start searching at
323 * @nr: The number of zeroed bits we're looking for
324 * @align_mask: Alignment mask for zero area
325 *
326 * The @align_mask should be one less than a power of 2; the effect is that
327 * the bit offset of all zero areas this function finds is multiples of that
328 * power of 2. A @align_mask of 0 means no alignment is required.
329 */
330unsigned long bitmap_find_next_zero_area(unsigned long *map,
331 unsigned long size,
332 unsigned long start,
333 unsigned int nr,
334 unsigned long align_mask)
335{
336 unsigned long index, end, i;
337again:
338 index = find_next_zero_bit(map, size, start);
339
340 /* Align allocation */
341 index = __ALIGN_MASK(index, align_mask);
342
343 end = index + nr;
344 if (end > size)
345 return end;
346 i = find_next_bit(map, end, index);
347 if (i < end) {
348 start = i + 1;
349 goto again;
350 }
351 return index;
352}
353EXPORT_SYMBOL(bitmap_find_next_zero_area);
354
274/* 355/*
275 * Bitmap printing & parsing functions: first version by Bill Irwin, 356 * Bitmap printing & parsing functions: first version by Bill Irwin,
276 * second version by Paul Jackson, third by Joe Korty. 357 * second version by Paul Jackson, third by Joe Korty.
diff --git a/lib/genalloc.c b/lib/genalloc.c
index eed2bdb865e7..e67f97495dd5 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/bitmap.h>
14#include <linux/genalloc.h> 15#include <linux/genalloc.h>
15 16
16 17
@@ -114,7 +115,7 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
114 struct gen_pool_chunk *chunk; 115 struct gen_pool_chunk *chunk;
115 unsigned long addr, flags; 116 unsigned long addr, flags;
116 int order = pool->min_alloc_order; 117 int order = pool->min_alloc_order;
117 int nbits, bit, start_bit, end_bit; 118 int nbits, start_bit, end_bit;
118 119
119 if (size == 0) 120 if (size == 0)
120 return 0; 121 return 0;
@@ -129,29 +130,19 @@ unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
129 end_bit -= nbits + 1; 130 end_bit -= nbits + 1;
130 131
131 spin_lock_irqsave(&chunk->lock, flags); 132 spin_lock_irqsave(&chunk->lock, flags);
132 bit = -1; 133 start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit, 0,
133 while (bit + 1 < end_bit) { 134 nbits, 0);
134 bit = find_next_zero_bit(chunk->bits, end_bit, bit + 1); 135 if (start_bit >= end_bit) {
135 if (bit >= end_bit)
136 break;
137
138 start_bit = bit;
139 if (nbits > 1) {
140 bit = find_next_bit(chunk->bits, bit + nbits,
141 bit + 1);
142 if (bit - start_bit < nbits)
143 continue;
144 }
145
146 addr = chunk->start_addr +
147 ((unsigned long)start_bit << order);
148 while (nbits--)
149 __set_bit(start_bit++, chunk->bits);
150 spin_unlock_irqrestore(&chunk->lock, flags); 136 spin_unlock_irqrestore(&chunk->lock, flags);
151 read_unlock(&pool->lock); 137 continue;
152 return addr;
153 } 138 }
139
140 addr = chunk->start_addr + ((unsigned long)start_bit << order);
141
142 bitmap_set(chunk->bits, start_bit, nbits);
154 spin_unlock_irqrestore(&chunk->lock, flags); 143 spin_unlock_irqrestore(&chunk->lock, flags);
144 read_unlock(&pool->lock);
145 return addr;
155 } 146 }
156 read_unlock(&pool->lock); 147 read_unlock(&pool->lock);
157 return 0; 148 return 0;
diff --git a/lib/iommu-helper.c b/lib/iommu-helper.c
index 75dbda03f4fb..c0251f4ad08b 100644
--- a/lib/iommu-helper.c
+++ b/lib/iommu-helper.c
@@ -3,41 +3,7 @@
3 */ 3 */
4 4
5#include <linux/module.h> 5#include <linux/module.h>
6#include <linux/bitops.h> 6#include <linux/bitmap.h>
7
8static unsigned long find_next_zero_area(unsigned long *map,
9 unsigned long size,
10 unsigned long start,
11 unsigned int nr,
12 unsigned long align_mask)
13{
14 unsigned long index, end, i;
15again:
16 index = find_next_zero_bit(map, size, start);
17
18 /* Align allocation */
19 index = (index + align_mask) & ~align_mask;
20
21 end = index + nr;
22 if (end >= size)
23 return -1;
24 for (i = index; i < end; i++) {
25 if (test_bit(i, map)) {
26 start = i+1;
27 goto again;
28 }
29 }
30 return index;
31}
32
33void iommu_area_reserve(unsigned long *map, unsigned long i, int len)
34{
35 unsigned long end = i + len;
36 while (i < end) {
37 __set_bit(i, map);
38 i++;
39 }
40}
41 7
42int iommu_is_span_boundary(unsigned int index, unsigned int nr, 8int iommu_is_span_boundary(unsigned int index, unsigned int nr,
43 unsigned long shift, 9 unsigned long shift,
@@ -55,31 +21,24 @@ unsigned long iommu_area_alloc(unsigned long *map, unsigned long size,
55 unsigned long align_mask) 21 unsigned long align_mask)
56{ 22{
57 unsigned long index; 23 unsigned long index;
24
25 /* We don't want the last of the limit */
26 size -= 1;
58again: 27again:
59 index = find_next_zero_area(map, size, start, nr, align_mask); 28 index = bitmap_find_next_zero_area(map, size, start, nr, align_mask);
60 if (index != -1) { 29 if (index < size) {
61 if (iommu_is_span_boundary(index, nr, shift, boundary_size)) { 30 if (iommu_is_span_boundary(index, nr, shift, boundary_size)) {
62 /* we could do more effectively */ 31 /* we could do more effectively */
63 start = index + 1; 32 start = index + 1;
64 goto again; 33 goto again;
65 } 34 }
66 iommu_area_reserve(map, index, nr); 35 bitmap_set(map, index, nr);
36 return index;
67 } 37 }
68 return index; 38 return -1;
69} 39}
70EXPORT_SYMBOL(iommu_area_alloc); 40EXPORT_SYMBOL(iommu_area_alloc);
71 41
72void iommu_area_free(unsigned long *map, unsigned long start, unsigned int nr)
73{
74 unsigned long end = start + nr;
75
76 while (start < end) {
77 __clear_bit(start, map);
78 start++;
79 }
80}
81EXPORT_SYMBOL(iommu_area_free);
82
83unsigned long iommu_num_pages(unsigned long addr, unsigned long len, 42unsigned long iommu_num_pages(unsigned long addr, unsigned long len,
84 unsigned long io_page_size) 43 unsigned long io_page_size)
85{ 44{
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 5bc01803f8f8..437eedb5a53b 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -549,7 +549,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
549 dma_mask = hwdev->coherent_dma_mask; 549 dma_mask = hwdev->coherent_dma_mask;
550 550
551 ret = (void *)__get_free_pages(flags, order); 551 ret = (void *)__get_free_pages(flags, order);
552 if (ret && swiotlb_virt_to_bus(hwdev, ret) + size > dma_mask) { 552 if (ret && swiotlb_virt_to_bus(hwdev, ret) + size - 1 > dma_mask) {
553 /* 553 /*
554 * The allocated memory isn't reachable by the device. 554 * The allocated memory isn't reachable by the device.
555 */ 555 */
@@ -571,7 +571,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
571 dev_addr = swiotlb_virt_to_bus(hwdev, ret); 571 dev_addr = swiotlb_virt_to_bus(hwdev, ret);
572 572
573 /* Confirm address can be DMA'd by device */ 573 /* Confirm address can be DMA'd by device */
574 if (dev_addr + size > dma_mask) { 574 if (dev_addr + size - 1 > dma_mask) {
575 printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n", 575 printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
576 (unsigned long long)dma_mask, 576 (unsigned long long)dma_mask,
577 (unsigned long long)dev_addr); 577 (unsigned long long)dev_addr);