diff options
Diffstat (limited to 'drivers/infiniband/ulp/ipoib')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib.h | 6 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_ib.c | 31 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_main.c | 25 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 117 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_verbs.c | 8 | ||||
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_vlan.c | 10 |
6 files changed, 78 insertions, 119 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 9923a15a9996..e0a5412b7e68 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -45,11 +45,11 @@ #include <linux/config.h> #include <linux/kref.h> #include <linux/if_infiniband.h> +#include <linux/mutex.h> #include <net/neighbour.h> #include <asm/atomic.h> -#include <asm/semaphore.h> #include <rdma/ib_verbs.h> #include <rdma/ib_pack.h> @@ -123,8 +123,8 @@ struct ipoib_dev_priv { unsigned long flags; - struct semaphore mcast_mutex; - struct semaphore vlan_mutex; + struct mutex mcast_mutex; + struct mutex vlan_mutex; struct rb_root path_tree; struct list_head path_list; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 54ef2fea530f..86bcdd72a107 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -52,7 +52,7 @@ MODULE_PARM_DESC(data_debug_level, #define IPOIB_OP_RECV (1ul << 31) -static DECLARE_MUTEX(pkey_sem); +static DEFINE_MUTEX(pkey_mutex); struct ipoib_ah *ipoib_create_ah(struct net_device *dev, struct ib_pd *pd, struct ib_ah_attr *attr) @@ -445,25 +445,16 @@ int ipoib_ib_dev_down(struct net_device *dev) /* Shutdown the P_Key thread if still active */ if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { - down(&pkey_sem); + mutex_lock(&pkey_mutex); set_bit(IPOIB_PKEY_STOP, &priv->flags); cancel_delayed_work(&priv->pkey_task); - up(&pkey_sem); + mutex_unlock(&pkey_mutex); flush_workqueue(ipoib_workqueue); } ipoib_mcast_stop_thread(dev, 1); - - /* - * Flush the multicast groups first so we stop any multicast joins. The - * completion thread may have already died and we may deadlock waiting - * for the completion thread to finish some multicast joins. - */ ipoib_mcast_dev_flush(dev); - /* Delete broadcast and local addresses since they will be recreated */ - ipoib_mcast_dev_down(dev); - ipoib_flush_paths(dev); return 0; @@ -608,9 +599,13 @@ void ipoib_ib_dev_flush(void *_dev) if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) ipoib_ib_dev_up(dev); + mutex_lock(&priv->vlan_mutex); + /* Flush any child interfaces too */ list_for_each_entry(cpriv, &priv->child_intfs, list) ipoib_ib_dev_flush(&cpriv->dev); + + mutex_unlock(&priv->vlan_mutex); } void ipoib_ib_dev_cleanup(struct net_device *dev) @@ -620,9 +615,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) ipoib_dbg(priv, "cleaning up ib_dev\n"); ipoib_mcast_stop_thread(dev, 1); - - /* Delete the broadcast address and the local address */ - ipoib_mcast_dev_down(dev); + ipoib_mcast_dev_flush(dev); ipoib_transport_dev_cleanup(dev); } @@ -658,12 +651,12 @@ void ipoib_pkey_poll(void *dev_ptr) if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) ipoib_open(dev); else { - down(&pkey_sem); + mutex_lock(&pkey_mutex); if (!test_bit(IPOIB_PKEY_STOP, &priv->flags)) queue_delayed_work(ipoib_workqueue, &priv->pkey_task, HZ); - up(&pkey_sem); + mutex_unlock(&pkey_mutex); } } @@ -677,12 +670,12 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev) /* P_Key value not assigned yet - start polling */ if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { - down(&pkey_sem); + mutex_lock(&pkey_mutex); clear_bit(IPOIB_PKEY_STOP, &priv->flags); queue_delayed_work(ipoib_workqueue, &priv->pkey_task, HZ); - up(&pkey_sem); + mutex_unlock(&pkey_mutex); return 1; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 2fa30751f362..fd3f5c862a5d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -47,6 +47,8 @@ #include <linux/ip.h> #include <linux/in.h> +#include <net/dst.h> + MODULE_AUTHOR("Roland Dreier"); MODULE_DESCRIPTION("IP-over-InfiniBand net driver"); MODULE_LICENSE("Dual BSD/GPL"); @@ -94,14 +96,16 @@ int ipoib_open(struct net_device *dev) if (ipoib_ib_dev_open(dev)) return -EINVAL; - if (ipoib_ib_dev_up(dev)) + if (ipoib_ib_dev_up(dev)) { + ipoib_ib_dev_stop(dev); return -EINVAL; + } if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { struct ipoib_dev_priv *cpriv; /* Bring up any child interfaces too */ - down(&priv->vlan_mutex); + mutex_lock(&priv->vlan_mutex); list_for_each_entry(cpriv, &priv->child_intfs, list) { int flags; @@ -111,7 +115,7 @@ int ipoib_open(struct net_device *dev) dev_change_flags(cpriv->dev, flags | IFF_UP); } - up(&priv->vlan_mutex); + mutex_unlock(&priv->vlan_mutex); } netif_start_queue(dev); @@ -136,7 +140,7 @@ static int ipoib_stop(struct net_device *dev) struct ipoib_dev_priv *cpriv; /* Bring down any child interfaces too */ - down(&priv->vlan_mutex); + mutex_lock(&priv->vlan_mutex); list_for_each_entry(cpriv, &priv->child_intfs, list) { int flags; @@ -146,7 +150,7 @@ static int ipoib_stop(struct net_device *dev) dev_change_flags(cpriv->dev, flags & ~IFF_UP); } - up(&priv->vlan_mutex); + mutex_unlock(&priv->vlan_mutex); } return 0; @@ -398,9 +402,9 @@ static void path_rec_completion(int status, while ((skb = __skb_dequeue(&neigh->queue))) __skb_queue_tail(&skqueue, skb); } - } else - path->query = NULL; + } + path->query = NULL; complete(&path->done); spin_unlock_irqrestore(&priv->lock, flags); @@ -428,7 +432,6 @@ static struct ipoib_path *path_rec_create(struct net_device *dev, skb_queue_head_init(&path->queue); INIT_LIST_HEAD(&path->neigh_list); - init_completion(&path->done); memcpy(path->pathrec.dgid.raw, gid->raw, sizeof (union ib_gid)); path->pathrec.sgid = priv->local_gid; @@ -446,6 +449,8 @@ static int path_rec_start(struct net_device *dev, ipoib_dbg(priv, "Start path record lookup for " IPOIB_GID_FMT "\n", IPOIB_GID_ARG(path->pathrec.dgid)); + init_completion(&path->done); + path->query_id = ib_sa_path_rec_get(priv->ca, priv->port, &path->pathrec, @@ -887,8 +892,8 @@ static void ipoib_setup(struct net_device *dev) spin_lock_init(&priv->lock); spin_lock_init(&priv->tx_lock); - init_MUTEX(&priv->mcast_mutex); - init_MUTEX(&priv->vlan_mutex); + mutex_init(&priv->mcast_mutex); + mutex_init(&priv->vlan_mutex); INIT_LIST_HEAD(&priv->path_list); INIT_LIST_HEAD(&priv->child_intfs); 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) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index e829e10400e3..faaf10e5fc7b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c @@ -65,9 +65,9 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid) } /* attach QP to multicast group */ - down(&priv->mcast_mutex); + mutex_lock(&priv->mcast_mutex); ret = ib_attach_mcast(priv->qp, mgid, mlid); - up(&priv->mcast_mutex); + mutex_unlock(&priv->mcast_mutex); if (ret) ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret); @@ -81,9 +81,9 @@ int ipoib_mcast_detach(struct net_device *dev, u16 mlid, union ib_gid *mgid) struct ipoib_dev_priv *priv = netdev_priv(dev); int ret; - down(&priv->mcast_mutex); + mutex_lock(&priv->mcast_mutex); ret = ib_detach_mcast(priv->qp, mgid, mlid); - up(&priv->mcast_mutex); + mutex_unlock(&priv->mcast_mutex); if (ret) ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index d280b341a37f..4ca175553f9f 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c @@ -63,7 +63,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) ppriv = netdev_priv(pdev); - down(&ppriv->vlan_mutex); + mutex_lock(&ppriv->vlan_mutex); /* * First ensure this isn't a duplicate. We check the parent device and @@ -124,7 +124,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) list_add_tail(&priv->list, &ppriv->child_intfs); - up(&ppriv->vlan_mutex); + mutex_unlock(&ppriv->vlan_mutex); return 0; @@ -139,7 +139,7 @@ device_init_failed: free_netdev(priv->dev); err: - up(&ppriv->vlan_mutex); + mutex_unlock(&ppriv->vlan_mutex); return result; } @@ -153,7 +153,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) ppriv = netdev_priv(pdev); - down(&ppriv->vlan_mutex); + mutex_lock(&ppriv->vlan_mutex); list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { if (priv->pkey == pkey) { unregister_netdev(priv->dev); @@ -167,7 +167,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) break; } } - up(&ppriv->vlan_mutex); + mutex_unlock(&ppriv->vlan_mutex); return ret; } |