Skip to content

Commit ff86aae

Browse files
madalinbucurdavem330
authored andcommitted
devres: add devm_alloc_percpu()
Introduce managed counterparts for alloc_percpu() and free_percpu(). Add devm_alloc_percpu() and devm_free_percpu() into the managed interfaces list. Signed-off-by: Madalin Bucur <madalin.bucur@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 319b053 commit ff86aae

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed

Documentation/driver-model/devres.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,10 @@ MEM
332332
MFD
333333
devm_mfd_add_devices()
334334

335+
PER-CPU MEM
336+
devm_alloc_percpu()
337+
devm_free_percpu()
338+
335339
PCI
336340
pcim_enable_device() : after success, all PCI ops become managed
337341
pcim_pin_device() : keep PCI device enabled after release

drivers/base/devres.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/device.h>
1111
#include <linux/module.h>
1212
#include <linux/slab.h>
13+
#include <linux/percpu.h>
1314

1415
#include "base.h"
1516

@@ -985,3 +986,68 @@ void devm_free_pages(struct device *dev, unsigned long addr)
985986
&devres));
986987
}
987988
EXPORT_SYMBOL_GPL(devm_free_pages);
989+
990+
static 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+
998+
static 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+
*/
1017+
void __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+
}
1039+
EXPORT_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+
*/
1048+
void 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+
}
1053+
EXPORT_SYMBOL_GPL(devm_free_percpu);

include/linux/device.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,25 @@ static inline int devm_add_action_or_reset(struct device *dev,
698698
return ret;
699699
}
700700

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+
716+
void __percpu *__devm_alloc_percpu(struct device *dev, size_t size,
717+
size_t align);
718+
void devm_free_percpu(struct device *dev, void __percpu *pdata);
719+
701720
struct device_dma_parameters {
702721
/*
703722
* a low level driver may set these to teach IOMMU code about

0 commit comments

Comments
 (0)