diff mbox series

[v1,1/2] driver core: Split devres APIs to device/devres.h

Message ID 20241203195340.855879-2-andriy.shevchenko@linux.intel.com (mailing list archive)
State Changes Requested
Headers show
Series driver core: move devres APIs to a separate header | expand

Commit Message

Andy Shevchenko Dec. 3, 2024, 7:48 p.m. UTC
device.h is a huge header which is hard to follow and easy to miss
something. Improve that by splitting devres APIs to device/devres.h.

In particular this helps to speedup the build of the code that includes
device.h solely for a devres APIs.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
 include/linux/device.h        | 122 +--------------------------------
 include/linux/device/devres.h | 124 ++++++++++++++++++++++++++++++++++
 2 files changed, 127 insertions(+), 119 deletions(-)
 create mode 100644 include/linux/device/devres.h

Comments

Jonathan Cameron Dec. 8, 2024, 5:10 p.m. UTC | #1
On Tue,  3 Dec 2024 21:48:51 +0200
Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:

> device.h is a huge header which is hard to follow and easy to miss
> something. Improve that by splitting devres APIs to device/devres.h.
> 
> In particular this helps to speedup the build of the code that includes
> device.h solely for a devres APIs.
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
>  include/linux/device.h        | 122 +--------------------------------
>  include/linux/device/devres.h | 124 ++++++++++++++++++++++++++++++++++
>  2 files changed, 127 insertions(+), 119 deletions(-)
>  create mode 100644 include/linux/device/devres.h
> 
> diff --git a/include/linux/device.h b/include/linux/device.h
> index 667cb6db9019..ad8ffbfc8651 100644
> --- a/include/linux/device.h
> +++ b/include/linux/device.h
> @@ -12,6 +12,7 @@
>  #ifndef _DEVICE_H_
>  #define _DEVICE_H_
>  
> +#include <linux/cleanup.h>
>  #include <linux/dev_printk.h>
>  #include <linux/energy_model.h>
>  #include <linux/ioport.h>
> @@ -26,11 +27,11 @@
>  #include <linux/atomic.h>
>  #include <linux/uidgid.h>
>  #include <linux/gfp.h>
> -#include <linux/overflow.h>
> +
Unrelated change.
>  #include <linux/device/bus.h>
>  #include <linux/device/class.h>
> +#include <linux/device/devres.h>
>  #include <linux/device/driver.h>
> -#include <linux/cleanup.h>
This header movement is unrelated.

I agree both are good but probably want to be a separate patch.

Otherwise this seems sensible to me, but your cc list seems a little short!

Greg and Rafael seems a good starting point so I've added them.

Jonathan


