summaryrefslogtreecommitdiff
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.c117
1 files changed, 39 insertions, 78 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index c33ed87f9dff..98039da0caf0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -43,6 +43,8 @@
#include <linux/delay.h>
#include <linux/completion.h>
+#include <net/dst.h>
+
#include "ipoib.h"
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
@@ -53,7 +55,7 @@ MODULE_PARM_DESC(mcast_debug_level,
"Enable multicast debug tracing if > 0");
#endif
-static DECLARE_MUTEX(mcast_mutex);
+static DEFINE_MUTEX(mcast_mutex);
/* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
struct ipoib_mcast {
@@ -95,8 +97,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_neigh *neigh, *tmp;
unsigned long flags;
- LIST_HEAD(ah_list);
- struct ipoib_ah *ah, *tah;
ipoib_dbg_mcast(netdev_priv(dev),
"deleting multicast group " IPOIB_GID_FMT "\n",
@@ -105,8 +105,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
spin_lock_irqsave(&priv->lock, flags);
list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) {
+ /*
+ * It's safe to call ipoib_put_ah() inside priv->lock
+ * here, because we know that mcast->ah will always
+ * hold one more reference, so ipoib_put_ah() will
+ * never do more than decrement the ref count.
+ */
if (neigh->ah)
- list_add_tail(&neigh->ah->list, &ah_list);
+ ipoib_put_ah(neigh->ah);
*to_ipoib_neigh(neigh->neighbour) = NULL;
neigh->neighbour->ops->destructor = NULL;
kfree(neigh);
@@ -114,9 +120,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
spin_unlock_irqrestore(&priv->lock, flags);
- list_for_each_entry_safe(ah, tah, &ah_list, list)
- ipoib_put_ah(ah);
-
if (mcast->ah)
ipoib_put_ah(mcast->ah);
@@ -135,20 +138,14 @@ static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev,
if (!mcast)
return NULL;
- init_completion(&mcast->done);
-
mcast->dev = dev;
mcast->created = jiffies;
mcast->backoff = 1;
- mcast->logcount = 0;
INIT_LIST_HEAD(&mcast->list);
INIT_LIST_HEAD(&mcast->neigh_list);
skb_queue_head_init(&mcast->pkt_queue);
- mcast->ah = NULL;
- mcast->query = NULL;
-
return mcast;
}
@@ -350,6 +347,8 @@ static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast)
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 |
@@ -386,10 +385,10 @@ static void ipoib_mcast_join_complete(int status,
if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) {
mcast->backoff = 1;
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_work(ipoib_workqueue, &priv->mcast_task);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
complete(&mcast->done);
return;
}
@@ -419,7 +418,7 @@ static void ipoib_mcast_join_complete(int status,
mcast->query = NULL;
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) {
if (status == -ETIMEDOUT)
queue_work(ipoib_workqueue, &priv->mcast_task);
@@ -428,7 +427,7 @@ static void ipoib_mcast_join_complete(int status,
mcast->backoff * HZ);
} else
complete(&mcast->done);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
return;
}
@@ -469,6 +468,8 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
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,
@@ -481,12 +482,12 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast,
if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS)
mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS;
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_delayed_work(ipoib_workqueue,
&priv->mcast_task,
mcast->backoff * HZ);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
} else
mcast->query_id = ret;
}
@@ -519,11 +520,11 @@ void ipoib_mcast_join_task(void *dev_ptr)
priv->broadcast = ipoib_mcast_alloc(dev, 1);
if (!priv->broadcast) {
ipoib_warn(priv, "failed to allocate broadcast group\n");
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (test_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_delayed_work(ipoib_workqueue,
&priv->mcast_task, HZ);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
return;
}
@@ -579,10 +580,10 @@ int ipoib_mcast_start_thread(struct net_device *dev)
ipoib_dbg_mcast(priv, "starting multicast thread\n");
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags))
queue_work(ipoib_workqueue, &priv->mcast_task);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
return 0;
}
@@ -594,10 +595,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush)
ipoib_dbg_mcast(priv, "stopping multicast thread\n");
- down(&mcast_mutex);
+ mutex_lock(&mcast_mutex);
clear_bit(IPOIB_MCAST_RUN, &priv->flags);
cancel_delayed_work(&priv->mcast_task);
- up(&mcast_mutex);
+ mutex_unlock(&mcast_mutex);
if (flush)
flush_workqueue(ipoib_workqueue);
@@ -741,48 +742,23 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
LIST_HEAD(remove_list);
- struct ipoib_mcast *mcast, *tmcast, *nmcast;
+ struct ipoib_mcast *mcast, *tmcast;
unsigned long flags;
ipoib_dbg_mcast(priv, "flushing multicast list\n");
spin_lock_irqsave(&priv->lock, flags);
- list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
- nmcast = ipoib_mcast_alloc(dev, 0);
- if (nmcast) {
- nmcast->flags =
- mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY);
-
- nmcast->mcmember.mgid = mcast->mcmember.mgid;
-
- /* Add the new group in before the to-be-destroyed group */
- list_add_tail(&nmcast->list, &mcast->list);
- list_del_init(&mcast->list);
-
- rb_replace_node(&mcast->rb_node, &nmcast->rb_node,
- &priv->multicast_tree);
- list_add_tail(&mcast->list, &remove_list);
- } else {
- ipoib_warn(priv, "could not reallocate multicast group "
- IPOIB_GID_FMT "\n",
- IPOIB_GID_ARG(mcast->mcmember.mgid));
- }
+ list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) {
+ list_del(&mcast->list);
+ rb_erase(&mcast->rb_node, &priv->multicast_tree);
+ list_add_tail(&mcast->list, &remove_list);
}
if (priv->broadcast) {
- nmcast = ipoib_mcast_alloc(dev, 0);
- if (nmcast) {
- nmcast->mcmember.mgid = priv->broadcast->mcmember.mgid;
-
- rb_replace_node(&priv->broadcast->rb_node,
- &nmcast->rb_node,
- &priv->multicast_tree);
-
- list_add_tail(&priv->broadcast->list, &remove_list);
- }
-
- priv->broadcast = nmcast;
+ rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
+ list_add_tail(&priv->broadcast->list, &remove_list);
+ priv->broadcast = NULL;
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -793,24 +769,6 @@ void ipoib_mcast_dev_flush(struct net_device *dev)
}
}
-void ipoib_mcast_dev_down(struct net_device *dev)
-{
- struct ipoib_dev_priv *priv = netdev_priv(dev);
- unsigned long flags;
-
- /* Delete broadcast since it will be recreated */
- if (priv->broadcast) {
- ipoib_dbg_mcast(priv, "deleting broadcast group\n");
-
- spin_lock_irqsave(&priv->lock, flags);
- rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree);
- spin_unlock_irqrestore(&priv->lock, flags);
- ipoib_mcast_leave(dev, priv->broadcast);
- ipoib_mcast_free(priv->broadcast);
- priv->broadcast = NULL;
- }
-}
-
void ipoib_mcast_restart_task(void *dev_ptr)
{
struct net_device *dev = dev_ptr;
@@ -824,7 +782,8 @@ void ipoib_mcast_restart_task(void *dev_ptr)
ipoib_mcast_stop_thread(dev, 0);
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&dev->xmit_lock, flags);
+ spin_lock(&priv->lock);
/*
* Unfortunately, the networking core only gives us a list of all of
@@ -896,7 +855,9 @@ void ipoib_mcast_restart_task(void *dev_ptr)
list_add_tail(&mcast->list, &remove_list);
}
}
- spin_unlock_irqrestore(&priv->lock, flags);
+
+ spin_unlock(&priv->lock);
+ spin_unlock_irqrestore(&dev->xmit_lock, flags);
/* We have to cancel outside of the spinlock */
list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {