diff options
author | Roland Dreier <rolandd@cisco.com> | 2009-01-14 17:55:41 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2009-01-14 17:55:41 -0500 |
commit | b8a1b1ce14252b59b2d5c89de25b54f9bfd4cc5e (patch) | |
tree | b3bf96fe0646bd30684391f1f9565347566cdd0c | |
parent | e0b325d310a6b11f1538413fd557d2eb98f2fae5 (diff) |
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>
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index dce0443f9d69..0bd2a4ff0842 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -106,23 +106,17 @@ int ipoib_open(struct net_device *dev) | |||
106 | 106 | ||
107 | ipoib_dbg(priv, "bringing up interface\n"); | 107 | ipoib_dbg(priv, "bringing up interface\n"); |
108 | 108 | ||
109 | set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); | 109 | if (!test_and_set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) |
110 | napi_enable(&priv->napi); | ||
110 | 111 | ||
111 | if (ipoib_pkey_dev_delay_open(dev)) | 112 | if (ipoib_pkey_dev_delay_open(dev)) |
112 | return 0; | 113 | return 0; |
113 | 114 | ||
114 | napi_enable(&priv->napi); | 115 | if (ipoib_ib_dev_open(dev)) |
116 | goto err_disable; | ||
115 | 117 | ||
116 | if (ipoib_ib_dev_open(dev)) { | 118 | if (ipoib_ib_dev_up(dev)) |
117 | napi_disable(&priv->napi); | 119 | goto err_stop; |
118 | return -EINVAL; | ||
119 | } | ||
120 | |||
121 | if (ipoib_ib_dev_up(dev)) { | ||
122 | ipoib_ib_dev_stop(dev, 1); | ||
123 | napi_disable(&priv->napi); | ||
124 | return -EINVAL; | ||
125 | } | ||
126 | 120 | ||
127 | if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { | 121 | if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { |
128 | struct ipoib_dev_priv *cpriv; | 122 | struct ipoib_dev_priv *cpriv; |
@@ -144,6 +138,15 @@ int ipoib_open(struct net_device *dev) | |||
144 | netif_start_queue(dev); | 138 | netif_start_queue(dev); |
145 | 139 | ||
146 | return 0; | 140 | return 0; |
141 | |||
142 | err_stop: | ||
143 | ipoib_ib_dev_stop(dev, 1); | ||
144 | |||
145 | err_disable: | ||
146 | napi_disable(&priv->napi); | ||
147 | clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); | ||
148 | |||
149 | return -EINVAL; | ||
147 | } | 150 | } |
148 | 151 | ||
149 | static int ipoib_stop(struct net_device *dev) | 152 | static int ipoib_stop(struct net_device *dev) |