[ewg] [PATCH 2/6] Backport dst->neighbour access helpers from 3.1

Shawn Bohrer sbohrer at rgmadvisors.com
Wed Dec 7 16:56:51 PST 2011


Backport upstream commits

69cce1d1404968f78b177a0314f5822d5afdbbfb
'net: Abstract dst->neighbour accesses behind helpers.'
22cfb0bf6721bb1f865f67bc21e3c36c272faf36
'IPoIB: Fix possible NULL dereference in ipoib_start_xmit()'
580da35a31f91a594f3090b7a2c39b85cb051a12
'IB: Fix RCU lockdep splats'

Signed-off-by: Shawn Bohrer <sbohrer at rgmadvisors.com>
---
 .../backport/3.1/net_0010_skb-dst_accessors.patch  |  149 +++++++
 .../backport/3.1/net_0020_dst_neighbour.patch      |  453 ++++++++++++++++++++
 .../backport/3.1/net_skb-dst_accessors.patch       |  149 -------
 3 files changed, 602 insertions(+), 149 deletions(-)
 create mode 100644 kernel_patches/backport/3.1/net_0010_skb-dst_accessors.patch
 create mode 100644 kernel_patches/backport/3.1/net_0020_dst_neighbour.patch
 delete mode 100644 kernel_patches/backport/3.1/net_skb-dst_accessors.patch