>  #include <asm/device.h>
>  
>  struct device;
> @@ -281,123 +282,6 @@ int __must_check device_create_bin_file(struct device *dev,
>  void device_remove_bin_file(struct device *dev,
>  			    const struct bin_attribute *attr);
>  
> -/* device resource management */
> -typedef void (*dr_release_t)(struct device *dev, void *res);
> -typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data);
> -
> -void *__devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp,
> -			  int nid, const char *name) __malloc;
> -#define devres_alloc(release, size, gfp) \
> -	__devres_alloc_node(release, size, gfp, NUMA_NO_NODE, #release)
> -#define devres_alloc_node(release, size, gfp, nid) \
> -	__devres_alloc_node(release, size, gfp, nid, #release)
> -
> -void devres_for_each_res(struct device *dev, dr_release_t release,
> -			 dr_match_t match, void *match_data,
> -			 void (*fn)(struct device *, void *, void *),
> -			 void *data);
> -void devres_free(void *res);
> -void devres_add(struct device *dev, void *res);
> -void *devres_find(struct device *dev, dr_release_t release,
> -		  dr_match_t match, void *match_data);
> -void *devres_get(struct device *dev, void *new_res,
> -		 dr_match_t match, void *match_data);
> -void *devres_remove(struct device *dev, dr_release_t release,
> -		    dr_match_t match, void *match_data);
> -int devres_destroy(struct device *dev, dr_release_t release,
> -		   dr_match_t match, void *match_data);
> -int devres_release(struct device *dev, dr_release_t release,
> -		   dr_match_t match, void *match_data);
> -
> -/* devres group */
> -void * __must_check devres_open_group(struct device *dev, void *id, gfp_t gfp);
> -void devres_close_group(struct device *dev, void *id);
> -void devres_remove_group(struct device *dev, void *id);
> -int devres_release_group(struct device *dev, void *id);
> -
> -/* managed devm_k.alloc/kfree for device drivers */
> -void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) __alloc_size(2);
> -void *devm_krealloc(struct device *dev, void *ptr, size_t size,
> -		    gfp_t gfp) __must_check __realloc_size(3);
> -__printf(3, 0) char *devm_kvasprintf(struct device *dev, gfp_t gfp,
> -				     const char *fmt, va_list ap) __malloc;
> -__printf(3, 4) char *devm_kasprintf(struct device *dev, gfp_t gfp,
> -				    const char *fmt, ...) __malloc;
> -static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
> -{
> -	return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
> -}
> -static inline void *devm_kmalloc_array(struct device *dev,
> -				       size_t n, size_t size, gfp_t flags)
> -{
> -	size_t bytes;
> -
> -	if (unlikely(check_mul_overflow(n, size, &bytes)))
> -		return NULL;
> -
> -	return devm_kmalloc(dev, bytes, flags);
> -}
> -static inline void *devm_kcalloc(struct device *dev,
> -				 size_t n, size_t size, gfp_t flags)
> -{
> -	return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
> -}
> -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)
> -{
> -	size_t bytes;
> -
> -	if (unlikely(check_mul_overflow(new_n, new_size, &bytes)))
> -		return NULL;
> -
> -	return devm_krealloc(dev, p, bytes, flags);
> -}
> -
> -void devm_kfree(struct device *dev, const void *p);
> -char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) __malloc;
> -const char *devm_kstrdup_const(struct device *dev, const char *s, gfp_t gfp);
> -void *devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp)
> -	__realloc_size(3);
> -
> -unsigned long devm_get_free_pages(struct device *dev,
> -				  gfp_t gfp_mask, unsigned int order);
> -void devm_free_pages(struct device *dev, unsigned long addr);
> -
> -#ifdef CONFIG_HAS_IOMEM
> -void __iomem *devm_ioremap_resource(struct device *dev,
> -				    const struct resource *res);
> -void __iomem *devm_ioremap_resource_wc(struct device *dev,
> -				       const struct resource *res);
> -
> -void __iomem *devm_of_iomap(struct device *dev,
> -			    struct device_node *node, int index,
> -			    resource_size_t *size);
> -#else
> -
> -static inline
> -void __iomem *devm_ioremap_resource(struct device *dev,
> -				    const struct resource *res)
> -{
> -	return ERR_PTR(-EINVAL);
> -}
> -
> -static inline
> -void __iomem *devm_ioremap_resource_wc(struct device *dev,
> -				       const struct resource *res)
> -{
> -	return ERR_PTR(-EINVAL);
> -}
> -
> -static inline
> -void __iomem *devm_of_iomap(struct device *dev,
> -			    struct device_node *node, int index,
> -			    resource_size_t *size)
> -{
> -	return ERR_PTR(-EINVAL);
> -}
> -
> -#endif
> -
>  /* allows to add/remove a custom action to devres stack */
>  void devm_remove_action(struct device *dev, void (*action)(void *), void *data);
>  void devm_release_action(struct device *dev, void (*action)(void *), void *data);
> diff --git a/include/linux/device/devres.h b/include/linux/device/devres.h
> new file mode 100644
> index 000000000000..128d65defafc
> --- /dev/null
> +++ b/include/linux/device/devres.h
> @@ -0,0 +1,124 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _DEVICE_DEVRES_H_
> +#define _DEVICE_DEVRES_H_
> +
> +#include <linux/err.h>
> +#include <linux/gfp_types.h>
> +#include <linux/numa.h>
> +#include <linux/overflow.h>
> +#include <linux/stdarg.h>
> +#include <linux/types.h>
> +
> +struct device;
> +struct device_node;
> +struct resource;
> +
> +/* device resource management */
> +typedef void (*dr_release_t)(struct device *dev, void *res);
> +typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data);
> +
> +void * __malloc
> +__devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid, const char *name);
> +#define devres_alloc(release, size, gfp) \
> +	__devres_alloc_node(release, size, gfp, NUMA_NO_NODE, #release)
> +#define devres_alloc_node(release, size, gfp, nid) \
> +	__devres_alloc_node(release, size, gfp, nid, #release)
> +
> +void devres_for_each_res(struct device *dev, dr_release_t release,
> +			 dr_match_t match, void *match_data,
> +			 void (*fn)(struct device *, void *, void *),
> +			 void *data);
> +void devres_free(void *res);
> +void devres_add(struct device *dev, void *res);
> +void *devres_find(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
> +void *devres_get(struct device *dev, void *new_res, dr_match_t match, void *match_data);
> +void *devres_remove(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
> +int devres_destroy(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
> +int devres_release(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
> +
> +/* devres group */
> +void * __must_check devres_open_group(struct device *dev, void *id, gfp_t gfp);
> +void devres_close_group(struct device *dev, void *id);
> +void devres_remove_group(struct device *dev, void *id);
> +int devres_release_group(struct device *dev, void *id);
> +
> +/* managed devm_k.alloc/kfree for device drivers */
> +void * __alloc_size(2)
> +devm_kmalloc(struct device *dev, size_t size, gfp_t gfp);
> +void * __must_check __realloc_size(3)
> +devm_krealloc(struct device *dev, void *ptr, size_t size, gfp_t gfp);
> +static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
> +{
> +	return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
> +}
> +static inline void *devm_kmalloc_array(struct device *dev, size_t n, size_t size, gfp_t flags)
> +{
> +	size_t bytes;
> +
> +	if (unlikely(check_mul_overflow(n, size, &bytes)))
> +		return NULL;
> +
> +	return devm_kmalloc(dev, bytes, flags);
> +}
> +static inline void *devm_kcalloc(struct device *dev, size_t n, size_t size, gfp_t flags)
> +{
> +	return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
> +}
> +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)
> +{
> +	size_t bytes;
> +
> +	if (unlikely(check_mul_overflow(new_n, new_size, &bytes)))
> +		return NULL;
> +
> +	return devm_krealloc(dev, p, bytes, flags);
> +}
> +
> +void devm_kfree(struct device *dev, const void *p);
> +
> +void * __realloc_size(3)
> +devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp);
> +
> +char * __malloc
> +devm_kstrdup(struct device *dev, const char *s, gfp_t gfp);
> +const char *devm_kstrdup_const(struct device *dev, const char *s, gfp_t gfp);
> +char * __printf(3, 0) __malloc
> +devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt, va_list ap);
> +char * __printf(3, 4) __malloc
> +devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...);
> +
> +unsigned long devm_get_free_pages(struct device *dev, gfp_t gfp_mask, unsigned int order);
> +void devm_free_pages(struct device *dev, unsigned long addr);
> +
> +#ifdef CONFIG_HAS_IOMEM
> +
> +void __iomem *devm_ioremap_resource(struct device *dev, const struct resource *res);
> +void __iomem *devm_ioremap_resource_wc(struct device *dev, const struct resource *res);
> +
> +void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index,
> +			    resource_size_t *size);
> +#else
> +
> +static inline
> +void __iomem *devm_ioremap_resource(struct device *dev, const struct resource *res)
> +{
> +	return ERR_PTR(-EINVAL);
> +}
> +
> +static inline
> +void __iomem *devm_ioremap_resource_wc(struct device *dev, const struct resource *res)
> +{
> +	return ERR_PTR(-EINVAL);
> +}
> +
> +static inline
> +void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index,
> +			    resource_size_t *size)
> +{
> +	return ERR_PTR(-EINVAL);
> +}
> +
> +#endif
> +
> +#endif /* _DEVICE_DEVRES_H_ */
Andy Shevchenko Dec. 9, 2024, 12:45 a.m. UTC | #2
On Sun, Dec 08, 2024 at 05:10:01PM +0000, Jonathan Cameron wrote:
> On Tue,  3 Dec 2024 21:48:51 +0200
> Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:
> 
> > device.h is a huge header which is hard to follow and easy to miss
> > something. Improve that by splitting devres APIs to device/devres.h.
> > 
> > In particular this helps to speedup the build of the code that includes
> > device.h solely for a devres APIs.

