Because ipoib_workqueue is not flushed when ipoib interface is brought down,
ipoib_mcast_join() may trigger a join to the broadcast group after 
priv->broadcast
was set to NULL (during cleanup). This will cause ipoib to be joined to the
broadcast group when interface is down.
As a side effect, this breaks the optimization of setting qkey only when joining
the broadcast group.

Signed-off-by: Yossi Etigin <[email protected]>

--

Changes from v1:
- Put checks in places where was assumed priv->broadcast != NULL.

Changes from v2:
- Put a lock around the NULL check in ipoib_mcast_join_task.

Fix bugzilla 1370.

---
drivers/infiniband/ulp/ipoib/ipoib_multicast.c |   16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)

Index: b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
===================================================================
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c    2008-12-31 
09:56:22.000000000 +0200
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c    2008-12-31 
09:57:13.000000000 +0200
@@ -502,7 +502,7 @@ static void ipoib_mcast_join(struct net_
                IB_SA_MCMEMBER_REC_PKEY         |
                IB_SA_MCMEMBER_REC_JOIN_STATE;

-       if (create) {
+       if (create && priv->broadcast) {
                comp_mask |=
                        IB_SA_MCMEMBER_REC_QKEY                 |
                        IB_SA_MCMEMBER_REC_MTU_SELECTOR         |
@@ -570,7 +570,8 @@ void ipoib_mcast_join_task(struct work_s
                        ipoib_warn(priv, "ib_query_port failed\n");
        }

-       if (!priv->broadcast) {
+       rtnl_lock();
+       if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags) && !priv->broadcast) {
                struct ipoib_mcast *broadcast;

                broadcast = ipoib_mcast_alloc(dev, 1);
@@ -581,6 +582,7 @@ void ipoib_mcast_join_task(struct work_s
                                queue_delayed_work(ipoib_workqueue,
                                                   &priv->mcast_join_task, HZ);
                        mutex_unlock(&mcast_mutex);
+                       rtnl_unlock();
                        return;
                }

@@ -592,12 +594,17 @@ void ipoib_mcast_join_task(struct work_s
                __ipoib_mcast_add(dev, priv->broadcast);
                spin_unlock_irq(&priv->lock);
        }
+       rtnl_unlock();

-       if (!test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
+       spin_lock_irq(&priv->lock);
+       if (priv->broadcast &&
+           !test_bit(IPOIB_MCAST_FLAG_ATTACHED, &priv->broadcast->flags)) {
                if (!test_bit(IPOIB_MCAST_FLAG_BUSY, &priv->broadcast->flags))
                        ipoib_mcast_join(dev, priv->broadcast, 0);
+               spin_unlock_irq(&priv->lock);
                return;
        }
+       spin_unlock_irq(&priv->lock);

        while (1) {
                struct ipoib_mcast *mcast = NULL;
@@ -622,7 +629,8 @@ void ipoib_mcast_join_task(struct work_s
                return;
        }

-       priv->mcast_mtu = 
IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
+       if (priv->broadcast)
+               priv->mcast_mtu = 
IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));

        if (!ipoib_cm_admin_enabled(dev)) {
                rtnl_lock();

--
--Yossi
_______________________________________________
general mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

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

Reply via email to