diff options
author | Michael S. Tsirkin <mst@mellanox.co.il> | 2006-08-03 15:16:06 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-09-22 18:17:18 -0400 |
commit | 9217b27b12eb5ab910d14b3376c2b6cd13d87711 (patch) | |
tree | 49d1f60e61013b7c60e13de0f60ec9ead81309b5 /drivers/infiniband/ulp/ipoib | |
parent | 9fd558f454b666aca218a990d44f9e1ffac6ed4d (diff) |
IB/ipoib: Fix flush/start xmit race (from code review)
Prevent flush task from freeing the ipoib_neigh pointer, while
ipoib_start_xmit() is accessing the ipoib_neigh through the pointer it
has loaded from the skb's hardware address.
Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/ulp/ipoib')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index cf71d2a5515c..36d76987a481 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -336,7 +336,8 @@ void ipoib_flush_paths(struct net_device *dev) | |||
336 | struct ipoib_path *path, *tp; | 336 | struct ipoib_path *path, *tp; |
337 | LIST_HEAD(remove_list); | 337 | LIST_HEAD(remove_list); |
338 | 338 | ||
339 | spin_lock_irq(&priv->lock); | 339 | spin_lock_irq(&priv->tx_lock); |
340 | spin_lock(&priv->lock); | ||
340 | 341 | ||
341 | list_splice(&priv->path_list, &remove_list); | 342 | list_splice(&priv->path_list, &remove_list); |
342 | INIT_LIST_HEAD(&priv->path_list); | 343 | INIT_LIST_HEAD(&priv->path_list); |
@@ -347,12 +348,15 @@ void ipoib_flush_paths(struct net_device *dev) | |||
347 | list_for_each_entry_safe(path, tp, &remove_list, list) { | 348 | list_for_each_entry_safe(path, tp, &remove_list, list) { |
348 | if (path->query) | 349 | if (path->query) |
349 | ib_sa_cancel_query(path->query_id, path->query); | 350 | ib_sa_cancel_query(path->query_id, path->query); |
350 | spin_unlock_irq(&priv->lock); | 351 | spin_unlock(&priv->lock); |
352 | spin_unlock_irq(&priv->tx_lock); | ||
351 | wait_for_completion(&path->done); | 353 | wait_for_completion(&path->done); |
352 | path_free(dev, path); | 354 | path_free(dev, path); |
353 | spin_lock_irq(&priv->lock); | 355 | spin_lock_irq(&priv->tx_lock); |
356 | spin_lock(&priv->lock); | ||
354 | } | 357 | } |
355 | spin_unlock_irq(&priv->lock); | 358 | spin_unlock(&priv->lock); |
359 | spin_unlock_irq(&priv->tx_lock); | ||
356 | } | 360 | } |
357 | 361 | ||
358 | static void path_rec_completion(int status, | 362 | static void path_rec_completion(int status, |