...

> > -#include <linux/overflow.h>
> > +
> Unrelated change.

Which one? Blank line?

...

> > -#include <linux/cleanup.h>
> This header movement is unrelated.

No problem to let it stay at the same place.

> I agree both are good but probably want to be a separate patch.
> 
> Otherwise this seems sensible to me, but your cc list seems a little short!
> 
> Greg and Rafael seems a good starting point so I've added them.

Thanks! I need to check why they were not included into the original
submission. Perhpas I need to amend MAINTAINERS,
Jonathan Cameron Dec. 11, 2024, 6:29 p.m. UTC | #3
On Mon, 9 Dec 2024 02:45:46 +0200
Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:

> On Sun, Dec 08, 2024 at 05:10:01PM +0000, Jonathan Cameron wrote:
> > On Tue,  3 Dec 2024 21:48:51 +0200
> > Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:
> >   
> > > device.h is a huge header which is hard to follow and easy to miss
> > > something. Improve that by splitting devres APIs to device/devres.h.
> > > 
> > > In particular this helps to speedup the build of the code that includes
> > > device.h solely for a devres APIs.  
> 
> ...
> 
> > > -#include <linux/overflow.h>
> > > +  
> > Unrelated change.  
> 
> Which one? Blank line?
I think that's what I meant :)  Was a trivial comment though.

