aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile2
-rw-r--r--lib/bitmap.c22
-rw-r--r--lib/cpumask.c79
-rw-r--r--lib/dynamic_printk.c4
-rw-r--r--lib/idr.c14
-rw-r--r--lib/scatterlist.c2
-rw-r--r--lib/string_helpers.c34
-rw-r--r--lib/swiotlb.c16
8 files changed, 148 insertions, 25 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 16feaab057b2..7cb65d85aeb0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -2,7 +2,7 @@
2# Makefile for some libs needed in the kernel. 2# Makefile for some libs needed in the kernel.
3# 3#
4 4
5ifdef CONFIG_FTRACE 5ifdef CONFIG_FUNCTION_TRACER
6ORIG_CFLAGS := $(KBUILD_CFLAGS) 6ORIG_CFLAGS := $(KBUILD_CFLAGS)
7KBUILD_CFLAGS = $(subst -pg,,$(ORIG_CFLAGS)) 7KBUILD_CFLAGS = $(subst -pg,,$(ORIG_CFLAGS))
8endif 8endif
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 482df94ea21e..1338469ac849 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -996,3 +996,25 @@ int bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
996 return 0; 996 return 0;
997} 997}
998EXPORT_SYMBOL(bitmap_allocate_region); 998EXPORT_SYMBOL(bitmap_allocate_region);
999
1000/**
1001 * bitmap_copy_le - copy a bitmap, putting the bits into little-endian order.
1002 * @dst: destination buffer
1003 * @src: bitmap to copy
1004 * @nbits: number of bits in the bitmap
1005 *
1006 * Require nbits % BITS_PER_LONG == 0.
1007 */
1008void bitmap_copy_le(void *dst, const unsigned long *src, int nbits)
1009{
1010 unsigned long *d = dst;
1011 int i;
1012
1013 for (i = 0; i < nbits/BITS_PER_LONG; i++) {
1014 if (BITS_PER_LONG == 64)
1015 d[i] = cpu_to_le64(src[i]);
1016 else
1017 d[i] = cpu_to_le32(src[i]);
1018 }
1019}
1020EXPORT_SYMBOL(bitmap_copy_le);
diff --git a/lib/cpumask.c b/lib/cpumask.c
index 5f97dc25ef9c..8d03f22c6ced 100644
--- a/lib/cpumask.c
+++ b/lib/cpumask.c
@@ -2,6 +2,7 @@
2#include <linux/bitops.h> 2#include <linux/bitops.h>
3#include <linux/cpumask.h> 3#include <linux/cpumask.h>
4#include <linux/module.h> 4#include <linux/module.h>
5#include <linux/bootmem.h>
5 6
6int __first_cpu(const cpumask_t *srcp) 7int __first_cpu(const cpumask_t *srcp)
7{ 8{
@@ -35,3 +36,81 @@ int __any_online_cpu(const cpumask_t *mask)
35 return cpu; 36 return cpu;
36} 37}
37EXPORT_SYMBOL(__any_online_cpu); 38EXPORT_SYMBOL(__any_online_cpu);
39
40/**
41 * cpumask_next_and - get the next cpu in *src1p & *src2p
42 * @n: the cpu prior to the place to search (ie. return will be > @n)
43 * @src1p: the first cpumask pointer
44 * @src2p: the second cpumask pointer
45 *
46 * Returns >= nr_cpu_ids if no further cpus set in both.
47 */
48int cpumask_next_and(int n, const struct cpumask *src1p,
49 const struct cpumask *src2p)
50{
51 while ((n = cpumask_next(n, src1p)) < nr_cpu_ids)
52 if (cpumask_test_cpu(n, src2p))
53 break;
54 return n;
55}
56EXPORT_SYMBOL(cpumask_next_and);
57
58/**
59 * cpumask_any_but - return a "random" in a cpumask, but not this one.
60 * @mask: the cpumask to search
61 * @cpu: the cpu to ignore.
62 *
63 * Often used to find any cpu but smp_processor_id() in a mask.
64 * Returns >= nr_cpu_ids if no cpus set.
65 */
66int cpumask_any_but(const struct cpumask *mask, unsigned int cpu)
67{
68 unsigned int i;
69
70 cpumask_check(cpu);
71 for_each_cpu(i, mask)
72 if (i != cpu)
73 break;
74 return i;
75}
76
77/* These are not inline because of header tangles. */
78#ifdef CONFIG_CPUMASK_OFFSTACK
79bool alloc_cpumask_var(cpumask_var_t *mask, gfp_t flags)
80{
81 if (likely(slab_is_available()))
82 *mask = kmalloc(cpumask_size(), flags);
83 else {
84#ifdef CONFIG_DEBUG_PER_CPU_MAPS
85 printk(KERN_ERR
86 "=> alloc_cpumask_var: kmalloc not available!\n");
87 dump_stack();
88#endif
89 *mask = NULL;
90 }
91#ifdef CONFIG_DEBUG_PER_CPU_MAPS
92 if (!*mask) {
93 printk(KERN_ERR "=> alloc_cpumask_var: failed!\n");
94 dump_stack();
95 }
96#endif
97 return *mask != NULL;
98}
99EXPORT_SYMBOL(alloc_cpumask_var);
100
101void __init alloc_bootmem_cpumask_var(cpumask_var_t *mask)
102{
103 *mask = alloc_bootmem(cpumask_size());
104}
105
106void free_cpumask_var(cpumask_var_t mask)
107{
108 kfree(mask);
109}
110EXPORT_SYMBOL(free_cpumask_var);
111
112void __init free_bootmem_cpumask_var(cpumask_var_t mask)
113{
114 free_bootmem((unsigned long)mask, cpumask_size());
115}
116#endif
diff --git a/lib/dynamic_printk.c b/lib/dynamic_printk.c
index d640f87bdc9e..d83660fd6fdd 100644
--- a/lib/dynamic_printk.c
+++ b/lib/dynamic_printk.c
@@ -402,6 +402,8 @@ static int __init dynamic_printk_init(void)
402 iter->logical_modname, 402 iter->logical_modname,
403 iter->flag_names, iter->hash, iter->hash2); 403 iter->flag_names, iter->hash, iter->hash2);
404 } 404 }
405 if (dynamic_enabled == DYNAMIC_ENABLED_ALL)
406 set_all(true);
405 return 0; 407 return 0;
406} 408}
407module_init(dynamic_printk_init); 409module_init(dynamic_printk_init);
@@ -411,7 +413,7 @@ static int __init dynamic_printk_setup(char *str)
411{ 413{
412 if (str) 414 if (str)
413 return -ENOENT; 415 return -ENOENT;
414 set_all(true); 416 dynamic_enabled = DYNAMIC_ENABLED_ALL;
415 return 0; 417 return 0;
416} 418}
417/* Use early_param(), so we can get debug output as early as possible */ 419/* Use early_param(), so we can get debug output as early as possible */
diff --git a/lib/idr.c b/lib/idr.c
index e728c7fccc4d..7a785a0c2ea0 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -185,6 +185,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
185 new = get_from_free_list(idp); 185 new = get_from_free_list(idp);
186 if (!new) 186 if (!new)
187 return -1; 187 return -1;
188 new->layer = l-1;
188 rcu_assign_pointer(p->ary[m], new); 189 rcu_assign_pointer(p->ary[m], new);
189 p->count++; 190 p->count++;
190 } 191 }
@@ -210,6 +211,7 @@ build_up:
210 if (unlikely(!p)) { 211 if (unlikely(!p)) {
211 if (!(p = get_from_free_list(idp))) 212 if (!(p = get_from_free_list(idp)))
212 return -1; 213 return -1;
214 p->layer = 0;
213 layers = 1; 215 layers = 1;
214 } 216 }
215 /* 217 /*
@@ -237,6 +239,7 @@ build_up:
237 } 239 }
238 new->ary[0] = p; 240 new->ary[0] = p;
239 new->count = 1; 241 new->count = 1;
242 new->layer = layers-1;
240 if (p->bitmap == IDR_FULL) 243 if (p->bitmap == IDR_FULL)
241 __set_bit(0, &new->bitmap); 244 __set_bit(0, &new->bitmap);
242 p = new; 245 p = new;
@@ -493,17 +496,21 @@ void *idr_find(struct idr *idp, int id)
493 int n; 496 int n;
494 struct idr_layer *p; 497 struct idr_layer *p;
495 498
496 n = idp->layers * IDR_BITS;
497 p = rcu_dereference(idp->top); 499 p = rcu_dereference(idp->top);
500 if (!p)
501 return NULL;
502 n = (p->layer+1) * IDR_BITS;
498 503
499 /* Mask off upper bits we don't use for the search. */ 504 /* Mask off upper bits we don't use for the search. */
500 id &= MAX_ID_MASK; 505 id &= MAX_ID_MASK;
501 506
502 if (id >= (1 << n)) 507 if (id >= (1 << n))
503 return NULL; 508 return NULL;
509 BUG_ON(n == 0);
504 510
505 while (n > 0 && p) { 511 while (n > 0 && p) {
506 n -= IDR_BITS; 512 n -= IDR_BITS;
513 BUG_ON(n != p->layer*IDR_BITS);
507 p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); 514 p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
508 } 515 }
509 return((void *)p); 516 return((void *)p);
@@ -582,8 +589,11 @@ void *idr_replace(struct idr *idp, void *ptr, int id)
582 int n; 589 int n;
583 struct idr_layer *p, *old_p; 590 struct idr_layer *p, *old_p;
584 591
585 n = idp->layers * IDR_BITS;
586 p = idp->top; 592 p = idp->top;
593 if (!p)
594 return ERR_PTR(-EINVAL);
595
596 n = (p->layer+1) * IDR_BITS;
587 597
588 id &= MAX_ID_MASK; 598 id &= MAX_ID_MASK;
589 599
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 8d2688ff1352..b7b449dafbe5 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -395,7 +395,7 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
395 WARN_ON(!irqs_disabled()); 395 WARN_ON(!irqs_disabled());
396 kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ); 396 kunmap_atomic(miter->addr, KM_BIO_SRC_IRQ);
397 } else 397 } else
398 kunmap(miter->addr); 398 kunmap(miter->page);
399 399
400 miter->page = NULL; 400 miter->page = NULL;
401 miter->addr = NULL; 401 miter->addr = NULL;
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 8347925030ff..ab431d4cc970 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -23,7 +23,7 @@
23int string_get_size(u64 size, const enum string_size_units units, 23int string_get_size(u64 size, const enum string_size_units units,
24 char *buf, int len) 24 char *buf, int len)
25{ 25{
26 const char *units_10[] = { "B", "KB", "MB", "GB", "TB", "PB", 26 const char *units_10[] = { "B", "kB", "MB", "GB", "TB", "PB",
27 "EB", "ZB", "YB", NULL}; 27 "EB", "ZB", "YB", NULL};
28 const char *units_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", 28 const char *units_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB",
29 "EiB", "ZiB", "YiB", NULL }; 29 "EiB", "ZiB", "YiB", NULL };
@@ -31,7 +31,7 @@ int string_get_size(u64 size, const enum string_size_units units,
31 [STRING_UNITS_10] = units_10, 31 [STRING_UNITS_10] = units_10,
32 [STRING_UNITS_2] = units_2, 32 [STRING_UNITS_2] = units_2,
33 }; 33 };
34 const int divisor[] = { 34 const unsigned int divisor[] = {
35 [STRING_UNITS_10] = 1000, 35 [STRING_UNITS_10] = 1000,
36 [STRING_UNITS_2] = 1024, 36 [STRING_UNITS_2] = 1024,
37 }; 37 };
@@ -40,23 +40,27 @@ int string_get_size(u64 size, const enum string_size_units units,
40 char tmp[8]; 40 char tmp[8];
41 41
42 tmp[0] = '\0'; 42 tmp[0] = '\0';
43 i = 0;
44 if (size >= divisor[units]) {
45 while (size >= divisor[units] && units_str[units][i]) {
46 remainder = do_div(size, divisor[units]);
47 i++;
48 }
43 49
44 for (i = 0; size > divisor[units] && units_str[units][i]; i++) 50 sf_cap = size;
45 remainder = do_div(size, divisor[units]); 51 for (j = 0; sf_cap*10 < 1000; j++)
52 sf_cap *= 10;
46 53
47 sf_cap = size; 54 if (j) {
48 for (j = 0; sf_cap*10 < 1000; j++) 55 remainder *= 1000;
49 sf_cap *= 10; 56 do_div(remainder, divisor[units]);
50 57 snprintf(tmp, sizeof(tmp), ".%03lld",
51 if (j) { 58 (unsigned long long)remainder);
52 remainder *= 1000; 59 tmp[j+1] = '\0';
53 do_div(remainder, divisor[units]); 60 }
54 snprintf(tmp, sizeof(tmp), ".%03lld",
55 (unsigned long long)remainder);
56 tmp[j+1] = '\0';
57 } 61 }
58 62
59 snprintf(buf, len, "%lld%s%s", (unsigned long long)size, 63 snprintf(buf, len, "%lld%s %s", (unsigned long long)size,
60 tmp, units_str[units][i]); 64 tmp, units_str[units][i]);
61 65
62 return 0; 66 return 0;
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index f8eebd489149..5f6c629a924d 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -467,9 +467,13 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
467 dma_addr_t dev_addr; 467 dma_addr_t dev_addr;
468 void *ret; 468 void *ret;
469 int order = get_order(size); 469 int order = get_order(size);
470 u64 dma_mask = DMA_32BIT_MASK;
471
472 if (hwdev && hwdev->coherent_dma_mask)
473 dma_mask = hwdev->coherent_dma_mask;
470 474
471 ret = (void *)__get_free_pages(flags, order); 475 ret = (void *)__get_free_pages(flags, order);
472 if (ret && address_needs_mapping(hwdev, virt_to_bus(ret), size)) { 476 if (ret && !is_buffer_dma_capable(dma_mask, virt_to_bus(ret), size)) {
473 /* 477 /*
474 * The allocated memory isn't reachable by the device. 478 * The allocated memory isn't reachable by the device.
475 * Fall back on swiotlb_map_single(). 479 * Fall back on swiotlb_map_single().
@@ -493,12 +497,14 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
493 dev_addr = virt_to_bus(ret); 497 dev_addr = virt_to_bus(ret);
494 498
495 /* Confirm address can be DMA'd by device */ 499 /* Confirm address can be DMA'd by device */
496 if (address_needs_mapping(hwdev, dev_addr, size)) { 500 if (!is_buffer_dma_capable(dma_mask, dev_addr, size)) {
497 printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n", 501 printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
498 (unsigned long long)*hwdev->dma_mask, 502 (unsigned long long)dma_mask,
499 (unsigned long long)dev_addr); 503 (unsigned long long)dev_addr);
500 panic("swiotlb_alloc_coherent: allocated memory is out of " 504
501 "range for device"); 505 /* DMA_TO_DEVICE to avoid memcpy in unmap_single */
506 unmap_single(hwdev, ret, size, DMA_TO_DEVICE);
507 return NULL;
502 } 508 }
503 *dma_handle = dev_addr; 509 *dma_handle = dev_addr;
504 return ret; 510 return ret;