diff options
Diffstat (limited to 'include/linux/percpu.h')
-rw-r--r-- | include/linux/percpu.h | 112 |
1 files changed, 78 insertions, 34 deletions
diff --git a/include/linux/percpu.h b/include/linux/percpu.h index 3577ffd90d45..ee5615d65211 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/slab.h> /* For kmalloc() */ | 5 | #include <linux/slab.h> /* For kmalloc() */ |
6 | #include <linux/smp.h> | 6 | #include <linux/smp.h> |
7 | #include <linux/cpumask.h> | 7 | #include <linux/cpumask.h> |
8 | #include <linux/pfn.h> | ||
8 | 9 | ||
9 | #include <asm/percpu.h> | 10 | #include <asm/percpu.h> |
10 | 11 | ||
@@ -52,17 +53,18 @@ | |||
52 | #define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var) | 53 | #define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var) |
53 | #define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var) | 54 | #define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var) |
54 | 55 | ||
55 | /* Enough to cover all DEFINE_PER_CPUs in kernel, including modules. */ | 56 | /* enough to cover all DEFINE_PER_CPUs in modules */ |
56 | #ifndef PERCPU_ENOUGH_ROOM | ||
57 | #ifdef CONFIG_MODULES | 57 | #ifdef CONFIG_MODULES |
58 | #define PERCPU_MODULE_RESERVE 8192 | 58 | #define PERCPU_MODULE_RESERVE (8 << 10) |
59 | #else | 59 | #else |
60 | #define PERCPU_MODULE_RESERVE 0 | 60 | #define PERCPU_MODULE_RESERVE 0 |
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | #ifndef PERCPU_ENOUGH_ROOM | ||
63 | #define PERCPU_ENOUGH_ROOM \ | 64 | #define PERCPU_ENOUGH_ROOM \ |
64 | (__per_cpu_end - __per_cpu_start + PERCPU_MODULE_RESERVE) | 65 | (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \ |
65 | #endif /* PERCPU_ENOUGH_ROOM */ | 66 | PERCPU_MODULE_RESERVE) |
67 | #endif | ||
66 | 68 | ||
67 | /* | 69 | /* |
68 | * Must be an lvalue. Since @var must be a simple identifier, | 70 | * Must be an lvalue. Since @var must be a simple identifier, |
@@ -76,52 +78,94 @@ | |||
76 | 78 | ||
77 | #ifdef CONFIG_SMP | 79 | #ifdef CONFIG_SMP |
78 | 80 | ||
81 | #ifdef CONFIG_HAVE_DYNAMIC_PER_CPU_AREA | ||
82 | |||
83 | /* minimum unit size, also is the maximum supported allocation size */ | ||
84 | #define PCPU_MIN_UNIT_SIZE PFN_ALIGN(64 << 10) | ||
85 | |||
86 | /* | ||
87 | * PERCPU_DYNAMIC_RESERVE indicates the amount of free area to piggy | ||
88 | * back on the first chunk for dynamic percpu allocation if arch is | ||
89 | * manually allocating and mapping it for faster access (as a part of | ||
90 | * large page mapping for example). | ||
91 | * | ||
92 | * The following values give between one and two pages of free space | ||
93 | * after typical minimal boot (2-way SMP, single disk and NIC) with | ||
94 | * both defconfig and a distro config on x86_64 and 32. More | ||
95 | * intelligent way to determine this would be nice. | ||
96 | */ | ||
97 | #if BITS_PER_LONG > 32 | ||
98 | #define PERCPU_DYNAMIC_RESERVE (20 << 10) | ||
99 | #else | ||
100 | #define PERCPU_DYNAMIC_RESERVE (12 << 10) | ||
101 | #endif | ||
102 | |||
103 | extern void *pcpu_base_addr; | ||
104 | |||
105 | typedef struct page * (*pcpu_get_page_fn_t)(unsigned int cpu, int pageno); | ||
106 | typedef void (*pcpu_populate_pte_fn_t)(unsigned long addr); | ||
107 | |||
108 | extern size_t __init pcpu_setup_first_chunk(pcpu_get_page_fn_t get_page_fn, | ||
109 | size_t static_size, size_t reserved_size, | ||
110 | ssize_t dyn_size, ssize_t unit_size, | ||
111 | void *base_addr, | ||
112 | pcpu_populate_pte_fn_t populate_pte_fn); | ||
113 | |||
114 | extern ssize_t __init pcpu_embed_first_chunk( | ||
115 | size_t static_size, size_t reserved_size, | ||
116 | ssize_t dyn_size, ssize_t unit_size); | ||
117 | |||
118 | /* | ||
119 | * Use this to get to a cpu's version of the per-cpu object | ||
120 | * dynamically allocated. Non-atomic access to the current CPU's | ||
121 | * version should probably be combined with get_cpu()/put_cpu(). | ||
122 | */ | ||
123 | #define per_cpu_ptr(ptr, cpu) SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu))) | ||
124 | |||
125 | extern void *__alloc_reserved_percpu(size_t size, size_t align); | ||
126 | |||
127 | #else /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ | ||
128 | |||
79 | struct percpu_data { | 129 | struct percpu_data { |
80 | void *ptrs[1]; | 130 | void *ptrs[1]; |
81 | }; | 131 | }; |
82 | 132 | ||
83 | #define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata) | 133 | #define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata) |
84 | /* | 134 | |
85 | * Use this to get to a cpu's version of the per-cpu object dynamically | 135 | #define per_cpu_ptr(ptr, cpu) \ |
86 | * allocated. Non-atomic access to the current CPU's version should | 136 | ({ \ |
87 | * probably be combined with get_cpu()/put_cpu(). | 137 | struct percpu_data *__p = __percpu_disguise(ptr); \ |
88 | */ | 138 | (__typeof__(ptr))__p->ptrs[(cpu)]; \ |
89 | #define percpu_ptr(ptr, cpu) \ | ||
90 | ({ \ | ||
91 | struct percpu_data *__p = __percpu_disguise(ptr); \ | ||
92 | (__typeof__(ptr))__p->ptrs[(cpu)]; \ | ||
93 | }) | 139 | }) |
94 | 140 | ||
95 | extern void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask); | 141 | #endif /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ |
96 | extern void percpu_free(void *__pdata); | 142 | |
143 | extern void *__alloc_percpu(size_t size, size_t align); | ||
144 | extern void free_percpu(void *__pdata); | ||
97 | 145 | ||
98 | #else /* CONFIG_SMP */ | 146 | #else /* CONFIG_SMP */ |
99 | 147 | ||
100 | #define percpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) | 148 | #define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) |
101 | 149 | ||
102 | static __always_inline void *__percpu_alloc_mask(size_t size, gfp_t gfp, cpumask_t *mask) | 150 | static inline void *__alloc_percpu(size_t size, size_t align) |
103 | { | 151 | { |
104 | return kzalloc(size, gfp); | 152 | /* |
153 | * Can't easily make larger alignment work with kmalloc. WARN | ||
154 | * on it. Larger alignment should only be used for module | ||
155 | * percpu sections on SMP for which this path isn't used. | ||
156 | */ | ||
157 | WARN_ON_ONCE(align > SMP_CACHE_BYTES); | ||
158 | return kzalloc(size, GFP_KERNEL); | ||
105 | } | 159 | } |
106 | 160 | ||
107 | static inline void percpu_free(void *__pdata) | 161 | static inline void free_percpu(void *p) |
108 | { | 162 | { |
109 | kfree(__pdata); | 163 | kfree(p); |
110 | } | 164 | } |
111 | 165 | ||
112 | #endif /* CONFIG_SMP */ | 166 | #endif /* CONFIG_SMP */ |
113 | 167 | ||
114 | #define percpu_alloc_mask(size, gfp, mask) \ | 168 | #define alloc_percpu(type) (type *)__alloc_percpu(sizeof(type), \ |
115 | __percpu_alloc_mask((size), (gfp), &(mask)) | 169 | __alignof__(type)) |
116 | |||
117 | #define percpu_alloc(size, gfp) percpu_alloc_mask((size), (gfp), cpu_online_map) | ||
118 | |||
119 | /* (legacy) interface for use without CPU hotplug handling */ | ||
120 | |||
121 | #define __alloc_percpu(size) percpu_alloc_mask((size), GFP_KERNEL, \ | ||
122 | cpu_possible_map) | ||
123 | #define alloc_percpu(type) (type *)__alloc_percpu(sizeof(type)) | ||
124 | #define free_percpu(ptr) percpu_free((ptr)) | ||
125 | #define per_cpu_ptr(ptr, cpu) percpu_ptr((ptr), (cpu)) | ||
126 | 170 | ||
127 | #endif /* __LINUX_PERCPU_H */ | 171 | #endif /* __LINUX_PERCPU_H */ |