diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 3 | ||||
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/bust_spinlocks.c | 3 | ||||
-rw-r--r-- | lib/dma-debug.c | 45 | ||||
-rw-r--r-- | lib/kobject.c | 9 | ||||
-rw-r--r-- | lib/swiotlb.c | 19 | ||||
-rw-r--r-- | lib/ucs2_string.c | 51 |
7 files changed, 111 insertions, 21 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 3958dc4389f9..fe01d418b09a 100644 --- a/lib/Kconfig +++ b/lib/Kconfig | |||
@@ -404,4 +404,7 @@ config OID_REGISTRY | |||
404 | help | 404 | help |
405 | Enable fast lookup object identifier registry. | 405 | Enable fast lookup object identifier registry. |
406 | 406 | ||
407 | config UCS2_STRING | ||
408 | tristate | ||
409 | |||
407 | endmenu | 410 | endmenu |
diff --git a/lib/Makefile b/lib/Makefile index d7946ff75b2e..6e2cc561f761 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -174,3 +174,5 @@ quiet_cmd_build_OID_registry = GEN $@ | |||
174 | cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@ | 174 | cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@ |
175 | 175 | ||
176 | clean-files += oid_registry_data.c | 176 | clean-files += oid_registry_data.c |
177 | |||
178 | obj-$(CONFIG_UCS2_STRING) += ucs2_string.o | ||
diff --git a/lib/bust_spinlocks.c b/lib/bust_spinlocks.c index 9681d54b95d1..f8e0e5367398 100644 --- a/lib/bust_spinlocks.c +++ b/lib/bust_spinlocks.c | |||
@@ -8,6 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/printk.h> | ||
11 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
12 | #include <linux/tty.h> | 13 | #include <linux/tty.h> |
13 | #include <linux/wait.h> | 14 | #include <linux/wait.h> |
@@ -28,5 +29,3 @@ void __attribute__((weak)) bust_spinlocks(int yes) | |||
28 | wake_up_klogd(); | 29 | wake_up_klogd(); |
29 | } | 30 | } |
30 | } | 31 | } |
31 | |||
32 | |||
diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 5e396accd3d0..d87a17a819d0 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c | |||
@@ -862,17 +862,21 @@ static void check_unmap(struct dma_debug_entry *ref) | |||
862 | entry = bucket_find_exact(bucket, ref); | 862 | entry = bucket_find_exact(bucket, ref); |
863 | 863 | ||
864 | if (!entry) { | 864 | if (!entry) { |
865 | /* must drop lock before calling dma_mapping_error */ | ||
866 | put_hash_bucket(bucket, &flags); | ||
867 | |||
865 | if (dma_mapping_error(ref->dev, ref->dev_addr)) { | 868 | if (dma_mapping_error(ref->dev, ref->dev_addr)) { |
866 | err_printk(ref->dev, NULL, | 869 | err_printk(ref->dev, NULL, |
867 | "DMA-API: device driver tries " | 870 | "DMA-API: device driver tries to free an " |
868 | "to free an invalid DMA memory address\n"); | 871 | "invalid DMA memory address\n"); |
869 | return; | 872 | } else { |
873 | err_printk(ref->dev, NULL, | ||
874 | "DMA-API: device driver tries to free DMA " | ||
875 | "memory it has not allocated [device " | ||
876 | "address=0x%016llx] [size=%llu bytes]\n", | ||
877 | ref->dev_addr, ref->size); | ||
870 | } | 878 | } |
871 | err_printk(ref->dev, NULL, "DMA-API: device driver tries " | 879 | return; |
872 | "to free DMA memory it has not allocated " | ||
873 | "[device address=0x%016llx] [size=%llu bytes]\n", | ||
874 | ref->dev_addr, ref->size); | ||
875 | goto out; | ||
876 | } | 880 | } |
877 | 881 | ||
878 | if (ref->size != entry->size) { | 882 | if (ref->size != entry->size) { |
@@ -936,7 +940,6 @@ static void check_unmap(struct dma_debug_entry *ref) | |||
936 | hash_bucket_del(entry); | 940 | hash_bucket_del(entry); |
937 | dma_entry_free(entry); | 941 | dma_entry_free(entry); |
938 | 942 | ||
939 | out: | ||
940 | put_hash_bucket(bucket, &flags); | 943 | put_hash_bucket(bucket, &flags); |
941 | } | 944 | } |
942 | 945 | ||
@@ -1082,13 +1085,27 @@ void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | |||
1082 | ref.dev = dev; | 1085 | ref.dev = dev; |
1083 | ref.dev_addr = dma_addr; | 1086 | ref.dev_addr = dma_addr; |
1084 | bucket = get_hash_bucket(&ref, &flags); | 1087 | bucket = get_hash_bucket(&ref, &flags); |
1085 | entry = bucket_find_exact(bucket, &ref); | ||
1086 | 1088 | ||
1087 | if (!entry) | 1089 | list_for_each_entry(entry, &bucket->list, list) { |
1088 | goto out; | 1090 | if (!exact_match(&ref, entry)) |
1091 | continue; | ||
1092 | |||
1093 | /* | ||
1094 | * The same physical address can be mapped multiple | ||
1095 | * times. Without a hardware IOMMU this results in the | ||
1096 | * same device addresses being put into the dma-debug | ||
1097 | * hash multiple times too. This can result in false | ||
1098 | * positives being reported. Therefore we implement a | ||
1099 | * best-fit algorithm here which updates the first entry | ||
1100 | * from the hash which fits the reference value and is | ||
1101 | * not currently listed as being checked. | ||
1102 | */ | ||
1103 | if (entry->map_err_type == MAP_ERR_NOT_CHECKED) { | ||
1104 | entry->map_err_type = MAP_ERR_CHECKED; | ||
1105 | break; | ||
1106 | } | ||
1107 | } | ||
1089 | 1108 | ||
1090 | entry->map_err_type = MAP_ERR_CHECKED; | ||
1091 | out: | ||
1092 | put_hash_bucket(bucket, &flags); | 1109 | put_hash_bucket(bucket, &flags); |
1093 | } | 1110 | } |
1094 | EXPORT_SYMBOL(debug_dma_mapping_error); | 1111 | EXPORT_SYMBOL(debug_dma_mapping_error); |
diff --git a/lib/kobject.c b/lib/kobject.c index e07ee1fcd6f1..a65486613d79 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
@@ -529,6 +529,13 @@ struct kobject *kobject_get(struct kobject *kobj) | |||
529 | return kobj; | 529 | return kobj; |
530 | } | 530 | } |
531 | 531 | ||
532 | static struct kobject *kobject_get_unless_zero(struct kobject *kobj) | ||
533 | { | ||
534 | if (!kref_get_unless_zero(&kobj->kref)) | ||
535 | kobj = NULL; | ||
536 | return kobj; | ||
537 | } | ||
538 | |||
532 | /* | 539 | /* |
533 | * kobject_cleanup - free kobject resources. | 540 | * kobject_cleanup - free kobject resources. |
534 | * @kobj: object to cleanup | 541 | * @kobj: object to cleanup |
@@ -751,7 +758,7 @@ struct kobject *kset_find_obj(struct kset *kset, const char *name) | |||
751 | 758 | ||
752 | list_for_each_entry(k, &kset->list, entry) { | 759 | list_for_each_entry(k, &kset->list, entry) { |
753 | if (kobject_name(k) && !strcmp(kobject_name(k), name)) { | 760 | if (kobject_name(k) && !strcmp(kobject_name(k), name)) { |
754 | ret = kobject_get(k); | 761 | ret = kobject_get_unless_zero(k); |
755 | break; | 762 | break; |
756 | } | 763 | } |
757 | } | 764 | } |
diff --git a/lib/swiotlb.c b/lib/swiotlb.c index bfe02b8fc55b..d23762e6652c 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c | |||
@@ -105,9 +105,9 @@ setup_io_tlb_npages(char *str) | |||
105 | if (!strcmp(str, "force")) | 105 | if (!strcmp(str, "force")) |
106 | swiotlb_force = 1; | 106 | swiotlb_force = 1; |
107 | 107 | ||
108 | return 1; | 108 | return 0; |
109 | } | 109 | } |
110 | __setup("swiotlb=", setup_io_tlb_npages); | 110 | early_param("swiotlb", setup_io_tlb_npages); |
111 | /* make io_tlb_overflow tunable too? */ | 111 | /* make io_tlb_overflow tunable too? */ |
112 | 112 | ||
113 | unsigned long swiotlb_nr_tbl(void) | 113 | unsigned long swiotlb_nr_tbl(void) |
@@ -115,6 +115,18 @@ unsigned long swiotlb_nr_tbl(void) | |||
115 | return io_tlb_nslabs; | 115 | return io_tlb_nslabs; |
116 | } | 116 | } |
117 | EXPORT_SYMBOL_GPL(swiotlb_nr_tbl); | 117 | EXPORT_SYMBOL_GPL(swiotlb_nr_tbl); |
118 | |||
119 | /* default to 64MB */ | ||
120 | #define IO_TLB_DEFAULT_SIZE (64UL<<20) | ||
121 | unsigned long swiotlb_size_or_default(void) | ||
122 | { | ||
123 | unsigned long size; | ||
124 | |||
125 | size = io_tlb_nslabs << IO_TLB_SHIFT; | ||
126 | |||
127 | return size ? size : (IO_TLB_DEFAULT_SIZE); | ||
128 | } | ||
129 | |||
118 | /* Note that this doesn't work with highmem page */ | 130 | /* Note that this doesn't work with highmem page */ |
119 | static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev, | 131 | static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev, |
120 | volatile void *address) | 132 | volatile void *address) |
@@ -188,8 +200,7 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) | |||
188 | void __init | 200 | void __init |
189 | swiotlb_init(int verbose) | 201 | swiotlb_init(int verbose) |
190 | { | 202 | { |
191 | /* default to 64MB */ | 203 | size_t default_size = IO_TLB_DEFAULT_SIZE; |
192 | size_t default_size = 64UL<<20; | ||
193 | unsigned char *vstart; | 204 | unsigned char *vstart; |
194 | unsigned long bytes; | 205 | unsigned long bytes; |
195 | 206 | ||
diff --git a/lib/ucs2_string.c b/lib/ucs2_string.c new file mode 100644 index 000000000000..6f500ef2301d --- /dev/null +++ b/lib/ucs2_string.c | |||
@@ -0,0 +1,51 @@ | |||
1 | #include <linux/ucs2_string.h> | ||
2 | #include <linux/module.h> | ||
3 | |||
4 | /* Return the number of unicode characters in data */ | ||
5 | unsigned long | ||
6 | ucs2_strnlen(const ucs2_char_t *s, size_t maxlength) | ||
7 | { | ||
8 | unsigned long length = 0; | ||
9 | |||
10 | while (*s++ != 0 && length < maxlength) | ||
11 | length++; | ||
12 | return length; | ||
13 | } | ||
14 | EXPORT_SYMBOL(ucs2_strnlen); | ||
15 | |||
16 | unsigned long | ||
17 | ucs2_strlen(const ucs2_char_t *s) | ||
18 | { | ||
19 | return ucs2_strnlen(s, ~0UL); | ||
20 | } | ||
21 | EXPORT_SYMBOL(ucs2_strlen); | ||
22 | |||
23 | /* | ||
24 | * Return the number of bytes is the length of this string | ||
25 | * Note: this is NOT the same as the number of unicode characters | ||
26 | */ | ||
27 | unsigned long | ||
28 | ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength) | ||
29 | { | ||
30 | return ucs2_strnlen(data, maxlength/sizeof(ucs2_char_t)) * sizeof(ucs2_char_t); | ||
31 | } | ||
32 | EXPORT_SYMBOL(ucs2_strsize); | ||
33 | |||
34 | int | ||
35 | ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len) | ||
36 | { | ||
37 | while (1) { | ||
38 | if (len == 0) | ||
39 | return 0; | ||
40 | if (*a < *b) | ||
41 | return -1; | ||
42 | if (*a > *b) | ||
43 | return 1; | ||
44 | if (*a == 0) /* implies *b == 0 */ | ||
45 | return 0; | ||
46 | a++; | ||
47 | b++; | ||
48 | len--; | ||
49 | } | ||
50 | } | ||
51 | EXPORT_SYMBOL(ucs2_strncmp); | ||