aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/ulp/ipoib/ipoib_multicast.c')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c58
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
612static 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
621int ipoib_mcast_stop_thread(struct net_device *dev, int flush) 628int 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 }