Convert IPoIB to use the new ib_multicast interfaces in place of direct
SA query calls.

Signed-off-by: Sean Hefty <[EMAIL PROTECTED]>

---

Testing was limited to bringing up ipoib and verifying that it worked.
If I can get some guidance on some additional testing, I can do that.
Code review would also be beneficial, as this patch removes a multicast
fix that was just added, which I no longer believe is required.


Index: ulp/ipoib/ipoib_multicast.c
===================================================================
--- ulp/ipoib/ipoib_multicast.c (revision 6307)
+++ ulp/ipoib/ipoib_multicast.c (working copy)
@@ -45,6 +45,8 @@
 
 #include <net/dst.h>
 
+#include <rdma/ib_multicast.h>
+
 #include "ipoib.h"
 
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
@@ -60,14 +62,11 @@ static DEFINE_MUTEX(mcast_mutex);
 /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
 struct ipoib_mcast {
        struct ib_sa_mcmember_rec mcmember;
+       struct ib_multicast      *mc;
        struct ipoib_ah          *ah;
 
        struct rb_node    rb_node;
        struct list_head  list;
-       struct completion done;
-
-       int                 query_id;
-       struct ib_sa_query *query;
 
        unsigned long created;
        unsigned long backoff;
@@ -299,18 +298,18 @@ static int ipoib_mcast_join_finish(struc
        return 0;
 }
 
-static void
+static int
 ipoib_mcast_sendonly_join_complete(int status,
-                                  struct ib_sa_mcmember_rec *mcmember,
-                                  void *mcast_ptr)
+                                  struct ib_multicast *multicast)
 {
-       struct ipoib_mcast *mcast = mcast_ptr;
+       struct ipoib_mcast *mcast = multicast->context;
        struct net_device *dev = mcast->dev;
        struct ipoib_dev_priv *priv = netdev_priv(dev);
 
        if (!status)
-               ipoib_mcast_join_finish(mcast, mcmember);
-       else {
+               status = ipoib_mcast_join_finish(mcast, &multicast->rec);
+       
+       if (status) {
                if (mcast->logcount++ < 20)
                        ipoib_dbg_mcast(netdev_priv(dev), "multicast join 
failed for "
                                        IPOIB_GID_FMT ", status %d\n",
@@ -325,10 +324,10 @@ ipoib_mcast_sendonly_join_complete(int s
                spin_unlock_irq(&priv->tx_lock);
 
                /* Clear the busy flag so we try again */
-               clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+               status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY,
+                                           &mcast->flags);
        }
-
-       complete(&mcast->done);
+       return status;
 }
 
 static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
@@ -358,35 +357,31 @@ static int ipoib_mcast_sendonly_join(str
        rec.port_gid = priv->local_gid;
        rec.pkey     = cpu_to_be16(priv->pkey);
 
-       init_completion(&mcast->done);
-
-       ret = ib_sa_mcmember_rec_set(priv->ca, priv->port, &rec,
-                                    IB_SA_MCMEMBER_REC_MGID            |
-                                    IB_SA_MCMEMBER_REC_PORT_GID        |
-                                    IB_SA_MCMEMBER_REC_PKEY            |
-                                    IB_SA_MCMEMBER_REC_JOIN_STATE,
-                                    1000, GFP_ATOMIC,
-                                    ipoib_mcast_sendonly_join_complete,
-                                    mcast, &mcast->query);
-       if (ret < 0) {
-               ipoib_warn(priv, "ib_sa_mcmember_rec_set failed (ret = %d)\n",
+       mcast->mc = ib_join_multicast(priv->ca, priv->port, &rec,
+                                     IB_SA_MCMEMBER_REC_MGID           |
+                                     IB_SA_MCMEMBER_REC_PORT_GID       |
+                                     IB_SA_MCMEMBER_REC_PKEY           |
+                                     IB_SA_MCMEMBER_REC_JOIN_STATE,
+                                     GFP_ATOMIC,
+                                     ipoib_mcast_sendonly_join_complete,
+                                     mcast);
+       if (IS_ERR(mcast->mc)) {
+               ret = PTR_ERR(mcast->mc);
+               clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+               ipoib_warn(priv, "ib_join_multicast failed (ret = %d)\n",
                           ret);
        } else {
                ipoib_dbg_mcast(priv, "no multicast record for " IPOIB_GID_FMT
                                ", starting join\n",
                                IPOIB_GID_ARG(mcast->mcmember.mgid));
-
-               mcast->query_id = ret;
        }
-
        return ret;
 }
 
-static void ipoib_mcast_join_complete(int status,
-                                     struct ib_sa_mcmember_rec *mcmember,
-                                     void *mcast_ptr)
+static int ipoib_mcast_join_complete(int status,
+                                    struct ib_multicast *multicast)
 {
-       struct ipoib_mcast *mcast = mcast_ptr;
+       struct ipoib_mcast *mcast = multicast->context;
        struct net_device *dev = mcast->dev;
        struct ipoib_dev_priv *priv = netdev_priv(dev);
 
@@ -394,23 +389,20 @@ static void ipoib_mcast_join_complete(in
                        " (status %d)\n",
                        IPOIB_GID_ARG(mcast->mcmember.mgid), status);
 
-       if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) {
+       if (!status)
+               status = ipoib_mcast_join_finish(mcast, &multicast->rec);
+
+       if (!status) {
                mcast->backoff = 1;
                mutex_lock(&mcast_mutex);
                if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
                        queue_work(ipoib_workqueue, &priv->mcast_task);
                mutex_unlock(&mcast_mutex);
-               complete(&mcast->done);
-               return;
-       }
-
-       if (status == -EINTR) {
-               complete(&mcast->done);
-               return;
+               return 0;
        }
 
-       if (status && mcast->logcount++ < 20) {
-               if (status == -ETIMEDOUT || status == -EINTR) {
+       if (mcast->logcount++ < 20) {
+               if (status == -ETIMEDOUT) {
                        ipoib_dbg_mcast(priv, "multicast join failed for " 
IPOIB_GID_FMT
                                        ", status %d\n",
                                        IPOIB_GID_ARG(mcast->mcmember.mgid),
@@ -427,23 +419,18 @@ static void ipoib_mcast_join_complete(in
        if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
                mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
 
-       mutex_lock(&mcast_mutex);
+       /* Clear the busy flag so we try again */
+       status = test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
 
+       mutex_lock(&mcast_mutex);
        spin_lock_irq(&priv->lock);
-       mcast->query = NULL;
-
-       if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) {
-               if (status == -ETIMEDOUT)
-                       queue_work(ipoib_workqueue, &priv->mcast_task);
-               else
-                       queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
-                                          mcast->backoff * HZ);
-       } else
-               complete(&mcast->done);
+       if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
+               queue_delayed_work(ipoib_workqueue, &priv->mcast_task,
+                                  mcast->backoff * HZ);
        spin_unlock_irq(&priv->lock);
        mutex_unlock(&mcast_mutex);
 
-       return;
+       return status;
 }
 
 static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
@@ -463,18 +450,16 @@ static void ipoib_mcast_join(struct net_
        rec.port_gid = priv->local_gid;
        rec.pkey     = cpu_to_be16(priv->pkey);
 
-       comp_mask =
-               IB_SA_MCMEMBER_REC_MGID         |
-               IB_SA_MCMEMBER_REC_PORT_GID     |
-               IB_SA_MCMEMBER_REC_PKEY         |
-               IB_SA_MCMEMBER_REC_JOIN_STATE;
+       comp_mask = IB_SA_MCMEMBER_REC_MGID             |
+                   IB_SA_MCMEMBER_REC_PORT_GID         |
+                   IB_SA_MCMEMBER_REC_PKEY             |
+                   IB_SA_MCMEMBER_REC_JOIN_STATE;
 
        if (create) {
-               comp_mask |=
-                       IB_SA_MCMEMBER_REC_QKEY         |
-                       IB_SA_MCMEMBER_REC_SL           |
-                       IB_SA_MCMEMBER_REC_FLOW_LABEL   |
-                       IB_SA_MCMEMBER_REC_TRAFFIC_CLASS;
+               comp_mask |= IB_SA_MCMEMBER_REC_QKEY            |
+                            IB_SA_MCMEMBER_REC_SL              |
+                            IB_SA_MCMEMBER_REC_FLOW_LABEL      |
+                            IB_SA_MCMEMBER_REC_TRAFFIC_CLASS;
 
                rec.qkey          = priv->broadcast->mcmember.qkey;
                rec.sl            = priv->broadcast->mcmember.sl;
@@ -482,15 +467,14 @@ static void ipoib_mcast_join(struct net_
                rec.traffic_class = priv->broadcast->mcmember.traffic_class;
        }
 
-       init_completion(&mcast->done);
-
-       ret = ib_sa_mcmember_rec_set(priv->ca, priv->port, &rec, comp_mask,
-                                    mcast->backoff * 1000, GFP_ATOMIC,
-                                    ipoib_mcast_join_complete,
-                                    mcast, &mcast->query);
-
-       if (ret < 0) {
-               ipoib_warn(priv, "ib_sa_mcmember_rec_set failed, status %d\n", 
ret);
+       set_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+       mcast->mc = ib_join_multicast(priv->ca, priv->port, &rec, comp_mask,
+                                     GFP_KERNEL, ipoib_mcast_join_complete,
+                                     mcast);
+       if (IS_ERR(mcast->mc)) {
+               clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
+               ret = PTR_ERR(mcast->mc);
+               ipoib_warn(priv, "ib_join_multicast failed, status %d\n", ret);
 
                mcast->backoff *= 2;
                if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
@@ -502,14 +486,14 @@ static void ipoib_mcast_join(struct net_
                                           &priv->mcast_task,
                                           mcast->backoff * HZ);
                mutex_unlock(&mcast_mutex);
-       } else
-               mcast->query_id = ret;
+       }
 }
 
 void ipoib_mcast_join_task(void *dev_ptr)
 {
        struct net_device *dev = dev_ptr;
        struct ipoib_dev_priv *priv = netdev_priv(dev);
+       struct ipoib_mcast *mcast;
 
        if (!test_bit(IPOIB_MCAST_RUN, &priv->flags))
                return;
@@ -553,36 +537,27 @@ void ipoib_mcast_join_task(void *dev_ptr
                spin_unlock_irq(&priv->lock);
        }
 
-       if (!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
+       if (!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags) &&
+           !test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags)) {
                ipoib_mcast_join(dev, priv->broadcast, 0);
                return;
        }
 
-       while (1) {
-               struct ipoib_mcast *mcast = NULL;
-
-               spin_lock_irq(&priv->lock);
-               list_for_each_entry(mcast, &priv->multicast_list, list) {
-                       if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)
-                           && !test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags)
-                           && !test_bit(IPOIB_MCAST_FLAG_ATTACHED, 
&mcast->flags)) {
-                               /* Found the next unjoined group */
-                               break;
-                       }
-               }
-               spin_unlock_irq(&priv->lock);
-
-               if (&mcast->list == &priv->multicast_list) {
-                       /* All done */
-                       break;
+       spin_lock_irq(&priv->lock);
+       list_for_each_entry(mcast, &priv->multicast_list, list) {
+               if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags) &&
+                   !test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags) &&
+                   !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
+                       /* Found the next unjoined group */
+                       spin_unlock_irq(&priv->lock);
+                       ipoib_mcast_join(dev, mcast, 1);
+                       return;
                }
-
-               ipoib_mcast_join(dev, mcast, 1);
-               return;
        }
+       spin_unlock_irq(&priv->lock);
 
        priv->mcast_mtu = ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu) -
-               IPOIB_ENCAP_LEN;
+                         IPOIB_ENCAP_LEN;
        dev->mtu = min(priv->mcast_mtu, priv->admin_mtu);
 
        ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n");
@@ -609,26 +584,9 @@ int ipoib_mcast_start_thread(struct net_
        return 0;
 }
 
-static void wait_for_mcast_join(struct ipoib_dev_priv *priv,
-                               struct ipoib_mcast *mcast)
-{
-       spin_lock_irq(&priv->lock);
-       if (mcast && mcast->query) {
-               ib_sa_cancel_query(mcast->query_id, mcast->query);
-               mcast->query = NULL;
-               spin_unlock_irq(&priv->lock);
-               ipoib_dbg_mcast(priv, "waiting for MGID " IPOIB_GID_FMT "\n",
-                               IPOIB_GID_ARG(mcast->mcmember.mgid));
-               wait_for_completion(&mcast->done);
-       }
-       else
-               spin_unlock_irq(&priv->lock);
-}
-
-int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
+void ipoib_mcast_stop_thread(struct net_device *dev, int flush)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
-       struct ipoib_mcast *mcast;
 
        ipoib_dbg_mcast(priv, "stopping multicast thread\n");
 
@@ -643,55 +601,26 @@ int ipoib_mcast_stop_thread(struct net_d
 
        if (flush)
                flush_workqueue(ipoib_workqueue);
-
-       wait_for_mcast_join(priv, priv->broadcast);
-
-       list_for_each_entry(mcast, &priv->multicast_list, list)
-               wait_for_mcast_join(priv, mcast);
-
-       return 0;
 }
 
-static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast)
+static void ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast 
*mcast)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
-       struct ib_sa_mcmember_rec rec = {
-               .join_state = 1
-       };
-       int ret = 0;
-
-       if (!test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags))
-               return 0;
-
-       ipoib_dbg_mcast(priv, "leaving MGID " IPOIB_GID_FMT "\n",
-                       IPOIB_GID_ARG(mcast->mcmember.mgid));
-
-       rec.mgid     = mcast->mcmember.mgid;
-       rec.port_gid = priv->local_gid;
-       rec.pkey     = cpu_to_be16(priv->pkey);
+       int ret;
 
-       /* Remove ourselves from the multicast group */
-       ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
-                                &mcast->mcmember.mgid);
-       if (ret)
-               ipoib_warn(priv, "ipoib_mcast_detach failed (result = %d)\n", 
ret);
+       if (test_and_clear_bit(IPOIB_MCAST_FLAG_ATTACHED, &mcast->flags)) {
+               ipoib_dbg_mcast(priv, "leaving MGID " IPOIB_GID_FMT "\n",
+                               IPOIB_GID_ARG(mcast->mcmember.mgid));
 
-       /*
-        * Just make one shot at leaving and don't wait for a reply;
-        * if we fail, too bad.
-        */
-       ret = ib_sa_mcmember_rec_delete(priv->ca, priv->port, &rec,
-                                       IB_SA_MCMEMBER_REC_MGID         |
-                                       IB_SA_MCMEMBER_REC_PORT_GID     |
-                                       IB_SA_MCMEMBER_REC_PKEY         |
-                                       IB_SA_MCMEMBER_REC_JOIN_STATE,
-                                       0, GFP_ATOMIC, NULL,
-                                       mcast, &mcast->query);
-       if (ret < 0)
-               ipoib_warn(priv, "ib_sa_mcmember_rec_delete failed "
-                          "for leave (result = %d)\n", ret);
+               /* Remove ourselves from the multicast group */
+               ret = ipoib_mcast_detach(dev, be16_to_cpu(mcast->mcmember.mlid),
+                                        &mcast->mcmember.mgid);
+               if (ret)
+                       ipoib_warn(priv, "ipoib_mcast_detach failed (result = 
%d)\n", ret);
+       }
 
