Commit 30df5888 authored by Ira W. Snyder's avatar Ira W. Snyder Committed by Marc Kleine-Budde

can: janz-ican3: avoid firmware lockup caused by infinite bus error quota

If the bus error quota is set to infinite and the host CPU cannot keep
up, the Janz VMOD-ICAN3 firmware will stop responding to control
messages until the controller is reset.

The firmware will automatically stop sending bus error messages when the
quota is reached, and will only resume sending bus error messages when
the quota is re-set to a positive value.

This limitation is worked around by setting the bus error quota to one
message, and then re-setting the quota to one message every time a bus
error message is received. By doing this, the firmware never stops
responding to control messages. The CAN bus can be reset without a
hard-reset of the controller card.
Signed-off-by: default avatarIra W. Snyder <iws@ovro.caltech.edu>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 83702f69
...@@ -972,6 +972,16 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg) ...@@ -972,6 +972,16 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg)
stats->rx_errors++; stats->rx_errors++;
} }
/*
* The controller automatically disables bus-error interrupts
* and therefore we must re-enable them.
*/
ret = ican3_set_buserror(mod, 1);
if (ret) {
dev_err(mod->dev, "unable to re-enable bus-error\n");
return ret;
}
/* bus error reporting is off, return immediately */ /* bus error reporting is off, return immediately */
if (!(mod->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) if (!(mod->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING))
return 0; return 0;
...@@ -1451,7 +1461,7 @@ static int __devinit ican3_startup_module(struct ican3_dev *mod) ...@@ -1451,7 +1461,7 @@ static int __devinit ican3_startup_module(struct ican3_dev *mod)
} }
/* default to "bus errors enabled" */ /* default to "bus errors enabled" */
ret = ican3_set_buserror(mod, ICAN3_BUSERR_QUOTA_MAX); ret = ican3_set_buserror(mod, 1);
if (ret) { if (ret) {
dev_err(mod->dev, "unable to set bus-error\n"); dev_err(mod->dev, "unable to set bus-error\n");
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment