drivers/pinctrl: grab default handles from device core
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / drivers / pinctrl / core.c
index e6373f30aeeb26895283ab486893b6396c814371..5a2fe9aae20f1f89ea1baf2248f09d46b74a6d3a 100644 (file)
@@ -14,6 +14,7 @@
 #define pr_fmt(fmt) "pinctrl core: " fmt
 
 #include <linux/kernel.h>
+#include <linux/kref.h>
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/device.h>
@@ -727,6 +728,8 @@ static struct pinctrl *create_pinctrl(struct device *dev)
                return ERR_PTR(ret);
        }
 
+       kref_init(&p->users);
+
        /* Add the pinctrl handle to the global list */
        list_add_tail(&p->node, &pinctrl_list);
 
@@ -740,9 +743,17 @@ static struct pinctrl *pinctrl_get_locked(struct device *dev)
        if (WARN_ON(!dev))
                return ERR_PTR(-EINVAL);
 
+       /*
+        * See if somebody else (such as the device core) has already
+        * obtained a handle to the pinctrl for this device. In that case,
+        * return another pointer to it.
+        */
        p = find_pinctrl(dev);
-       if (p != NULL)
-               return ERR_PTR(-EBUSY);
+       if (p != NULL) {
+               dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n");
+               kref_get(&p->users);
+               return p;
+       }
 
        return create_pinctrl(dev);
 }
@@ -798,13 +809,24 @@ static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
 }
 
 /**
- * pinctrl_put() - release a previously claimed pinctrl handle
+ * pinctrl_release() - release the pinctrl handle
+ * @kref: the kref in the pinctrl being released
+ */
+void pinctrl_release(struct kref *kref)
+{
+       struct pinctrl *p = container_of(kref, struct pinctrl, users);
+
+       pinctrl_put_locked(p, true);
+}
+
+/**
+ * pinctrl_put() - decrease use count on a previously claimed pinctrl handle
  * @p: the pinctrl handle to release
  */
 void pinctrl_put(struct pinctrl *p)
 {
        mutex_lock(&pinctrl_mutex);
-       pinctrl_put_locked(p, true);
+       kref_put(&p->users, pinctrl_release);
        mutex_unlock(&pinctrl_mutex);
 }
 EXPORT_SYMBOL_GPL(pinctrl_put);