1a21cad93SAndy Shevchenko /* SPDX-License-Identifier: GPL-2.0 */
2a21cad93SAndy Shevchenko #ifndef _DEVICE_DEVRES_H_
3a21cad93SAndy Shevchenko #define _DEVICE_DEVRES_H_
4a21cad93SAndy Shevchenko
5a21cad93SAndy Shevchenko #include <linux/err.h>
6a21cad93SAndy Shevchenko #include <linux/gfp_types.h>
7a21cad93SAndy Shevchenko #include <linux/numa.h>
8a21cad93SAndy Shevchenko #include <linux/overflow.h>
9a21cad93SAndy Shevchenko #include <linux/stdarg.h>
10a21cad93SAndy Shevchenko #include <linux/types.h>
11f5e5631dSAndy Shevchenko #include <asm/bug.h>
12a21cad93SAndy Shevchenko
13a21cad93SAndy Shevchenko struct device;
14a21cad93SAndy Shevchenko struct device_node;
15a21cad93SAndy Shevchenko struct resource;
16a21cad93SAndy Shevchenko
17a21cad93SAndy Shevchenko /* device resource management */
18a21cad93SAndy Shevchenko typedef void (*dr_release_t)(struct device *dev, void *res);
19a21cad93SAndy Shevchenko typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data);
20a21cad93SAndy Shevchenko
21a21cad93SAndy Shevchenko void * __malloc
22a21cad93SAndy Shevchenko __devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid, const char *name);
23a21cad93SAndy Shevchenko #define devres_alloc(release, size, gfp) \
24a21cad93SAndy Shevchenko __devres_alloc_node(release, size, gfp, NUMA_NO_NODE, #release)
25a21cad93SAndy Shevchenko #define devres_alloc_node(release, size, gfp, nid) \
26a21cad93SAndy Shevchenko __devres_alloc_node(release, size, gfp, nid, #release)
27a21cad93SAndy Shevchenko
28a21cad93SAndy Shevchenko void devres_for_each_res(struct device *dev, dr_release_t release,
29a21cad93SAndy Shevchenko dr_match_t match, void *match_data,
30a21cad93SAndy Shevchenko void (*fn)(struct device *, void *, void *),
31a21cad93SAndy Shevchenko void *data);
32a21cad93SAndy Shevchenko void devres_free(void *res);
33a21cad93SAndy Shevchenko void devres_add(struct device *dev, void *res);
34a21cad93SAndy Shevchenko void *devres_find(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
35a21cad93SAndy Shevchenko void *devres_get(struct device *dev, void *new_res, dr_match_t match, void *match_data);
36a21cad93SAndy Shevchenko void *devres_remove(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
37a21cad93SAndy Shevchenko int devres_destroy(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
38a21cad93SAndy Shevchenko int devres_release(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
39a21cad93SAndy Shevchenko
40a21cad93SAndy Shevchenko /* devres group */
41a21cad93SAndy Shevchenko void * __must_check devres_open_group(struct device *dev, void *id, gfp_t gfp);
42a21cad93SAndy Shevchenko void devres_close_group(struct device *dev, void *id);
43a21cad93SAndy Shevchenko void devres_remove_group(struct device *dev, void *id);
44a21cad93SAndy Shevchenko int devres_release_group(struct device *dev, void *id);
45a21cad93SAndy Shevchenko
46a21cad93SAndy Shevchenko /* managed devm_k.alloc/kfree for device drivers */
47a21cad93SAndy Shevchenko void * __alloc_size(2)
48a21cad93SAndy Shevchenko devm_kmalloc(struct device *dev, size_t size, gfp_t gfp);
49a21cad93SAndy Shevchenko void * __must_check __realloc_size(3)
50a21cad93SAndy Shevchenko devm_krealloc(struct device *dev, void *ptr, size_t size, gfp_t gfp);
devm_kzalloc(struct device * dev,size_t size,gfp_t gfp)51a21cad93SAndy Shevchenko static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
52a21cad93SAndy Shevchenko {
53a21cad93SAndy Shevchenko return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
54a21cad93SAndy Shevchenko }
devm_kmalloc_array(struct device * dev,size_t n,size_t size,gfp_t flags)55a21cad93SAndy Shevchenko static inline void *devm_kmalloc_array(struct device *dev, size_t n, size_t size, gfp_t flags)
56a21cad93SAndy Shevchenko {
57a21cad93SAndy Shevchenko size_t bytes;
58a21cad93SAndy Shevchenko
59a21cad93SAndy Shevchenko if (unlikely(check_mul_overflow(n, size, &bytes)))
60a21cad93SAndy Shevchenko return NULL;
61a21cad93SAndy Shevchenko
62a21cad93SAndy Shevchenko return devm_kmalloc(dev, bytes, flags);
63a21cad93SAndy Shevchenko }
devm_kcalloc(struct device * dev,size_t n,size_t size,gfp_t flags)64a21cad93SAndy Shevchenko static inline void *devm_kcalloc(struct device *dev, size_t n, size_t size, gfp_t flags)
65a21cad93SAndy Shevchenko {
66a21cad93SAndy Shevchenko return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
67a21cad93SAndy Shevchenko }
68a21cad93SAndy Shevchenko static inline __realloc_size(3, 4) void * __must_check
devm_krealloc_array(struct device * dev,void * p,size_t new_n,size_t new_size,gfp_t flags)69a21cad93SAndy Shevchenko devm_krealloc_array(struct device *dev, void *p, size_t new_n, size_t new_size, gfp_t flags)
70a21cad93SAndy Shevchenko {
71a21cad93SAndy Shevchenko size_t bytes;
72a21cad93SAndy Shevchenko
73a21cad93SAndy Shevchenko if (unlikely(check_mul_overflow(new_n, new_size, &bytes)))
74a21cad93SAndy Shevchenko return NULL;
75a21cad93SAndy Shevchenko
76a21cad93SAndy Shevchenko return devm_krealloc(dev, p, bytes, flags);
77a21cad93SAndy Shevchenko }
78a21cad93SAndy Shevchenko
79a21cad93SAndy Shevchenko void devm_kfree(struct device *dev, const void *p);
80a21cad93SAndy Shevchenko
81a21cad93SAndy Shevchenko void * __realloc_size(3)
82a21cad93SAndy Shevchenko devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp);
devm_kmemdup_array(struct device * dev,const void * src,size_t n,size_t size,gfp_t flags)83a103b833SRaag Jadav static inline void *devm_kmemdup_array(struct device *dev, const void *src,
84a103b833SRaag Jadav size_t n, size_t size, gfp_t flags)
85a103b833SRaag Jadav {
86a103b833SRaag Jadav return devm_kmemdup(dev, src, size_mul(size, n), flags);
87a103b833SRaag Jadav }
88a21cad93SAndy Shevchenko
89a21cad93SAndy Shevchenko char * __malloc
90a21cad93SAndy Shevchenko devm_kstrdup(struct device *dev, const char *s, gfp_t gfp);
91a21cad93SAndy Shevchenko const char *devm_kstrdup_const(struct device *dev, const char *s, gfp_t gfp);
92a21cad93SAndy Shevchenko char * __printf(3, 0) __malloc
93a21cad93SAndy Shevchenko devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt, va_list ap);
94a21cad93SAndy Shevchenko char * __printf(3, 4) __malloc
95a21cad93SAndy Shevchenko devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...);
96a21cad93SAndy Shevchenko
97a21cad93SAndy Shevchenko unsigned long devm_get_free_pages(struct device *dev, gfp_t gfp_mask, unsigned int order);
98a21cad93SAndy Shevchenko void devm_free_pages(struct device *dev, unsigned long addr);
99a21cad93SAndy Shevchenko
100a21cad93SAndy Shevchenko #ifdef CONFIG_HAS_IOMEM
101a21cad93SAndy Shevchenko
102a21cad93SAndy Shevchenko void __iomem *devm_ioremap_resource(struct device *dev, const struct resource *res);
103a21cad93SAndy Shevchenko void __iomem *devm_ioremap_resource_wc(struct device *dev, const struct resource *res);
104a21cad93SAndy Shevchenko
105a21cad93SAndy Shevchenko void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index,
106a21cad93SAndy Shevchenko resource_size_t *size);
107a21cad93SAndy Shevchenko #else
108a21cad93SAndy Shevchenko
109a21cad93SAndy Shevchenko static inline
devm_ioremap_resource(struct device * dev,const struct resource * res)110a21cad93SAndy Shevchenko void __iomem *devm_ioremap_resource(struct device *dev, const struct resource *res)
111a21cad93SAndy Shevchenko {
112a21cad93SAndy Shevchenko return IOMEM_ERR_PTR(-EINVAL);
113a21cad93SAndy Shevchenko }
114a21cad93SAndy Shevchenko
115a21cad93SAndy Shevchenko static inline
devm_ioremap_resource_wc(struct device * dev,const struct resource * res)116a21cad93SAndy Shevchenko void __iomem *devm_ioremap_resource_wc(struct device *dev, const struct resource *res)
117a21cad93SAndy Shevchenko {
118a21cad93SAndy Shevchenko return IOMEM_ERR_PTR(-EINVAL);
119a21cad93SAndy Shevchenko }
120a21cad93SAndy Shevchenko
121a21cad93SAndy Shevchenko static inline
devm_of_iomap(struct device * dev,struct device_node * node,int index,resource_size_t * size)122a21cad93SAndy Shevchenko void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index,
123a21cad93SAndy Shevchenko resource_size_t *size)
124a21cad93SAndy Shevchenko {
125a21cad93SAndy Shevchenko return IOMEM_ERR_PTR(-EINVAL);
126a21cad93SAndy Shevchenko }
127a21cad93SAndy Shevchenko
128a21cad93SAndy Shevchenko #endif
129a21cad93SAndy Shevchenko
130f5e5631dSAndy Shevchenko /* allows to add/remove a custom action to devres stack */
131f5e5631dSAndy Shevchenko int devm_remove_action_nowarn(struct device *dev, void (*action)(void *), void *data);
132f5e5631dSAndy Shevchenko
133f5e5631dSAndy Shevchenko /**
134f5e5631dSAndy Shevchenko * devm_remove_action() - removes previously added custom action
135f5e5631dSAndy Shevchenko * @dev: Device that owns the action
136f5e5631dSAndy Shevchenko * @action: Function implementing the action
137f5e5631dSAndy Shevchenko * @data: Pointer to data passed to @action implementation
138f5e5631dSAndy Shevchenko *
139f5e5631dSAndy Shevchenko * Removes instance of @action previously added by devm_add_action().
140f5e5631dSAndy Shevchenko * Both action and data should match one of the existing entries.
141f5e5631dSAndy Shevchenko */
142f5e5631dSAndy Shevchenko static inline
devm_remove_action(struct device * dev,void (* action)(void *),void * data)143f5e5631dSAndy Shevchenko void devm_remove_action(struct device *dev, void (*action)(void *), void *data)
144f5e5631dSAndy Shevchenko {
145f5e5631dSAndy Shevchenko WARN_ON(devm_remove_action_nowarn(dev, action, data));
146f5e5631dSAndy Shevchenko }
147f5e5631dSAndy Shevchenko
148f5e5631dSAndy Shevchenko void devm_release_action(struct device *dev, void (*action)(void *), void *data);
149f5e5631dSAndy Shevchenko
150f5e5631dSAndy Shevchenko int __devm_add_action(struct device *dev, void (*action)(void *), void *data, const char *name);
151f5e5631dSAndy Shevchenko #define devm_add_action(dev, action, data) \
152f5e5631dSAndy Shevchenko __devm_add_action(dev, action, data, #action)
153f5e5631dSAndy Shevchenko
__devm_add_action_or_reset(struct device * dev,void (* action)(void *),void * data,const char * name)154f5e5631dSAndy Shevchenko static inline int __devm_add_action_or_reset(struct device *dev, void (*action)(void *),
155f5e5631dSAndy Shevchenko void *data, const char *name)
156f5e5631dSAndy Shevchenko {
157f5e5631dSAndy Shevchenko int ret;
158f5e5631dSAndy Shevchenko
159f5e5631dSAndy Shevchenko ret = __devm_add_action(dev, action, data, name);
160f5e5631dSAndy Shevchenko if (ret)
161f5e5631dSAndy Shevchenko action(data);
162f5e5631dSAndy Shevchenko
163f5e5631dSAndy Shevchenko return ret;
164f5e5631dSAndy Shevchenko }
165f5e5631dSAndy Shevchenko #define devm_add_action_or_reset(dev, action, data) \
166f5e5631dSAndy Shevchenko __devm_add_action_or_reset(dev, action, data, #action)
167f5e5631dSAndy Shevchenko
168*e383bb8fSAndy Shevchenko bool devm_is_action_added(struct device *dev, void (*action)(void *), void *data);
169*e383bb8fSAndy Shevchenko
170a21cad93SAndy Shevchenko #endif /* _DEVICE_DEVRES_H_ */
171