net: ethernet: ti: cpts: fix unbalanced clk api usage in cpts_register/unregister
authorGrygorii Strashko <grygorii.strashko@ti.com>
Wed, 7 Dec 2016 00:00:36 +0000 (18:00 -0600)
committerDavid S. Miller <davem@davemloft.net>
Wed, 7 Dec 2016 16:13:46 +0000 (11:13 -0500)
There are two issues with TI CPTS code which are reproducible when TI
CPSW ethX device passes few up/down iterations:
- cpts refclk prepare counter continuously incremented after each
up/down iteration;
- devm_clk_get(dev, "cpts") is called many times.

Hence, fix these issues by using clk_disable_unprepare() in
cpts_clk_release() and skipping devm_clk_get() if cpts refclk has been
acquired already.

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ti/cpts.c

index 8cb0369f0d1adbf7d437f53e6b382123df980526..61198f154a04a3d43b48b438e42829bb7a50230b 100644 (file)
@@ -230,18 +230,20 @@ static void cpts_overflow_check(struct work_struct *work)
 
 static void cpts_clk_init(struct device *dev, struct cpts *cpts)
 {
-       cpts->refclk = devm_clk_get(dev, "cpts");
-       if (IS_ERR(cpts->refclk)) {
-               dev_err(dev, "Failed to get cpts refclk\n");
-               cpts->refclk = NULL;
-               return;
+       if (!cpts->refclk) {
+               cpts->refclk = devm_clk_get(dev, "cpts");
+               if (IS_ERR(cpts->refclk)) {
+                       dev_err(dev, "Failed to get cpts refclk\n");
+                       cpts->refclk = NULL;
+                       return;
+               }
        }
        clk_prepare_enable(cpts->refclk);
 }
 
 static void cpts_clk_release(struct cpts *cpts)
 {
-       clk_disable(cpts->refclk);
+       clk_disable_unprepare(cpts->refclk);
 }
 
 static int cpts_match(struct sk_buff *skb, unsigned int ptp_class,