Skip to content

Commit

Permalink
net: stmmac: Prevent RX starvation in stmmac_napi_poll()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jose Abreu authored and David S. Miller committed Jan 11, 2019
1 parent 3b50946 commit fa0be0a
Showing 1 changed file with 14 additions and 13 deletions.
27 changes: 14 additions & 13 deletions drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit fa0be0a

Please sign in to comment.