aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
diff options
context:
space:
mode:
authorJose Abreu <jose.abreu@synopsys.com>2019-01-09 10:06:00 +0100
committerDavid S. Miller <davem@davemloft.net>2019-01-11 15:35:06 -0800
commitfa0be0a43f101888ac677dba31b590963eafeaa1 (patch)
treeb075afe3743760f4b27da8f4a3b3dce9938def07 /drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
parentnet: stmmac: Fix the logic of checking if RX Watchdog must be enabled (diff)
downloadlinux-dev-fa0be0a43f101888ac677dba31b590963eafeaa1.tar.xz
linux-dev-fa0be0a43f101888ac677dba31b590963eafeaa1.zip
net: stmmac: Prevent RX starvation in stmmac_napi_poll()
Currently, TX is given a budget which is consumed by stmmac_tx_clean() and stmmac_rx() is given the remaining non-consumed budget. This is wrong and in case we are sending a large number of packets this can starve RX because remaining budget will be low. Let's give always the same budget for RX and TX clean. While at it, check if we missed any interrupts while we were in NAPI callback by looking at DMA interrupt status. Cc: Joao Pinto <jpinto@synopsys.com> Cc: David S. Miller <davem@davemloft.net> Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com> Cc: Alexandre Torgue <alexandre.torgue@st.com> Signed-off-by: Jose Abreu <joabreu@synopsys.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to '')
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 83ceb1a12e77..3f23e14891df 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3525,27 +3525,28 @@ static int stmmac_napi_poll(struct napi_struct *napi, int budget)
struct stmmac_channel *ch =
container_of(napi, struct stmmac_channel, napi);
struct stmmac_priv *priv = ch->priv_data;
- int work_done = 0, work_rem = budget;
+ int work_done, rx_done = 0, tx_done = 0;
u32 chan = ch->index;
priv->xstats.napi_poll++;
- if (ch->has_tx) {
- int done = stmmac_tx_clean(priv, work_rem, chan);
+ if (ch->has_tx)
+ tx_done = stmmac_tx_clean(priv, budget, chan);
+ if (ch->has_rx)
+ rx_done = stmmac_rx(priv, budget, chan);
- work_done += done;
- work_rem -= done;
- }
-
- if (ch->has_rx) {
- int done = stmmac_rx(priv, work_rem, chan);
+ work_done = max(rx_done, tx_done);
+ work_done = min(work_done, budget);
- work_done += done;
- work_rem -= done;
- }
+ if (work_done < budget && napi_complete_done(napi, work_done)) {
+ int stat;
- if (work_done < budget && napi_complete_done(napi, work_done))
stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
+ stat = stmmac_dma_interrupt_status(priv, priv->ioaddr,
+ &priv->xstats, chan);
+ if (stat && napi_reschedule(napi))
+ stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
+ }
return work_done;
}