Skip to content

Commit 717c6ec

Browse files
miquelraynalmarckleinebudde
authored andcommitted
can: sja1000: Prevent overrun stalls with a soft reset on Renesas SoCs
In their RZN1 SoC, Renesas put a CAN controller supposed to act very similarly to the original Philips sja1000. In practice, while flooding the bus with another device, we discovered that the controller very often after an overrun situation would just refuse any new frame, drop them all and trigger over and over again the overrun interrupt, even though the buffer would have been totally emptied. The controller acts like if its internal buffer offsets (where it writes and where the host reads) where totally screwed-up. Renesas manual mentions a single action to perform in order to resynchronize the read and write offsets within the buffer: performing a soft reset. Performing a soft reset takes a bit of time and involves small delays, so better do that in a threaded handler rather than inside the hard IRQ handler. Add platform data to recognize the platforms which need this workaround, and when the faulty situation is diagnosed, stop what is being performed and request the threaded handler to be executed in order to perform the reset. Tested-by: Jérémie Dautheribes <[email protected]> # 5.10 Signed-off-by: Miquel Raynal <[email protected]> Link: https://lore.kernel.org/all/[email protected] Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent af7647a commit 717c6ec

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

drivers/net/can/sja1000/sja1000.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,16 @@ static void sja1000_rx(struct net_device *dev)
387387
netif_rx(skb);
388388
}
389389

390+
static irqreturn_t sja1000_reset_interrupt(int irq, void *dev_id)
391+
{
392+
struct net_device *dev = (struct net_device *)dev_id;
393+
394+
netdev_dbg(dev, "performing a soft reset upon overrun\n");
395+
sja1000_start(dev);
396+
397+
return IRQ_HANDLED;
398+
}
399+
390400
static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
391401
{
392402
struct sja1000_priv *priv = netdev_priv(dev);
@@ -397,6 +407,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
397407
enum can_state rx_state, tx_state;
398408
unsigned int rxerr, txerr;
399409
uint8_t ecc, alc;
410+
int ret = 0;
400411

401412
skb = alloc_can_err_skb(dev, &cf);
402413
if (skb == NULL)
@@ -413,6 +424,15 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
413424
stats->rx_over_errors++;
414425
stats->rx_errors++;
415426
sja1000_write_cmdreg(priv, CMD_CDO); /* clear bit */
427+
428+
/* Some controllers needs additional handling upon overrun
429+
* condition: the controller may sometimes be totally confused
430+
* and refuse any new frame while its buffer is empty. The only
431+
* way to re-sync the read vs. write buffer offsets is to
432+
* stop any current handling and perform a reset.
433+
*/
434+
if (priv->flags & SJA1000_QUIRK_RESET_ON_OVERRUN)
435+
ret = IRQ_WAKE_THREAD;
416436
}
417437

418438
if (isrc & IRQ_EI) {
@@ -492,7 +512,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
492512

493513
netif_rx(skb);
494514

495-
return 0;
515+
return ret;
496516
}
497517

498518
irqreturn_t sja1000_interrupt(int irq, void *dev_id)
@@ -548,6 +568,8 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
548568
if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) {
549569
/* error interrupt */
550570
err = sja1000_err(dev, isrc, status);
571+
if (err == IRQ_WAKE_THREAD)
572+
ret = err;
551573
if (err)
552574
break;
553575
}
@@ -582,8 +604,9 @@ static int sja1000_open(struct net_device *dev)
582604

583605
/* register interrupt handler, if not done by the device driver */
584606
if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) {
585-
err = request_irq(dev->irq, sja1000_interrupt, priv->irq_flags,
586-
dev->name, (void *)dev);
607+
err = request_threaded_irq(dev->irq, sja1000_interrupt,
608+
sja1000_reset_interrupt,
609+
priv->irq_flags, dev->name, (void *)dev);
587610
if (err) {
588611
close_candev(dev);
589612
return -EAGAIN;

drivers/net/can/sja1000/sja1000.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@
147147
*/
148148
#define SJA1000_CUSTOM_IRQ_HANDLER BIT(0)
149149
#define SJA1000_QUIRK_NO_CDR_REG BIT(1)
150+
#define SJA1000_QUIRK_RESET_ON_OVERRUN BIT(2)
150151

151152
/*
152153
* SJA1000 private data structure

drivers/net/can/sja1000/sja1000_platform.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ static void sp_technologic_init(struct sja1000_priv *priv, struct device_node *o
106106

107107
static void sp_rzn1_init(struct sja1000_priv *priv, struct device_node *of)
108108
{
109-
priv->flags = SJA1000_QUIRK_NO_CDR_REG;
109+
priv->flags = SJA1000_QUIRK_NO_CDR_REG | SJA1000_QUIRK_RESET_ON_OVERRUN;
110110
}
111111

112112
static void sp_populate(struct sja1000_priv *priv,
@@ -277,6 +277,9 @@ static int sp_probe(struct platform_device *pdev)
277277
priv->irq_flags = IRQF_SHARED;
278278
}
279279

280+
if (priv->flags & SJA1000_QUIRK_RESET_ON_OVERRUN)
281+
priv->irq_flags |= IRQF_ONESHOT;
282+
280283
dev->irq = irq;
281284
priv->reg_base = addr;
282285

0 commit comments

Comments
 (0)