| From 4dcf924c2eda0c47a5c53b7703e3dc65ddaa8920 Mon Sep 17 00:00:00 2001 |
| From: Gerhard Bertelsmann <info@gerhard-bertelsmann.de> |
| Date: Mon, 6 Nov 2017 18:16:56 +0100 |
| Subject: can: sun4i: handle overrun in RX FIFO |
| |
| From: Gerhard Bertelsmann <info@gerhard-bertelsmann.de> |
| |
| commit 4dcf924c2eda0c47a5c53b7703e3dc65ddaa8920 upstream. |
| |
| SUN4Is CAN IP has a 64 byte deep FIFO buffer. If the buffer is not |
| drained fast enough (overrun) it's getting mangled. Already received |
| frames are dropped - the data can't be restored. |
| |
| Signed-off-by: Gerhard Bertelsmann <info@gerhard-bertelsmann.de> |
| Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/net/can/sun4i_can.c | 12 ++++++++++-- |
| 1 file changed, 10 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/net/can/sun4i_can.c |
| +++ b/drivers/net/can/sun4i_can.c |
| @@ -539,6 +539,13 @@ static int sun4i_can_err(struct net_devi |
| } |
| stats->rx_over_errors++; |
| stats->rx_errors++; |
| + |
| + /* reset the CAN IP by entering reset mode |
| + * ignoring timeout error |
| + */ |
| + set_reset_mode(dev); |
| + set_normal_mode(dev); |
| + |
| /* clear bit */ |
| sun4i_can_write_cmdreg(priv, SUN4I_CMD_CLEAR_OR_FLAG); |
| } |
| @@ -653,8 +660,9 @@ static irqreturn_t sun4i_can_interrupt(i |
| netif_wake_queue(dev); |
| can_led_event(dev, CAN_LED_EVENT_TX); |
| } |
| - if (isrc & SUN4I_INT_RBUF_VLD) { |
| - /* receive interrupt */ |
| + if ((isrc & SUN4I_INT_RBUF_VLD) && |
| + !(isrc & SUN4I_INT_DATA_OR)) { |
| + /* receive interrupt - don't read if overrun occurred */ |
| while (status & SUN4I_STA_RBUF_RDY) { |
| /* RX buffer is not empty */ |
| sun4i_can_rx(dev); |