diff --git a/kernel_patches/backport/3.1/net_0010_skb-dst_accessors.patch b/kernel_patches/backport/3.1/net_0010_skb-dst_accessors.patch
new file mode 100644
index 0000000..c742dad
--- /dev/null
+++ b/kernel_patches/backport/3.1/net_0010_skb-dst_accessors.patch
@@ -0,0 +1,149 @@
+From: Sven-Thorsten Dietrich <sdietrich at suse.de>
+Subject: Forward-port new accessor for net: dst.
+
+See Kernel.org:
+commit adf30907d63893e4208dfe3f5c88ae12bc2f25d5
+Author: Eric Dumazet <eric.dumazet at gmail.com>
+Date:   Tue Jun 2 05:19:30 2009 +0000
+Subject: net: skb->dst accessors
+
+Signed-off-by: Sven-Thorsten Dietrich <sdietrich at suse.de>
+--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+@@ -1394,8 +1394,8 @@ void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
+ 	struct ipoib_dev_priv *priv = netdev_priv(dev);
+ 	int e = skb_queue_empty(&priv->cm.skb_queue);
+ 
+-	if (skb->dst)
+-		skb->dst->ops->update_pmtu(skb->dst, mtu);
++	if (skb_dst(skb))
++		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
+ 
+ 	skb_queue_tail(&priv->cm.skb_queue, skb);
+ 	if (e)
+--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
+@@ -561,7 +561,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
+ 	struct ipoib_neigh *neigh;
+ 	unsigned long flags;
+ 
+-	neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev);
++	neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev);
+ 	if (!neigh) {
+ 		++dev->stats.tx_dropped;
+ 		dev_kfree_skb_any(skb);
+@@ -570,9 +570,9 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+-	path = __path_find(dev, skb->dst->neighbour->ha + 4);
++	path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4);
+ 	if (!path) {
+-		path = path_rec_create(dev, skb->dst->neighbour->ha + 4);
++		path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4);
+ 		if (!path)
+ 			goto err_path;
+ 
+@@ -605,7 +605,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
+ 				goto err_drop;
+ 			}
+ 		} else
+-			ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb->dst->neighbour->ha));
++			ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
+ 	} else {
+ 		neigh->ah  = NULL;
+ 
+@@ -635,15 +635,15 @@ static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
+ 	struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
+ 
+ 	/* Look up path record for unicasts */
+-	if (skb->dst->neighbour->ha[4] != 0xff) {
++	if (skb_dst(skb)->neighbour->ha[4] != 0xff) {
+ 		neigh_add_path(skb, dev);
+ 		return;
+ 	}
+ 
+ 	/* Add in the P_Key for multicasts */
+-	skb->dst->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
+-	skb->dst->neighbour->ha[9] = priv->pkey & 0xff;
+-	ipoib_mcast_send(dev, skb->dst->neighbour->ha + 4, skb);
++	skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
++	skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff;
++	ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb);
+ }
+ 
+ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
+@@ -708,16 +708,16 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	struct ipoib_neigh *neigh;
+ 	unsigned long flags;
+ 
+-	if (likely(skb->dst && skb->dst->neighbour)) {
+-		if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) {
++	if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) {
++		if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) {
+ 			ipoib_path_lookup(skb, dev);
+ 			return NETDEV_TX_OK;
+ 		}
+ 
+-		neigh = *to_ipoib_neigh(skb->dst->neighbour);
++		neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour);
+ 
+ 		if (unlikely((memcmp(&neigh->dgid.raw,
+-				     skb->dst->neighbour->ha + 4,
++				     skb_dst(skb)->neighbour->ha + 4,
+ 				     sizeof(union ib_gid))) ||
+ 			     (neigh->dev != dev))) {
+ 			spin_lock_irqsave(&priv->lock, flags);
+@@ -743,7 +743,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 				return NETDEV_TX_OK;
+ 			}
+ 		} else if (neigh->ah) {
+-			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb->dst->neighbour->ha));
++			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
+ 			return NETDEV_TX_OK;
+ 		}
+ 
+@@ -772,7 +772,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 			if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) &&
+ 			    (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) {
+ 				ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n",
+-					   skb->dst ? "neigh" : "dst",
++					   skb_dst(skb) ? "neigh" : "dst",
+ 					   be16_to_cpup((__be16 *) skb->data),
+ 					   IPOIB_QPN(phdr->hwaddr),
+ 					   phdr->hwaddr + 4);
+@@ -817,7 +817,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
+ 	 * destination address onto the front of the skb so we can
+ 	 * figure out where to send the packet later.
+ 	 */
+-	if ((!skb->dst || !skb->dst->neighbour) && daddr) {
++	if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) {
+ 		struct ipoib_pseudoheader *phdr =
+ 			(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
+ 		memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
+--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+@@ -261,7 +261,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
+ 
+ 		skb->dev = dev;
+ 
+-		if (!skb->dst || !skb->dst->neighbour) {
++		if (!skb_dst(skb) || !skb_dst(skb)->neighbour) {
+ 			/* put pseudoheader back on for next time */
+ 			skb_push(skb, sizeof (struct ipoib_pseudoheader));
+ 		}
+@@ -707,10 +707,10 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
+ 
+ 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 (skb_dst(skb)		&&
++		    skb_dst(skb)->neighbour &&
++		    !*to_ipoib_neigh(skb_dst(skb)->neighbour)) {
++			struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour,
+ 									skb->dev);
+ 
+ 			if (neigh) {
diff --git a/kernel_patches/backport/3.1/net_0020_dst_neighbour.patch b/kernel_patches/backport/3.1/net_0020_dst_neighbour.patch
new file mode 100644
index 0000000..c4c3cc9
--- /dev/null
+++ b/kernel_patches/backport/3.1/net_0020_dst_neighbour.patch
@@ -0,0 +1,453 @@
+commit bb7fb8c3f56aeebe027026609c032bd7fab6a3b9
+Author: Shawn Bohrer <sbohrer at berbox6.rgmadvisors.com>
+Date:   Mon Nov 28 16:40:23 2011 -0600
+
+    net backport dst->neighbour helpers
+    
+    Backport kernel.org commit:
+    
+    commit 69cce1d1404968f78b177a0314f5822d5afdbbfb
+    Author: David S. Miller <davem at davemloft.net>
+    Date:   Sun Jul 17 23:09:49 2011 -0700
+    
+        net: Abstract dst->neighbour accesses behind helpers.
+    
+    Signed-off-by: Shawn Bohrer <sbohrer at rgmadvisors.com>
+
+Index: ofed_kernel/drivers/infiniband/core/addr.c
+===================================================================
+--- ofed_kernel.orig/drivers/infiniband/core/addr.c
++++ ofed_kernel/drivers/infiniband/core/addr.c
+@@ -209,7 +209,9 @@ static int addr4_resolve(struct sockaddr
+ 
+ 	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
+ 	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
+-		neigh_event_send(rt->dst.neighbour, NULL);
++		rcu_read_lock();
++		neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
++		rcu_read_unlock();
+ 		ret = -ENODATA;
+ 		if (neigh)
+ 			goto release;
+@@ -266,15 +268,17 @@ static int addr6_resolve(struct sockaddr
+ 		ret = rdma_copy_addr(addr, dst->dev, NULL);
+ 		goto put;
+ 	}
+-	
+-	neigh = dst->neighbour;
++
++	rcu_read_lock();
++	neigh = dst_get_neighbour(dst);
+ 	if (!neigh || !(neigh->nud_state & NUD_VALID)) {
+-		neigh_event_send(dst->neighbour, NULL);
++		if (neigh)
++			neigh_event_send(neigh, NULL);
+ 		ret = -ENODATA;
+-		goto put;
++	} else {
++		ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
+ 	}
+-
+-	ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
++	rcu_read_unlock();
+ put:
+ 	dst_release(dst);
+ 	return ret;
+Index: ofed_kernel/drivers/infiniband/hw/cxgb3/iwch_cm.c
+===================================================================
+--- ofed_kernel.orig/drivers/infiniband/hw/cxgb3/iwch_cm.c
++++ ofed_kernel/drivers/infiniband/hw/cxgb3/iwch_cm.c
+@@ -1351,6 +1351,7 @@ static int pass_accept_req(struct t3cdev
+ 	struct iwch_ep *child_ep, *parent_ep = ctx;
+ 	struct cpl_pass_accept_req *req = cplhdr(skb);
+ 	unsigned int hwtid = GET_TID(req);
++	struct neighbour *neigh;
+ 	struct dst_entry *dst;
+ 	struct l2t_entry *l2t;
+ 	struct rtable *rt;
+@@ -1394,7 +1395,10 @@ static int pass_accept_req(struct t3cdev
+ 		goto reject;
+ 	}
+ 	dst = &rt->dst;
+-	l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev);
++	rcu_read_lock();
++	neigh = dst_get_neighbour(dst);
++	l2t = t3_l2t_get(tdev, neigh, neigh->dev);
++	rcu_read_unlock();
+ 	if (!l2t) {
+ 		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
+ 		       __func__);
+@@ -1904,10 +1908,11 @@ static int is_loopback_dst(struct iw_cm_
+ 
+ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
+ {
+-	int err = 0;
+ 	struct iwch_dev *h = to_iwch_dev(cm_id->device);
++	struct neighbour *neigh;
+ 	struct iwch_ep *ep;
+ 	struct rtable *rt;
++	int err = 0;
+ 
+ 	if (is_loopback_dst(cm_id)) {
+ 		err = -ENOSYS;
+@@ -1963,9 +1968,12 @@ int iwch_connect(struct iw_cm_id *cm_id,
+ 	}
+ 	ep->dst = &rt->dst;
+ 
++	rcu_read_lock();
++	neigh = dst_get_neighbour(ep->dst);
++
+ 	/* get a l2t entry */
+-	ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour,
+-			     ep->dst->neighbour->dev);
++	ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
++	rcu_read_unlock();
+ 	if (!ep->l2t) {
+ 		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
+ 		err = -ENOMEM;
+Index: ofed_kernel/drivers/infiniband/hw/cxgb4/cm.c
+===================================================================
+--- ofed_kernel.orig/drivers/infiniband/hw/cxgb4/cm.c
++++ ofed_kernel/drivers/infiniband/hw/cxgb4/cm.c
+@@ -1585,6 +1585,7 @@ static int pass_accept_req(struct c4iw_d
+ 	unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid));
+ 	struct tid_info *t = dev->rdev.lldi.tids;
+ 	unsigned int hwtid = GET_TID(req);
++	struct neighbour *neigh;
+ 	struct dst_entry *dst;
+ 	struct l2t_entry *l2t;
+ 	struct rtable *rt;
+@@ -1617,11 +1618,12 @@ static int pass_accept_req(struct c4iw_d
+ 		goto reject;
+ 	}
+ 	dst = &rt->dst;
+-	if (dst->neighbour->dev->flags & IFF_LOOPBACK) {
++	rcu_read_lock();
++	neigh = dst_get_neighbour(dst);
++	if (neigh->dev->flags & IFF_LOOPBACK) {
+ 		pdev = ip_dev_find(&init_net, peer_ip);
+ 		BUG_ON(!pdev);
+-		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour,
+-				    pdev, 0);
++		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, pdev, 0);
+ 		mtu = pdev->mtu;
+ 		tx_chan = cxgb4_port_chan(pdev);
+ 		smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+@@ -1632,18 +1634,18 @@ static int pass_accept_req(struct c4iw_d
+ 		rss_qid = dev->rdev.lldi.rxq_ids[cxgb4_port_idx(pdev) * step];
+ 		dev_put(pdev);
+ 	} else {
+-		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour,
+-					dst->neighbour->dev, 0);
++		l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, neigh->dev, 0);
+ 		mtu = dst_mtu(dst);
+-		tx_chan = cxgb4_port_chan(dst->neighbour->dev);
+-		smac_idx = (cxgb4_port_viid(dst->neighbour->dev) & 0x7F) << 1;
++		tx_chan = cxgb4_port_chan(neigh->dev);
++		smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
+ 		step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;
+-		txq_idx = cxgb4_port_idx(dst->neighbour->dev) * step;
+-		ctrlq_idx = cxgb4_port_idx(dst->neighbour->dev);
++		txq_idx = cxgb4_port_idx(neigh->dev) * step;
++		ctrlq_idx = cxgb4_port_idx(neigh->dev);
+ 		step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
+ 		rss_qid = dev->rdev.lldi.rxq_ids[
+-			  cxgb4_port_idx(dst->neighbour->dev) * step];
++			  cxgb4_port_idx(neigh->dev) * step];
+ 	}
++	rcu_read_unlock();
+ 	if (!l2t) {
+ 		printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
+ 		       __func__);
+@@ -2263,6 +2265,7 @@ int c4iw_connect(struct iw_cm_id *cm_id,
+ 	struct c4iw_ep *ep;
+ 	struct rtable *rt;
+ 	struct net_device *pdev;
++	struct neighbour *neigh;
+ 	int step;
+ 
+ 	if ((conn_param->ord > c4iw_max_read_depth) ||
+@@ -2324,14 +2327,16 @@ int c4iw_connect(struct iw_cm_id *cm_id,
+ 	}
+ 	ep->dst = &rt->dst;
+ 
++	rcu_read_lock();
++	neigh = dst_get_neighbour(ep->dst);
++
+ 	/* get a l2t entry */
+-	if (ep->dst->neighbour->dev->flags & IFF_LOOPBACK) {
++	if (neigh->dev->flags & IFF_LOOPBACK) {
+ 		PDBG("%s LOOPBACK\n", __func__);
+ 		pdev = ip_dev_find(&init_net,
+ 				   cm_id->remote_addr.sin_addr.s_addr);
+ 		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+-					ep->dst->neighbour,
+-					pdev, 0);
++					neigh, pdev, 0);
+ 		ep->mtu = pdev->mtu;
+ 		ep->tx_chan = cxgb4_port_chan(pdev);
+ 		ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
+@@ -2346,23 +2351,22 @@ int c4iw_connect(struct iw_cm_id *cm_id,
+ 		dev_put(pdev);
+ 	} else {
+ 		ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
+-					ep->dst->neighbour,
+-					ep->dst->neighbour->dev, 0);
++					neigh, neigh->dev, 0);
+ 		ep->mtu = dst_mtu(ep->dst);
+-		ep->tx_chan = cxgb4_port_chan(ep->dst->neighbour->dev);
+-		ep->smac_idx = (cxgb4_port_viid(ep->dst->neighbour->dev) &
+-				0x7F) << 1;
++		ep->tx_chan = cxgb4_port_chan(neigh->dev);
++		ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
+ 		step = ep->com.dev->rdev.lldi.ntxq /
+ 		       ep->com.dev->rdev.lldi.nchan;
+-		ep->txq_idx = cxgb4_port_idx(ep->dst->neighbour->dev) * step;
+-		ep->ctrlq_idx = cxgb4_port_idx(ep->dst->neighbour->dev);
++		ep->txq_idx = cxgb4_port_idx(neigh->dev) * step;
++		ep->ctrlq_idx = cxgb4_port_idx(neigh->dev);
+ 		step = ep->com.dev->rdev.lldi.nrxq /
+ 		       ep->com.dev->rdev.lldi.nchan;
+ 		ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
+-			      cxgb4_port_idx(ep->dst->neighbour->dev) * step];
++			      cxgb4_port_idx(neigh->dev) * step];
+ 		ep->retry_with_mpa_v1 = 0;
+ 		ep->tried_with_mpa_v1 = 0;
+ 	}
++	rcu_read_unlock();
+ 	if (!ep->l2t) {
+ 		printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
+ 		err = -ENOMEM;
+Index: ofed_kernel/drivers/infiniband/hw/nes/nes_cm.c
+===================================================================
+--- ofed_kernel.orig/drivers/infiniband/hw/nes/nes_cm.c
++++ ofed_kernel/drivers/infiniband/hw/nes/nes_cm.c
+@@ -1373,9 +1373,11 @@ static int nes_addr_resolve_neigh(struct
+ 		neigh_release(neigh);
+ 	}
+ 
+-	if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
+-		neigh_event_send(rt->dst.neighbour, NULL);
+-
++	if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) {
++		rcu_read_lock();
++		neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
++		rcu_read_unlock();
++	}
+ 	ip_rt_put(rt);
+ 	return rc;
+ }
+Index: ofed_kernel/drivers/infiniband/ulp/ipoib/ipoib_main.c
+===================================================================
+--- ofed_kernel.orig/drivers/infiniband/ulp/ipoib/ipoib_main.c
++++ ofed_kernel/drivers/infiniband/ulp/ipoib/ipoib_main.c
+@@ -589,14 +589,17 @@ static int path_rec_start(struct net_dev
+ 	return 0;
+ }
+ 
++/* called with rcu_read_lock */
+ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
+ {
+ 	struct ipoib_dev_priv *priv = netdev_priv(dev);
+ 	struct ipoib_path *path;
+ 	struct ipoib_neigh *neigh;
++	struct neighbour *n;
+ 	unsigned long flags;
+ 
+-	neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev);
++	n = dst_get_neighbour(skb_dst(skb));
++	neigh = ipoib_neigh_alloc(n, skb->dev);
+ 	if (!neigh) {
+ 		++dev->stats.tx_dropped;
+ 		dev_kfree_skb_any(skb);
+@@ -605,9 +608,9 @@ static void neigh_add_path(struct sk_buf
+ 
+ 	spin_lock_irqsave(&priv->lock, flags);
+ 
+-	path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4);
++	path = __path_find(dev, n->ha + 4);
+ 	if (!path) {
+-		path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4);
++		path = path_rec_create(dev, n->ha + 4);
+ 		if (!path)
+ 			goto err_path;
+ 
+@@ -640,7 +643,7 @@ static void neigh_add_path(struct sk_buf
+ 				goto err_drop;
+ 			}
+ 		} else
+-			ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
++			ipoib_send(dev, skb, path->ah, IPOIB_QPN(n->ha));
+ 	} else {
+ 		neigh->ah  = NULL;
+ 
+@@ -665,20 +668,24 @@ err_drop:
+ 	spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ 
++/* called with rcu_read_lock */
+ static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
+ {
+ 	struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
++	struct dst_entry *dst = skb_dst(skb);
++	struct neighbour *n;
+ 
+ 	/* Look up path record for unicasts */
+-	if (skb_dst(skb)->neighbour->ha[4] != 0xff) {
++	n = dst_get_neighbour(dst);
++	if (n->ha[4] != 0xff) {
+ 		neigh_add_path(skb, dev);
+ 		return;
+ 	}
+ 
+ 	/* Add in the P_Key for multicasts */
+-	skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
+-	skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff;
+-	ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb);
++	n->ha[8] = (priv->pkey >> 8) & 0xff;
++	n->ha[9] = priv->pkey & 0xff;
++	ipoib_mcast_send(dev, n->ha + 4, skb);
+ }
+ 
+ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
+@@ -741,18 +748,23 @@ static int ipoib_start_xmit(struct sk_bu
+ {
+ 	struct ipoib_dev_priv *priv = netdev_priv(dev);
+ 	struct ipoib_neigh *neigh;
++	struct neighbour *n = NULL;
+ 	unsigned long flags;
+ 
+-	if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) {
+-		if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) {
++	rcu_read_lock();
++	if (likely(skb_dst(skb)))
++		n = dst_get_neighbour(skb_dst(skb));
++
++	if (likely(n)) {
++		if (unlikely(!*to_ipoib_neigh(n))) {
+ 			ipoib_path_lookup(skb, dev);
+-			return NETDEV_TX_OK;
++			goto unlock;
+ 		}
+ 
+-		neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour);
++		neigh = *to_ipoib_neigh(n);
+ 
+ 		if (unlikely((memcmp(&neigh->dgid.raw,
+-				     skb_dst(skb)->neighbour->ha + 4,
++				     n->ha + 4,
+ 				     sizeof(union ib_gid))) ||
+ 			     (neigh->dev != dev))) {
+ 			spin_lock_irqsave(&priv->lock, flags);
+@@ -769,17 +781,17 @@ static int ipoib_start_xmit(struct sk_bu
+ 			ipoib_neigh_free(dev, neigh);
+ 			spin_unlock_irqrestore(&priv->lock, flags);
+ 			ipoib_path_lookup(skb, dev);
+-			return NETDEV_TX_OK;
++			goto unlock;
+ 		}
+ 
+ 		if (ipoib_cm_get(neigh)) {
+ 			if (ipoib_cm_up(neigh)) {
+ 				ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
+-				return NETDEV_TX_OK;
++				goto unlock;
+ 			}
+ 		} else if (neigh->ah) {
+-			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
+-			return NETDEV_TX_OK;
++			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
++			goto unlock;
+ 		}
+ 
+ 		if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
+@@ -813,13 +825,14 @@ static int ipoib_start_xmit(struct sk_bu
+ 					   phdr->hwaddr + 4);
+ 				dev_kfree_skb_any(skb);
+ 				++dev->stats.tx_dropped;
+-				return NETDEV_TX_OK;
++				goto unlock;
+ 			}
+ 
+ 			unicast_arp_send(skb, dev, phdr);
+ 		}
+ 	}
+-
++unlock:
++	rcu_read_unlock();
+ 	return NETDEV_TX_OK;
+ }
+ 
+@@ -841,6 +854,8 @@ static int ipoib_hard_header(struct sk_b
+ 			     const void *daddr, const void *saddr, unsigned len)
+ {
+ 	struct ipoib_header *header;
++	struct dst_entry *dst;
++	struct neighbour *n;
+ 
+ 	header = (struct ipoib_header *) skb_push(skb, sizeof *header);
+ 
+@@ -852,7 +867,11 @@ static int ipoib_hard_header(struct sk_b
+ 	 * destination address onto the front of the skb so we can
+ 	 * figure out where to send the packet later.
+ 	 */
+-	if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) {
++	dst = skb_dst(skb);
++	n = NULL;
++	if (dst)
++		n = dst_get_neighbour_raw(dst);
++	if ((!dst || !n) && daddr) {
+ 		struct ipoib_pseudoheader *phdr =
+ 			(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
+ 		memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
+Index: ofed_kernel/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+===================================================================
+--- ofed_kernel.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
++++ ofed_kernel/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+@@ -259,11 +259,15 @@ static int ipoib_mcast_join_finish(struc
+ 	netif_tx_lock_bh(dev);
+ 	while (!skb_queue_empty(&mcast->pkt_queue)) {
+ 		struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
++		struct dst_entry *dst = skb_dst(skb);
++		struct neighbour *n = NULL;
++
+ 		netif_tx_unlock_bh(dev);
+ 
+ 		skb->dev = dev;
+-
+-		if (!skb_dst(skb) || !skb_dst(skb)->neighbour) {
++		if (dst)
++			n = dst_get_neighbour_raw(dst);
++		if (!dst || !n) {
+ 			/* put pseudoheader back on for next time */
+ 			skb_push(skb, sizeof (struct ipoib_pseudoheader));
+ 		}
+@@ -754,11 +758,15 @@ void ipoib_mcast_send(struct net_device
+ 
+ out:
+ 	if (mcast && mcast->ah) {
+-		if (skb_dst(skb)		&&
+-		    skb_dst(skb)->neighbour &&
+-		    !*to_ipoib_neigh(skb_dst(skb)->neighbour)) {
+-			struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour,
+-									skb->dev);
++		struct dst_entry *dst = skb_dst(skb);
++		struct neighbour *n = NULL;
++
++		rcu_read_lock();
++		if (dst)
++			n = dst_get_neighbour(dst);
++		if (n && !*to_ipoib_neigh(n)) {
++			struct ipoib_neigh *neigh = ipoib_neigh_alloc(n,
++								      skb->dev);
+ 
+ 			if (neigh) {
+ 				kref_get(&mcast->ah->ref);
+@@ -767,6 +775,7 @@ out:
+ 			}
+ 		}
+ 
++		rcu_read_unlock();
+ 		ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
+ 	}
+ 
diff --git a/kernel_patches/backport/3.1/net_skb-dst_accessors.patch b/kernel_patches/backport/3.1/net_skb-dst_accessors.patch
deleted file mode 100644
index c742dad..0000000
--- a/kernel_patches/backport/3.1/net_skb-dst_accessors.patch
+++ /dev/null
@@ -1,149 +0,0 @@
-From: Sven-Thorsten Dietrich <sdietrich at suse.de>
-Subject: Forward-port new accessor for net: dst.
-
-See Kernel.org:
-commit adf30907d63893e4208dfe3f5c88ae12bc2f25d5
-Author: Eric Dumazet <eric.dumazet at gmail.com>
-Date:   Tue Jun 2 05:19:30 2009 +0000
-Subject: net: skb->dst accessors
-
-Signed-off-by: Sven-Thorsten Dietrich <sdietrich at suse.de>
---- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
-+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
-@@ -1394,8 +1394,8 @@ void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
- 	struct ipoib_dev_priv *priv = netdev_priv(dev);
- 	int e = skb_queue_empty(&priv->cm.skb_queue);
- 
--	if (skb->dst)
--		skb->dst->ops->update_pmtu(skb->dst, mtu);
-+	if (skb_dst(skb))
-+		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
- 
- 	skb_queue_tail(&priv->cm.skb_queue, skb);
- 	if (e)
---- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
-+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
-@@ -561,7 +561,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
- 	struct ipoib_neigh *neigh;
- 	unsigned long flags;
- 
--	neigh = ipoib_neigh_alloc(skb->dst->neighbour, skb->dev);
-+	neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev);
- 	if (!neigh) {
- 		++dev->stats.tx_dropped;
- 		dev_kfree_skb_any(skb);
-@@ -570,9 +570,9 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
- 
- 	spin_lock_irqsave(&priv->lock, flags);
- 
--	path = __path_find(dev, skb->dst->neighbour->ha + 4);
-+	path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4);
- 	if (!path) {
--		path = path_rec_create(dev, skb->dst->neighbour->ha + 4);
-+		path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4);
- 		if (!path)
- 			goto err_path;
- 
-@@ -605,7 +605,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
- 				goto err_drop;
- 			}
- 		} else
--			ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb->dst->neighbour->ha));
-+			ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
- 	} else {
- 		neigh->ah  = NULL;
- 
-@@ -635,15 +635,15 @@ static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
- 	struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
- 
- 	/* Look up path record for unicasts */
--	if (skb->dst->neighbour->ha[4] != 0xff) {
-+	if (skb_dst(skb)->neighbour->ha[4] != 0xff) {
- 		neigh_add_path(skb, dev);
- 		return;
- 	}
- 
- 	/* Add in the P_Key for multicasts */
--	skb->dst->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
--	skb->dst->neighbour->ha[9] = priv->pkey & 0xff;
--	ipoib_mcast_send(dev, skb->dst->neighbour->ha + 4, skb);
-+	skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
-+	skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff;
-+	ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb);
- }
- 
- static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
-@@ -708,16 +708,16 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
- 	struct ipoib_neigh *neigh;
- 	unsigned long flags;
- 
--	if (likely(skb->dst && skb->dst->neighbour)) {
--		if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) {
-+	if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) {
-+		if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) {
- 			ipoib_path_lookup(skb, dev);
- 			return NETDEV_TX_OK;
- 		}
- 
--		neigh = *to_ipoib_neigh(skb->dst->neighbour);
-+		neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour);
- 
- 		if (unlikely((memcmp(&neigh->dgid.raw,
--				     skb->dst->neighbour->ha + 4,
-+				     skb_dst(skb)->neighbour->ha + 4,
- 				     sizeof(union ib_gid))) ||
- 			     (neigh->dev != dev))) {
- 			spin_lock_irqsave(&priv->lock, flags);
-@@ -743,7 +743,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
- 				return NETDEV_TX_OK;
- 			}
- 		} else if (neigh->ah) {
--			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb->dst->neighbour->ha));
-+			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
- 			return NETDEV_TX_OK;
- 		}
- 
-@@ -772,7 +772,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
- 			if ((be16_to_cpup((__be16 *) skb->data) != ETH_P_ARP) &&
- 			    (be16_to_cpup((__be16 *) skb->data) != ETH_P_RARP)) {
- 				ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n",
--					   skb->dst ? "neigh" : "dst",
-+					   skb_dst(skb) ? "neigh" : "dst",
- 					   be16_to_cpup((__be16 *) skb->data),
- 					   IPOIB_QPN(phdr->hwaddr),
- 					   phdr->hwaddr + 4);
-@@ -817,7 +817,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
- 	 * destination address onto the front of the skb so we can
- 	 * figure out where to send the packet later.
- 	 */
--	if ((!skb->dst || !skb->dst->neighbour) && daddr) {
-+	if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) {
- 		struct ipoib_pseudoheader *phdr =
- 			(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
- 		memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
---- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
-+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
-@@ -261,7 +261,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
- 
- 		skb->dev = dev;
- 
--		if (!skb->dst || !skb->dst->neighbour) {
-+		if (!skb_dst(skb) || !skb_dst(skb)->neighbour) {
- 			/* put pseudoheader back on for next time */
- 			skb_push(skb, sizeof (struct ipoib_pseudoheader));
- 		}
-@@ -707,10 +707,10 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
- 
- 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 (skb_dst(skb)		&&
-+		    skb_dst(skb)->neighbour &&
-+		    !*to_ipoib_neigh(skb_dst(skb)->neighbour)) {
-+			struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour,
- 									skb->dev);
- 
- 			if (neigh) {
-- 
1.7.6



---------------------------------------------------------------
This email, along with any attachments, is confidential. If you 
believe you received this message in error, please contact the 
sender immediately and delete all copies of the message.  
Thank you.




More information about the ewg mailing list