aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can/xilinx_can.c
diff options
context:
space:
mode:
authorAnssi Hannula <anssi.hannula@bitwise.fi>2019-04-03 15:18:53 +0300
committerMarc Kleine-Budde <mkl@pengutronix.de>2019-08-13 16:42:05 +0200
commit3486cc40ccbfe4cbf55feecce88a792e3043c178 (patch)
treefade36b3c95a9949967b572435f8c195397f16e5 /drivers/net/can/xilinx_can.c
parentcan: ti_hecc: ti_hecc_mailbox_read(): remove set but not used variable 'mbx_mask' (diff)
downloadlinux-dev-3486cc40ccbfe4cbf55feecce88a792e3043c178.tar.xz
linux-dev-3486cc40ccbfe4cbf55feecce88a792e3043c178.zip
can: xilinx_can: xcan_chip_start(): fix failure with invalid bus
Currently the xilinx_can xcan_chip_start() function, called from .ndo_open() and via CAN_MODE_START (bus-off restart), waits for the SR register to show the wanted operating state, with a 1 sec timeout. However, that register bit will only be set once the HW has observed 11 consecutive recessive bits (BusIdle) on the bus. If the bus will not see the 11 bits (e.g. it is stuck dominant), the function will timeout and return an error. If this was done as part of a scheduled restart from bus-off, the interface will stay in bus-off state forever even if the bus recovers later. According to M_CAN and FLEXCAN documentation they also wait for 11 consecutive recessive bits, but their drivers do not seem to wait for that. To make the behavior consistent, modify xilinx_can to also not wait for the synchronization to complete. The only way for users to know for sure that the bus has been joined successfully is to see successfully received or transmitted frames. That does not seem optimal, but it is consistent with other drivers and we should have a properly working restart-ms with xilinx_can. Tested on ZynqMP with Xilinx CAN-FD 1.0. Fixes: b1201e44f50b ("can: xilinx CAN controller support") Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi> Tested-by: Appana Durga Kedareswara Rao <appana.durga.rao@xilinx.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can/xilinx_can.c')
-rw-r--r--drivers/net/can/xilinx_can.c13
1 files changed, 1 insertions, 12 deletions
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index bd95cfaff857..c7d043a40837 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -456,9 +456,8 @@ static int xcan_set_bittiming(struct net_device *ndev)
static int xcan_chip_start(struct net_device *ndev)
{
struct xcan_priv *priv = netdev_priv(ndev);
- u32 reg_msr, reg_sr_mask;
+ u32 reg_msr;
int err;
- unsigned long timeout;
u32 ier;
/* Check if it is in reset mode */
@@ -484,10 +483,8 @@ static int xcan_chip_start(struct net_device *ndev)
/* Check whether it is loopback mode or normal mode */
if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
reg_msr = XCAN_MSR_LBACK_MASK;
- reg_sr_mask = XCAN_SR_LBACK_MASK;
} else {
reg_msr = 0x0;
- reg_sr_mask = XCAN_SR_NORMAL_MASK;
}
/* enable the first extended filter, if any, as cores with extended
@@ -499,14 +496,6 @@ static int xcan_chip_start(struct net_device *ndev)
priv->write_reg(priv, XCAN_MSR_OFFSET, reg_msr);
priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK);
- timeout = jiffies + XCAN_TIMEOUT;
- while (!(priv->read_reg(priv, XCAN_SR_OFFSET) & reg_sr_mask)) {
- if (time_after(jiffies, timeout)) {
- netdev_warn(ndev,
- "timed out for correct mode\n");
- return -ETIMEDOUT;
- }
- }
netdev_dbg(ndev, "status:#x%08x\n",
priv->read_reg(priv, XCAN_SR_OFFSET));