aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSangjung Woo <sangjung.woo@samsung.com>2014-04-21 06:10:08 -0400
committerChanwoo Choi <cw00.choi@samsung.com>2014-04-24 06:36:55 -0400
commit1111244ff4493448c0ee66e814e20c6e81d3b93d (patch)
tree67e3d29dc335fcd67f85d4a4683c271d3749829a
parent369afd4ba22f5b8de0c9229b6e62b3f9e2207034 (diff)
extcon: Add resource-managed extcon register function
Add resource-managed extcon device register function for convenience. For example, if a extcon device is attached with new devm_extcon_dev_register(), that extcon device is automatically unregistered on driver detach. Signed-off-by: Sangjung Woo <sangjung.woo@samsung.com> [Fix bug about devm_extcon_dev_match/release() and code clean by Chanwoo Choi] Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
-rw-r--r--drivers/extcon/extcon-class.c69
-rw-r--r--include/linux/extcon.h13
2 files changed, 82 insertions, 0 deletions
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
index 7ab21aa6eaa1..f6df68989651 100644
--- a/drivers/extcon/extcon-class.c
+++ b/drivers/extcon/extcon-class.c
@@ -819,6 +819,75 @@ void extcon_dev_unregister(struct extcon_dev *edev)
819} 819}
820EXPORT_SYMBOL_GPL(extcon_dev_unregister); 820EXPORT_SYMBOL_GPL(extcon_dev_unregister);
821 821
822static void devm_extcon_dev_unreg(struct device *dev, void *res)
823{
824 extcon_dev_unregister(*(struct extcon_dev **)res);
825}
826
827static int devm_extcon_dev_match(struct device *dev, void *res, void *data)
828{
829 struct extcon_dev **r = res;
830
831 if (!r || !*r) {
832 WARN_ON(!r || !*r);
833 return 0;
834 }
835
836 return *r == data;
837}
838
839/**
840 * devm_extcon_dev_register() - Resource-managed extcon_dev_register()
841 * @dev: device to allocate extcon device
842 * @edev: the new extcon device to register
843 *
844 * Managed extcon_dev_register() function. If extcon device is attached with
845 * this function, that extcon device is automatically unregistered on driver
846 * detach. Internally this function calls extcon_dev_register() function.
847 * To get more information, refer that function.
848 *
849 * If extcon device is registered with this function and the device needs to be
850 * unregistered separately, devm_extcon_dev_unregister() should be used.
851 *
852 * Returns 0 if success or negaive error number if failure.
853 */
854int devm_extcon_dev_register(struct device *dev, struct extcon_dev *edev)
855{
856 struct extcon_dev **ptr;
857 int ret;
858
859 ptr = devres_alloc(devm_extcon_dev_unreg, sizeof(*ptr), GFP_KERNEL);
860 if (!ptr)
861 return -ENOMEM;
862
863 ret = extcon_dev_register(edev);
864 if (ret) {
865 devres_free(ptr);
866 return ret;
867 }
868
869 *ptr = edev;
870 devres_add(dev, ptr);
871
872 return 0;
873}
874EXPORT_SYMBOL_GPL(devm_extcon_dev_register);
875
876/**
877 * devm_extcon_dev_unregister() - Resource-managed extcon_dev_unregister()
878 * @dev: device the extcon belongs to
879 * @edev: the extcon device to unregister
880 *
881 * Unregister extcon device that is registered with devm_extcon_dev_register()
882 * function.
883 */
884void devm_extcon_dev_unregister(struct device *dev, struct extcon_dev *edev)
885{
886 WARN_ON(devres_release(dev, devm_extcon_dev_unreg,
887 devm_extcon_dev_match, edev));
888}
889EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister);
890
822#ifdef CONFIG_OF 891#ifdef CONFIG_OF
823/* 892/*
824 * extcon_get_edev_by_phandle - Get the extcon device from devicetree 893 * extcon_get_edev_by_phandle - Get the extcon device from devicetree
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index f488145bb2d4..548447be2d8f 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -185,6 +185,10 @@ struct extcon_specific_cable_nb {
185 */ 185 */
186extern int extcon_dev_register(struct extcon_dev *edev); 186extern int extcon_dev_register(struct extcon_dev *edev);
187extern void extcon_dev_unregister(struct extcon_dev *edev); 187extern void extcon_dev_unregister(struct extcon_dev *edev);
188extern int devm_extcon_dev_register(struct device *dev,
189 struct extcon_dev *edev);
190extern void devm_extcon_dev_unregister(struct device *dev,
191 struct extcon_dev *edev);
188extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name); 192extern struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name);
189 193
190/* 194/*
@@ -254,6 +258,15 @@ static inline int extcon_dev_register(struct extcon_dev *edev)
254 258
255static inline void extcon_dev_unregister(struct extcon_dev *edev) { } 259static inline void extcon_dev_unregister(struct extcon_dev *edev) { }
256 260
261static inline int devm_extcon_dev_register(struct device *dev,
262 struct extcon_dev *edev)
263{
264 return -EINVAL;
265}
266
267static inline void devm_extcon_dev_unregister(struct device *dev,
268 struct extcon_dev *edev) { }
269
257static inline u32 extcon_get_state(struct extcon_dev *edev) 270static inline u32 extcon_get_state(struct extcon_dev *edev)
258{ 271{
259 return 0; 272 return 0;