linuxkpi: Add devm_add_action and devm_add_action_or_reset

Those adds a new devres and will exectute some function on release.

Reviewed by:	bz
Differential Revision:	https://reviews.freebsd.org/D39142
Sponsored by:	Beckhoff Automation GmbH & Co. KG
This commit is contained in:
Emmanuel Vadot 2023-03-17 12:22:06 +01:00
parent f1d7ae31d4
commit aaf6129c9d
2 changed files with 50 additions and 0 deletions

View file

@ -680,4 +680,11 @@ devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp)
#define devm_kcalloc(_dev, _sizen, _size, _gfp) \
devm_kmalloc((_dev), ((_sizen) * (_size)), (_gfp) | __GFP_ZERO)
int lkpi_devm_add_action(struct device *dev, void (*action)(void *), void *data);
#define devm_add_action(dev, action, data) \
lkpi_devm_add_action(dev, action, data);
int lkpi_devm_add_action_or_reset(struct device *dev, void (*action)(void *), void *data);
#define devm_add_action_or_reset(dev, action, data) \
lkpi_devm_add_action_or_reset(dev, action, data)
#endif /* _LINUXKPI_LINUX_DEVICE_H_ */

View file

@ -224,3 +224,46 @@ lkpi_devm_kmalloc_release(struct device *dev __unused, void *p __unused)
/* Nothing to do. Freed with the devres. */
}
struct devres_action {
void *data;
void (*action)(void *);
};
static void
lkpi_devm_action_release(struct device *dev, void *res)
{
struct devres_action *devres;
devres = (struct devres_action *)res;
devres->action(devres->data);
}
int
lkpi_devm_add_action(struct device *dev, void (*action)(void *), void *data)
{
struct devres_action *devres;
KASSERT(action != NULL, ("%s: action is NULL\n", __func__));
devres = lkpi_devres_alloc(lkpi_devm_action_release,
sizeof(struct devres_action), GFP_KERNEL);
if (devres == NULL)
return (-ENOMEM);
devres->data = data;
devres->action = action;
devres_add(dev, devres);
return (0);
}
int
lkpi_devm_add_action_or_reset(struct device *dev, void (*action)(void *), void *data)
{
int rv;
rv = lkpi_devm_add_action(dev, action, data);
if (rv != 0)
action(data);
return (rv);
}