diff options
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_multicast.c')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 58 |
1 files changed, 23 insertions, 35 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 93c462eaf4fd..1dae4b238252 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
@@ -114,8 +114,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
114 | */ | 114 | */ |
115 | if (neigh->ah) | 115 | if (neigh->ah) |
116 | ipoib_put_ah(neigh->ah); | 116 | ipoib_put_ah(neigh->ah); |
117 | *to_ipoib_neigh(neigh->neighbour) = NULL; | 117 | ipoib_neigh_free(neigh); |
118 | kfree(neigh); | ||
119 | } | 118 | } |
120 | 119 | ||
121 | spin_unlock_irqrestore(&priv->lock, flags); | 120 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -251,6 +250,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, | |||
251 | .port_num = priv->port, | 250 | .port_num = priv->port, |
252 | .sl = mcast->mcmember.sl, | 251 | .sl = mcast->mcmember.sl, |
253 | .ah_flags = IB_AH_GRH, | 252 | .ah_flags = IB_AH_GRH, |
253 | .static_rate = mcast->mcmember.rate, | ||
254 | .grh = { | 254 | .grh = { |
255 | .flow_label = be32_to_cpu(mcast->mcmember.flow_label), | 255 | .flow_label = be32_to_cpu(mcast->mcmember.flow_label), |
256 | .hop_limit = mcast->mcmember.hop_limit, | 256 | .hop_limit = mcast->mcmember.hop_limit, |
@@ -258,17 +258,8 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, | |||
258 | .traffic_class = mcast->mcmember.traffic_class | 258 | .traffic_class = mcast->mcmember.traffic_class |
259 | } | 259 | } |
260 | }; | 260 | }; |
261 | int path_rate = ib_sa_rate_enum_to_int(mcast->mcmember.rate); | ||
262 | |||
263 | av.grh.dgid = mcast->mcmember.mgid; | 261 | av.grh.dgid = mcast->mcmember.mgid; |
264 | 262 | ||
265 | if (path_rate > 0 && priv->local_rate > path_rate) | ||
266 | av.static_rate = (priv->local_rate - 1) / path_rate; | ||
267 | |||
268 | ipoib_dbg_mcast(priv, "static_rate %d for local port %dX, mcmember %dX\n", | ||
269 | av.static_rate, priv->local_rate, | ||
270 | ib_sa_rate_enum_to_int(mcast->mcmember.rate)); | ||
271 | |||
272 | ah = ipoib_create_ah(dev, priv->pd, &av); | 263 | ah = ipoib_create_ah(dev, priv->pd, &av); |
273 | if (!ah) { | 264 | if (!ah) { |
274 | ipoib_warn(priv, "ib_address_create failed\n"); | 265 | ipoib_warn(priv, "ib_address_create failed\n"); |
@@ -618,6 +609,22 @@ int ipoib_mcast_start_thread(struct net_device *dev) | |||
618 | return 0; | 609 | return 0; |
619 | } | 610 | } |
620 | 611 | ||
612 | static void wait_for_mcast_join(struct ipoib_dev_priv *priv, | ||
613 | struct ipoib_mcast *mcast) | ||
614 | { | ||
615 | spin_lock_irq(&priv->lock); | ||
616 | if (mcast && mcast->query) { | ||
617 | ib_sa_cancel_query(mcast->query_id, mcast->query); | ||
618 | mcast->query = NULL; | ||
619 | spin_unlock_irq(&priv->lock); | ||
620 | ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n", | ||
621 | IPOIB_GID_ARG(mcast->mcmember.mgid)); | ||
622 | wait_for_completion(&mcast->done); | ||
623 | } | ||
624 | else | ||
625 | spin_unlock_irq(&priv->lock); | ||
626 | } | ||
627 | |||
621 | int ipoib_mcast_stop_thread(struct net_device *dev, int flush) | 628 | int ipoib_mcast_stop_thread(struct net_device *dev, int flush) |
622 | { | 629 | { |
623 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 630 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
@@ -637,28 +644,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush) | |||
637 | if (flush) | 644 | if (flush) |
638 | flush_workqueue(ipoib_workqueue); | 645 | flush_workqueue(ipoib_workqueue); |
639 | 646 | ||
640 | spin_lock_irq(&priv->lock); | 647 | wait_for_mcast_join(priv, priv->broadcast); |
641 | if (priv->broadcast && priv->broadcast->query) { | ||
642 | ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query); | ||
643 | priv->broadcast->query = NULL; | ||
644 | spin_unlock_irq(&priv->lock); | ||
645 | ipoib_dbg_mcast(priv, "waiting for bcast\n"); | ||
646 | wait_for_completion(&priv->broadcast->done); | ||
647 | } else | ||
648 | spin_unlock_irq(&priv->lock); | ||
649 | 648 | ||
650 | list_for_each_entry(mcast, &priv->multicast_list, list) { | 649 | list_for_each_entry(mcast, &priv->multicast_list, list) |
651 | spin_lock_irq(&priv->lock); | 650 | wait_for_mcast_join(priv, mcast); |
652 | if (mcast->query) { | ||
653 | ib_sa_cancel_query(mcast->query_id, mcast->query); | ||
654 | mcast->query = NULL; | ||
655 | spin_unlock_irq(&priv->lock); | ||
656 | ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n", | ||
657 | IPOIB_GID_ARG(mcast->mcmember.mgid)); | ||
658 | wait_for_completion(&mcast->done); | ||
659 | } else | ||
660 | spin_unlock_irq(&priv->lock); | ||
661 | } | ||
662 | 651 | ||
663 | return 0; | 652 | return 0; |
664 | } | 653 | } |
@@ -772,13 +761,11 @@ out: | |||
772 | if (skb->dst && | 761 | if (skb->dst && |
773 | skb->dst->neighbour && | 762 | skb->dst->neighbour && |
774 | !*to_ipoib_neigh(skb->dst->neighbour)) { | 763 | !*to_ipoib_neigh(skb->dst->neighbour)) { |
775 | struct ipoib_neigh *neigh = kmalloc(sizeof *neigh, GFP_ATOMIC); | 764 | struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb->dst->neighbour); |
776 | 765 | ||
777 | if (neigh) { | 766 | if (neigh) { |
778 | kref_get(&mcast->ah->ref); | 767 | kref_get(&mcast->ah->ref); |
779 | neigh->ah = mcast->ah; | 768 | neigh->ah = mcast->ah; |
780 | neigh->neighbour = skb->dst->neighbour; | ||
781 | *to_ipoib_neigh(skb->dst->neighbour) = neigh; | ||
782 | list_add_tail(&neigh->list, &mcast->neigh_list); | 769 | list_add_tail(&neigh->list, &mcast->neigh_list); |
783 | } | 770 | } |
784 | } | 771 | } |
@@ -913,6 +900,7 @@ void ipoib_mcast_restart_task(void *dev_ptr) | |||
913 | 900 | ||
914 | /* We have to cancel outside of the spinlock */ | 901 | /* We have to cancel outside of the spinlock */ |
915 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { | 902 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { |
903 | wait_for_mcast_join(priv, mcast); | ||
916 | ipoib_mcast_leave(mcast->dev, mcast); | 904 | ipoib_mcast_leave(mcast->dev, mcast); |
917 | ipoib_mcast_free(mcast); | 905 | ipoib_mcast_free(mcast); |
918 | } | 906 | } |