Hello, On Thu, Aug 11, 2022 at 11:42:54AM +0200, Marc Kleine-Budde wrote: > 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. > > Fixes: 4e9c9484b085 ("can: rx-offload: Prepare for CAN FD support") > Suggested-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx> > Signed-off-by: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx> This patch (rebased onto v5.15) fixes the issue on our i.MX25 board. Tested-by: Thorsten Scherer <t.scherer@xxxxxxxxxxxx> Thank you! Best regards Thorsten > --- > drivers/net/can/flexcan/flexcan-core.c | 10 +++++----- > 1 file changed, 5 insertions(+), 5 deletions(-) > > diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c > index f857968efed7..ccb438eca517 100644 > --- a/drivers/net/can/flexcan/flexcan-core.c > +++ b/drivers/net/can/flexcan/flexcan-core.c > @@ -941,11 +941,6 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload, > u32 reg_ctrl, reg_id, reg_iflag1; > int i; > > - if (unlikely(drop)) { > - skb = ERR_PTR(-ENOBUFS); > - goto mark_as_read; > - } > - > mb = flexcan_get_mb(priv, n); > > 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, > reg_ctrl = priv->read(&mb->can_ctrl); > } > > + if (unlikely(drop)) { > + skb = ERR_PTR(-ENOBUFS); > + goto mark_as_read; > + } > + > if (reg_ctrl & FLEXCAN_MB_CNT_EDL) > skb = alloc_canfd_skb(offload->dev, &cfd); > else > -- > 2.35.1 > >