Skip to contentSkip to conversation

Introduce devm_clk_register()

PATCH Superseded Stephen Boyd 4 participants 16 messages Sep 19, 2012 – Oct 29, 2012

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Introduce devm_clk_register()

The first patch in this series fixes error checking in the wm831x clock driver and is here to prevent context conflicts in the third patch. I split it out in case it needed to merge sooner rather than later.

The goal of this series is to add devm_clk_register() so I can use it in some MSM clock code I'm sending out in the near future. The second patch adds the API and the third patch moves over an existing user of clk_unregister() to the devm API.

Stephen Boyd (3):
clk: wm831x: Fix clk_register() error code checking
clk: Add devm_clk_{register,unregister}()
clk: wm831x: Use devm_clk_register() to simplify code

 drivers/clk/clk-wm831x.c     |  34 ++++---------
 drivers/clk/clk.c            | 111 +++++++++++++++++++++++++++++++++++--------
 include/linux/clk-provider.h |   2 +
 3 files changed, 101 insertions(+), 46 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#1 lore raw

PATCH 1/3 clk: wm831x: Fix clk_register() error code checking

clk_register() returns an ERR_PTR upon failure, not NULL. Fix these error paths.

---
 drivers/clk/clk-wm831x.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/clk/clk-wm831x.c +6 -6
index e7b7765..eb1afaf 100644
@@ -371,20 +371,20 @@ static __devinit int wm831x_clk_probe(struct platform_device *pdev)
 
 	clkdata->xtal_hw.init = &wm831x_xtal_init;
 	clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
-	if (!clkdata->xtal)
-		return -EINVAL;
+	if (IS_ERR(clkdata->xtal))
+		return PTR_ERR(clkdata->xtal);
 
 	clkdata->fll_hw.init = &wm831x_fll_init;
 	clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
