diff options
author | Stefan Agner <stefan@agner.ch> | 2014-07-15 12:56:20 (GMT) |
---|---|---|
committer | Matthew Weigel <Matthew.Weigel@freescale.com> | 2014-12-11 18:38:28 (GMT) |
commit | 1acd73335ac4081194b09b83866395c09b0a9d68 (patch) | |
tree | f902170c920068d602455ab9614261263ca4095a /drivers/net | |
parent | 23023807a913050ac2578040f0d329b5a33c08db (diff) | |
download | linux-fsl-qoriq-1acd73335ac4081194b09b83866395c09b0a9d68.tar.xz |
can: flexcan: flexcan_get_berr_counter(): switch on clocks before accessing ecr register
The funcion flexcan_get_berr_counter() may be called from userspace even if the
interface is down, this the clocks are disabled. This patch switches on the
clocks before accessing the ecr register.
Reported-by: Ashutosh Singh <ashuleapyear@gmail.com>
Signed-off-by: Stefan Agner <stefan@agner.ch>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
Cherry-picked from linux-next: ec56acfef2af184ca485ffeba16adbd56c110c94
Change-Id: I53ead04b0d5ae7c995809c51aef57acaedd3c3f4
Reviewed-on: http://git.am.freescale.net:8181/21842
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Zhengxiong Jin <Jason.Jin@freescale.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/can/flexcan.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 2eb30de..89970ea 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -375,8 +375,9 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv) return 0; } -static int flexcan_get_berr_counter(const struct net_device *dev, - struct can_berr_counter *bec) + +static int __flexcan_get_berr_counter(const struct net_device *dev, + struct can_berr_counter *bec) { const struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_regs __iomem *regs = priv->base; @@ -388,6 +389,29 @@ static int flexcan_get_berr_counter(const struct net_device *dev, return 0; } +static int flexcan_get_berr_counter(const struct net_device *dev, + struct can_berr_counter *bec) +{ + const struct flexcan_priv *priv = netdev_priv(dev); + int err; + + err = clk_prepare_enable(priv->clk_ipg); + if (err) + return err; + + err = clk_prepare_enable(priv->clk_per); + if (err) + goto out_disable_ipg; + + err = __flexcan_get_berr_counter(dev, bec); + + clk_disable_unprepare(priv->clk_per); + out_disable_ipg: + clk_disable_unprepare(priv->clk_ipg); + + return err; +} + static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) { const struct flexcan_priv *priv = netdev_priv(dev); @@ -500,7 +524,7 @@ static void do_state(struct net_device *dev, struct flexcan_priv *priv = netdev_priv(dev); struct can_berr_counter bec; - flexcan_get_berr_counter(dev, &bec); + __flexcan_get_berr_counter(dev, &bec); switch (priv->can.state) { case CAN_STATE_ERROR_ACTIVE: |