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