-	if (!clkdata->fll) {
-		ret = -EINVAL;
+	if (IS_ERR(clkdata->fll)) {
+		ret = PTR_ERR(clkdata->fll);
 		goto err_xtal;
 	}
 
 	clkdata->clkout_hw.init = &wm831x_clkout_init;
 	clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
-	if (!clkdata->clkout) {
-		ret = -EINVAL;
+	if (IS_ERR(clkdata->clkout)) {
+		ret = PTR_ERR(clkdata->clkout);
 		goto err_fll;
 	}
 
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
Acked-by on v1 1/3
#2 lore raw

Re: [PATCH 1/3] clk: wm831x: Fix clk_register() error code checking

Quoted 2 lines · Stephen Boyd

clk_register() returns an ERR_PTR upon failure, not NULL. Fix these error paths.

this is an API change since the driver was sent which the driver didn't get updatd for.

#3 lore raw

PATCH 2/3 clk: Add devm_clk_{register,unregister}()

In reply to Stephen Boyd

Some clock drivers can be simplified if devres takes care of unregistering any registered clocks along error paths. Introduce devm_clk_register() so that clock drivers get unregistration for free along with simplified error paths.

---
 drivers/clk/clk.c            | 111 +++++++++++++++++++++++++++++++++++--------
 include/linux/clk-provider.h |   2 +
 2 files changed, 92 insertions(+), 21 deletions(-)
drivers/clk/clk.c +90 -21
index 56e4495e..6852809 100644
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/device.h>
 
 static DEFINE_SPINLOCK(enable_lock);
 static DEFINE_MUTEX(prepare_lock);
@@ -1361,28 +1362,9 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
 }
 EXPORT_SYMBOL_GPL(__clk_register);
 
-/**
- * clk_register - allocate a new clock, register it and return an opaque cookie
- * @dev: device that is registering this clock
- * @hw: link to hardware-specific clock data
- *
- * clk_register is the primary interface for populating the clock tree with new
- * clock nodes.  It returns a pointer to the newly allocated struct clk which
- * cannot be dereferenced by driver code but may be used in conjuction with the
- * rest of the clock API.  In the event of an error clk_register will return an
- * error code; drivers must test for an error code after calling clk_register.
- */
-struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
 {
 	int i, ret;
-	struct clk *clk;
-
-	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
-	if (!clk) {
-		pr_err("%s: could not allocate clk\n", __func__);
-		ret = -ENOMEM;
-		goto fail_out;
-	}
 
 	clk->name = kstrdup(hw->init->name, GFP_KERNEL);
 	if (!clk->name) {
@@ -1420,7 +1402,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 
 	ret = __clk_init(dev, clk);
 	if (!ret)
-		return clk;
+		return 0;
 
 fail_parent_names_copy:
 	while (--i >= 0)
@@ -1429,6 +1411,36 @@ fail_parent_names_copy:
 fail_parent_names:
 	kfree(clk->name);
 fail_name:
+	return ret;
+}
+
+/**
+ * clk_register - allocate a new clock, register it and return an opaque cookie
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * clk_register is the primary interface for populating the clock tree with new
+ * clock nodes.  It returns a pointer to the newly allocated struct clk which
+ * cannot be dereferenced by driver code but may be used in conjuction with the
+ * rest of the clock API.  In the event of an error clk_register will return an
+ * error code; drivers must test for an error code after calling clk_register.
+ */
+struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+{
+	int ret;
+	struct clk *clk;
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+	if (!clk) {
+		pr_err("%s: could not allocate clk\n", __func__);
+		ret = -ENOMEM;
+		goto fail_out;
+	}
+
+	ret = _clk_register(dev, hw, clk);
+	if (!ret)
+		return clk;
+
 	kfree(clk);
 fail_out:
 	return ERR_PTR(ret);
@@ -1444,6 +1456,63 @@ EXPORT_SYMBOL_GPL(clk_register);
 void clk_unregister(struct clk *clk) {}
 EXPORT_SYMBOL_GPL(clk_unregister);
 
+static void devm_clk_release(struct device *dev, void *res)
+{
+	clk_unregister(res);
+}
+
+/**
+ * devm_clk_register - resource managed clk_register()
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * Managed clk_register(). Clocks returned from this function are
+ * automatically clk_unregister()ed on driver detach. See clk_register() for
+ * more information.
+ */
+struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
+{
+	struct clk *clk;
+	int ret;
+
+	clk = devres_alloc(devm_clk_release, sizeof(*clk), GFP_KERNEL);
+	if (!clk)
+		return ERR_PTR(-ENOMEM);
+
+	ret = _clk_register(dev, hw, clk);
+	if (!ret) {
+		devres_add(dev, clk);
+	} else {
+		devres_free(clk);
+		clk = ERR_PTR(ret);
+	}
+
+	return clk;
+}
+EXPORT_SYMBOL_GPL(devm_clk_register);
+
+static int devm_clk_match(struct device *dev, void *res, void *data)
+{
+	struct clk *c = res;
+	if (WARN_ON(!c))
+		return 0;
+	return c == data;
+}
+
+/**
+ * devm_clk_unregister - resource managed clk_unregister()
+ * @clk: clock to unregister
+ *
+ * Deallocate a clock allocated with devm_clk_register(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_clk_unregister(struct device *dev, struct clk *clk)
+{
+	WARN_ON(devres_destroy(dev, devm_clk_release, devm_clk_match, clk));
+}
+EXPORT_SYMBOL(devm_clk_unregister);
+
 /***        clk rate change notifiers        ***/
 
 /**
include/linux/clk-provider.h +2 -0
index c127315..710c6cb 100644
@@ -327,8 +327,10 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
  * error code; drivers must test for an error code after calling clk_register.
  */
 struct clk *clk_register(struct device *dev, struct clk_hw *hw);
+struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
 
 void clk_unregister(struct clk *clk);
+void devm_clk_unregister(struct device *dev, struct clk *clk);
 
 /* helper functions */
 const char *__clk_get_name(struct clk *clk);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#4 lore raw

Re: [PATCH 2/3] clk: Add devm_clk_{register,unregister}()

Review

Quoted 3 lines · Stephen Boyd
(quoted diff) +3 -0
+void devm_clk_unregister(struct device *dev, struct clk *clk)
+{
+	WARN_ON(devres_destroy(dev, devm_clk_release, devm_clk_match, clk));

Hm... I guess this needs to be devres_release() instead of destroy. Can you squash this in or should I resend for the few character change?

drivers/clk/clk.c +1 -1
index 6852809..f02f4fe 100644
@@ -1509,7 +1509,7 @@ static int devm_clk_match(struct device *dev, void *res, void *data)
  */
 void devm_clk_unregister(struct device *dev, struct clk *clk)
 {
-       WARN_ON(devres_destroy(dev, devm_clk_release, devm_clk_match, clk));
+       WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk));
 }
 EXPORT_SYMBOL(devm_clk_unregister);
 
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
#5 lore raw

PATCH 2/3 clk: Add devm_clk_{register,unregister}()

Quoting Stephen Boyd (2012-09-20 19:33:42)

Quoted 8 lines · Stephen Boyd

Review

Quoted 3 lines
(quoted diff) +3 -0
+void devm_clk_unregister(struct device *dev, struct clk *clk)
+{
+     WARN_ON(devres_destroy(dev, devm_clk_release, devm_clk_match, clk));

Hm... I guess this needs to be devres_release() instead of destroy. Can you squash this in or should I resend for the few character change?

I'm not taking any more changes for 3.7, so in the interest of me being lazy can you resend with the fixup?

Thanks,
Mike

Quoted 23 lines
drivers/clk/clk.c +1 -1
index 6852809..f02f4fe 100644
@@ -1509,7 +1509,7 @@ static int devm_clk_match(struct device *dev, void *res, void *data)
  */
 void devm_clk_unregister(struct device *dev, struct clk *clk)
 {
-       WARN_ON(devres_destroy(dev, devm_clk_release, devm_clk_match, clk));
+       WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk));
 }
 EXPORT_SYMBOL(devm_clk_unregister);
 
Signature · 9 lines
-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#6 lore raw

Re: [PATCH 2/3] clk: Add devm_clk_{register,unregister}()

On 9/21/2012 6:07 PM, Mike Turquette wrote

Quoted 2 lines

I'm not taking any more changes for 3.7, so in the interest of me being lazy can you resend with the fixup?

Sure. I'll pick up Mark's acks too and send the whole series again.

Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
#7 lore raw

PATCH 3/3 clk: wm831x: Use devm_clk_register() to simplify code

In reply to Stephen Boyd

Move this driver to use devm_clk_register() to simplify some error paths and reduce lines of code.

---
 drivers/clk/clk-wm831x.c | 30 +++++++-----------------------
 1 file changed, 7 insertions(+), 23 deletions(-)
drivers/clk/clk-wm831x.c +7 -23
index eb1afaf..db4fbf2 100644
@@ -370,43 +370,27 @@ static __devinit int wm831x_clk_probe(struct platform_device *pdev)
 	clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
 
 	clkdata->xtal_hw.init = &wm831x_xtal_init;
-	clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
+	clkdata->xtal = devm_clk_register(&pdev->dev, &clkdata->xtal_hw);
 	if (IS_ERR(clkdata->xtal))
 		return PTR_ERR(clkdata->xtal);
 
 	clkdata->fll_hw.init = &wm831x_fll_init;
-	clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
-	if (IS_ERR(clkdata->fll)) {
-		ret = PTR_ERR(clkdata->fll);
-		goto err_xtal;
-	}
+	clkdata->fll = devm_clk_register(&pdev->dev, &clkdata->fll_hw);
+	if (IS_ERR(clkdata->fll))
+		return PTR_ERR(clkdata->fll);
 
 	clkdata->clkout_hw.init = &wm831x_clkout_init;
-	clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
-	if (IS_ERR(clkdata->clkout)) {
-		ret = PTR_ERR(clkdata->clkout);
-		goto err_fll;
-	}
+	clkdata->clkout = devm_clk_register(&pdev->dev, &clkdata->clkout_hw);
+	if (IS_ERR(clkdata->clkout))
+		return PTR_ERR(clkdata->clkout);
 
 	dev_set_drvdata(&pdev->dev, clkdata);
 
 	return 0;
-
-err_fll:
-	clk_unregister(clkdata->fll);
-err_xtal:
-	clk_unregister(clkdata->xtal);
-	return ret;
 }
 
 static int __devexit wm831x_clk_remove(struct platform_device *pdev)
 {
-	struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
-
-	clk_unregister(clkdata->clkout);
-	clk_unregister(clkdata->fll);
-	clk_unregister(clkdata->xtal);
-
 	return 0;
 }
 
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
Acked-by on v1 3/3
#8 lore raw

