xref: /linux-6.15/include/linux/async.h (revision bf52b1ac)
1b886d83cSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
222a9d645SArjan van de Ven /*
322a9d645SArjan van de Ven  * async.h: Asynchronous function calls for boot performance
422a9d645SArjan van de Ven  *
522a9d645SArjan van de Ven  * (C) Copyright 2009 Intel Corporation
622a9d645SArjan van de Ven  * Author: Arjan van de Ven <[email protected]>
722a9d645SArjan van de Ven  */
82955b47dSDan Williams #ifndef __ASYNC_H__
92955b47dSDan Williams #define __ASYNC_H__
1022a9d645SArjan van de Ven 
1122a9d645SArjan van de Ven #include <linux/types.h>
1222a9d645SArjan van de Ven #include <linux/list.h>
136be9238eSAlexander Duyck #include <linux/numa.h>
146be9238eSAlexander Duyck #include <linux/device.h>
1522a9d645SArjan van de Ven 
1622a9d645SArjan van de Ven typedef u64 async_cookie_t;
17362f2b09SLai Jiangshan typedef void (*async_func_t) (void *data, async_cookie_t cookie);
182955b47dSDan Williams struct async_domain {
1952722794STejun Heo 	struct list_head pending;
202955b47dSDan Williams 	unsigned registered:1;
212955b47dSDan Williams };
222955b47dSDan Williams 
232955b47dSDan Williams /*
242955b47dSDan Williams  * domain participates in global async_synchronize_full
252955b47dSDan Williams  */
262955b47dSDan Williams #define ASYNC_DOMAIN(_name) \
27cc2a8b1aSLai Jiangshan 	struct async_domain _name = { .pending = LIST_HEAD_INIT(_name.pending),	\
282955b47dSDan Williams 				      .registered = 1 }
292955b47dSDan Williams 
302955b47dSDan Williams /*
312955b47dSDan Williams  * domain is free to go out of scope as soon as all pending work is
322955b47dSDan Williams  * complete, this domain does not participate in async_synchronize_full
332955b47dSDan Williams  */
342955b47dSDan Williams #define ASYNC_DOMAIN_EXCLUSIVE(_name) \
35cc2a8b1aSLai Jiangshan 	struct async_domain _name = { .pending = LIST_HEAD_INIT(_name.pending), \
362955b47dSDan Williams 				      .registered = 0 }
3722a9d645SArjan van de Ven 
386be9238eSAlexander Duyck async_cookie_t async_schedule_node(async_func_t func, void *data,
396be9238eSAlexander Duyck 				   int node);
406be9238eSAlexander Duyck async_cookie_t async_schedule_node_domain(async_func_t func, void *data,
416be9238eSAlexander Duyck 					  int node,
422955b47dSDan Williams 					  struct async_domain *domain);
436be9238eSAlexander Duyck 
446be9238eSAlexander Duyck /**
456be9238eSAlexander Duyck  * async_schedule - schedule a function for asynchronous execution
466be9238eSAlexander Duyck  * @func: function to execute asynchronously
476be9238eSAlexander Duyck  * @data: data pointer to pass to the function
486be9238eSAlexander Duyck  *
496be9238eSAlexander Duyck  * Returns an async_cookie_t that may be used for checkpointing later.
506be9238eSAlexander Duyck  * Note: This function may be called from atomic or non-atomic contexts.
516be9238eSAlexander Duyck  */
async_schedule(async_func_t func,void * data)526be9238eSAlexander Duyck static inline async_cookie_t async_schedule(async_func_t func, void *data)
536be9238eSAlexander Duyck {
546be9238eSAlexander Duyck 	return async_schedule_node(func, data, NUMA_NO_NODE);
556be9238eSAlexander Duyck }
566be9238eSAlexander Duyck 
576be9238eSAlexander Duyck /**
586be9238eSAlexander Duyck  * async_schedule_domain - schedule a function for asynchronous execution within a certain domain
596be9238eSAlexander Duyck  * @func: function to execute asynchronously
606be9238eSAlexander Duyck  * @data: data pointer to pass to the function
616be9238eSAlexander Duyck  * @domain: the domain
626be9238eSAlexander Duyck  *
636be9238eSAlexander Duyck  * Returns an async_cookie_t that may be used for checkpointing later.
646be9238eSAlexander Duyck  * @domain may be used in the async_synchronize_*_domain() functions to
656be9238eSAlexander Duyck  * wait within a certain synchronization domain rather than globally.
666be9238eSAlexander Duyck  * Note: This function may be called from atomic or non-atomic contexts.
676be9238eSAlexander Duyck  */
686be9238eSAlexander Duyck static inline async_cookie_t
async_schedule_domain(async_func_t func,void * data,struct async_domain * domain)696be9238eSAlexander Duyck async_schedule_domain(async_func_t func, void *data,
706be9238eSAlexander Duyck 		      struct async_domain *domain)
716be9238eSAlexander Duyck {
726be9238eSAlexander Duyck 	return async_schedule_node_domain(func, data, NUMA_NO_NODE, domain);
736be9238eSAlexander Duyck }
746be9238eSAlexander Duyck 
756be9238eSAlexander Duyck /**
766be9238eSAlexander Duyck  * async_schedule_dev - A device specific version of async_schedule
776be9238eSAlexander Duyck  * @func: function to execute asynchronously
786be9238eSAlexander Duyck  * @dev: device argument to be passed to function
796be9238eSAlexander Duyck  *
806be9238eSAlexander Duyck  * Returns an async_cookie_t that may be used for checkpointing later.
816be9238eSAlexander Duyck  * @dev is used as both the argument for the function and to provide NUMA
826be9238eSAlexander Duyck  * context for where to run the function. By doing this we can try to
836be9238eSAlexander Duyck  * provide for the best possible outcome by operating on the device on the
846be9238eSAlexander Duyck  * CPUs closest to the device.
856be9238eSAlexander Duyck  * Note: This function may be called from atomic or non-atomic contexts.
866be9238eSAlexander Duyck  */
876be9238eSAlexander Duyck static inline async_cookie_t
async_schedule_dev(async_func_t func,struct device * dev)886be9238eSAlexander Duyck async_schedule_dev(async_func_t func, struct device *dev)
896be9238eSAlexander Duyck {
906be9238eSAlexander Duyck 	return async_schedule_node(func, dev, dev_to_node(dev));
916be9238eSAlexander Duyck }
926be9238eSAlexander Duyck 
937d4b5d7aSRafael J. Wysocki bool async_schedule_dev_nocall(async_func_t func, struct device *dev);
947d4b5d7aSRafael J. Wysocki 
956be9238eSAlexander Duyck /**
966be9238eSAlexander Duyck  * async_schedule_dev_domain - A device specific version of async_schedule_domain
976be9238eSAlexander Duyck  * @func: function to execute asynchronously
986be9238eSAlexander Duyck  * @dev: device argument to be passed to function
996be9238eSAlexander Duyck  * @domain: the domain
1006be9238eSAlexander Duyck  *
1016be9238eSAlexander Duyck  * Returns an async_cookie_t that may be used for checkpointing later.
1026be9238eSAlexander Duyck  * @dev is used as both the argument for the function and to provide NUMA
1036be9238eSAlexander Duyck  * context for where to run the function. By doing this we can try to
1046be9238eSAlexander Duyck  * provide for the best possible outcome by operating on the device on the
1056be9238eSAlexander Duyck  * CPUs closest to the device.
1066be9238eSAlexander Duyck  * @domain may be used in the async_synchronize_*_domain() functions to
1076be9238eSAlexander Duyck  * wait within a certain synchronization domain rather than globally.
1086be9238eSAlexander Duyck  * Note: This function may be called from atomic or non-atomic contexts.
1096be9238eSAlexander Duyck  */
1106be9238eSAlexander Duyck static inline async_cookie_t
async_schedule_dev_domain(async_func_t func,struct device * dev,struct async_domain * domain)1116be9238eSAlexander Duyck async_schedule_dev_domain(async_func_t func, struct device *dev,
1126be9238eSAlexander Duyck 			  struct async_domain *domain)
1136be9238eSAlexander Duyck {
1146be9238eSAlexander Duyck 	return async_schedule_node_domain(func, dev, dev_to_node(dev), domain);
1156be9238eSAlexander Duyck }
1166be9238eSAlexander Duyck 
11722a9d645SArjan van de Ven extern void async_synchronize_full(void);
1182955b47dSDan Williams extern void async_synchronize_full_domain(struct async_domain *domain);
11922a9d645SArjan van de Ven extern void async_synchronize_cookie(async_cookie_t cookie);
120766ccb9eSCornelia Huck extern void async_synchronize_cookie_domain(async_cookie_t cookie,
1212955b47dSDan Williams 					    struct async_domain *domain);
12284b233adSTejun Heo extern bool current_is_async(void);
123*bf52b1acSTejun Heo extern void async_init(void);
1242955b47dSDan Williams #endif
125