If the RXACT flag is not cleared on the mscan, the slprq will eventually
fail. This could be the situation when some opposite is keeping resending
frames because of some communication errors. This way we will the initrq or
cswai will also not be set and the mscan controller will got stuck till
the bus is restarted. To avoid this we kick out setting the err value beyong a
slprq failure to let the controller proceed. This is hacky since calling e.g.
initrq while the mscan is really doing stuffs might disturb the bus
communication. For now we however don't have other possiblities to work around
the behaviour of mscan mentioned above.

Signed-off-by: Luotao Fu <[email protected]>
---
 drivers/net/can/mscan/mscan.c |   20 ++++++++++++++------
 1 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index ad09c63..b38a920 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -137,13 +137,21 @@ static int mscan_set_mode(struct net_device *dev, u8 mode)
                                udelay(100);
                        }
                        if (i >= MSCAN_SET_MODE_RETRIES)
-                               ret = -ENODEV;
+                       /* XXX: sometimes while there are irregular activities
+                        * on bus, like somebody keeps retransmitting. The mscan
+                        * will fail to enter sleep mode. We proceed to init or
+                        * wait mode in this case any how, since otherwise the
+                        * controller will get stuck. The sleep mode is for now
+                        * never set alone, so there should be no further
+                        * impact caused by not catching this error */
+                               dev_warn(dev->dev.parent,
+                                       "SLPRQ timeout reached, "
+                                       "failed to enter sleep mode!\n");
+                       else
+                               priv->can.state = CAN_STATE_SLEEPING;
                }
-               if (!ret)
-                       priv->can.state = CAN_STATE_SLEEPING;
 
-               if (!ret && (mode & MSCAN_INITRQ)
-                   && (canctl1 & MSCAN_INITAK) == 0) {
+               if ((mode & MSCAN_INITRQ) && (canctl1 & MSCAN_INITAK) == 0) {
                        out_8(&regs->canctl0,
                              in_8(&regs->canctl0) | MSCAN_INITRQ);
                        for (i = 0; i < MSCAN_SET_MODE_RETRIES; i++) {
@@ -156,7 +164,7 @@ static int mscan_set_mode(struct net_device *dev, u8 mode)
                if (!ret)
                        priv->can.state = CAN_STATE_STOPPED;
 
-               if (!ret && (mode & MSCAN_CSWAI))
+               if (mode & MSCAN_CSWAI)
                        out_8(&regs->canctl0,
                              in_8(&regs->canctl0) | MSCAN_CSWAI);
 
-- 
1.6.5

_______________________________________________
Socketcan-users mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-users

Reply via email to