Commit 2873d4d5 authored by Andreas Larsson's avatar Andreas Larsson Committed by Marc Kleine-Budde

can: grcan: only use the NAPI poll budget for RX

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: 6cec9b07 ("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: default avatarAndreas Larsson <andreas@gaisler.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 1e93ed26
...@@ -1125,7 +1125,7 @@ static int grcan_close(struct net_device *dev) ...@@ -1125,7 +1125,7 @@ static int grcan_close(struct net_device *dev)
return 0; 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); struct grcan_priv *priv = netdev_priv(dev);
unsigned long flags; unsigned long flags;
...@@ -1133,7 +1133,7 @@ static int grcan_transmit_catch_up(struct net_device *dev, int budget) ...@@ -1133,7 +1133,7 @@ static int grcan_transmit_catch_up(struct net_device *dev, int budget)
spin_lock_irqsave(&priv->lock, flags); 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 (work_done) {
if (!priv->resetting && !priv->closing && if (!priv->resetting && !priv->closing &&
!(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
...@@ -1147,8 +1147,6 @@ static int grcan_transmit_catch_up(struct net_device *dev, int budget) ...@@ -1147,8 +1147,6 @@ static int grcan_transmit_catch_up(struct net_device *dev, int budget)
} }
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
return work_done;
} }
static int grcan_receive(struct net_device *dev, int budget) static int grcan_receive(struct net_device *dev, int budget)
...@@ -1230,19 +1228,13 @@ static int grcan_poll(struct napi_struct *napi, int budget) ...@@ -1230,19 +1228,13 @@ static int grcan_poll(struct napi_struct *napi, int budget)
struct net_device *dev = priv->dev; struct net_device *dev = priv->dev;
struct grcan_registers __iomem *regs = priv->regs; struct grcan_registers __iomem *regs = priv->regs;
unsigned long flags; unsigned long flags;
int tx_work_done, rx_work_done; int work_done;
int rx_budget = budget / 2;
int tx_budget = budget - rx_budget;
/* Half of the budget for receiving messages */ work_done = grcan_receive(dev, budget);
rx_work_done = grcan_receive(dev, rx_budget);
/* Half of the budget for transmitting messages as that can trigger echo grcan_transmit_catch_up(dev);
* frames being received
*/
tx_work_done = grcan_transmit_catch_up(dev, tx_budget);
if (rx_work_done < rx_budget && tx_work_done < tx_budget) { if (work_done < budget) {
napi_complete(napi); napi_complete(napi);
/* Guarantee no interference with a running reset that otherwise /* Guarantee no interference with a running reset that otherwise
...@@ -1259,7 +1251,7 @@ static int grcan_poll(struct napi_struct *napi, int budget) ...@@ -1259,7 +1251,7 @@ static int grcan_poll(struct napi_struct *napi, int budget)
spin_unlock_irqrestore(&priv->lock, flags); 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, /* Work tx bug by waiting while for the risky situation to clear. If that fails,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment