diff mbox series

[OpenWrt-Devel] ramips: ethernet: fix to interrupt handling

Message ID 20190306040846.21746-1-rosenp@gmail.com
State Superseded
Headers show
Series [OpenWrt-Devel] ramips: ethernet: fix to interrupt handling | expand

Commit Message

Rosen Penev March 6, 2019, 4:08 a.m. UTC
From: NeilBrown <neil@brown.name>

The current code acknowledged interrupts *after* polling.
This is the wrong way around, and could cause an interrupt to
be missed.
This is not likely to be fatal as another packet, and so another
interrupt, should come along soon.  But maybe it is causing
problems, so let's fix it anyway.

Signed-off-by: NeilBrown <neil@brown.name>
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 .../drivers/net/ethernet/mediatek/mtk_eth_soc.c       | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

Comments

Mingyu Li March 6, 2019, 8:37 a.m. UTC | #1
the original code use status register to keep there still have some
pkts in buffer.
need next napi call to receive it.

if 128 packets in buffer. you clear status first. because napi max
handle 64 packets in buffer.
so 64 packets need to handle in next napi poll. if no new packet
comming. the status register will not set.
so fe_poll function will not call fe_poll_tx or fe_poll_rx. that would
be a problem.

the status register also use to control napi interrupt enable. must
make sure no packets need to
handle then enable interrupt.