Re: [PATCH 3/3] clk: wm831x: Use devm_clk_register() to simplify code

Quoted 2 lines · Stephen Boyd

Move this driver to use devm_clk_register() to simplify some error paths and reduce lines of code.

#9 lore raw
In reply to Stephen Boyd
Quoted 8 lines · Stephen Boyd

The first patch in this series fixes error checking in the wm831x clock driver and is here to prevent context conflicts in the third patch. I split it out in case it needed to merge sooner rather than later.

The goal of this series is to add devm_clk_register() so I can use it in some MSM clock code I'm sending out in the near future. The second patch adds the API and the third patch moves over an existing user of clk_unregister() to the devm API.

Can we guarantee that the clocks are unused when the module is removed? If we can't make that guarantee, then devm_* should not be used here, and instead there should be refcounting done in the clocks (that's what the __clk_get() and __clk_put() hooks are there for.)

#10 lore raw
Quoted 5 lines · Russell King - ARM Linux
Quoted 4 lines · Stephen Boyd

The first patch in this series fixes error checking in the wm831x clock driver and is here to prevent context conflicts in the third patch. I split it out in case it needed to merge sooner rather than later.

Quoted 8 lines
Quoted 4 lines

The goal of this series is to add devm_clk_register() so I can use it in some MSM clock code I'm sending out in the near future. The second patch adds the API and the third patch moves over an existing user of clk_unregister() to the devm API.

