diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 23 |
2 files changed, 24 insertions, 0 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 | ||
213 | struct ipoib_neigh { | 213 | struct 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; |