aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Ledford <dledford@redhat.com>2014-12-10 11:47:02 -0500
committerRoland Dreier <roland@purestorage.com>2014-12-15 21:11:15 -0500
commit3bcce487fda8161597c20ed303d510e41ad7770e (patch)
tree0f36ea1c32ea745e2efd51d36940f382ab28bd5e
parente5d1dcf1b0951f4ba00d93653942dda6196109d8 (diff)
IPoIB: change init sequence ordering
In preparation for using per device work queues, we need to move the start of the neighbor thread task to after ipoib_ib_dev_init and move the destruction of the neighbor task to before ipoib_ib_dev_cleanup. Otherwise we will end up freeing our workqueue with work possibly still on it. Signed-off-by: Doug Ledford <dledford@redhat.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 58b5aa3b6f2d..2cf81ef51412 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1262,15 +1262,13 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
1262{ 1262{
1263 struct ipoib_dev_priv *priv = netdev_priv(dev); 1263 struct ipoib_dev_priv *priv = netdev_priv(dev);
1264 1264
1265 if (ipoib_neigh_hash_init(priv) < 0)
1266 goto out;
1267 /* Allocate RX/TX "rings" to hold queued skbs */ 1265 /* Allocate RX/TX "rings" to hold queued skbs */
1268 priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring, 1266 priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring,
1269 GFP_KERNEL); 1267 GFP_KERNEL);
1270 if (!priv->rx_ring) { 1268 if (!priv->rx_ring) {
1271 printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n", 1269 printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n",
1272 ca->name, ipoib_recvq_size); 1270 ca->name, ipoib_recvq_size);
1273 goto out_neigh_hash_cleanup; 1271 goto out;
1274 } 1272 }
1275 1273
1276 priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring); 1274 priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring);
@@ -1285,16 +1283,24 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
1285 if (ipoib_ib_dev_init(dev, ca, port)) 1283 if (ipoib_ib_dev_init(dev, ca, port))
1286 goto out_tx_ring_cleanup; 1284 goto out_tx_ring_cleanup;
1287 1285
1286 /*
1287 * Must be after ipoib_ib_dev_init so we can allocate a per
1288 * device wq there and use it here
1289 */
1290 if (ipoib_neigh_hash_init(priv) < 0)
1291 goto out_dev_uninit;
1292
1288 return 0; 1293 return 0;
1289 1294
1295out_dev_uninit:
1296 ipoib_ib_dev_cleanup();
1297
1290out_tx_ring_cleanup: 1298out_tx_ring_cleanup:
1291 vfree(priv->tx_ring); 1299 vfree(priv->tx_ring);
1292 1300
1293out_rx_ring_cleanup: 1301out_rx_ring_cleanup:
1294 kfree(priv->rx_ring); 1302 kfree(priv->rx_ring);
1295 1303
1296out_neigh_hash_cleanup:
1297 ipoib_neigh_hash_uninit(dev);
1298out: 1304out:
1299 return -ENOMEM; 1305 return -ENOMEM;
1300} 1306}
@@ -1317,6 +1323,12 @@ void ipoib_dev_cleanup(struct net_device *dev)
1317 } 1323 }
1318 unregister_netdevice_many(&head); 1324 unregister_netdevice_many(&head);
1319 1325
1326 /*
1327 * Must be before ipoib_ib_dev_cleanup or we delete an in use
1328 * work queue
1329 */
1330 ipoib_neigh_hash_uninit(dev);
1331
1320 ipoib_ib_dev_cleanup(dev); 1332 ipoib_ib_dev_cleanup(dev);
1321 1333
1322 kfree(priv->rx_ring); 1334 kfree(priv->rx_ring);
@@ -1324,8 +1336,6 @@ void ipoib_dev_cleanup(struct net_device *dev)
1324 1336
1325 priv->rx_ring = NULL; 1337 priv->rx_ring = NULL;
1326 priv->tx_ring = NULL; 1338 priv->tx_ring = NULL;
1327
1328 ipoib_neigh_hash_uninit(dev);
1329} 1339}
1330 1340
1331static const struct header_ops ipoib_header_ops = { 1341static const struct header_ops ipoib_header_ops = {