]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
can: flexcan: flexcan_mailbox_read() fix return value for drop = true
authorMarc Kleine-Budde <mkl@pengutronix.de>
Thu, 11 Aug 2022 08:25:44 +0000 (10:25 +0200)
committerStefan Bader <stefan.bader@canonical.com>
Wed, 23 Nov 2022 14:11:39 +0000 (15:11 +0100)
BugLink: https://bugs.launchpad.net/bugs/1995420
commit a09721dd47c8468b3f2fdd73f40422699ffe26dd upstream.

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/20220810144536.389237-1-u.kleine-koenig@pengutronix.de
- 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: 4e9c9484b085 ("can: rx-offload: Prepare for CAN FD support")
Link: https://lore.kernel.org/all/20220811094254.1864367-1-mkl@pengutronix.de
Cc: stable@vger.kernel.org # v5.5
Suggested-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Reviewed-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Tested-by: Thorsten Scherer <t.scherer@eckelmann.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
drivers/net/can/flexcan.c

index 18d7bb99ec1bdc07564c6240fce64129f4341c7a..837bca7347594c45ab78110c221f3eca2046754d 100644 (file)
@@ -1036,11 +1036,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) {
@@ -1069,6 +1064,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