> 
> ...
> 
> > > -#include <linux/cleanup.h>  
> > This header movement is unrelated.  
> 
> No problem to let it stay at the same place.
> 
> > I agree both are good but probably want to be a separate patch.
> > 
> > Otherwise this seems sensible to me, but your cc list seems a little short!
> > 
> > Greg and Rafael seems a good starting point so I've added them.  
> 
> Thanks! I need to check why they were not included into the original
> submission. Perhpas I need to amend MAINTAINERS,
>
Andy Shevchenko Dec. 12, 2024, 2:35 p.m. UTC | #4
On Wed, Dec 11, 2024 at 06:29:58PM +0000, Jonathan Cameron wrote:
> On Mon, 9 Dec 2024 02:45:46 +0200
> Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:
> > On Sun, Dec 08, 2024 at 05:10:01PM +0000, Jonathan Cameron wrote:
> > > On Tue,  3 Dec 2024 21:48:51 +0200
> > > Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:
> > >   
> > > > device.h is a huge header which is hard to follow and easy to miss
> > > > something. Improve that by splitting devres APIs to device/devres.h.
> > > > 
> > > > In particular this helps to speedup the build of the code that includes
> > > > device.h solely for a devres APIs.  

...

> > > > -#include <linux/overflow.h>
> > > > +  
> > > Unrelated change.  
> > 
> > Which one? Blank line?
> I think that's what I meant :)  Was a trivial comment though.

Got it!

...

> > > > -#include <linux/cleanup.h>  
> > > This header movement is unrelated.  
> > 
> > No problem to let it stay at the same place.
> > 
> > > I agree both are good but probably want to be a separate patch.
> > > 
> > > Otherwise this seems sensible to me, but your cc list seems a little short!
> > > 
> > > Greg and Rafael seems a good starting point so I've added them.  
> > 
> > Thanks! I need to check why they were not included into the original
> > submission. Perhpas I need to amend MAINTAINERS,

I added the file to MAINTAINERS locally.
diff mbox series

Patch

diff --git a/include/linux/device.h b/include/linux/device.h
index 667cb6db9019..ad8ffbfc8651 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -12,6 +12,7 @@ 
 #ifndef _DEVICE_H_
 #define _DEVICE_H_
 
+#include <linux/cleanup.h>
 #include <linux/dev_printk.h>
 #include <linux/energy_model.h>
 #include <linux/ioport.h>
@@ -26,11 +27,11 @@ 
 #include <linux/atomic.h>
 #include <linux/uidgid.h>
 #include <linux/gfp.h>
-#include <linux/overflow.h>
+
 #include <linux/device/bus.h>
 #include <linux/device/class.h>
+#include <linux/device/devres.h>
 #include <linux/device/driver.h>
-#include <linux/cleanup.h>
 #include <asm/device.h>
 
 struct device;
