From 46b1744143e29af4925d612f14e214882c1e0049 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Wed, 25 Nov 2015 14:52:06 +1100 Subject: [PATCH] net/faraday: Use ncsi_stop_dev() We're using ncsi_suspend_dev() to tear down NCSI device when bringing down the network interface. In ncsi_suspend_dev(), NCSI packets might be sent over NCSI link to stop the interface physically. However, the NCSI packets might not be sent successfully when the NCSI interface is down. In that case, we potentially release the buffers and their ring for twice exceptionally, which eventually leads to kernel crash. To resolve the above problem, this calls ncsi_stop_dev() to tear down the NCSI interface without sending NCSI packets over the link. At the same time, a flag (priv->enabled) introduced to avoid releasing the buffers and their rings for twice. Signed-off-by: Gavin Shan Signed-off-by: Joel Stanley --- drivers/net/ethernet/faraday/ftgmac100.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index e42f4d95833886..2fcb7f9713cc61 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -78,6 +78,7 @@ struct ftgmac100 { int old_speed; bool use_ncsi; + bool enabled; }; static int ftgmac100_alloc_rx_page(struct ftgmac100 *priv, @@ -1174,6 +1175,8 @@ static int ftgmac100_open(struct net_device *netdev) if (err) goto err_ncsi; } + + priv->enabled = true; return 0; err_ncsi: @@ -1192,7 +1195,11 @@ static int ftgmac100_stop_dev(struct net_device *netdev) { struct ftgmac100 *priv = netdev_priv(netdev); + if (!priv->enabled) + return 0; + /* disable all interrupts */ + priv->enabled = false; iowrite32(0, priv->base + FTGMAC100_OFFSET_IER); netif_stop_queue(netdev); @@ -1212,10 +1219,8 @@ static int ftgmac100_stop(struct net_device *netdev) struct ftgmac100 *priv = netdev_priv(netdev); /* Stop NCSI device */ - if (priv->use_ncsi) { - ncsi_suspend_dev(priv->ndev); - return 0; - } + if (priv->use_ncsi) + ncsi_stop_dev(priv->ndev); return ftgmac100_stop_dev(netdev); }