diff options
Diffstat (limited to 'include/linux/init.h')
-rw-r--r-- | include/linux/init.h | 38 |
1 files changed, 13 insertions, 25 deletions
diff --git a/include/linux/init.h b/include/linux/init.h index 6935d02474aa..e571fec4bb28 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
@@ -150,24 +150,8 @@ extern bool initcall_debug; | |||
150 | 150 | ||
151 | #ifndef __ASSEMBLY__ | 151 | #ifndef __ASSEMBLY__ |
152 | 152 | ||
153 | #ifdef CONFIG_LTO | 153 | /* |
154 | /* Work around a LTO gcc problem: when there is no reference to a variable | 154 | * initcalls are now grouped by functionality into separate |
155 | * in a module it will be moved to the end of the program. This causes | ||
156 | * reordering of initcalls which the kernel does not like. | ||
157 | * Add a dummy reference function to avoid this. The function is | ||
158 | * deleted by the linker. | ||
159 | */ | ||
160 | #define LTO_REFERENCE_INITCALL(x) \ | ||
161 | ; /* yes this is needed */ \ | ||
162 | static __used __exit void *reference_##x(void) \ | ||
163 | { \ | ||
164 | return &x; \ | ||
165 | } | ||
166 | #else | ||
167 | #define LTO_REFERENCE_INITCALL(x) | ||
168 | #endif | ||
169 | |||
170 | /* initcalls are now grouped by functionality into separate | ||
171 | * subsections. Ordering inside the subsections is determined | 155 | * subsections. Ordering inside the subsections is determined |
172 | * by link order. | 156 | * by link order. |
173 | * For backwards compatibility, initcall() puts the call in | 157 | * For backwards compatibility, initcall() puts the call in |
@@ -175,12 +159,16 @@ extern bool initcall_debug; | |||
175 | * | 159 | * |
176 | * The `id' arg to __define_initcall() is needed so that multiple initcalls | 160 | * The `id' arg to __define_initcall() is needed so that multiple initcalls |
177 | * can point at the same handler without causing duplicate-symbol build errors. | 161 | * can point at the same handler without causing duplicate-symbol build errors. |
162 | * | ||
163 | * Initcalls are run by placing pointers in initcall sections that the | ||
164 | * kernel iterates at runtime. The linker can do dead code / data elimination | ||
165 | * and remove that completely, so the initcall sections have to be marked | ||
166 | * as KEEP() in the linker script. | ||
178 | */ | 167 | */ |
179 | 168 | ||
180 | #define __define_initcall(fn, id) \ | 169 | #define __define_initcall(fn, id) \ |
181 | static initcall_t __initcall_##fn##id __used \ | 170 | static initcall_t __initcall_##fn##id __used \ |
182 | __attribute__((__section__(".initcall" #id ".init"))) = fn; \ | 171 | __attribute__((__section__(".initcall" #id ".init"))) = fn; |
183 | LTO_REFERENCE_INITCALL(__initcall_##fn##id) | ||
184 | 172 | ||
185 | /* | 173 | /* |
186 | * Early initcalls run before initializing SMP. | 174 | * Early initcalls run before initializing SMP. |
@@ -216,15 +204,15 @@ extern bool initcall_debug; | |||
216 | 204 | ||
217 | #define __initcall(fn) device_initcall(fn) | 205 | #define __initcall(fn) device_initcall(fn) |
218 | 206 | ||
219 | #define __exitcall(fn) \ | 207 | #define __exitcall(fn) \ |
220 | static exitcall_t __exitcall_##fn __exit_call = fn | 208 | static exitcall_t __exitcall_##fn __exit_call = fn |
221 | 209 | ||
222 | #define console_initcall(fn) \ | 210 | #define console_initcall(fn) \ |
223 | static initcall_t __initcall_##fn \ | 211 | static initcall_t __initcall_##fn \ |
224 | __used __section(.con_initcall.init) = fn | 212 | __used __section(.con_initcall.init) = fn |
225 | 213 | ||
226 | #define security_initcall(fn) \ | 214 | #define security_initcall(fn) \ |
227 | static initcall_t __initcall_##fn \ | 215 | static initcall_t __initcall_##fn \ |
228 | __used __section(.security_initcall.init) = fn | 216 | __used __section(.security_initcall.init) = fn |
229 | 217 | ||
230 | struct obs_kernel_param { | 218 | struct obs_kernel_param { |