This patch add device managed devm_extcon_dev_{allocate,free} to automatically free the memory of extcon_dev structure without handling free operation.
Signed-off-by: Chanwoo Choi <cw00.c...@samsung.com> --- drivers/extcon/extcon-class.c | 57 +++++++++++++++++++++++++++++++++++++++++++ include/linux/extcon.h | 16 ++++++++++++ 2 files changed, 73 insertions(+) diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c index 600043c..b130446 100644 --- a/drivers/extcon/extcon-class.c +++ b/drivers/extcon/extcon-class.c @@ -848,6 +848,63 @@ void extcon_dev_free(struct extcon_dev *edev) } EXPORT_SYMBOL_GPL(extcon_dev_free); +static void devm_extcon_device_release(struct device *dev, void *res) +{ + extcon_dev_free(*(struct extcon_dev **)res); +} + +static int devm_extcon_dev_match(struct device *dev, void *res, void *data) +{ + struct extcon_dev **r = res; + if (!r || !*r) { + WARN_ON(!r || !*r); + return 0; + } + return *r == data; +} + +/** + * devm_extcon_dev_allocate - Allocate managed extcon device + * @dev: device owning the extcon device being created + * @supported_cable: Array of supported cable names ending with NULL. + * If supported_cable is NULL, cable name related APIs + * are disabled. + * + * This function manages automatically the memory of extcon device using device + * resource management and simplify the control of freeing the memory of extcon + * device. + * + * Returns the pointer memory of allocated extcon_dev if success or NULL if fail + */ +struct extcon_dev *devm_extcon_dev_allocate(struct device *dev, + const char **supported_cable) +{ + struct extcon_dev **res, *edev; + + res = devres_alloc(devm_extcon_device_release, sizeof(*res), + GFP_KERNEL); + if (!res) + return NULL; + + edev = extcon_dev_allocate(supported_cable); + if (!IS_ERR(edev)) { + *res = edev; + devres_add(dev, res); + } else { + devres_free(res); + } + + return edev; +} +EXPORT_SYMBOL_GPL(devm_extcon_dev_allocate); + +void devm_extcon_dev_free(struct device *dev, struct extcon_dev *edev) +{ + WARN_ON(devres_release(dev, devm_extcon_device_release, + devm_extcon_dev_match, edev)); +} +EXPORT_SYMBOL_GPL(devm_extcon_dev_free); + #ifdef CONFIG_OF /* * extcon_get_edev_by_phandle - Get the extcon device from devicetree diff --git a/include/linux/extcon.h b/include/linux/extcon.h index ffb3a03..12ab2a8 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -246,6 +246,8 @@ extern int extcon_unregister_notifier(struct extcon_dev *edev, /* * Following APIs control the memory of extcon device. */ +extern struct extcon_dev *devm_extcon_dev_allocate(struct device *dev, + const char **cables); extern struct extcon_dev *extcon_dev_allocate(const char **cables); extern void extcon_dev_free(struct extcon_dev *edev); @@ -345,11 +347,25 @@ static inline struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, return ERR_PTR(-ENODEV); } +static inline struct extcon_dev *devm_extcon_dev_allocate(struct device *dev, + const char **cables) +{ + return -ENOMEM; +} + static inline struct extcon_dev *extcon_dev_allocate(const char **cables) { return ERR_PTR(-ENOMEM); } static inline void extcon_dev_free(struct extcon_dev *edev) { } + +static inline struct extcon_dev *devm_extcon_dev_allocate(struct device *dev, + const char **cables) +{ + return ERR_PTR(-ENOMEM); +} + +static inline void devm_extcon_dev_free(struct extcon_dev *edev) { } #endif /* CONFIG_EXTCON */ #endif /* __LINUX_EXTCON_H__ */ -- 1.8.0 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/