@@ -281,123 +282,6 @@  int __must_check device_create_bin_file(struct device *dev,
 void device_remove_bin_file(struct device *dev,
 			    const struct bin_attribute *attr);
 
-/* device resource management */
-typedef void (*dr_release_t)(struct device *dev, void *res);
-typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data);
-
-void *__devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp,
-			  int nid, const char *name) __malloc;
-#define devres_alloc(release, size, gfp) \
-	__devres_alloc_node(release, size, gfp, NUMA_NO_NODE, #release)
-#define devres_alloc_node(release, size, gfp, nid) \
-	__devres_alloc_node(release, size, gfp, nid, #release)
-
-void devres_for_each_res(struct device *dev, dr_release_t release,
-			 dr_match_t match, void *match_data,
-			 void (*fn)(struct device *, void *, void *),
-			 void *data);
-void devres_free(void *res);
-void devres_add(struct device *dev, void *res);
-void *devres_find(struct device *dev, dr_release_t release,
-		  dr_match_t match, void *match_data);
-void *devres_get(struct device *dev, void *new_res,
-		 dr_match_t match, void *match_data);
-void *devres_remove(struct device *dev, dr_release_t release,
-		    dr_match_t match, void *match_data);
-int devres_destroy(struct device *dev, dr_release_t release,
-		   dr_match_t match, void *match_data);
-int devres_release(struct device *dev, dr_release_t release,
-		   dr_match_t match, void *match_data);
-
-/* devres group */
-void * __must_check devres_open_group(struct device *dev, void *id, gfp_t gfp);
-void devres_close_group(struct device *dev, void *id);
-void devres_remove_group(struct device *dev, void *id);
-int devres_release_group(struct device *dev, void *id);
-
-/* managed devm_k.alloc/kfree for device drivers */
-void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) __alloc_size(2);
-void *devm_krealloc(struct device *dev, void *ptr, size_t size,
-		    gfp_t gfp) __must_check __realloc_size(3);
-__printf(3, 0) char *devm_kvasprintf(struct device *dev, gfp_t gfp,
-				     const char *fmt, va_list ap) __malloc;
-__printf(3, 4) char *devm_kasprintf(struct device *dev, gfp_t gfp,
-				    const char *fmt, ...) __malloc;
-static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
-{
-	return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
-}
-static inline void *devm_kmalloc_array(struct device *dev,
-				       size_t n, size_t size, gfp_t flags)
-{
-	size_t bytes;
-
-	if (unlikely(check_mul_overflow(n, size, &bytes)))
-		return NULL;
-
-	return devm_kmalloc(dev, bytes, flags);
-}
-static inline void *devm_kcalloc(struct device *dev,
-				 size_t n, size_t size, gfp_t flags)
-{
-	return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
-}
-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)
-{
-	size_t bytes;
-
-	if (unlikely(check_mul_overflow(new_n, new_size, &bytes)))
-		return NULL;
-
-	return devm_krealloc(dev, p, bytes, flags);
-}
-
-void devm_kfree(struct device *dev, const void *p);
-char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) __malloc;
-const char *devm_kstrdup_const(struct device *dev, const char *s, gfp_t gfp);
-void *devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp)
-	__realloc_size(3);
-
-unsigned long devm_get_free_pages(struct device *dev,
-				  gfp_t gfp_mask, unsigned int order);
-void devm_free_pages(struct device *dev, unsigned long addr);
-
-#ifdef CONFIG_HAS_IOMEM
-void __iomem *devm_ioremap_resource(struct device *dev,
-				    const struct resource *res);
-void __iomem *devm_ioremap_resource_wc(struct device *dev,
-				       const struct resource *res);
-
-void __iomem *devm_of_iomap(struct device *dev,
-			    struct device_node *node, int index,
-			    resource_size_t *size);
-#else
-
-static inline
-void __iomem *devm_ioremap_resource(struct device *dev,
-				    const struct resource *res)
-{
-	return ERR_PTR(-EINVAL);
-}
-
-static inline
-void __iomem *devm_ioremap_resource_wc(struct device *dev,
-				       const struct resource *res)
-{
-	return ERR_PTR(-EINVAL);
-}
-
-static inline
-void __iomem *devm_of_iomap(struct device *dev,
-			    struct device_node *node, int index,
-			    resource_size_t *size)
-{
-	return ERR_PTR(-EINVAL);
-}
-
-#endif
-
 /* allows to add/remove a custom action to devres stack */
 void devm_remove_action(struct device *dev, void (*action)(void *), void *data);
 void devm_release_action(struct device *dev, void (*action)(void *), void *data);
