aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Ledford <dledford@redhat.com>2015-02-21 19:27:00 -0500
committerDoug Ledford <dledford@redhat.com>2015-04-15 16:06:17 -0400
commitbe7aa663fc1d9156798f5af3c60e6df45e1fe5de (patch)
treeb359b4429be35816f0abf9889942e02933c59e84
parente135106fac9525352feb8e49077c8f46c3eaf288 (diff)
IB/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>
-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 657b89b1d291..98c738d827d1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1269,15 +1269,13 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
1269{ 1269{
1270 struct ipoib_dev_priv *priv = netdev_priv(dev); 1270 struct ipoib_dev_priv *priv = netdev_priv(dev);
1271 1271
1272 if (ipoib_neigh_hash_init(priv) < 0)
1273 goto out;
1274 /* Allocate RX/TX "rings" to hold queued skbs */ 1272 /* Allocate RX/TX "rings" to hold queued skbs */
1275 priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring, 1273 priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring,
1276 GFP_KERNEL); 1274 GFP_KERNEL);
1277 if (!priv->rx_ring) { 1275 if (!priv->rx_ring) {
1278 printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n", 1276 printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n",
1279 ca->name, ipoib_recvq_size); 1277 ca->name, ipoib_recvq_size);
1280 goto out_neigh_hash_cleanup; 1278 goto out;
1281 } 1279 }
1282 1280
1283 priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring); 1281 priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring);
@@ -1292,16 +1290,24 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
1292 if (ipoib_ib_dev_init(dev, ca, port)) 1290 if (ipoib_ib_dev_init(dev, ca, port))
1293 goto out_tx_ring_cleanup; 1291 goto out_tx_ring_cleanup;
1294 1292
1293 /*
1294 * Must be after ipoib_ib_dev_init so we can allocate a per
1295 * device wq there and use it here
1296 */
1297 if (ipoib_neigh_hash_init(priv) < 0)
1298 goto out_dev_uninit;
1299
1295 return 0; 1300 return 0;
1296 1301
1302out_dev_uninit:
1303 ipoib_ib_dev_cleanup(dev);
1304
1297out_tx_ring_cleanup: 1305out_tx_ring_cleanup:
1298 vfree(priv->tx_ring); 1306 vfree(priv->tx_ring);
1299 1307
1300out_rx_ring_cleanup: 1308out_rx_ring_cleanup:
1301 kfree(priv->rx_ring); 1309 kfree(priv->rx_ring);
1302 1310
1303out_neigh_hash_cleanup:
1304 ipoib_neigh_hash_uninit(dev);
1305out: 1311out:
1306 return -ENOMEM; 1312 return -ENOMEM;
1307} 1313}
@@ -1324,6 +1330,12 @@ void ipoib_dev_cleanup(struct net_device *dev)
1324 } 1330 }
1325 unregister_netdevice_many(&head); 1331 unregister_netdevice_many(&head);
1326 1332
1333 /*
1334 * Must be before ipoib_ib_dev_cleanup or we delete an in use
1335 * work queue
1336 */
1337 ipoib_neigh_hash_uninit(dev);
1338
1327 ipoib_ib_dev_cleanup(dev); 1339 ipoib_ib_dev_cleanup(dev);
1328 1340
1329 kfree(priv->rx_ring); 1341 kfree(priv->rx_ring);
@@ -1331,8 +1343,6 @@ void ipoib_dev_cleanup(struct net_device *dev)
1331 1343
1332 priv->rx_ring = NULL; 1344 priv->rx_ring = NULL;
1333 priv->tx_ring = NULL; 1345 priv->tx_ring = NULL;
1334
1335 ipoib_neigh_hash_uninit(dev);
1336} 1346}
1337 1347
1338static const struct header_ops ipoib_header_ops = { 1348static const struct header_ops ipoib_header_ops = {