Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=732a2170f499ce7cf5f0bdd4f9e0b0c8337b67e1
Commit:     732a2170f499ce7cf5f0bdd4f9e0b0c8337b67e1
Parent:     a8a935dae5de65a8f5a5371a58ad2aa73a0ea2da
Author:     Moni Shoua <[EMAIL PROTECTED]>
AuthorDate: Tue Oct 9 19:43:36 2007 -0700
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Mon Oct 15 14:20:45 2007 -0400

    IB/ipoib: Bound the net device to the ipoib_neigh structue
    
    IPoIB uses a two layer neighboring scheme, such that for each struct 
neighbour
    whose device is an ipoib one, there is a struct ipoib_neigh buddy which is
    created on demand at the tx flow by an 
ipoib_neigh_alloc(skb->dst->neighbour)
    call.
    
    When using the bonding driver, neighbours are created by the net stack on 
behalf
    of the bonding (master) device. On the tx flow the bonding code gets an skb 
such
    that skb->dev points to the master device, it changes this skb to point on 
the
    slave device and calls the slave hard_start_xmit function.
    
    Under this scheme, ipoib_neigh_destructor assumption that for each struct
    neighbour it gets, n->dev is an ipoib device and hence netdev_priv(n->dev)
    can be casted to struct ipoib_dev_priv is buggy.
    
    To fix it, this patch adds a dev field to struct ipoib_neigh which is used
    instead of the struct neighbour dev one, when n->dev->flags has the
    IFF_MASTER bit set.
    
    Signed-off-by: Moni Shoua <monis at voltaire.com>
    Signed-off-by: Or Gerlitz <ogerlitz at voltaire.com>
    Acked-by: Roland Dreier <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/infiniband/ulp/ipoib/ipoib.h           |    4 +++-
 drivers/infiniband/ulp/ipoib/ipoib_main.c      |   24 +++++++++++++++---------
 drivers/infiniband/ulp/ipoib/ipoib_multicast.c |    3 ++-
 3 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h 
b/drivers/infiniband/ulp/ipoib/ipoib.h
index 6545fa7..1b3327a 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -349,6 +349,7 @@ struct ipoib_neigh {
        struct sk_buff_head queue;
 
        struct neighbour   *neighbour;
+       struct net_device *dev;
 
        struct list_head    list;
 };
@@ -365,7 +366,8 @@ static inline struct ipoib_neigh **to_ipoib_neigh(struct 
neighbour *neigh)
                                     INFINIBAND_ALEN, sizeof(void *));
 }
 
-struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh);
+struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh,
+                                     struct net_device *dev);
 void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh);
 
 extern struct workqueue_struct *ipoib_workqueue;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c 
b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index e072f3c..cae026c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -517,7 +517,7 @@ static void neigh_add_path(struct sk_buff *skb, struct 
net_device *dev)
        struct ipoib_path *path;
        struct ipoib_neigh *neigh;
 
-       neigh = ipoib_neigh_alloc(skb->dst->neighbour);
+       neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev);
        if (!neigh) {
                ++dev->stats.tx_dropped;
                dev_kfree_skb_any(skb);
@@ -817,6 +817,13 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
        unsigned long flags;
        struct ipoib_ah *ah = NULL;
 
+       neigh = *to_ipoib_neigh(n);
+       if (neigh) {
+               priv = netdev_priv(neigh->dev);
+               ipoib_dbg(priv, "neigh_destructor for bonding device: %s\n",
+                         n->dev->name);
+       } else
+               return;
        ipoib_dbg(priv,
                  "neigh_cleanup for %06x " IPOIB_GID_FMT "\n",
                  IPOIB_QPN(n->ha),
@@ -824,13 +831,10 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       neigh = *to_ipoib_neigh(n);
-       if (neigh) {
-               if (neigh->ah)
-                       ah = neigh->ah;
-               list_del(&neigh->list);
-               ipoib_neigh_free(n->dev, neigh);
-       }
+       if (neigh->ah)
+               ah = neigh->ah;
+       list_del(&neigh->list);
+       ipoib_neigh_free(n->dev, neigh);
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
@@ -838,7 +842,8 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
                ipoib_put_ah(ah);
 }
 
-struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour)
+struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour,
+                                     struct net_device *dev)
 {
        struct ipoib_neigh *neigh;
 
@@ -847,6 +852,7 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour 
*neighbour)
                return NULL;
 
        neigh->neighbour = neighbour;
+       neigh->dev = dev;
        *to_ipoib_neigh(neighbour) = neigh;
        skb_queue_head_init(&neigh->queue);
        ipoib_cm_set(neigh, NULL);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 
b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 827820e..9bcfc7a 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -705,7 +705,8 @@ out:
                if (skb->dst            &&
                    skb->dst->neighbour &&
                    !*to_ipoib_neigh(skb->dst->neighbour)) {
-                       struct ipoib_neigh *neigh = 
ipoib_neigh_alloc(skb->dst->neighbour);
+                       struct ipoib_neigh *neigh = 
ipoib_neigh_alloc(skb->dst->neighbour,
+                                                                       
skb->dev);
 
                        if (neigh) {
                                kref_get(&mcast->ah->ref);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to