diff --git a/include/linux/device/devres.h b/include/linux/device/devres.h
new file mode 100644
index 000000000000..128d65defafc
--- /dev/null
+++ b/include/linux/device/devres.h
@@ -0,0 +1,124 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _DEVICE_DEVRES_H_
+#define _DEVICE_DEVRES_H_
+
+#include <linux/err.h>
+#include <linux/gfp_types.h>
+#include <linux/numa.h>
+#include <linux/overflow.h>
+#include <linux/stdarg.h>
+#include <linux/types.h>
+
+struct device;
+struct device_node;
+struct resource;
+
+/* device resource management */
+typedef void (*dr_release_t)(struct device *dev, void *res);
+typedef int (*dr_match_t)(struct device *dev, void *res, void *match_data);
+
+void * __malloc
+__devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid, const char *name);
+#define devres_alloc(release, size, gfp) \
+	__devres_alloc_node(release, size, gfp, NUMA_NO_NODE, #release)
+#define devres_alloc_node(release, size, gfp, nid) \
+	__devres_alloc_node(release, size, gfp, nid, #release)
+
+void devres_for_each_res(struct device *dev, dr_release_t release,
+			 dr_match_t match, void *match_data,
+			 void (*fn)(struct device *, void *, void *),
+			 void *data);
+void devres_free(void *res);
+void devres_add(struct device *dev, void *res);
+void *devres_find(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
+void *devres_get(struct device *dev, void *new_res, dr_match_t match, void *match_data);
+void *devres_remove(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
+int devres_destroy(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
+int devres_release(struct device *dev, dr_release_t release, dr_match_t match, void *match_data);
+
+/* devres group */
+void * __must_check devres_open_group(struct device *dev, void *id, gfp_t gfp);
+void devres_close_group(struct device *dev, void *id);
+void devres_remove_group(struct device *dev, void *id);
+int devres_release_group(struct device *dev, void *id);
+
+/* managed devm_k.alloc/kfree for device drivers */
+void * __alloc_size(2)
+devm_kmalloc(struct device *dev, size_t size, gfp_t gfp);
+void * __must_check __realloc_size(3)
+devm_krealloc(struct device *dev, void *ptr, size_t size, gfp_t gfp);
+static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
+{
+	return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
+}
+static inline void *devm_kmalloc_array(struct device *dev, size_t n, size_t size, gfp_t flags)
+{
+	size_t bytes;
+
+	if (unlikely(check_mul_overflow(n, size, &bytes)))
+		return NULL;
+
+	return devm_kmalloc(dev, bytes, flags);
+}
+static inline void *devm_kcalloc(struct device *dev, size_t n, size_t size, gfp_t flags)
+{
+	return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
+}
+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)
+{
+	size_t bytes;
+
+	if (unlikely(check_mul_overflow(new_n, new_size, &bytes)))
+		return NULL;
+
+	return devm_krealloc(dev, p, bytes, flags);
+}
+
+void devm_kfree(struct device *dev, const void *p);
+
+void * __realloc_size(3)
+devm_kmemdup(struct device *dev, const void *src, size_t len, gfp_t gfp);
+
+char * __malloc
+devm_kstrdup(struct device *dev, const char *s, gfp_t gfp);
+const char *devm_kstrdup_const(struct device *dev, const char *s, gfp_t gfp);
+char * __printf(3, 0) __malloc
+devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt, va_list ap);
+char * __printf(3, 4) __malloc
+devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...);
+
+unsigned long devm_get_free_pages(struct device *dev, gfp_t gfp_mask, unsigned int order);
+void devm_free_pages(struct device *dev, unsigned long addr);
+
+#ifdef CONFIG_HAS_IOMEM
+
+void __iomem *devm_ioremap_resource(struct device *dev, const struct resource *res);
+void __iomem *devm_ioremap_resource_wc(struct device *dev, const struct resource *res);
+
+void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index,
+			    resource_size_t *size);
+#else
+
+static inline
+void __iomem *devm_ioremap_resource(struct device *dev, const struct resource *res)
+{
+	return ERR_PTR(-EINVAL);
+}
+
+static inline
+void __iomem *devm_ioremap_resource_wc(struct device *dev, const struct resource *res)
+{
+	return ERR_PTR(-EINVAL);
+}
+
+static inline
+void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index,
+			    resource_size_t *size)
+{
+	return ERR_PTR(-EINVAL);
+}
+
+#endif
+
+#endif /* _DEVICE_DEVRES_H_ */