diff options
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_multicast.c')
| -rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 57 |
1 files changed, 19 insertions, 38 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 7cecb16d3d48..13f4aa7593c8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
| @@ -69,28 +69,13 @@ struct ipoib_mcast_iter { | |||
| 69 | static void ipoib_mcast_free(struct ipoib_mcast *mcast) | 69 | static void ipoib_mcast_free(struct ipoib_mcast *mcast) |
| 70 | { | 70 | { |
| 71 | struct net_device *dev = mcast->dev; | 71 | struct net_device *dev = mcast->dev; |
| 72 | struct ipoib_dev_priv *priv = netdev_priv(dev); | ||
| 73 | struct ipoib_neigh *neigh, *tmp; | ||
| 74 | int tx_dropped = 0; | 72 | int tx_dropped = 0; |
| 75 | 73 | ||
| 76 | ipoib_dbg_mcast(netdev_priv(dev), "deleting multicast group %pI6\n", | 74 | ipoib_dbg_mcast(netdev_priv(dev), "deleting multicast group %pI6\n", |
| 77 | mcast->mcmember.mgid.raw); | 75 | mcast->mcmember.mgid.raw); |
| 78 | 76 | ||
| 79 | spin_lock_irq(&priv->lock); | 77 | /* remove all neigh connected to this mcast */ |
| 80 | 78 | ipoib_del_neighs_by_gid(dev, mcast->mcmember.mgid.raw); | |
| 81 | list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) { | ||
| 82 | /* | ||
| 83 | * It's safe to call ipoib_put_ah() inside priv->lock | ||
| 84 | * here, because we know that mcast->ah will always | ||
| 85 | * hold one more reference, so ipoib_put_ah() will | ||
| 86 | * never do more than decrement the ref count. | ||
| 87 | */ | ||
| 88 | if (neigh->ah) | ||
| 89 | ipoib_put_ah(neigh->ah); | ||
| 90 | ipoib_neigh_free(dev, neigh); | ||
| 91 | } | ||
| 92 | |||
| 93 | spin_unlock_irq(&priv->lock); | ||
| 94 | 79 | ||
| 95 | if (mcast->ah) | 80 | if (mcast->ah) |
| 96 | ipoib_put_ah(mcast->ah); | 81 | ipoib_put_ah(mcast->ah); |
| @@ -655,17 +640,12 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast) | |||
| 655 | return 0; | 640 | return 0; |
| 656 | } | 641 | } |
| 657 | 642 | ||
| 658 | void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) | 643 | void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb) |
| 659 | { | 644 | { |
| 660 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 645 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
| 661 | struct dst_entry *dst = skb_dst(skb); | ||
| 662 | struct ipoib_mcast *mcast; | 646 | struct ipoib_mcast *mcast; |
| 663 | struct neighbour *n; | ||
| 664 | unsigned long flags; | 647 | unsigned long flags; |
| 665 | 648 | void *mgid = daddr + 4; | |
| 666 | n = NULL; | ||
| 667 | if (dst) | ||
| 668 | n = dst_neigh_lookup_skb(dst, skb); | ||
| 669 | 649 | ||
| 670 | spin_lock_irqsave(&priv->lock, flags); | 650 | spin_lock_irqsave(&priv->lock, flags); |
| 671 | 651 | ||
| @@ -721,28 +701,29 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) | |||
| 721 | 701 | ||
| 722 | out: | 702 | out: |
| 723 | if (mcast && mcast->ah) { | 703 | if (mcast && mcast->ah) { |
| 724 | if (n) { | 704 | struct ipoib_neigh *neigh; |
| 725 | if (!*to_ipoib_neigh(n)) { | 705 | |
| 726 | struct ipoib_neigh *neigh; | 706 | spin_unlock_irqrestore(&priv->lock, flags); |
| 727 | 707 | neigh = ipoib_neigh_get(dev, daddr); | |
| 728 | neigh = ipoib_neigh_alloc(n, skb->dev); | 708 | spin_lock_irqsave(&priv->lock, flags); |
| 729 | if (neigh) { | 709 | if (!neigh) { |
| 730 | kref_get(&mcast->ah->ref); | 710 | spin_unlock_irqrestore(&priv->lock, flags); |
| 731 | neigh->ah = mcast->ah; | 711 | neigh = ipoib_neigh_alloc(daddr, dev); |
| 732 | list_add_tail(&neigh->list, | 712 | spin_lock_irqsave(&priv->lock, flags); |
| 733 | &mcast->neigh_list); | 713 | if (neigh) { |
| 734 | } | 714 | kref_get(&mcast->ah->ref); |
| 715 | neigh->ah = mcast->ah; | ||
| 716 | list_add_tail(&neigh->list, &mcast->neigh_list); | ||
| 735 | } | 717 | } |
| 736 | neigh_release(n); | ||
| 737 | } | 718 | } |
| 738 | spin_unlock_irqrestore(&priv->lock, flags); | 719 | spin_unlock_irqrestore(&priv->lock, flags); |
| 739 | ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN); | 720 | ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN); |
| 721 | if (neigh) | ||
| 722 | ipoib_neigh_put(neigh); | ||
| 740 | return; | 723 | return; |
| 741 | } | 724 | } |
| 742 | 725 | ||
| 743 | unlock: | 726 | unlock: |
| 744 | if (n) | ||
| 745 | neigh_release(n); | ||
| 746 | spin_unlock_irqrestore(&priv->lock, flags); | 727 | spin_unlock_irqrestore(&priv->lock, flags); |
| 747 | } | 728 | } |
| 748 | 729 | ||
