Skip to content

Commit 7d4b5d7

Browse files
committed
async: Introduce async_schedule_dev_nocall()
In preparation for subsequent changes, introduce a specialized variant of async_schedule_dev() that will not invoke the argument function synchronously when it cannot be scheduled for asynchronous execution. The new function, async_schedule_dev_nocall(), will be used for fixing possible deadlocks in the system-wide power management core code. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Reviewed-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com> for the series. Tested-by: Youngmin Nam <youngmin.nam@samsung.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent 6aa09a5 commit 7d4b5d7

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

include/linux/async.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ async_schedule_dev(async_func_t func, struct device *dev)
9090
return async_schedule_node(func, dev, dev_to_node(dev));
9191
}
9292

93+
bool async_schedule_dev_nocall(async_func_t func, struct device *dev);
94+
9395
/**
9496
* async_schedule_dev_domain - A device specific version of async_schedule_domain
9597
* @func: function to execute asynchronously

kernel/async.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,35 @@ async_cookie_t async_schedule_node(async_func_t func, void *data, int node)
243243
}
244244
EXPORT_SYMBOL_GPL(async_schedule_node);
245245

246+
/**
247+
* async_schedule_dev_nocall - A simplified variant of async_schedule_dev()
248+
* @func: function to execute asynchronously
249+
* @dev: device argument to be passed to function
250+
*
251+
* @dev is used as both the argument for the function and to provide NUMA
252+
* context for where to run the function.
253+
*
254+
* If the asynchronous execution of @func is scheduled successfully, return
255+
* true. Otherwise, do nothing and return false, unlike async_schedule_dev()
256+
* that will run the function synchronously then.
257+
*/
258+
bool async_schedule_dev_nocall(async_func_t func, struct device *dev)
259+
{
260+
struct async_entry *entry;
261+
262+
entry = kzalloc(sizeof(struct async_entry), GFP_KERNEL);
263+
264+
/* Give up if there is no memory or too much work. */
265+
if (!entry || atomic_read(&entry_count) > MAX_WORK) {
266+
kfree(entry);
267+
return false;
268+
}
269+
270+
__async_schedule_node_domain(func, dev, dev_to_node(dev),
271+
&async_dfl_domain, entry);
272+
return true;
273+
}
274+
246275
/**
247276
* async_synchronize_full - synchronize all asynchronous function calls
248277
*

0 commit comments

Comments
 (0)