Commit 9a00b697 authored by Masahisa KOJIMA's avatar Masahisa KOJIMA Committed by David S. Miller

net: socionext: reset hardware in ndo_stop

When the interface is down, head/tail of the descriptor
ring address is set to 0 in netsec_netdev_stop().
But netsec hardware still keeps the previous descriptor
ring address, so there is inconsistency between driver
and hardware after interface is up at a later time.
To address this inconsistency, add netsec_reset_hardware()
when the interface is down.

In addition, to minimize the reset process,
add flag to decide whether driver loads the netsec microcode.
Even if driver resets the netsec hardware, netsec microcode
keeps resident on RAM, so it is ok we only load the microcode
at initialization.

This patch is critical for installation over network.
Signed-off-by: default avatarMasahisa KOJIMA <masahisa.kojima@linaro.org>
Fixes: 533dd11a ("net: socionext: Add Synquacer NetSec driver")
Signed-off-by: default avatarJassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c009f413
...@@ -1057,7 +1057,8 @@ static int netsec_netdev_load_microcode(struct netsec_priv *priv) ...@@ -1057,7 +1057,8 @@ static int netsec_netdev_load_microcode(struct netsec_priv *priv)
return 0; return 0;
} }
static int netsec_reset_hardware(struct netsec_priv *priv) static int netsec_reset_hardware(struct netsec_priv *priv,
bool load_ucode)
{ {
u32 value; u32 value;
int err; int err;
...@@ -1102,12 +1103,15 @@ static int netsec_reset_hardware(struct netsec_priv *priv) ...@@ -1102,12 +1103,15 @@ static int netsec_reset_hardware(struct netsec_priv *priv)
netsec_write(priv, NETSEC_REG_NRM_RX_CONFIG, netsec_write(priv, NETSEC_REG_NRM_RX_CONFIG,
1 << NETSEC_REG_DESC_ENDIAN); 1 << NETSEC_REG_DESC_ENDIAN);
if (load_ucode) {
err = netsec_netdev_load_microcode(priv); err = netsec_netdev_load_microcode(priv);
if (err) { if (err) {
netif_err(priv, probe, priv->ndev, netif_err(priv, probe, priv->ndev,
"%s: failed to load microcode (%d)\n", __func__, err); "%s: failed to load microcode (%d)\n",
__func__, err);
return err; return err;
} }
}
/* start DMA engines */ /* start DMA engines */
netsec_write(priv, NETSEC_REG_DMA_TMR_CTRL, priv->freq / 1000000 - 1); netsec_write(priv, NETSEC_REG_DMA_TMR_CTRL, priv->freq / 1000000 - 1);
...@@ -1328,6 +1332,7 @@ static int netsec_netdev_open(struct net_device *ndev) ...@@ -1328,6 +1332,7 @@ static int netsec_netdev_open(struct net_device *ndev)
static int netsec_netdev_stop(struct net_device *ndev) static int netsec_netdev_stop(struct net_device *ndev)
{ {
int ret;
struct netsec_priv *priv = netdev_priv(ndev); struct netsec_priv *priv = netdev_priv(ndev);
netif_stop_queue(priv->ndev); netif_stop_queue(priv->ndev);
...@@ -1343,12 +1348,14 @@ static int netsec_netdev_stop(struct net_device *ndev) ...@@ -1343,12 +1348,14 @@ static int netsec_netdev_stop(struct net_device *ndev)
netsec_uninit_pkt_dring(priv, NETSEC_RING_TX); netsec_uninit_pkt_dring(priv, NETSEC_RING_TX);
netsec_uninit_pkt_dring(priv, NETSEC_RING_RX); netsec_uninit_pkt_dring(priv, NETSEC_RING_RX);
ret = netsec_reset_hardware(priv, false);
phy_stop(ndev->phydev); phy_stop(ndev->phydev);
phy_disconnect(ndev->phydev); phy_disconnect(ndev->phydev);
pm_runtime_put_sync(priv->dev); pm_runtime_put_sync(priv->dev);
return 0; return ret;
} }
static int netsec_netdev_init(struct net_device *ndev) static int netsec_netdev_init(struct net_device *ndev)
...@@ -1364,7 +1371,7 @@ static int netsec_netdev_init(struct net_device *ndev) ...@@ -1364,7 +1371,7 @@ static int netsec_netdev_init(struct net_device *ndev)
if (ret) if (ret)
goto err1; goto err1;
ret = netsec_reset_hardware(priv); ret = netsec_reset_hardware(priv, true);
if (ret) if (ret)
goto err2; goto err2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment