1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * async.h: Asynchronous function calls for boot performance 4 * 5 * (C) Copyright 2009 Intel Corporation 6 * Author: Arjan van de Ven <arjan@linux.intel.com> 7 */ 8 #ifndef __ASYNC_H__ 9 #define __ASYNC_H__ 10 11 #include <linux/types.h> 12 #include <linux/list.h> 13 #include <linux/numa.h> 14 #include <linux/device.h> 15 16 typedef u64 async_cookie_t; 17 typedef void (*async_func_t) (void *data, async_cookie_t cookie); 18 struct async_domain { 19 struct list_head pending; 20 unsigned registered:1; 21 }; 22 23 /* 24 * domain participates in global async_synchronize_full 25 */ 26 #define ASYNC_DOMAIN(_name) \ 27 struct async_domain _name = { .pending = LIST_HEAD_INIT(_name.pending), \ 28 .registered = 1 } 29 30 /* 31 * domain is free to go out of scope as soon as all pending work is 32 * complete, this domain does not participate in async_synchronize_full 33 */ 34 #define ASYNC_DOMAIN_EXCLUSIVE(_name) \ 35 struct async_domain _name = { .pending = LIST_HEAD_INIT(_name.pending), \ 36 .registered = 0 } 37 38 async_cookie_t async_schedule_node(async_func_t func, void *data, 39 int node); 40 async_cookie_t async_schedule_node_domain(async_func_t func, void *data, 41 int node, 42 struct async_domain *domain); 43 44 /** 45 * async_schedule - schedule a function for asynchronous execution 46 * @func: function to execute asynchronously 47 * @data: data pointer to pass to the function 48 * 49 * Returns an async_cookie_t that may be used for checkpointing later. 50 * Note: This function may be called from atomic or non-atomic contexts. 51 */ 52 static inline async_cookie_t async_schedule(async_func_t func, void *data) 53 { 54 return async_schedule_node(func, data, NUMA_NO_NODE); 55 } 56 57 /** 58 * async_schedule_domain - schedule a function for asynchronous execution within a certain domain 59 * @func: function to execute asynchronously 60 * @data: data pointer to pass to the function 61 * @domain: the domain 62 * 63 * Returns an async_cookie_t that may be used for checkpointing later. 64 * @domain may be used in the async_synchronize_*_domain() functions to 65 * wait within a certain synchronization domain rather than globally. 66 * Note: This function may be called from atomic or non-atomic contexts. 67 */ 68 static inline async_cookie_t 69 async_schedule_domain(async_func_t func, void *data, 70 struct async_domain *domain) 71 { 72 return async_schedule_node_domain(func, data, NUMA_NO_NODE, domain); 73 } 74 75 /** 76 * async_schedule_dev - A device specific version of async_schedule 77 * @func: function to execute asynchronously 78 * @dev: device argument to be passed to function 79 * 80 * Returns an async_cookie_t that may be used for checkpointing later. 81 * @dev is used as both the argument for the function and to provide NUMA 82 * context for where to run the function. By doing this we can try to 83 * provide for the best possible outcome by operating on the device on the 84 * CPUs closest to the device. 85 * Note: This function may be called from atomic or non-atomic contexts. 86 */ 87 static inline async_cookie_t 88 async_schedule_dev(async_func_t func, struct device *dev) 89 { 90 return async_schedule_node(func, dev, dev_to_node(dev)); 91 } 92 93 /** 94 * async_schedule_dev_domain - A device specific version of async_schedule_domain 95 * @func: function to execute asynchronously 96 * @dev: device argument to be passed to function 97 * @domain: the domain 98 * 99 * Returns an async_cookie_t that may be used for checkpointing later. 100 * @dev is used as both the argument for the function and to provide NUMA 101 * context for where to run the function. By doing this we can try to 102 * provide for the best possible outcome by operating on the device on the 103 * CPUs closest to the device. 104 * @domain may be used in the async_synchronize_*_domain() functions to 105 * wait within a certain synchronization domain rather than globally. 106 * Note: This function may be called from atomic or non-atomic contexts. 107 */ 108 static inline async_cookie_t 109 async_schedule_dev_domain(async_func_t func, struct device *dev, 110 struct async_domain *domain) 111 { 112 return async_schedule_node_domain(func, dev, dev_to_node(dev), domain); 113 } 114 115 void async_unregister_domain(struct async_domain *domain); 116 extern void async_synchronize_full(void); 117 extern void async_synchronize_full_domain(struct async_domain *domain); 118 extern void async_synchronize_cookie(async_cookie_t cookie); 119 extern void async_synchronize_cookie_domain(async_cookie_t cookie, 120 struct async_domain *domain); 121 extern bool current_is_async(void); 122 #endif