-       return 0;
+       if (test_and_clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
+               ib_free_multicast(mcast->mc);
 }
 
 void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
@@ -726,7 +655,7 @@ void ipoib_mcast_send(struct net_device 
                                   "multicast structure\n");
                        ++priv->stats.tx_dropped;
                        dev_kfree_skb_any(skb);
-                       goto out;
+                       goto unlock;
                }
 
                set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags);
@@ -743,7 +672,7 @@ void ipoib_mcast_send(struct net_device 
                        dev_kfree_skb_any(skb);
                }
 
-               if (mcast->query)
+               if (test_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags))
                        ipoib_dbg_mcast(priv, "no address vector, "
                                        "but multicast join already started\n");
                else if (test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags))
@@ -753,25 +682,20 @@ void ipoib_mcast_send(struct net_device 
                 * If lookup completes between here and out:, don't
                 * want to send packet twice.
                 */
-               mcast = NULL;
+               goto unlock;
        }
 
-out:
-       if (mcast && mcast->ah) {
-               if (skb->dst            &&
-                   skb->dst->neighbour &&
-                   !*to_ipoib_neigh(skb->dst->neighbour)) {
-                       struct ipoib_neigh *neigh = 
ipoib_neigh_alloc(skb->dst->neighbour);
-
-                       if (neigh) {
-                               kref_get(&mcast->ah->ref);
-                               neigh->ah       = mcast->ah;
-                               list_add_tail(&neigh->list, &mcast->neigh_list);
-                       }
-               }
+       if (skb->dst && skb->dst->neighbour &&
+           !*to_ipoib_neigh(skb->dst->neighbour)) {
+               struct ipoib_neigh *neigh = 
ipoib_neigh_alloc(skb->dst->neighbour);
 
-               ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
+               if (neigh) {
+                       kref_get(&mcast->ah->ref);
+                       neigh->ah = mcast->ah;
+                       list_add_tail(&neigh->list, &mcast->neigh_list);
+               }
        }
+       ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
 
 unlock:
        spin_unlock(&priv->lock);
@@ -900,7 +824,6 @@ void ipoib_mcast_restart_task(void *dev_
 
        /* We have to cancel outside of the spinlock */
        list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
-               wait_for_mcast_join(priv, mcast);
                ipoib_mcast_leave(mcast->dev, mcast);
                ipoib_mcast_free(mcast);
        }
Index: ulp/ipoib/ipoib.h
===================================================================
--- ulp/ipoib/ipoib.h   (revision 6307)
+++ ulp/ipoib/ipoib.h   (working copy)
@@ -283,7 +283,7 @@ void ipoib_mcast_send(struct net_device 
 
 void ipoib_mcast_restart_task(void *dev_ptr);
 int ipoib_mcast_start_thread(struct net_device *dev);
-int ipoib_mcast_stop_thread(struct net_device *dev, int flush);
+void ipoib_mcast_stop_thread(struct net_device *dev, int flush);
 
 void ipoib_mcast_dev_down(struct net_device *dev);
 void ipoib_mcast_dev_flush(struct net_device *dev);

_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to