Skip to content

Commit 1172650

Browse files
author
Danilo Krummrich
committed
devres: add devm_remove_action_nowarn()
devm_remove_action() warns if the action to remove does not exist (anymore). The Rust devres abstraction, however, has a use-case to call devm_remove_action() at a point where it can't be guaranteed that the corresponding action hasn't been released yet. In particular, an instance of `Devres<T>` may be dropped after the action has been released. So far, `Devres<T>` worked around this by keeping the inner type alive. Hence, add devm_remove_action_nowarn(), which returns an error code if the action has been removed already. A subsequent patch uses devm_remove_action_nowarn() to remove the action when `Devres<T>` is dropped. Signed-off-by: Danilo Krummrich <[email protected]>
1 parent 9e15363 commit 1172650

File tree

2 files changed

+35
-6
lines changed

2 files changed

+35
-6
lines changed

drivers/base/devres.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -750,25 +750,38 @@ int __devm_add_action(struct device *dev, void (*action)(void *), void *data, co
750750
EXPORT_SYMBOL_GPL(__devm_add_action);
751751

752752
/**
753-
* devm_remove_action() - removes previously added custom action
753+
* devm_remove_action_nowarn() - removes previously added custom action
754754
* @dev: Device that owns the action
755755
* @action: Function implementing the action
756756
* @data: Pointer to data passed to @action implementation
757757
*
758758
* Removes instance of @action previously added by devm_add_action().
759759
* Both action and data should match one of the existing entries.
760+
*
761+
* In contrast to devm_remove_action(), this function does not WARN() if no
762+
* entry could have been found.
763+
*
764+
* This should only be used if the action is contained in an object with
765+
* independent lifetime management, e.g. the Devres rust abstraction.
766+
*
767+
* Causing the warning from regular driver code most likely indicates an abuse
768+
* of the devres API.
769+
*
770+
* Returns: 0 on success, -ENOENT if no entry could have been found.
760771
*/
761-
void devm_remove_action(struct device *dev, void (*action)(void *), void *data)
772+
int devm_remove_action_nowarn(struct device *dev,
773+
void (*action)(void *),
774+
void *data)
762775
{
763776
struct action_devres devres = {
764777
.data = data,
765778
.action = action,
766779
};
767780

768-
WARN_ON(devres_destroy(dev, devm_action_release, devm_action_match,
769-
&devres));
781+
return devres_destroy(dev, devm_action_release, devm_action_match,
782+
&devres);
770783
}
771-
EXPORT_SYMBOL_GPL(devm_remove_action);
784+
EXPORT_SYMBOL_GPL(devm_remove_action_nowarn);
772785

773786
/**
774787
* devm_release_action() - release previously added custom action

include/linux/device.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,23 @@ void __iomem *devm_of_iomap(struct device *dev,
399399
#endif
400400

401401
/* allows to add/remove a custom action to devres stack */
402-
void devm_remove_action(struct device *dev, void (*action)(void *), void *data);
402+
int devm_remove_action_nowarn(struct device *dev, void (*action)(void *), void *data);
403+
404+
/**
405+
* devm_remove_action() - removes previously added custom action
406+
* @dev: Device that owns the action
407+
* @action: Function implementing the action
408+
* @data: Pointer to data passed to @action implementation
409+
*
410+
* Removes instance of @action previously added by devm_add_action().
411+
* Both action and data should match one of the existing entries.
412+
*/
413+
static inline
414+
void devm_remove_action(struct device *dev, void (*action)(void *), void *data)
415+
{
416+
WARN_ON(devm_remove_action_nowarn(dev, action, data));
417+
}
418+
403419
void devm_release_action(struct device *dev, void (*action)(void *), void *data);
404420

405421
int __devm_add_action(struct device *dev, void (*action)(void *), void *data, const char *name);

0 commit comments

Comments
 (0)