diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Kconfig.debug | 1 | ||||
| -rw-r--r-- | lib/bitmap.c | 81 | ||||
| -rw-r--r-- | lib/genalloc.c | 33 | ||||
| -rw-r--r-- | lib/iommu-helper.c | 59 | ||||
| -rw-r--r-- | lib/lmb.c | 7 | ||||
| -rw-r--r-- | lib/swiotlb.c | 4 | ||||
| -rw-r--r-- | lib/vsprintf.c | 13 |
7 files changed, 123 insertions, 75 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 8cf9938dd147..25c3ed594c54 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
| @@ -360,6 +360,7 @@ config DEBUG_KMEMLEAK | |||
| 360 | select DEBUG_FS if SYSFS | 360 | select DEBUG_FS if SYSFS |
| 361 | select STACKTRACE if STACKTRACE_SUPPORT | 361 | select STACKTRACE if STACKTRACE_SUPPORT |
| 362 | select KALLSYMS | 362 | select KALLSYMS |
| 363 | select CRC32 | ||
| 363 | help | 364 | help |
| 364 | Say Y here if you want to enable the memory leak | 365 | Say Y here if you want to enable the memory leak |
| 365 | detector. The memory allocation/freeing is traced in a way | 366 | detector. The memory allocation/freeing is traced in a way |
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 | } |
| 272 | EXPORT_SYMBOL(__bitmap_weight); | 272 | EXPORT_SYMBOL(__bitmap_weight); |
| 273 | 273 | ||
| 274 | #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) | ||
| 275 | |||
| 276 | void 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 | } | ||
| 295 | EXPORT_SYMBOL(bitmap_set); | ||
| 296 | |||
| 297 | void 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 | } | ||
| 316 | EXPORT_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 | */ | ||
| 330 | unsigned 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; | ||
| 337 | again: | ||
| 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 | } | ||
| 353 | EXPORT_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 | |||
| 8 | static 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; | ||
| 15 | again: | ||
| 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 | |||
| 33 | void 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 | ||
| 42 | int iommu_is_span_boundary(unsigned int index, unsigned int nr, | 8 | int 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; | ||
| 58 | again: | 27 | again: |
| 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 | } |
| 70 | EXPORT_SYMBOL(iommu_area_alloc); | 40 | EXPORT_SYMBOL(iommu_area_alloc); |
| 71 | 41 | ||
| 72 | void 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 | } | ||
| 81 | EXPORT_SYMBOL(iommu_area_free); | ||
| 82 | |||
| 83 | unsigned long iommu_num_pages(unsigned long addr, unsigned long len, | 42 | unsigned long iommu_num_pages(unsigned long addr, unsigned long len, |
| 84 | unsigned long io_page_size) | 43 | unsigned long io_page_size) |
| 85 | { | 44 | { |
| @@ -263,7 +263,7 @@ long __init lmb_reserve(u64 base, u64 size) | |||
| 263 | return lmb_add_region(_rgn, base, size); | 263 | return lmb_add_region(_rgn, base, size); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | long __init lmb_overlaps_region(struct lmb_region *rgn, u64 base, u64 size) | 266 | long lmb_overlaps_region(struct lmb_region *rgn, u64 base, u64 size) |
| 267 | { | 267 | { |
| 268 | unsigned long i; | 268 | unsigned long i; |
| 269 | 269 | ||
| @@ -493,6 +493,11 @@ int __init lmb_is_reserved(u64 addr) | |||
| 493 | return 0; | 493 | return 0; |
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | int lmb_is_region_reserved(u64 base, u64 size) | ||
| 497 | { | ||
| 498 | return lmb_overlaps_region(&lmb.reserved, base, size); | ||
| 499 | } | ||
| 500 | |||
| 496 | /* | 501 | /* |
| 497 | * Given a <base, len>, find which memory regions belong to this range. | 502 | * Given a <base, len>, find which memory regions belong to this range. |
| 498 | * Adjust the request and return a contiguous chunk. | 503 | * Adjust the request and return a contiguous chunk. |
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); |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 735343fc857a..d4996cf46eb6 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -1179,7 +1179,18 @@ qualifier: | |||
| 1179 | * %ps output the name of a text symbol without offset | 1179 | * %ps output the name of a text symbol without offset |
| 1180 | * %pF output the name of a function pointer with its offset | 1180 | * %pF output the name of a function pointer with its offset |
| 1181 | * %pf output the name of a function pointer without its offset | 1181 | * %pf output the name of a function pointer without its offset |
| 1182 | * %pR output the address range in a struct resource | 1182 | * %pR output the address range in a struct resource with decoded flags |
| 1183 | * %pr output the address range in a struct resource with raw flags | ||
| 1184 | * %pM output a 6-byte MAC address with colons | ||
| 1185 | * %pm output a 6-byte MAC address without colons | ||
| 1186 | * %pI4 print an IPv4 address without leading zeros | ||
| 1187 | * %pi4 print an IPv4 address with leading zeros | ||
| 1188 | * %pI6 print an IPv6 address with colons | ||
| 1189 | * %pi6 print an IPv6 address without colons | ||
| 1190 | * %pI6c print an IPv6 address as specified by | ||
| 1191 | * http://www.ietf.org/id/draft-kawamura-ipv6-text-representation-03.txt | ||
| 1192 | * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper | ||
| 1193 | * case. | ||
| 1183 | * %n is ignored | 1194 | * %n is ignored |
| 1184 | * | 1195 | * |
| 1185 | * The return value is the number of characters which would | 1196 | * The return value is the number of characters which would |
