*/
atomic_t refcount;
+ /* Stop the channel on hardware failure.
+ * Once this is true, nothing will be sent to the TTY.
+ */
+ bool hw_failure;
+
/* TTY TX helpers */
struct work_struct tx_work; /* Flushes TTY TX buffer */
unsigned char txbuf[32];
{
int actual;
+ if (elm->hw_failure) {
+ return;
+ }
+
memcpy(elm->txbuf, buf, len);
/* Order of next two lines is *very* important.
{
struct can_frame frame = {0};
- frame.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED;
+ frame.can_id = CAN_ERR_FLAG;
frame.can_dlc = CAN_ERR_DLC;
+ frame.data[5] = 'R';
+ frame.data[6] = 'I';
+ frame.data[7] = 'P';
elm327_feed_frame_to_netdev(elm, &frame);
- pr_err("ELM327 misbehaved. Re-initializing.\n");
+ netdev_err(elm->dev, "ELM327 misbehaved. "
+ "Blocking further communication.\n");
- elm->can.can_stats.restarts++;
- elm327_init(elm);
+ elm->hw_failure = true;
+ can_bus_off(elm->dev);
}
int err;
spin_lock_bh(&elm->lock);
+ if (elm->hw_failure) {
+ netdev_err(elm->dev, "Refusing to open interface after "
+ "a hardware fault has been detected.\n");
+ spin_unlock_bh(&elm->lock);
+ return -EIO;
+ }
+
if (elm->tty == NULL) {
spin_unlock_bh(&elm->lock);
return -ENODEV;
* See Documentation/networking/netdevices.txt
*/
spin_lock(&elm->lock);
+
+ /* We shouldn't get here after a hardware fault:
+ * can_bus_off() calls netif_carrier_off()
+ */
+ BUG_ON(elm->hw_failure);
+
if (elm->tty == NULL
|| elm->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
spin_unlock(&elm->lock);
ssize_t actual;
spin_lock_bh(&elm->lock);
- /* First make sure we're connected. */
+ if (elm->hw_failure) {
+ spin_unlock_bh(&elm->lock);
+ return;
+ }
+
if (!elm->tty || !netif_running(elm->dev)) {
spin_unlock_bh(&elm->lock);
return;