diff options
author | Stefan Agner <stefan@agner.ch> | 2014-07-15 14:56:20 +0200 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2014-08-18 01:03:39 +0200 |
commit | ec56acfef2af184ca485ffeba16adbd56c110c94 (patch) | |
tree | 3c7509c81a1ae6854a437a7d98f0df313e1e0565 /drivers/net/can/flexcan.c | |
parent | 4ade6feb52262eae0c40d6714e3446bfa4d19a5f (diff) | |
download | linux-ec56acfef2af184ca485ffeba16adbd56c110c94.tar.bz2 |
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>
Diffstat (limited to 'drivers/net/can/flexcan.c')
-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 f425ec2c7839..6bfe24aefea0 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -378,8 +378,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; @@ -391,6 +392,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); @@ -503,7 +527,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: |