Commit e028cc55 authored by Yossi Etigin's avatar Yossi Etigin Committed by Roland Dreier

IPoIB: Disable NAPI while CQ is being drained

If NAPI is enabled while IPoIB's CQ is being drained, it creates a
race on priv->ibwc between ipoib_poll() and ipoib_drain_cq(), leading
to memory corruption.

The solution is to enable/disable NAPI in ipoib_ib_dev_{open/stop}()
instead of in ipoib_{open/stop}(), and sync NAPI on the INITIALIZED
flag instead on the ADMIN_UP flag. This way NAPI will be disabled when
ipoib_drain_cq() is called.

This fixes <https://bugs.openfabrics.org/show_bug.cgi?id=1587>.
Signed-off-by: default avatarYossi Etigin <yosefe@voltaire.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent a939b96c
...@@ -685,7 +685,8 @@ int ipoib_ib_dev_open(struct net_device *dev) ...@@ -685,7 +685,8 @@ int ipoib_ib_dev_open(struct net_device *dev)
queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task,
round_jiffies_relative(HZ)); round_jiffies_relative(HZ));
set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
napi_enable(&priv->napi);
return 0; return 0;
} }
...@@ -804,7 +805,8 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush) ...@@ -804,7 +805,8 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
struct ipoib_tx_buf *tx_req; struct ipoib_tx_buf *tx_req;
int i; int i;
clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
napi_disable(&priv->napi);
ipoib_cm_dev_stop(dev); ipoib_cm_dev_stop(dev);
......
...@@ -106,8 +106,7 @@ int ipoib_open(struct net_device *dev) ...@@ -106,8 +106,7 @@ int ipoib_open(struct net_device *dev)
ipoib_dbg(priv, "bringing up interface\n"); ipoib_dbg(priv, "bringing up interface\n");
if (!test_and_set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
napi_enable(&priv->napi);
if (ipoib_pkey_dev_delay_open(dev)) if (ipoib_pkey_dev_delay_open(dev))
return 0; return 0;
...@@ -143,7 +142,6 @@ int ipoib_open(struct net_device *dev) ...@@ -143,7 +142,6 @@ int ipoib_open(struct net_device *dev)
ipoib_ib_dev_stop(dev, 1); ipoib_ib_dev_stop(dev, 1);
err_disable: err_disable:
napi_disable(&priv->napi);
clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
return -EINVAL; return -EINVAL;
...@@ -156,7 +154,6 @@ static int ipoib_stop(struct net_device *dev) ...@@ -156,7 +154,6 @@ static int ipoib_stop(struct net_device *dev)
ipoib_dbg(priv, "stopping interface\n"); ipoib_dbg(priv, "stopping interface\n");
clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
napi_disable(&priv->napi);
netif_stop_queue(dev); netif_stop_queue(dev);
......
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