.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * async.c: Asynchronous function calls for boot performance |
---|
3 | 4 | * |
---|
4 | 5 | * (C) Copyright 2009 Intel Corporation |
---|
5 | 6 | * Author: Arjan van de Ven <arjan@linux.intel.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License |
---|
9 | | - * as published by the Free Software Foundation; version 2 |
---|
10 | | - * of the License. |
---|
11 | 7 | */ |
---|
12 | 8 | |
---|
13 | 9 | |
---|
.. | .. |
---|
115 | 111 | struct async_entry *entry = |
---|
116 | 112 | container_of(work, struct async_entry, work); |
---|
117 | 113 | unsigned long flags; |
---|
118 | | - ktime_t uninitialized_var(calltime), delta, rettime; |
---|
| 114 | + ktime_t calltime, delta, rettime; |
---|
119 | 115 | |
---|
120 | 116 | /* 1) run (and print duration) */ |
---|
121 | 117 | if (initcall_debug && system_state < SYSTEM_RUNNING) { |
---|
122 | | - pr_debug("calling %lli_%pF @ %i\n", |
---|
| 118 | + pr_debug("calling %lli_%pS @ %i\n", |
---|
123 | 119 | (long long)entry->cookie, |
---|
124 | 120 | entry->func, task_pid_nr(current)); |
---|
125 | 121 | calltime = ktime_get(); |
---|
.. | .. |
---|
128 | 124 | if (initcall_debug && system_state < SYSTEM_RUNNING) { |
---|
129 | 125 | rettime = ktime_get(); |
---|
130 | 126 | delta = ktime_sub(rettime, calltime); |
---|
131 | | - pr_debug("initcall %lli_%pF returned 0 after %lld usecs\n", |
---|
| 127 | + pr_debug("initcall %lli_%pS returned 0 after %lld usecs\n", |
---|
132 | 128 | (long long)entry->cookie, |
---|
133 | 129 | entry->func, |
---|
134 | 130 | (long long)ktime_to_ns(delta) >> 10); |
---|
.. | .. |
---|
149 | 145 | wake_up(&async_done); |
---|
150 | 146 | } |
---|
151 | 147 | |
---|
152 | | -static async_cookie_t __async_schedule(async_func_t func, void *data, struct async_domain *domain) |
---|
| 148 | +/** |
---|
| 149 | + * async_schedule_node_domain - NUMA specific version of async_schedule_domain |
---|
| 150 | + * @func: function to execute asynchronously |
---|
| 151 | + * @data: data pointer to pass to the function |
---|
| 152 | + * @node: NUMA node that we want to schedule this on or close to |
---|
| 153 | + * @domain: the domain |
---|
| 154 | + * |
---|
| 155 | + * Returns an async_cookie_t that may be used for checkpointing later. |
---|
| 156 | + * @domain may be used in the async_synchronize_*_domain() functions to |
---|
| 157 | + * wait within a certain synchronization domain rather than globally. |
---|
| 158 | + * |
---|
| 159 | + * Note: This function may be called from atomic or non-atomic contexts. |
---|
| 160 | + * |
---|
| 161 | + * The node requested will be honored on a best effort basis. If the node |
---|
| 162 | + * has no CPUs associated with it then the work is distributed among all |
---|
| 163 | + * available CPUs. |
---|
| 164 | + */ |
---|
| 165 | +async_cookie_t async_schedule_node_domain(async_func_t func, void *data, |
---|
| 166 | + int node, struct async_domain *domain) |
---|
153 | 167 | { |
---|
154 | 168 | struct async_entry *entry; |
---|
155 | 169 | unsigned long flags; |
---|
.. | .. |
---|
192 | 206 | spin_unlock_irqrestore(&async_lock, flags); |
---|
193 | 207 | |
---|
194 | 208 | /* schedule for execution */ |
---|
195 | | - queue_work(system_unbound_wq, &entry->work); |
---|
| 209 | + queue_work_node(node, system_unbound_wq, &entry->work); |
---|
196 | 210 | |
---|
197 | 211 | return newcookie; |
---|
198 | 212 | } |
---|
| 213 | +EXPORT_SYMBOL_GPL(async_schedule_node_domain); |
---|
199 | 214 | |
---|
200 | 215 | /** |
---|
201 | | - * async_schedule - schedule a function for asynchronous execution |
---|
| 216 | + * async_schedule_node - NUMA specific version of async_schedule |
---|
202 | 217 | * @func: function to execute asynchronously |
---|
203 | 218 | * @data: data pointer to pass to the function |
---|
| 219 | + * @node: NUMA node that we want to schedule this on or close to |
---|
204 | 220 | * |
---|
205 | 221 | * Returns an async_cookie_t that may be used for checkpointing later. |
---|
206 | 222 | * Note: This function may be called from atomic or non-atomic contexts. |
---|
207 | | - */ |
---|
208 | | -async_cookie_t async_schedule(async_func_t func, void *data) |
---|
209 | | -{ |
---|
210 | | - return __async_schedule(func, data, &async_dfl_domain); |
---|
211 | | -} |
---|
212 | | -EXPORT_SYMBOL_GPL(async_schedule); |
---|
213 | | - |
---|
214 | | -/** |
---|
215 | | - * async_schedule_domain - schedule a function for asynchronous execution within a certain domain |
---|
216 | | - * @func: function to execute asynchronously |
---|
217 | | - * @data: data pointer to pass to the function |
---|
218 | | - * @domain: the domain |
---|
219 | 223 | * |
---|
220 | | - * Returns an async_cookie_t that may be used for checkpointing later. |
---|
221 | | - * @domain may be used in the async_synchronize_*_domain() functions to |
---|
222 | | - * wait within a certain synchronization domain rather than globally. A |
---|
223 | | - * synchronization domain is specified via @domain. Note: This function |
---|
224 | | - * may be called from atomic or non-atomic contexts. |
---|
| 224 | + * The node requested will be honored on a best effort basis. If the node |
---|
| 225 | + * has no CPUs associated with it then the work is distributed among all |
---|
| 226 | + * available CPUs. |
---|
225 | 227 | */ |
---|
226 | | -async_cookie_t async_schedule_domain(async_func_t func, void *data, |
---|
227 | | - struct async_domain *domain) |
---|
| 228 | +async_cookie_t async_schedule_node(async_func_t func, void *data, int node) |
---|
228 | 229 | { |
---|
229 | | - return __async_schedule(func, data, domain); |
---|
| 230 | + return async_schedule_node_domain(func, data, node, &async_dfl_domain); |
---|
230 | 231 | } |
---|
231 | | -EXPORT_SYMBOL_GPL(async_schedule_domain); |
---|
| 232 | +EXPORT_SYMBOL_GPL(async_schedule_node); |
---|
232 | 233 | |
---|
233 | 234 | /** |
---|
234 | 235 | * async_synchronize_full - synchronize all asynchronous function calls |
---|
.. | .. |
---|
283 | 284 | */ |
---|
284 | 285 | void async_synchronize_cookie_domain(async_cookie_t cookie, struct async_domain *domain) |
---|
285 | 286 | { |
---|
286 | | - ktime_t uninitialized_var(starttime), delta, endtime; |
---|
| 287 | + ktime_t starttime, delta, endtime; |
---|
287 | 288 | |
---|
288 | 289 | if (initcall_debug && system_state < SYSTEM_RUNNING) { |
---|
289 | 290 | pr_debug("async_waiting @ %i\n", task_pid_nr(current)); |
---|