aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/driver-model/devres.txt4
-rw-r--r--drivers/base/devres.c66
-rw-r--r--include/linux/device.h19
3 files changed, 89 insertions, 0 deletions
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 167070895498..ca9d1eb46bc0 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -332,6 +332,10 @@ MEM
332MFD 332MFD
333 devm_mfd_add_devices() 333 devm_mfd_add_devices()
334 334
335PER-CPU MEM
336 devm_alloc_percpu()
337 devm_free_percpu()
338
335PCI 339PCI
336 pcim_enable_device() : after success, all PCI ops become managed 340 pcim_enable_device() : after success, all PCI ops become managed
337 pcim_pin_device() : keep PCI device enabled after release 341 pcim_pin_device() : keep PCI device enabled after release
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 8fc654f0807b..71d577025285 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -10,6 +10,7 @@
10#include <linux/device.h> 10#include <linux/device.h>
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/percpu.h>
13 14
14#include "base.h" 15#include "base.h"
15 16
@@ -985,3 +986,68 @@ void devm_free_pages(struct device *dev, unsigned long addr)
985 &devres)); 986 &devres));
986} 987}
987EXPORT_SYMBOL_GPL(devm_free_pages); 988EXPORT_SYMBOL_GPL(devm_free_pages);
989
990static void devm_percpu_release(struct device *dev, void *pdata)
991{
992 void __percpu *p;
993
994 p = *(void __percpu **)pdata;
995 free_percpu(p);
996}
997
998static int devm_percpu_match(struct device *dev, void *data, void *p)
999{
1000 struct devres *devr = container_of(data, struct devres, data);
1001
1002 return *(void **)devr->data == p;
1003}
1004
1005/**
1006 * __devm_alloc_percpu - Resource-managed alloc_percpu
1007 * @dev: Device to allocate per-cpu memory for
1008 * @size: Size of per-cpu memory to allocate
1009 * @align: Alignment of per-cpu memory to allocate
1010 *
1011 * Managed alloc_percpu. Per-cpu memory allocated with this function is
1012 * automatically freed on driver detach.
1013 *
1014 * RETURNS:
1015 * Pointer to allocated memory on success, NULL on failure.
1016 */
1017void __percpu *__devm_alloc_percpu(struct device *dev, size_t size,
1018 size_t align)
1019{
1020 void *p;
1021 void __percpu *pcpu;
1022
1023 pcpu = __alloc_percpu(size, align);
1024 if (!pcpu)
1025 return NULL;
1026
1027 p = devres_alloc(devm_percpu_release, sizeof(void *), GFP_KERNEL);
1028 if (!p) {
1029 free_percpu(pcpu);
1030 return NULL;
1031 }
1032
1033 *(void __percpu **)p = pcpu;
1034
1035 devres_add(dev, p);
1036
1037 return pcpu;
1038}
1039EXPORT_SYMBOL_GPL(__devm_alloc_percpu);
1040
1041/**
1042 * devm_free_percpu - Resource-managed free_percpu
1043 * @dev: Device this memory belongs to
1044 * @pdata: Per-cpu memory to free
1045 *
1046 * Free memory allocated with devm_alloc_percpu().
1047 */
1048void devm_free_percpu(struct device *dev, void __percpu *pdata)
1049{
1050 WARN_ON(devres_destroy(dev, devm_percpu_release, devm_percpu_match,
1051 (void *)pdata));
1052}
1053EXPORT_SYMBOL_GPL(devm_free_percpu);
diff --git a/include/linux/device.h b/include/linux/device.h
index bc41e87a969b..a00105cf795e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -698,6 +698,25 @@ static inline int devm_add_action_or_reset(struct device *dev,
698 return ret; 698 return ret;
699} 699}
700 700
701/**
702 * devm_alloc_percpu - Resource-managed alloc_percpu
703 * @dev: Device to allocate per-cpu memory for
704 * @type: Type to allocate per-cpu memory for
705 *
706 * Managed alloc_percpu. Per-cpu memory allocated with this function is
707 * automatically freed on driver detach.
708 *
709 * RETURNS:
710 * Pointer to allocated memory on success, NULL on failure.
711 */
712#define devm_alloc_percpu(dev, type) \
713 ((typeof(type) __percpu *)__devm_alloc_percpu((dev), sizeof(type), \
714 __alignof__(type)))
715
716void __percpu *__devm_alloc_percpu(struct device *dev, size_t size,
717 size_t align);
718void devm_free_percpu(struct device *dev, void __percpu *pdata);
719
701struct device_dma_parameters { 720struct device_dma_parameters {
702 /* 721 /*
703 * a low level driver may set these to teach IOMMU code about 722 * a low level driver may set these to teach IOMMU code about