| 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, data: dev, node: dev_to_node(dev)); | 
|---|
| 91 | } | 
|---|
| 92 |  | 
|---|
| 93 | bool async_schedule_dev_nocall(async_func_t func, struct device *dev); | 
|---|
| 94 |  | 
|---|
| 95 | /** | 
|---|
| 96 | * async_schedule_dev_domain - A device specific version of async_schedule_domain | 
|---|
| 97 | * @func: function to execute asynchronously | 
|---|
| 98 | * @dev: device argument to be passed to function | 
|---|
| 99 | * @domain: the domain | 
|---|
| 100 | * | 
|---|
| 101 | * Returns an async_cookie_t that may be used for checkpointing later. | 
|---|
| 102 | * @dev is used as both the argument for the function and to provide NUMA | 
|---|
| 103 | * context for where to run the function. By doing this we can try to | 
|---|
| 104 | * provide for the best possible outcome by operating on the device on the | 
|---|
| 105 | * CPUs closest to the device. | 
|---|
| 106 | * @domain may be used in the async_synchronize_*_domain() functions to | 
|---|
| 107 | * wait within a certain synchronization domain rather than globally. | 
|---|
| 108 | * Note: This function may be called from atomic or non-atomic contexts. | 
|---|
| 109 | */ | 
|---|
| 110 | static inline async_cookie_t | 
|---|
| 111 | async_schedule_dev_domain(async_func_t func, struct device *dev, | 
|---|
| 112 | struct async_domain *domain) | 
|---|
| 113 | { | 
|---|
| 114 | return async_schedule_node_domain(func, data: dev, node: dev_to_node(dev), domain); | 
|---|
| 115 | } | 
|---|
| 116 |  | 
|---|
| 117 | extern void async_synchronize_full(void); | 
|---|
| 118 | extern void async_synchronize_full_domain(struct async_domain *domain); | 
|---|
| 119 | extern void async_synchronize_cookie(async_cookie_t cookie); | 
|---|
| 120 | extern void async_synchronize_cookie_domain(async_cookie_t cookie, | 
|---|
| 121 | struct async_domain *domain); | 
|---|
| 122 | extern bool current_is_async(void); | 
|---|
| 123 | extern void async_init(void); | 
|---|
| 124 | #endif | 
|---|
| 125 |  | 
|---|