Skip to content

Commit a09721d

Browse files
can: flexcan: flexcan_mailbox_read() fix return value for drop = true
The following happened on an i.MX25 using flexcan with many packets on the bus: The rx-offload queue reached a length more than skb_queue_len_max. In can_rx_offload_offload_one() the drop variable was set to true which made the call to .mailbox_read() (here: flexcan_mailbox_read()) to _always_ return ERR_PTR(-ENOBUFS) and drop the rx'ed CAN frame. So can_rx_offload_offload_one() returned ERR_PTR(-ENOBUFS), too. can_rx_offload_irq_offload_fifo() looks as follows: | while (1) { | skb = can_rx_offload_offload_one(offload, 0); | if (IS_ERR(skb)) | continue; | if (!skb) | break; | ... | } The flexcan driver wrongly always returns ERR_PTR(-ENOBUFS) if drop is requested, even if there is no CAN frame pending. As the i.MX25 is a single core CPU, while the rx-offload processing is active, there is no thread to process packets from the offload queue. So the queue doesn't get any shorter and this results is a tight loop. Instead of always returning ERR_PTR(-ENOBUFS) if drop is requested, return NULL if no CAN frame is pending. Changes since v1: https://lore.kernel.org/all/[email protected] - don't break in can_rx_offload_irq_offload_fifo() in case of an error, return NULL in flexcan_mailbox_read() in case of no pending CAN frame instead Fixes: 4e9c948 ("can: rx-offload: Prepare for CAN FD support") Link: https://lore.kernel.org/all/[email protected] Cc: [email protected] # v5.5 Suggested-by: Uwe Kleine-König <[email protected]> Reviewed-by: Uwe Kleine-König <[email protected]> Tested-by: Thorsten Scherer <[email protected]> Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent 6a1dbfe commit a09721d

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

drivers/net/can/flexcan/flexcan-core.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -941,11 +941,6 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
941941
u32 reg_ctrl, reg_id, reg_iflag1;
942942
int i;
943943

944-
if (unlikely(drop)) {
945-
skb = ERR_PTR(-ENOBUFS);
946-
goto mark_as_read;
947-
}
948-
949944
mb = flexcan_get_mb(priv, n);
950945

951946
if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) {
@@ -974,6 +969,11 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
974969
reg_ctrl = priv->read(&mb->can_ctrl);
975970
}
976971

972+
if (unlikely(drop)) {
973+
skb = ERR_PTR(-ENOBUFS);
974+
goto mark_as_read;
975+
}
976+
977977
if (reg_ctrl & FLEXCAN_MB_CNT_EDL)
978978
skb = alloc_canfd_skb(offload->dev, &cfd);
979979
else

0 commit comments

Comments
 (0)