aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/ti/cpts.c
diff options
context:
space:
mode:
authorGrygorii Strashko <grygorii.strashko@ti.com>2016-12-06 18:00:36 -0600
committerDavid S. Miller <davem@davemloft.net>2016-12-07 11:13:46 -0500
commitfd123a9414766e73fa704547e7f03595741b7de1 (patch)
tree97211277028a4eeb31860690c9dfcb01726084b7 /drivers/net/ethernet/ti/cpts.c
parentnet: ethernet: ti: cpsw: minimize direct access to struct cpts (diff)
downloadlinux-dev-fd123a9414766e73fa704547e7f03595741b7de1.tar.xz
linux-dev-fd123a9414766e73fa704547e7f03595741b7de1.zip
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.c14
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,