diff mbox series

[net-next,v2,06/10] net: stmmac: Do not disable interrupts when cleaning TX

Message ID e4e9ee4cb9c3e7957fe0a09f88b20bc011e2bd4c.1561706801.git.joabreu@synopsys.com
State Accepted
Delegated to: David Miller
Headers show
Series net: stmmac: 10GbE using XGMAC | expand

Commit Message

Jose Abreu June 28, 2019, 7:29 a.m. UTC
This is a performance killer and anyways the interrupts are being
disabled by RX NAPI so no need to disable them again.

Signed-off-by: Jose Abreu <joabreu@synopsys.com>
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>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

Comments

Willem de Bruijn June 28, 2019, 7:08 p.m. UTC | #1
On Fri, Jun 28, 2019 at 3:30 AM Jose Abreu <Jose.Abreu@synopsys.com> wrote:
>
> This is a performance killer and anyways the interrupts are being
> disabled by RX NAPI so no need to disable them again.

By the

        if ((status & handle_rx) && (chan < priv->plat->rx_queues_to_use)) {
                stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
                napi_schedule_irqoff(&ch->rx_napi);
        }

branch directly above? If so, is it possible to have fewer rx than tx
queues and miss this?

this logic seems more complex than needed?

        if (status)
                status |= handle_rx | handle_tx;

        if ((status & handle_rx) && (chan < priv->plat->rx_queues_to_use)) {

        }

        if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use)) {

        }

status & handle_rx implies status & handle_tx and vice versa.


>
> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
> 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>
> ---
>  drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 8 +++-----
>  1 file changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 4a5941caaadc..e8f3e76889c8 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -2061,10 +2061,8 @@ static int stmmac_napi_check(struct stmmac_priv *priv, u32 chan)
>                 napi_schedule_irqoff(&ch->rx_napi);
>         }
>
> -       if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use)) {
> -               stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
> +       if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use))
>                 napi_schedule_irqoff(&ch->tx_napi);
> -       }
>
>         return status;
>  }
> @@ -3570,8 +3568,8 @@ static int stmmac_napi_poll_tx(struct napi_struct *napi, int budget)
>         work_done = stmmac_tx_clean(priv, DMA_TX_SIZE, chan);
>         work_done = min(work_done, budget);
>
> -       if (work_done < budget && napi_complete_done(napi, work_done))
> -               stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
> +       if (work_done < budget)
> +               napi_complete_done(napi, work_done);

It does seem odd that stmmac_napi_poll_rx and stmmac_napi_poll_tx both
call stmmac_enable_dma_irq(..) independent of the other. Shouldn't the
IRQ remain masked while either is active or scheduled? That is almost
what this patch does, though not exactly.
Jose Abreu July 1, 2019, 10:15 a.m. UTC | #2
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>

> By the
> 
>         if ((status & handle_rx) && (chan < priv->plat->rx_queues_to_use)) {
>                 stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
>                 napi_schedule_irqoff(&ch->rx_napi);
>         }
> 
> branch directly above? If so, is it possible to have fewer rx than tx
> queues and miss this?

Yes, it is possible.

> this logic seems more complex than needed?
> 
>         if (status)
>                 status |= handle_rx | handle_tx;
> 
>         if ((status & handle_rx) && (chan < priv->plat->rx_queues_to_use)) {
> 
>         }
> 
>         if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use)) {
> 
>         }
> 
> status & handle_rx implies status & handle_tx and vice versa.

This is removed in patch 09/10.

> > -       if (work_done < budget && napi_complete_done(napi, work_done))
> > -               stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
> > +       if (work_done < budget)
> > +               napi_complete_done(napi, work_done);
> 
> It does seem odd that stmmac_napi_poll_rx and stmmac_napi_poll_tx both
> call stmmac_enable_dma_irq(..) independent of the other. Shouldn't the
> IRQ remain masked while either is active or scheduled? That is almost
> what this patch does, though not exactly.

After patch 09/10 the interrupts will only be disabled by RX NAPI and 
re-enabled by it again. I can do some tests on whether disabling 
interrupts independently gives more performance but I wouldn't expect so 
because the real bottleneck when I do iperf3 tests is the RX path ...
Willem de Bruijn July 1, 2019, 12:23 p.m. UTC | #3
On Mon, Jul 1, 2019 at 6:15 AM Jose Abreu <Jose.Abreu@synopsys.com> wrote:
>
> From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
>
> > By the
> >
> >         if ((status & handle_rx) && (chan < priv->plat->rx_queues_to_use)) {
> >                 stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
> >                 napi_schedule_irqoff(&ch->rx_napi);
> >         }
> >
> > branch directly above? If so, is it possible to have fewer rx than tx
> > queues and miss this?
>
> Yes, it is possible.

And that is not a problem?

>
> > this logic seems more complex than needed?
> >
> >         if (status)
> >                 status |= handle_rx | handle_tx;
> >
> >         if ((status & handle_rx) && (chan < priv->plat->rx_queues_to_use)) {
> >
> >         }
> >
> >         if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use)) {
> >
> >         }
> >
> > status & handle_rx implies status & handle_tx and vice versa.
>
> This is removed in patch 09/10.
>
> > > -       if (work_done < budget && napi_complete_done(napi, work_done))
> > > -               stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
> > > +       if (work_done < budget)
> > > +               napi_complete_done(napi, work_done);
> >
> > It does seem odd that stmmac_napi_poll_rx and stmmac_napi_poll_tx both
> > call stmmac_enable_dma_irq(..) independent of the other. Shouldn't the
> > IRQ remain masked while either is active or scheduled? That is almost
> > what this patch does, though not exactly.
>
> After patch 09/10 the interrupts will only be disabled by RX NAPI and
> re-enabled by it again. I can do some tests on whether disabling
> interrupts independently gives more performance but I wouldn't expect so
> because the real bottleneck when I do iperf3 tests is the RX path ...

Sharing the IRQ sounds fine. My only concern was TX-only IRQs in case
more TX than RX queues are configured. If that is possible with this
driver.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 4a5941caaadc..e8f3e76889c8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2061,10 +2061,8 @@  static int stmmac_napi_check(struct stmmac_priv *priv, u32 chan)
 		napi_schedule_irqoff(&ch->rx_napi);
 	}
 
-	if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use)) {
-		stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
+	if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use))
 		napi_schedule_irqoff(&ch->tx_napi);
-	}
 
 	return status;
 }
@@ -3570,8 +3568,8 @@  static int stmmac_napi_poll_tx(struct napi_struct *napi, int budget)
 	work_done = stmmac_tx_clean(priv, DMA_TX_SIZE, chan);
 	work_done = min(work_done, budget);
 
-	if (work_done < budget && napi_complete_done(napi, work_done))
-		stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
+	if (work_done < budget)
+		napi_complete_done(napi, work_done);
 
 	/* Force transmission restart */
 	tx_q = &priv->tx_queue[chan];