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>

authored by Yossi Etigin and committed by Roland Dreier e028cc55 a939b96c

+5 -6
+4 -2
drivers/infiniband/ulp/ipoib/ipoib_ib.c
··· 685 685 queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task, 686 686 round_jiffies_relative(HZ)); 687 687 688 - set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); 688 + if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) 689 + napi_enable(&priv->napi); 689 690 690 691 return 0; 691 692 } ··· 805 804 struct ipoib_tx_buf *tx_req; 806 805 int i; 807 806 808 - clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); 807 + if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) 808 + napi_disable(&priv->napi); 809 809 810 810 ipoib_cm_dev_stop(dev); 811 811
+1 -4
drivers/infiniband/ulp/ipoib/ipoib_main.c
··· 106 106 107 107 ipoib_dbg(priv, "bringing up interface\n"); 108 108 109 - if (!test_and_set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) 110 - napi_enable(&priv->napi); 109 + set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 111 110 112 111 if (ipoib_pkey_dev_delay_open(dev)) 113 112 return 0; ··· 142 143 ipoib_ib_dev_stop(dev, 1); 143 144 144 145 err_disable: 145 - napi_disable(&priv->napi); 146 146 clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 147 147 148 148 return -EINVAL; ··· 154 156 ipoib_dbg(priv, "stopping interface\n"); 155 157 156 158 clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 157 - napi_disable(&priv->napi); 158 159 159 160 netif_stop_queue(dev); 160 161