Rosen Penev <rosenp@gmail.com> 於 2019年3月6日 週三 下午12:08寫道:
>
> From: NeilBrown <neil@brown.name>
>
> The current code acknowledged interrupts *after* polling.
> This is the wrong way around, and could cause an interrupt to
> be missed.
> This is not likely to be fatal as another packet, and so another
> interrupt, should come along soon.  But maybe it is causing
> problems, so let's fix it anyway.
>
> Signed-off-by: NeilBrown <neil@brown.name>
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
> ---
>  .../drivers/net/ethernet/mediatek/mtk_eth_soc.c       | 11 +++++------
>  1 file changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> index e0bc0ab818..2e0c8f94ca 100644
> --- a/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> @@ -876,6 +876,8 @@ static int fe_poll_rx(struct napi_struct *napi, int budget,
>         struct fe_rx_dma *rxd, trxd;
>         int done = 0, pad;
>
> +       fe_reg_w32(rx_intr, FE_REG_FE_INT_STATUS);
> +
>         if (netdev->features & NETIF_F_RXCSUM)
>                 checksum_bit = soc->checksum_bit;
>         else
> @@ -963,9 +965,6 @@ release_desc:
>                 done++;
>         }
>
> -       if (done < budget)
> -               fe_reg_w32(rx_intr, FE_REG_FE_INT_STATUS);
> -
>         return done;
>  }
>
> @@ -981,6 +980,8 @@ static int fe_poll_tx(struct fe_priv *priv, int budget, u32 tx_intr,
>         u32 idx, hwidx;
>         struct fe_tx_ring *ring = &priv->tx_ring;
>
> +       fe_reg_w32(tx_intr, FE_REG_FE_INT_STATUS);
> +
>         idx = ring->tx_free_idx;
>         hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0);
>
> @@ -1004,9 +1005,7 @@ static int fe_poll_tx(struct fe_priv *priv, int budget, u32 tx_intr,
>         if (idx == hwidx) {
>                 /* read hw index again make sure no new tx packet */
>                 hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0);
> -               if (idx == hwidx)
> -                       fe_reg_w32(tx_intr, FE_REG_FE_INT_STATUS);
> -               else
> +               if (idx != hwidx)
>                         *tx_again = 1;
>         } else {
>                 *tx_again = 1;
> --
> 2.17.1
>
>
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel@lists.openwrt.org
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel
Rosen Penev Oct. 29, 2019, 4:50 p.m. UTC | #2
On Wed, Mar 6, 2019 at 12:37 AM Mingyu Li <igvtee@gmail.com> wrote:
>
> the original code use status register to keep there still have some
> pkts in buffer.
> need next napi call to receive it.
>
> if 128 packets in buffer. you clear status first. because napi max
> handle 64 packets in buffer.
> so 64 packets need to handle in next napi poll. if no new packet
> comming. the status register will not set.
> so fe_poll function will not call fe_poll_tx or fe_poll_rx. that would
> be a problem.
>
> the status register also use to control napi interrupt enable. must
> make sure no packets need to
> handle then enable interrupt.
I took a look at this again. The upstream kernel driver does the same
as this patch: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/net/ethernet/mediatek/mtk_eth_soc.c?h=v4.14.151#n1189
>
> Rosen Penev <rosenp@gmail.com> 於 2019年3月6日 週三 下午12:08寫道:
> >
> > From: NeilBrown <neil@brown.name>
> >
> > The current code acknowledged interrupts *after* polling.
> > This is the wrong way around, and could cause an interrupt to
> > be missed.
> > This is not likely to be fatal as another packet, and so another
> > interrupt, should come along soon.  But maybe it is causing
> > problems, so let's fix it anyway.
> >
> > Signed-off-by: NeilBrown <neil@brown.name>
> > Signed-off-by: Rosen Penev <rosenp@gmail.com>
> > ---
> >  .../drivers/net/ethernet/mediatek/mtk_eth_soc.c       | 11 +++++------
> >  1 file changed, 5 insertions(+), 6 deletions(-)
> >
> > diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > index e0bc0ab818..2e0c8f94ca 100644
> > --- a/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > @@ -876,6 +876,8 @@ static int fe_poll_rx(struct napi_struct *napi, int budget,
> >         struct fe_rx_dma *rxd, trxd;
> >         int done = 0, pad;
> >
> > +       fe_reg_w32(rx_intr, FE_REG_FE_INT_STATUS);
> > +
> >         if (netdev->features & NETIF_F_RXCSUM)
> >                 checksum_bit = soc->checksum_bit;
> >         else
> > @@ -963,9 +965,6 @@ release_desc:
> >                 done++;
> >         }
> >
> > -       if (done < budget)
> > -               fe_reg_w32(rx_intr, FE_REG_FE_INT_STATUS);
> > -
> >         return done;
> >  }
> >
> > @@ -981,6 +980,8 @@ static int fe_poll_tx(struct fe_priv *priv, int budget, u32 tx_intr,
> >         u32 idx, hwidx;
> >         struct fe_tx_ring *ring = &priv->tx_ring;
> >
> > +       fe_reg_w32(tx_intr, FE_REG_FE_INT_STATUS);
> > +
> >         idx = ring->tx_free_idx;
> >         hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0);
> >
> > @@ -1004,9 +1005,7 @@ static int fe_poll_tx(struct fe_priv *priv, int budget, u32 tx_intr,
> >         if (idx == hwidx) {
> >                 /* read hw index again make sure no new tx packet */
> >                 hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0);
> > -               if (idx == hwidx)
> > -                       fe_reg_w32(tx_intr, FE_REG_FE_INT_STATUS);
> > -               else
> > +               if (idx != hwidx)
> >                         *tx_again = 1;
> >         } else {
> >                 *tx_again = 1;
> > --
> > 2.17.1
> >
> >
> > _______________________________________________
> > openwrt-devel mailing list
> > openwrt-devel@lists.openwrt.org
> > https://lists.openwrt.org/mailman/listinfo/openwrt-devel
Mingyu Li Oct. 31, 2019, 3:23 p.m. UTC | #3
the upstream kernel. the function mtk_napi_rx always be called if it have
packet to receive. it doesn't check status register.
but on openwrt code. check the status register first. then call fe_poll_rx.
if you clear status register. fe_poll_rx will will not be called next time.

Rosen Penev <rosenp@gmail.com> 於 2019年10月30日 週三 上午12:51寫道:
>
> On Wed, Mar 6, 2019 at 12:37 AM Mingyu Li <igvtee@gmail.com> wrote:
> >
> > the original code use status register to keep there still have some
> > pkts in buffer.
> > need next napi call to receive it.
> >
> > if 128 packets in buffer. you clear status first. because napi max
> > handle 64 packets in buffer.
> > so 64 packets need to handle in next napi poll. if no new packet
> > comming. the status register will not set.
> > so fe_poll function will not call fe_poll_tx or fe_poll_rx. that would
> > be a problem.
> >
> > the status register also use to control napi interrupt enable. must
> > make sure no packets need to
> > handle then enable interrupt.
> I took a look at this again. The upstream kernel driver does the same
> as this patch: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/net/ethernet/mediatek/mtk_eth_soc.c?h=v4.14.151#n1189
> >
> > Rosen Penev <rosenp@gmail.com> 於 2019年3月6日 週三 下午12:08寫道:
> > >
> > > From: NeilBrown <neil@brown.name>
> > >
> > > The current code acknowledged interrupts *after* polling.
> > > This is the wrong way around, and could cause an interrupt to
> > > be missed.
> > > This is not likely to be fatal as another packet, and so another
> > > interrupt, should come along soon.  But maybe it is causing
> > > problems, so let's fix it anyway.
> > >
> > > Signed-off-by: NeilBrown <neil@brown.name>
> > > Signed-off-by: Rosen Penev <rosenp@gmail.com>
> > > ---
> > >  .../drivers/net/ethernet/mediatek/mtk_eth_soc.c       | 11 +++++------
> > >  1 file changed, 5 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > > index e0bc0ab818..2e0c8f94ca 100644
> > > --- a/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > > +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
> > > @@ -876,6 +876,8 @@ static int fe_poll_rx(struct napi_struct *napi, int budget,
> > >         struct fe_rx_dma *rxd, trxd;
> > >         int done = 0, pad;
> > >
> > > +       fe_reg_w32(rx_intr, FE_REG_FE_INT_STATUS);
> > > +
> > >         if (netdev->features & NETIF_F_RXCSUM)
> > >                 checksum_bit = soc->checksum_bit;
> > >         else
> > > @@ -963,9 +965,6 @@ release_desc:
> > >                 done++;
> > >         }
> > >
> > > -       if (done < budget)
> > > -               fe_reg_w32(rx_intr, FE_REG_FE_INT_STATUS);
> > > -
> > >         return done;
> > >  }
> > >
> > > @@ -981,6 +980,8 @@ static int fe_poll_tx(struct fe_priv *priv, int budget, u32 tx_intr,
> > >         u32 idx, hwidx;
> > >         struct fe_tx_ring *ring = &priv->tx_ring;
> > >
> > > +       fe_reg_w32(tx_intr, FE_REG_FE_INT_STATUS);
> > > +
> > >         idx = ring->tx_free_idx;
> > >         hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0);
> > >
> > > @@ -1004,9 +1005,7 @@ static int fe_poll_tx(struct fe_priv *priv, int budget, u32 tx_intr,
> > >         if (idx == hwidx) {
> > >                 /* read hw index again make sure no new tx packet */
> > >                 hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0);
> > > -               if (idx == hwidx)
> > > -                       fe_reg_w32(tx_intr, FE_REG_FE_INT_STATUS);
> > > -               else
> > > +               if (idx != hwidx)
> > >                         *tx_again = 1;
> > >         } else {
> > >                 *tx_again = 1;
> > > --
> > > 2.17.1
> > >
> > >
> > > _______________________________________________
> > > openwrt-devel mailing list
> > > openwrt-devel@lists.openwrt.org
> > > https://lists.openwrt.org/mailman/listinfo/openwrt-devel
diff mbox series

Patch

diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index e0bc0ab818..2e0c8f94ca 100644
--- a/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -876,6 +876,8 @@  static int fe_poll_rx(struct napi_struct *napi, int budget,
 	struct fe_rx_dma *rxd, trxd;
 	int done = 0, pad;
 
+	fe_reg_w32(rx_intr, FE_REG_FE_INT_STATUS);
+
 	if (netdev->features & NETIF_F_RXCSUM)
 		checksum_bit = soc->checksum_bit;
 	else
@@ -963,9 +965,6 @@  release_desc:
 		done++;
 	}
 
-	if (done < budget)
-		fe_reg_w32(rx_intr, FE_REG_FE_INT_STATUS);
-
 	return done;
 }
 
@@ -981,6 +980,8 @@  static int fe_poll_tx(struct fe_priv *priv, int budget, u32 tx_intr,
 	u32 idx, hwidx;
 	struct fe_tx_ring *ring = &priv->tx_ring;
 
+	fe_reg_w32(tx_intr, FE_REG_FE_INT_STATUS);
+
 	idx = ring->tx_free_idx;
 	hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0);
 
@@ -1004,9 +1005,7 @@  static int fe_poll_tx(struct fe_priv *priv, int budget, u32 tx_intr,
 	if (idx == hwidx) {
 		/* read hw index again make sure no new tx packet */
 		hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0);
-		if (idx == hwidx)
-			fe_reg_w32(tx_intr, FE_REG_FE_INT_STATUS);
-		else
+		if (idx != hwidx)
 			*tx_again = 1;
 	} else {
 		*tx_again = 1;