Branch data Line data Source code
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 : 84 : static inline async_cookie_t async_schedule(async_func_t func, void *data) 53 : : { 54 : 84 : 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 : 0 : async_schedule_domain(async_func_t func, void *data, 70 : : struct async_domain *domain) 71 : : { 72 : 0 : 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 : 56 : async_schedule_dev(async_func_t func, struct device *dev) 89 : : { 90 : 56 : 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