mirror of
https://github.com/torvalds/linux.git
synced 2024-10-26 23:12:36 +00:00
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: Yossi Etigin <yosefe@voltaire.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
parent
a939b96ccc
commit
e028cc55cc
|
@ -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)
|
||||||
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)
|
||||||
|
|
||||||
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 @@ err_stop:
|
||||||
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)
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user