[PATCH 1/1] net: sni_netsec: Add workaround for timeout error

Masahisa Kojima masahisa.kojima at linaro.org
Mon Aug 7 01:19:43 CEST 2023


On Thu, 3 Aug 2023 at 23:56, Ryosuke Saito <ryosuke.saito at linaro.org> wrote:
>
> The NETSEC GMAC occasionally falls into a weird state where
> MAC_REG_DESC_SOFT_RST has never been cleared and shows errors like the
> below when networking commands are issued:
>
>     => ping 192.168.1.1
>     ethernet at 522d0000 Waiting for PHY auto negotiation to complete... done
>     netsec_wait_while_busy: timeout
>     Using ethernet at 522d0000 device
>
>     ARP Retry count exceeded; starting again
>     ping failed; host 192.168.1.1 is not alive
>
> It happens on not only 'ping' but also 'dhcp', 'tftp' and so on.
>
> Luckily, restarting the NETSEC GMAC and trying again seems to fix the
> problematic state. So first ensure that we haven't entered the state by
> checking MAC_REG_DESC_SOFT_RST to be cleared; otherwise, restarting
> NETSEC/PHY and trying again would work as a workaround.
>
> Signed-off-by: Ryosuke Saito <ryosuke.saito at linaro.org>
> ---
>  drivers/net/sni_netsec.c | 50 ++++++++++++++++++++++++++++++++--------
>  1 file changed, 41 insertions(+), 9 deletions(-)

Tested-By: Masahisa Kojima <masahisa.kojima at linaro.org>

Overnight testing of 'dhcp->ping->reset' sequence works for me.
Thank you for fixing the issue.

Regards,
Masahisa Kojima


>
> diff --git a/drivers/net/sni_netsec.c b/drivers/net/sni_netsec.c
> index 9780f2092bd4..71afe78fd28a 100644
> --- a/drivers/net/sni_netsec.c
> +++ b/drivers/net/sni_netsec.c
> @@ -286,6 +286,8 @@ struct netsec_rx_pkt_info {
>         bool err_flag;
>  };
>
> +static int netsec_reset_hardware(struct netsec_priv *priv, bool load_ucode);
> +
>  static void netsec_write_reg(struct netsec_priv *priv, u32 reg_addr, u32 val)
>  {
>         writel(val, priv->ioaddr + reg_addr);
> @@ -532,18 +534,11 @@ static int netsec_mac_update_to_phy_state(struct netsec_priv *priv)
>         return 0;
>  }
>
> -static int netsec_start_gmac(struct netsec_priv *priv)
> +static int netsec_reset_gmac(struct netsec_priv *priv)
>  {
>         u32 value = 0;
>         int ret;
>
> -       if (priv->max_speed != SPEED_1000)
> -               value = (NETSEC_GMAC_MCR_REG_CST |
> -                        NETSEC_GMAC_MCR_REG_HALF_DUPLEX_COMMON);
> -
> -       if (netsec_set_mac_reg(priv, GMAC_REG_MCR, value))
> -               return -ETIMEDOUT;
> -
>         if (netsec_set_mac_reg(priv, GMAC_REG_BMR,
>                                NETSEC_GMAC_BMR_REG_RESET))
>                 return -ETIMEDOUT;
> @@ -558,10 +553,47 @@ static int netsec_start_gmac(struct netsec_priv *priv)
>         if (value & NETSEC_GMAC_BMR_REG_SWR)
>                 return -EAGAIN;
>
> +       /**
> +        * NETSEC GMAC sometimes shows the peculiar behaviour where
> +        * MAC_REG_DESC_SOFT_RST never been cleared, resulting in the loss of
> +        * sending packets.
> +        *
> +        * Workaround:
> +        *   Restart NETSEC and PHY, retry again.
> +        */
>         netsec_write_reg(priv, MAC_REG_DESC_SOFT_RST, 1);
> -       if (netsec_wait_while_busy(priv, MAC_REG_DESC_SOFT_RST, 1))
> +       udelay(1000);
> +       if (netsec_read_reg(priv, MAC_REG_DESC_SOFT_RST)) {
> +               phy_shutdown(priv->phydev);
> +               netsec_reset_hardware(priv, false);
> +               phy_startup(priv->phydev);
> +               return -EAGAIN;
> +       }
> +       return 0;
> +}
> +
> +static int netsec_start_gmac(struct netsec_priv *priv)
> +{
> +       u32 value = 0;
> +       u32 failure = 0;
> +       int ret;
> +
> +       if (priv->max_speed != SPEED_1000)
> +               value = (NETSEC_GMAC_MCR_REG_CST |
> +                        NETSEC_GMAC_MCR_REG_HALF_DUPLEX_COMMON);
> +
> +       if (netsec_set_mac_reg(priv, GMAC_REG_MCR, value))
>                 return -ETIMEDOUT;
>
> +       /* Reset GMAC */
> +       while ((ret = netsec_reset_gmac(priv)) == -EAGAIN && ++failure < 3)
> +               ;
> +
> +       if (ret) {
> +               pr_err("%s: failed to reset gmac(err=%d).\n", __func__, ret);
> +               return ret;
> +       }
> +
>         netsec_write_reg(priv, MAC_REG_DESC_INIT, 1);
>         if (netsec_wait_while_busy(priv, MAC_REG_DESC_INIT, 1))
>                 return -ETIMEDOUT;
> --
> 2.41.0
>


More information about the U-Boot mailing list