瀏覽代碼

IPoIB: Fix hang in napi_disable() if P_Key is never found

After commit fe25c561 ("IPoIB: Don't enable NAPI when it's already
enabled"), if an interface is brought up but the corresponding P_Key
never appears, then ipoib_stop() will hang in napi_disable(), because
ipoib_open() returns before it does napi_enable().

Fix this by changing ipoib_open() to call napi_enable() even if the
P_Key isn't present.

Reported-by: Yossi Etigin <yosefe@Voltaire.COM>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Roland Dreier 16 年之前
父節點
當前提交
b8a1b1ce14
共有 1 個文件被更改,包括 15 次插入12 次删除
  1. 15 12
      drivers/infiniband/ulp/ipoib/ipoib_main.c

+ 15 - 12
drivers/infiniband/ulp/ipoib/ipoib_main.c

@@ -106,23 +106,17 @@ int ipoib_open(struct net_device *dev)
 
 
 	ipoib_dbg(priv, "bringing up interface\n");
 	ipoib_dbg(priv, "bringing up interface\n");
 
 
-	set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
+	if (!test_and_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;
 
 
-	napi_enable(&priv->napi);
+	if (ipoib_ib_dev_open(dev))
+		goto err_disable;
 
 
-	if (ipoib_ib_dev_open(dev)) {
-		napi_disable(&priv->napi);
-		return -EINVAL;
-	}
-
-	if (ipoib_ib_dev_up(dev)) {
-		ipoib_ib_dev_stop(dev, 1);
-		napi_disable(&priv->napi);
-		return -EINVAL;
-	}
+	if (ipoib_ib_dev_up(dev))
+		goto err_stop;
 
 
 	if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
 	if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
 		struct ipoib_dev_priv *cpriv;
 		struct ipoib_dev_priv *cpriv;
@@ -144,6 +138,15 @@ int ipoib_open(struct net_device *dev)
 	netif_start_queue(dev);
 	netif_start_queue(dev);
 
 
 	return 0;
 	return 0;
+
+err_stop:
+	ipoib_ib_dev_stop(dev, 1);
+
+err_disable:
+	napi_disable(&priv->napi);
+	clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
+
+	return -EINVAL;
 }
 }
 
 
 static int ipoib_stop(struct net_device *dev)
 static int ipoib_stop(struct net_device *dev)