aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c23
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c8
3 files changed, 28 insertions, 4 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 3f89f5e19036..474aa214ab57 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -212,6 +212,7 @@ struct ipoib_path {
212 212
213struct ipoib_neigh { 213struct ipoib_neigh {
214 struct ipoib_ah *ah; 214 struct ipoib_ah *ah;
215 union ib_gid dgid;
215 struct sk_buff_head queue; 216 struct sk_buff_head queue;
216 217
217 struct neighbour *neighbour; 218 struct neighbour *neighbour;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 1c6ea1c682a5..cf71d2a5515c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -404,6 +404,8 @@ static void path_rec_completion(int status,
404 list_for_each_entry(neigh, &path->neigh_list, list) { 404 list_for_each_entry(neigh, &path->neigh_list, list) {
405 kref_get(&path->ah->ref); 405 kref_get(&path->ah->ref);
406 neigh->ah = path->ah; 406 neigh->ah = path->ah;
407 memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw,
408 sizeof(union ib_gid));
407 409
408 while ((skb = __skb_dequeue(&neigh->queue))) 410 while ((skb = __skb_dequeue(&neigh->queue)))
409 __skb_queue_tail(&skqueue, skb); 411 __skb_queue_tail(&skqueue, skb);
@@ -510,6 +512,8 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
510 if (path->ah) { 512 if (path->ah) {
511 kref_get(&path->ah->ref); 513 kref_get(&path->ah->ref);
512 neigh->ah = path->ah; 514 neigh->ah = path->ah;
515 memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw,
516 sizeof(union ib_gid));
513 517
514 ipoib_send(dev, skb, path->ah, 518 ipoib_send(dev, skb, path->ah,
515 be32_to_cpup((__be32 *) skb->dst->neighbour->ha)); 519 be32_to_cpup((__be32 *) skb->dst->neighbour->ha));
@@ -633,6 +637,25 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
633 neigh = *to_ipoib_neigh(skb->dst->neighbour); 637 neigh = *to_ipoib_neigh(skb->dst->neighbour);
634 638
635 if (likely(neigh->ah)) { 639 if (likely(neigh->ah)) {
640 if (unlikely(memcmp(&neigh->dgid.raw,
641 skb->dst->neighbour->ha + 4,
642 sizeof(union ib_gid)))) {
643 spin_lock(&priv->lock);
644 /*
645 * It's safe to call ipoib_put_ah() inside
646 * priv->lock here, because we know that
647 * path->ah will always hold one more reference,
648 * so ipoib_put_ah() will never do more than
649 * decrement the ref count.
650 */
651 ipoib_put_ah(neigh->ah);
652 list_del(&neigh->list);
653 ipoib_neigh_free(neigh);
654 spin_unlock(&priv->lock);
655 ipoib_path_lookup(skb, dev);
656 goto out;
657 }
658
636 ipoib_send(dev, skb, neigh->ah, 659 ipoib_send(dev, skb, neigh->ah,
637 be32_to_cpup((__be32 *) skb->dst->neighbour->ha)); 660 be32_to_cpup((__be32 *) skb->dst->neighbour->ha));
638 goto out; 661 goto out;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index ab40488182b3..b5e6a7be603d 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -264,6 +264,10 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
264 if (!ah) { 264 if (!ah) {
265 ipoib_warn(priv, "ib_address_create failed\n"); 265 ipoib_warn(priv, "ib_address_create failed\n");
266 } else { 266 } else {
267 spin_lock_irq(&priv->lock);
268 mcast->ah = ah;
269 spin_unlock_irq(&priv->lock);
270
267 ipoib_dbg_mcast(priv, "MGID " IPOIB_GID_FMT 271 ipoib_dbg_mcast(priv, "MGID " IPOIB_GID_FMT
268 " AV %p, LID 0x%04x, SL %d\n", 272 " AV %p, LID 0x%04x, SL %d\n",
269 IPOIB_GID_ARG(mcast->mcmember.mgid), 273 IPOIB_GID_ARG(mcast->mcmember.mgid),
@@ -271,10 +275,6 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
271 be16_to_cpu(mcast->mcmember.mlid), 275 be16_to_cpu(mcast->mcmember.mlid),
272 mcast->mcmember.sl); 276 mcast->mcmember.sl);
273 } 277 }
274
275 spin_lock_irq(&priv->lock);
276 mcast->ah = ah;
277 spin_unlock_irq(&priv->lock);
278 } 278 }
279 279
280 /* actually send any queued packets */ 280 /* actually send any queued packets */