Skip to content

Commit 32bee8f

Browse files
l1kmarckleinebudde
authored andcommitted
can: hi311x: Work around TX complete interrupt erratum
When sending packets as fast as possible using "cangen -g 0 -i -x", the HI-3110 occasionally latches the interrupt pin high on completion of a packet, but doesn't set the TXCPLT bit in the INTF register. The INTF register contains 0x00 as if no interrupt has occurred. Even waiting for a few milliseconds after the interrupt doesn't help. Work around this apparent erratum by instead checking the TXMTY bit in the STATF register ("TX FIFO empty"). We know that we've queued up a packet for transmission if priv->tx_len is nonzero. If the TX FIFO is empty, transmission of that packet must have completed. Note that this is congruent with our handling of received packets, which likewise gleans from the STATF register whether a packet is waiting in the RX FIFO, instead of looking at the INTF register. Cc: Mathias Duckeck <[email protected]> Cc: Akshay Bhat <[email protected]> Cc: Casey Fitzpatrick <[email protected]> Cc: [email protected] # v4.12+ Signed-off-by: Lukas Wunner <[email protected]> Acked-by: Akshay Bhat <[email protected]> Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent 5cec942 commit 32bee8f

File tree

1 file changed

+5
-4
lines changed

1 file changed

+5
-4
lines changed

drivers/net/can/spi/hi311x.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
#define HI3110_STAT_BUSOFF BIT(2)
9292
#define HI3110_STAT_ERRP BIT(3)
9393
#define HI3110_STAT_ERRW BIT(4)
94+
#define HI3110_STAT_TXMTY BIT(7)
9495

9596
#define HI3110_BTR0_SJW_SHIFT 6
9697
#define HI3110_BTR0_BRP_SHIFT 0
@@ -737,10 +738,7 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
737738
}
738739
}
739740

740-
if (intf == 0)
741-
break;
742-
743-
if (intf & HI3110_INT_TXCPLT) {
741+
if (priv->tx_len && statf & HI3110_STAT_TXMTY) {
744742
net->stats.tx_packets++;
745743
net->stats.tx_bytes += priv->tx_len - 1;
746744
can_led_event(net, CAN_LED_EVENT_TX);
@@ -750,6 +748,9 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
750748
}
751749
netif_wake_queue(net);
752750
}
751+
752+
if (intf == 0)
753+
break;
753754
}
754755
mutex_unlock(&priv->hi3110_lock);
755756
return IRQ_HANDLED;

0 commit comments

Comments
 (0)