]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
9cb72427efd8f1e0c7a0329887f158f6d30924a9
[thirdparty/kernel/stable-queue.git] /
1 From 702de2c21eed04c67cefaaedc248ef16e5f6b293 Mon Sep 17 00:00:00 2001
2 From: Biju Das <biju.das.jz@bp.renesas.com>
3 Date: Tue, 25 Oct 2022 16:56:55 +0100
4 Subject: can: rcar_canfd: rcar_canfd_handle_global_receive(): fix IRQ storm on global FIFO receive
5
6 From: Biju Das <biju.das.jz@bp.renesas.com>
7
8 commit 702de2c21eed04c67cefaaedc248ef16e5f6b293 upstream.
9
10 We are seeing an IRQ storm on the global receive IRQ line under heavy
11 CAN bus load conditions with both CAN channels enabled.
12
13 Conditions:
14
15 The global receive IRQ line is shared between can0 and can1, either of
16 the channels can trigger interrupt while the other channel's IRQ line
17 is disabled (RFIE).
18
19 When global a receive IRQ interrupt occurs, we mask the interrupt in
20 the IRQ handler. Clearing and unmasking of the interrupt is happening
21 in rx_poll(). There is a race condition where rx_poll() unmasks the
22 interrupt, but the next IRQ handler does not mask the IRQ due to
23 NAPIF_STATE_MISSED flag (e.g.: can0 RX FIFO interrupt is disabled and
24 can1 is triggering RX interrupt, the delay in rx_poll() processing
25 results in setting NAPIF_STATE_MISSED flag) leading to an IRQ storm.
26
27 This patch fixes the issue by checking IRQ active and enabled before
28 handling the IRQ on a particular channel.
29
30 Fixes: dd3bd23eb438 ("can: rcar_canfd: Add Renesas R-Car CAN FD driver")
31 Suggested-by: Marc Kleine-Budde <mkl@pengutronix.de>
32 Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
33 Link: https://lore.kernel.org/all/20221025155657.1426948-2-biju.das.jz@bp.renesas.com
34 Cc: stable@vger.kernel.org
35 [mkl: adjust commit message]
36 Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
37 [biju: removed gpriv from RCANFD_RFCC_RFIE macro]
38 Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
39 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
40 ---
41 drivers/net/can/rcar/rcar_canfd.c | 6 ++++--
42 1 file changed, 4 insertions(+), 2 deletions(-)
43
44 diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
45 index 67f0f14e2bf4..c61534a2a2d3 100644
46 --- a/drivers/net/can/rcar/rcar_canfd.c
47 +++ b/drivers/net/can/rcar/rcar_canfd.c
48 @@ -1075,7 +1075,7 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
49 struct rcar_canfd_global *gpriv = dev_id;
50 struct net_device *ndev;
51 struct rcar_canfd_channel *priv;
52 - u32 sts, gerfl;
53 + u32 sts, cc, gerfl;
54 u32 ch, ridx;
55
56 /* Global error interrupts still indicate a condition specific
57 @@ -1093,7 +1093,9 @@ static irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id)
58
59 /* Handle Rx interrupts */
60 sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx));
61 - if (likely(sts & RCANFD_RFSTS_RFIF)) {
62 + cc = rcar_canfd_read(priv->base, RCANFD_RFCC(ridx));
63 + if (likely(sts & RCANFD_RFSTS_RFIF &&
64 + cc & RCANFD_RFCC_RFIE)) {
65 if (napi_schedule_prep(&priv->napi)) {
66 /* Disable Rx FIFO interrupts */
67 rcar_canfd_clear_bit(priv->base,
68 --
69 2.25.1
70