UPSTREAM: extcon: Add resource-managed functions to register extcon notifier
authorChanwoo Choi <cw00.choi@samsung.com>
Mon, 27 Jun 2016 11:03:39 +0000 (20:03 +0900)
committerHuang, Tao <huangtao@rock-chips.com>
Wed, 3 Aug 2016 01:41:25 +0000 (09:41 +0800)
This patch adds the resource-managed functions for register/unregister
the extcon notifier with the id of each external connector. This function
will make it easy to handle the extcon notifier.

- int devm_extcon_register_notifier(struct device *dev,
struct extcon_dev *edev, unsigned int id,
struct notifier_block *nb);
- void devm_extcon_unregister_notifier(struct device *dev,
struct extcon_dev *edev, unsigned int id,
struct notifier_block *nb);

Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
(cherry picked from commit 58f386560a68dd98bd6744a28fc853eef11faebe
  git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/extcon.git extcon-next)
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Change-Id: I852184d12dc4a03b6d526112e998b087931726e5
Signed-off-by: Chris Zhong <zyw@rock-chips.com>
drivers/extcon/devres.c
include/linux/extcon.h

index 694ca85d5a70f0a56bce6be5adb364d5eab8f28b..e686acd1c459176596d1b20a0e081b9335a13f3f 100644 (file)
@@ -37,6 +37,19 @@ static void devm_extcon_dev_unreg(struct device *dev, void *res)
        extcon_dev_unregister(*(struct extcon_dev **)res);
 }
 
+struct extcon_dev_notifier_devres {
+       struct extcon_dev *edev;
+       unsigned int id;
+       struct notifier_block *nb;
+};
+
+static void devm_extcon_dev_notifier_unreg(struct device *dev, void *res)
+{
+       struct extcon_dev_notifier_devres *this = res;
+
+       extcon_unregister_notifier(this->edev, this->id, this->nb);
+}
+
 /**
  * devm_extcon_dev_allocate - Allocate managed extcon device
  * @dev:               device owning the extcon device being created
@@ -141,3 +154,63 @@ void devm_extcon_dev_unregister(struct device *dev, struct extcon_dev *edev)
                               devm_extcon_dev_match, edev));
 }
 EXPORT_SYMBOL_GPL(devm_extcon_dev_unregister);
+
+/**
+ * devm_extcon_register_notifier() - Resource-managed extcon_register_notifier()
+ * @dev:       device to allocate extcon device
+ * @edev:      the extcon device that has the external connecotr.
+ * @id:                the unique id of each external connector in extcon enumeration.
+ * @nb:                a notifier block to be registered.
+ *
+ * This function manages automatically the notifier of extcon device using
+ * device resource management and simplify the control of unregistering
+ * the notifier of extcon device.
+ *
+ * Note that the second parameter given to the callback of nb (val) is
+ * "old_state", not the current state. The current state can be retrieved
+ * by looking at the third pameter (edev pointer)'s state value.
+ *
+ * Returns 0 if success or negaive error number if failure.
+ */
+int devm_extcon_register_notifier(struct device *dev, struct extcon_dev *edev,
+                               unsigned int id, struct notifier_block *nb)
+{
+       struct extcon_dev_notifier_devres *ptr;
+       int ret;
+
+       ptr = devres_alloc(devm_extcon_dev_notifier_unreg, sizeof(*ptr),
+                               GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+
+       ret = extcon_register_notifier(edev, id, nb);
+       if (ret) {
+               devres_free(ptr);
+               return ret;
+       }
+
+       ptr->edev = edev;
+       ptr->id = id;
+       ptr->nb = nb;
+       devres_add(dev, ptr);
+
+       return 0;
+}
+EXPORT_SYMBOL(devm_extcon_register_notifier);
+
+/**
+ * devm_extcon_unregister_notifier()
+                       - Resource-managed extcon_unregister_notifier()
+ * @dev:       device to allocate extcon device
+ * @edev:      the extcon device that has the external connecotr.
+ * @id:                the unique id of each external connector in extcon enumeration.
+ * @nb:                a notifier block to be registered.
+ */
+void devm_extcon_unregister_notifier(struct device *dev,
+                               struct extcon_dev *edev, unsigned int id,
+                               struct notifier_block *nb)
+{
+       WARN_ON(devres_release(dev, devm_extcon_dev_notifier_unreg,
+                              devm_extcon_dev_match, edev));
+}
+EXPORT_SYMBOL(devm_extcon_unregister_notifier);
index 1b2c8b6809ccc371ca1b1513157a42b81d9b95c3..7bf530f3f4f54c95f135de767daf738bd0aff6d8 100644 (file)
@@ -182,6 +182,12 @@ extern int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
                                    struct notifier_block *nb);
 extern int extcon_unregister_notifier(struct extcon_dev *edev, unsigned int id,
                                    struct notifier_block *nb);
+extern int devm_extcon_register_notifier(struct device *dev,
+                               struct extcon_dev *edev, unsigned int id,
+                               struct notifier_block *nb);
+extern void devm_extcon_unregister_notifier(struct device *dev,
+                               struct extcon_dev *edev, unsigned int id,
+                               struct notifier_block *nb);
 
 /*
  * Following API get the extcon device from devicetree.
@@ -273,6 +279,17 @@ static inline int extcon_unregister_notifier(struct extcon_dev *edev,
        return 0;
 }
 
+static inline int devm_extcon_register_notifier(struct device *dev,
+                               struct extcon_dev *edev, unsigned int id,
+                               struct notifier_block *nb)
+{
+       return -ENOSYS;
+}
+
+static inline  void devm_extcon_unregister_notifier(struct device *dev,
+                               struct extcon_dev *edev, unsigned int id,
+                               struct notifier_block *nb) { }
+
 static inline struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev,
                                                            int index)
 {