From: Andreas Larsson andreas@gaisler.com
commit 2873d4d52f7c52d60b316ba6c47bd7122b5a9861 upstream.
The previous split budget between TX and RX made it return not using the entire budget but at the same time not having calling called napi_complete. This sometimes led to the poll to not be called, and at the same time having TX and RX interrupts disabled resulting in the driver getting stuck.
Fixes: 6cec9b07fe6a ("can: grcan: Add device driver for GRCAN and GRHCAN cores") Link: https://lore.kernel.org/all/20220429084656.29788-4-andreas@gaisler.com Cc: stable@vger.kernel.org Signed-off-by: Andreas Larsson andreas@gaisler.com Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/net/can/grcan.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-)
--- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -1137,7 +1137,7 @@ static int grcan_close(struct net_device return 0; }
-static int grcan_transmit_catch_up(struct net_device *dev, int budget) +static void grcan_transmit_catch_up(struct net_device *dev) { struct grcan_priv *priv = netdev_priv(dev); unsigned long flags; @@ -1145,7 +1145,7 @@ static int grcan_transmit_catch_up(struc
spin_lock_irqsave(&priv->lock, flags);
- work_done = catch_up_echo_skb(dev, budget, true); + work_done = catch_up_echo_skb(dev, -1, true); if (work_done) { if (!priv->resetting && !priv->closing && !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) @@ -1159,8 +1159,6 @@ static int grcan_transmit_catch_up(struc }
spin_unlock_irqrestore(&priv->lock, flags); - - return work_done; }
static int grcan_receive(struct net_device *dev, int budget) @@ -1242,19 +1240,13 @@ static int grcan_poll(struct napi_struct struct net_device *dev = priv->dev; struct grcan_registers __iomem *regs = priv->regs; unsigned long flags; - int tx_work_done, rx_work_done; - int rx_budget = budget / 2; - int tx_budget = budget - rx_budget; + int work_done;
- /* Half of the budget for receiving messages */ - rx_work_done = grcan_receive(dev, rx_budget); + work_done = grcan_receive(dev, budget);
- /* Half of the budget for transmitting messages as that can trigger echo - * frames being received - */ - tx_work_done = grcan_transmit_catch_up(dev, tx_budget); + grcan_transmit_catch_up(dev);
- if (rx_work_done < rx_budget && tx_work_done < tx_budget) { + if (work_done < budget) { napi_complete(napi);
/* Guarantee no interference with a running reset that otherwise @@ -1271,7 +1263,7 @@ static int grcan_poll(struct napi_struct spin_unlock_irqrestore(&priv->lock, flags); }
- return rx_work_done + tx_work_done; + return work_done; }
/* Work tx bug by waiting while for the risky situation to clear. If that fails,