diff options
author | Grygorii Strashko <grygorii.strashko@ti.com> | 2016-12-07 03:00:36 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-12-07 19:13:46 +0300 |
commit | fd123a9414766e73fa704547e7f03595741b7de1 (patch) | |
tree | 97211277028a4eeb31860690c9dfcb01726084b7 /drivers/net/ethernet/ti/cpts.c | |
parent | b63ba58ee9957261b39209f3031ff06714cf13cb (diff) | |
download | linux-fd123a9414766e73fa704547e7f03595741b7de1.tar.xz |
net: ethernet: ti: cpts: fix unbalanced clk api usage in cpts_register/unregister
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>
Diffstat (limited to 'drivers/net/ethernet/ti/cpts.c')
-rw-r--r-- | drivers/net/ethernet/ti/cpts.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c index 8cb0369f0d1a..61198f154a04 100644 --- a/drivers/net/ethernet/ti/cpts.c +++ b/drivers/net/ethernet/ti/cpts.c @@ -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, |