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
