| From 77f27453b5d446cbb84482d6d703a6c5f2c59273 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 21 Apr 2021 13:52:46 +0900 |
| Subject: net: renesas: ravb: Fix a stuck issue when a lot of frames are |
| received |
| |
| From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> |
| |
| [ Upstream commit 5718458b092bf6bf4482c5df32affba3c3259517 ] |
| |
| When a lot of frames were received in the short term, the driver |
| caused a stuck of receiving until a new frame was received. For example, |
| the following command from other device could cause this issue. |
| |
| $ sudo ping -f -l 1000 -c 1000 <this driver's ipaddress> |
| |
| The previous code always cleared the interrupt flag of RX but checks |
| the interrupt flags in ravb_poll(). So, ravb_poll() could not call |
| ravb_rx() in the next time until a new RX frame was received if |
| ravb_rx() returned true. To fix the issue, always calls ravb_rx() |
| regardless the interrupt flags condition. |
| |
| Fixes: c156633f1353 ("Renesas Ethernet AVB driver proper") |
| Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/ethernet/renesas/ravb_main.c | 35 ++++++++---------------- |
| 1 file changed, 12 insertions(+), 23 deletions(-) |
| |
| diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c |
| index bd30505fbc57..f96eed67e1a2 100644 |
| --- a/drivers/net/ethernet/renesas/ravb_main.c |
| +++ b/drivers/net/ethernet/renesas/ravb_main.c |
| @@ -911,31 +911,20 @@ static int ravb_poll(struct napi_struct *napi, int budget) |
| int q = napi - priv->napi; |
| int mask = BIT(q); |
| int quota = budget; |
| - u32 ris0, tis; |
| |
| - for (;;) { |
| - tis = ravb_read(ndev, TIS); |
| - ris0 = ravb_read(ndev, RIS0); |
| - if (!((ris0 & mask) || (tis & mask))) |
| - break; |
| + /* Processing RX Descriptor Ring */ |
| + /* Clear RX interrupt */ |
| + ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0); |
| + if (ravb_rx(ndev, "a, q)) |
| + goto out; |
| |
| - /* Processing RX Descriptor Ring */ |
| - if (ris0 & mask) { |
| - /* Clear RX interrupt */ |
| - ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0); |
| - if (ravb_rx(ndev, "a, q)) |
| - goto out; |
| - } |
| - /* Processing TX Descriptor Ring */ |
| - if (tis & mask) { |
| - spin_lock_irqsave(&priv->lock, flags); |
| - /* Clear TX interrupt */ |
| - ravb_write(ndev, ~(mask | TIS_RESERVED), TIS); |
| - ravb_tx_free(ndev, q, true); |
| - netif_wake_subqueue(ndev, q); |
| - spin_unlock_irqrestore(&priv->lock, flags); |
| - } |
| - } |
| + /* Processing RX Descriptor Ring */ |
| + spin_lock_irqsave(&priv->lock, flags); |
| + /* Clear TX interrupt */ |
| + ravb_write(ndev, ~(mask | TIS_RESERVED), TIS); |
| + ravb_tx_free(ndev, q, true); |
| + netif_wake_subqueue(ndev, q); |
| + spin_unlock_irqrestore(&priv->lock, flags); |
| |
| napi_complete(napi); |
| |
| -- |
| 2.30.2 |
| |