Can we guarantee that the clocks are unused when the module is removed? If we can't make that guarantee, then devm_* should not be used here, and instead there should be refcounting done in the clocks (that's what the __clk_get() and __clk_put() hooks are there for.)

We could guarantee that when clk_unregister() is actually implemented. __clk_get() would need to forward a call to the module providing the clock via try_module_get(). Similarly we would call module_put() in __clk_put(). That would prevent unbinding the driver from the device via module removal.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
#11 lore raw
Quoted 15 lines · Stephen Boyd
Quoted 5 lines · Russell King - ARM Linux
Quoted 4 lines · Stephen Boyd

The first patch in this series fixes error checking in the wm831x clock driver and is here to prevent context conflicts in the third patch. I split it out in case it needed to merge sooner rather than later.

Quoted 8 lines
Quoted 4 lines

The goal of this series is to add devm_clk_register() so I can use it in some MSM clock code I'm sending out in the near future. The second patch adds the API and the third patch moves over an existing user of clk_unregister() to the devm API.

Can we guarantee that the clocks are unused when the module is removed? If we can't make that guarantee, then devm_* should not be used here, and instead there should be refcounting done in the clocks (that's what the __clk_get() and __clk_put() hooks are there for.)

Quoted 5 lines

We could guarantee that when clk_unregister() is actually implemented. __clk_get() would need to forward a call to the module providing the clock via try_module_get(). Similarly we would call module_put() in __clk_put(). That would prevent unbinding the driver from the device via module removal.

Strangely enough... mach-integrator's clkdev.h... precisely because it has a module which may provide a clock.

static inline int __clk_get(struct clk *clk)

{
        return try_module_get(clk->owner);
}

static inline void __clk_put(struct clk *clk)

{
        module_put(clk->owner);
}
#12 lore raw

PATCH v2 1/3 clk: wm831x: Fix clk_register() error code checking

In reply to Stephen Boyd

clk_register() returns an ERR_PTR upon failure, not NULL. Fix these error paths.

---

v2: No changes

 drivers/clk/clk-wm831x.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/clk/clk-wm831x.c +6 -6
index e7b7765..eb1afaf 100644
@@ -371,20 +371,20 @@ static __devinit int wm831x_clk_probe(struct platform_device *pdev)
 
 	clkdata->xtal_hw.init = &wm831x_xtal_init;
 	clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
-	if (!clkdata->xtal)
-		return -EINVAL;
+	if (IS_ERR(clkdata->xtal))
+		return PTR_ERR(clkdata->xtal);
 
 	clkdata->fll_hw.init = &wm831x_fll_init;
 	clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
