aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJose Abreu <jose.abreu@synopsys.com>2019-01-09 04:06:00 -0500
committerDavid S. Miller <davem@davemloft.net>2019-01-11 18:35:06 -0500
commitfa0be0a43f101888ac677dba31b590963eafeaa1 (patch)
treeb075afe3743760f4b27da8f4a3b3dce9938def07
parent3b5094665e273c4a2a99f7f5f16977c0f1e19095 (diff)
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>
-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)
3525 struct stmmac_channel *ch = 3525 struct stmmac_channel *ch =
3526 container_of(napi, struct stmmac_channel, napi); 3526 container_of(napi, struct stmmac_channel, napi);
3527 struct stmmac_priv *priv = ch->priv_data; 3527 struct stmmac_priv *priv = ch->priv_data;
3528 int work_done = 0, work_rem = budget; 3528 int work_done, rx_done = 0, tx_done = 0;
3529 u32 chan = ch->index; 3529 u32 chan = ch->index;
3530 3530
3531 priv->xstats.napi_poll++; 3531 priv->xstats.napi_poll++;
3532 3532
3533 if (ch->has_tx) { 3533 if (ch->has_tx)
3534 int done = stmmac_tx_clean(priv, work_rem, chan); 3534 tx_done = stmmac_tx_clean(priv, budget, chan);
3535 if (ch->has_rx)
3536 rx_done = stmmac_rx(priv, budget, chan);
3535 3537
3536 work_done += done; 3538 work_done = max(rx_done, tx_done);
3537 work_rem -= done; 3539 work_done = min(work_done, budget);
3538 }
3539
3540 if (ch->has_rx) {
3541 int done = stmmac_rx(priv, work_rem, chan);
3542 3540
3543 work_done += done; 3541 if (work_done < budget && napi_complete_done(napi, work_done)) {
3544 work_rem -= done; 3542 int stat;
3545 }
3546 3543
3547 if (work_done < budget && napi_complete_done(napi, work_done))
3548 stmmac_enable_dma_irq(priv, priv->ioaddr, chan); 3544 stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
3545 stat = stmmac_dma_interrupt_status(priv, priv->ioaddr,
3546 &priv->xstats, chan);
3547 if (stat && napi_reschedule(napi))
3548 stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
3549 }
3549 3550
3550 return work_done; 3551 return work_done;
3551} 3552}