-	if (!clkdata->fll) {
-		ret = -EINVAL;
+	if (IS_ERR(clkdata->fll)) {
+		ret = PTR_ERR(clkdata->fll);
 		goto err_xtal;
 	}
 
 	clkdata->clkout_hw.init = &wm831x_clkout_init;
 	clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
-	if (!clkdata->clkout) {
-		ret = -EINVAL;
+	if (IS_ERR(clkdata->clkout)) {
+		ret = PTR_ERR(clkdata->clkout);
 		goto err_fll;
 	}
 
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#13 lore raw

PATCH v2 2/3 clk: Add devm_clk_{register,unregister}()

Some clock drivers can be simplified if devres takes care of unregistering any registered clocks along error paths. Introduce devm_clk_register() so that clock drivers get unregistration for free along with simplified error paths.

---

v2: Use devres_release()

 drivers/clk/clk.c            | 111 +++++++++++++++++++++++++++++++++++--------
 include/linux/clk-provider.h |   2 +
 2 files changed, 92 insertions(+), 21 deletions(-)
drivers/clk/clk.c +90 -21
index 56e4495e..6852809 100644
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/device.h>
 
 static DEFINE_SPINLOCK(enable_lock);
 static DEFINE_MUTEX(prepare_lock);
@@ -1361,28 +1362,9 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
 }
 EXPORT_SYMBOL_GPL(__clk_register);
 
-/**
- * clk_register - allocate a new clock, register it and return an opaque cookie
- * @dev: device that is registering this clock
- * @hw: link to hardware-specific clock data
- *
- * clk_register is the primary interface for populating the clock tree with new
- * clock nodes.  It returns a pointer to the newly allocated struct clk which
- * cannot be dereferenced by driver code but may be used in conjuction with the
- * rest of the clock API.  In the event of an error clk_register will return an
- * error code; drivers must test for an error code after calling clk_register.
- */
-struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
 {
 	int i, ret;
-	struct clk *clk;
-
-	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
-	if (!clk) {
-		pr_err("%s: could not allocate clk\n", __func__);
-		ret = -ENOMEM;
-		goto fail_out;
-	}
 
 	clk->name = kstrdup(hw->init->name, GFP_KERNEL);
 	if (!clk->name) {
@@ -1420,7 +1402,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 
 	ret = __clk_init(dev, clk);
 	if (!ret)
-		return clk;
+		return 0;
 
 fail_parent_names_copy:
 	while (--i >= 0)
@@ -1429,6 +1411,36 @@ fail_parent_names_copy:
 fail_parent_names:
 	kfree(clk->name);
 fail_name:
+	return ret;
+}
+
+/**
+ * clk_register - allocate a new clock, register it and return an opaque cookie
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * clk_register is the primary interface for populating the clock tree with new
+ * clock nodes.  It returns a pointer to the newly allocated struct clk which
+ * cannot be dereferenced by driver code but may be used in conjuction with the
+ * rest of the clock API.  In the event of an error clk_register will return an
+ * error code; drivers must test for an error code after calling clk_register.
+ */
+struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+{
+	int ret;
+	struct clk *clk;
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+	if (!clk) {
+		pr_err("%s: could not allocate clk\n", __func__);
+		ret = -ENOMEM;
+		goto fail_out;
+	}
+
+	ret = _clk_register(dev, hw, clk);
+	if (!ret)
+		return clk;
+
 	kfree(clk);
 fail_out:
 	return ERR_PTR(ret);
@@ -1444,6 +1456,63 @@ EXPORT_SYMBOL_GPL(clk_register);
 void clk_unregister(struct clk *clk) {}
 EXPORT_SYMBOL_GPL(clk_unregister);
 
+static void devm_clk_release(struct device *dev, void *res)
+{
+	clk_unregister(res);
+}
+
+/**
+ * devm_clk_register - resource managed clk_register()
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * Managed clk_register(). Clocks returned from this function are
+ * automatically clk_unregister()ed on driver detach. See clk_register() for
+ * more information.
+ */
+struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
+{
+	struct clk *clk;
+	int ret;
+
+	clk = devres_alloc(devm_clk_release, sizeof(*clk), GFP_KERNEL);
+	if (!clk)
+		return ERR_PTR(-ENOMEM);
+
+	ret = _clk_register(dev, hw, clk);
+	if (!ret) {
+		devres_add(dev, clk);
+	} else {
+		devres_free(clk);
+		clk = ERR_PTR(ret);
+	}
+
+	return clk;
+}
+EXPORT_SYMBOL_GPL(devm_clk_register);
+
+static int devm_clk_match(struct device *dev, void *res, void *data)
+{
+	struct clk *c = res;
+	if (WARN_ON(!c))
+		return 0;
+	return c == data;
+}
+
+/**
+ * devm_clk_unregister - resource managed clk_unregister()
+ * @clk: clock to unregister
+ *
+ * Deallocate a clock allocated with devm_clk_register(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_clk_unregister(struct device *dev, struct clk *clk)
+{
+	WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk));
+}
+EXPORT_SYMBOL_GPL(devm_clk_unregister);
+
 /***        clk rate change notifiers        ***/
 
 /**
include/linux/clk-provider.h +2 -0
index c127315..710c6cb 100644
@@ -327,8 +327,10 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
  * error code; drivers must test for an error code after calling clk_register.
  */
 struct clk *clk_register(struct device *dev, struct clk_hw *hw);
+struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
 
 void clk_unregister(struct clk *clk);
+void devm_clk_unregister(struct device *dev, struct clk *clk);
 
 /* helper functions */
 const char *__clk_get_name(struct clk *clk);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#14 lore raw

PATCH v2 3/3 clk: wm831x: Use devm_clk_register() to simplify code

In reply to Stephen Boyd

Move this driver to use devm_clk_register() to simplify some error paths and reduce lines of code.

---

v2: No changes

 drivers/clk/clk-wm831x.c | 30 +++++++-----------------------
 1 file changed, 7 insertions(+), 23 deletions(-)
drivers/clk/clk-wm831x.c +7 -23
index eb1afaf..db4fbf2 100644
@@ -370,43 +370,27 @@ static __devinit int wm831x_clk_probe(struct platform_device *pdev)
 	clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
 
 	clkdata->xtal_hw.init = &wm831x_xtal_init;
-	clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
+	clkdata->xtal = devm_clk_register(&pdev->dev, &clkdata->xtal_hw);
 	if (IS_ERR(clkdata->xtal))
 		return PTR_ERR(clkdata->xtal);
 
 	clkdata->fll_hw.init = &wm831x_fll_init;
-	clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
-	if (IS_ERR(clkdata->fll)) {
-		ret = PTR_ERR(clkdata->fll);
-		goto err_xtal;
-	}
+	clkdata->fll = devm_clk_register(&pdev->dev, &clkdata->fll_hw);
+	if (IS_ERR(clkdata->fll))
+		return PTR_ERR(clkdata->fll);
 
 	clkdata->clkout_hw.init = &wm831x_clkout_init;
-	clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
-	if (IS_ERR(clkdata->clkout)) {
-		ret = PTR_ERR(clkdata->clkout);
-		goto err_fll;
-	}
+	clkdata->clkout = devm_clk_register(&pdev->dev, &clkdata->clkout_hw);
+	if (IS_ERR(clkdata->clkout))
+		return PTR_ERR(clkdata->clkout);
 
 	dev_set_drvdata(&pdev->dev, clkdata);
 
 	return 0;
-
-err_fll:
-	clk_unregister(clkdata->fll);
-err_xtal:
-	clk_unregister(clkdata->xtal);
-	return ret;
 }
 
 static int __devexit wm831x_clk_remove(struct platform_device *pdev)
 {
-	struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
-
-	clk_unregister(clkdata->clkout);
-	clk_unregister(clkdata->fll);
-	clk_unregister(clkdata->xtal);
-
 	return 0;
 }
 
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#15 lore raw

PATCH v2 1/3 clk: wm831x: Fix clk_register() error code checking

In reply to Stephen Boyd

Quoting Stephen Boyd (2012-09-24 13:38:03)

Quoted 5 lines

clk_register() returns an ERR_PTR upon failure, not NULL. Fix these error paths.

Thanks for sending V2. Taken into clk-next.

Regards,
Mike

Quoted 41 lines

---

v2: No changes

 drivers/clk/clk-wm831x.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/clk/clk-wm831x.c +6 -6
index e7b7765..eb1afaf 100644
@@ -371,20 +371,20 @@ static __devinit int wm831x_clk_probe(struct platform_device *pdev)
 
        clkdata->xtal_hw.init = &wm831x_xtal_init;
        clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
-       if (!clkdata->xtal)
-               return -EINVAL;
+       if (IS_ERR(clkdata->xtal))
+               return PTR_ERR(clkdata->xtal);
 
        clkdata->fll_hw.init = &wm831x_fll_init;
        clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
-       if (!clkdata->fll) {
-               ret = -EINVAL;
+       if (IS_ERR(clkdata->fll)) {
+               ret = PTR_ERR(clkdata->fll);
                goto err_xtal;
        }
 
        clkdata->clkout_hw.init = &wm831x_clkout_init;
        clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
-       if (!clkdata->clkout) {
-               ret = -EINVAL;
+       if (IS_ERR(clkdata->clkout)) {
+               ret = PTR_ERR(clkdata->clkout);
                goto err_fll;
        }
 
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation