aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2012-02-09 16:13:19 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-02-13 14:06:13 -0500
commit8a533666d1591cf4ea596c6bd710e2fe682cb56a (patch)
tree0c525703fd834499c659490b3cb38835fde14f51 /drivers/infiniband
parent323a479328cbc2fb5cf647790f7414ca570a577b (diff)
net: fix NULL dereferences in check_peer_redir()
[ Upstream commit d3aaeb38c40e5a6c08dd31a1b64da65c4352be36, along with dependent backports of commits: 69cce1d1404968f78b177a0314f5822d5afdbbfb 9de79c127cccecb11ae6a21ab1499e87aa222880 218fa90f072e4aeff9003d57e390857f4f35513e 580da35a31f91a594f3090b7a2c39b85cb051a12 f7e57044eeb1841847c24aa06766c8290c202583 e049f28883126c689cf95859480d9ee4ab23b7fa ] Gergely Kalman reported crashes in check_peer_redir(). It appears commit f39925dbde778 (ipv4: Cache learned redirect information in inetpeer.) added a race, leading to possible NULL ptr dereference. Since we can now change dst neighbour, we should make sure a reader can safely use a neighbour. Add RCU protection to dst neighbour, and make sure check_peer_redir() can be called safely by different cpus in parallel. As neighbours are already freed after one RCU grace period, this patch should not add typical RCU penalty (cache cold effects) Many thanks to Gergely for providing a pretty report pointing to the bug. Reported-by: Gergely Kalman <synapse@hippy.csoma.elte.hu> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/addr.c16
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c16
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c46
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c2
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c8
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c59
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c24
7 files changed, 108 insertions, 63 deletions
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 8e21d457b89..f2a84c6f854 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -215,7 +215,9 @@ static int addr4_resolve(struct sockaddr_in *src_in,
215 215
216 neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev); 216 neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
217 if (!neigh || !(neigh->nud_state & NUD_VALID)) { 217 if (!neigh || !(neigh->nud_state & NUD_VALID)) {
218 neigh_event_send(rt->dst.neighbour, NULL); 218 rcu_read_lock();
219 neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
220 rcu_read_unlock();
219 ret = -ENODATA; 221 ret = -ENODATA;
220 if (neigh) 222 if (neigh)
221 goto release; 223 goto release;
@@ -273,14 +275,16 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
273 goto put; 275 goto put;
274 } 276 }
275 277
276 neigh = dst->neighbour; 278 rcu_read_lock();
279 neigh = dst_get_neighbour(dst);
277 if (!neigh || !(neigh->nud_state & NUD_VALID)) { 280 if (!neigh || !(neigh->nud_state & NUD_VALID)) {
278 neigh_event_send(dst->neighbour, NULL); 281 if (neigh)
282 neigh_event_send(neigh, NULL);
279 ret = -ENODATA; 283 ret = -ENODATA;
280 goto put; 284 } else {
285 ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
281 } 286 }
282 287 rcu_read_unlock();
283 ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
284put: 288put:
285 dst_release(dst); 289 dst_release(dst);
286 return ret; 290 return ret;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 2332dc22aa0..e55ce7a428b 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1328,6 +1328,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1328 struct iwch_ep *child_ep, *parent_ep = ctx; 1328 struct iwch_ep *child_ep, *parent_ep = ctx;
1329 struct cpl_pass_accept_req *req = cplhdr(skb); 1329 struct cpl_pass_accept_req *req = cplhdr(skb);
1330 unsigned int hwtid = GET_TID(req); 1330 unsigned int hwtid = GET_TID(req);
1331 struct neighbour *neigh;
1331 struct dst_entry *dst; 1332 struct dst_entry *dst;
1332 struct l2t_entry *l2t; 1333 struct l2t_entry *l2t;
1333 struct rtable *rt; 1334 struct rtable *rt;
@@ -1364,7 +1365,10 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
1364 goto reject; 1365 goto reject;
1365 } 1366 }
1366 dst = &rt->dst; 1367 dst = &rt->dst;
1367 l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev); 1368 rcu_read_lock();
1369 neigh = dst_get_neighbour(dst);
1370 l2t = t3_l2t_get(tdev, neigh, neigh->dev);
1371 rcu_read_unlock();
1368 if (!l2t) { 1372 if (!l2t) {
1369 printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", 1373 printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
1370 __func__); 1374 __func__);
@@ -1874,10 +1878,11 @@ static int is_loopback_dst(struct iw_cm_id *cm_id)
1874 1878
1875int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) 1879int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
1876{ 1880{
1877 int err = 0;
1878 struct iwch_dev *h = to_iwch_dev(cm_id->device); 1881 struct iwch_dev *h = to_iwch_dev(cm_id->device);
1882 struct neighbour *neigh;
1879 struct iwch_ep *ep; 1883 struct iwch_ep *ep;
1880 struct rtable *rt; 1884 struct rtable *rt;
1885 int err = 0;
1881 1886
1882 if (is_loopback_dst(cm_id)) { 1887 if (is_loopback_dst(cm_id)) {
1883 err = -ENOSYS; 1888 err = -ENOSYS;
@@ -1933,9 +1938,12 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
1933 } 1938 }
1934 ep->dst = &rt->dst; 1939 ep->dst = &rt->dst;
1935 1940
1941 rcu_read_lock();
1942 neigh = dst_get_neighbour(ep->dst);
1943
1936 /* get a l2t entry */ 1944 /* get a l2t entry */
1937 ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour, 1945 ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
1938 ep->dst->neighbour->dev); 1946 rcu_read_unlock();
1939 if (!ep->l2t) { 1947 if (!ep->l2t) {
1940 printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); 1948 printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
1941 err = -ENOMEM; 1949 err = -ENOMEM;
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 31fb44085c9..daa93e942e1 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -1325,6 +1325,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
1325 unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid)); 1325 unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid));
1326 struct tid_info *t = dev->rdev.lldi.tids; 1326 struct tid_info *t = dev->rdev.lldi.tids;
1327 unsigned int hwtid = GET_TID(req); 1327 unsigned int hwtid = GET_TID(req);
1328 struct neighbour *neigh;
1328 struct dst_entry *dst; 1329 struct dst_entry *dst;
1329 struct l2t_entry *l2t; 1330 struct l2t_entry *l2t;
1330 struct rtable *rt; 1331 struct rtable *rt;
@@ -1357,11 +1358,12 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
1357 goto reject; 1358 goto reject;
1358 } 1359 }
1359 dst = &rt->dst; 1360 dst = &rt->dst;
1360 if (dst->neighbour->dev->flags & IFF_LOOPBACK) { 1361 rcu_read_lock();
1362 neigh = dst_get_neighbour(dst);
1363 if (neigh->dev->flags & IFF_LOOPBACK) {
1361 pdev = ip_dev_find(&init_net, peer_ip); 1364 pdev = ip_dev_find(&init_net, peer_ip);
1362 BUG_ON(!pdev); 1365 BUG_ON(!pdev);
1363 l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour, 1366 l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, pdev, 0);
1364 pdev, 0);
1365 mtu = pdev->mtu; 1367 mtu = pdev->mtu;
1366 tx_chan = cxgb4_port_chan(pdev); 1368 tx_chan = cxgb4_port_chan(pdev);
1367 smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; 1369 smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
@@ -1372,18 +1374,18 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
1372 rss_qid = dev->rdev.lldi.rxq_ids[cxgb4_port_idx(pdev) * step]; 1374 rss_qid = dev->rdev.lldi.rxq_ids[cxgb4_port_idx(pdev) * step];
1373 dev_put(pdev); 1375 dev_put(pdev);
1374 } else { 1376 } else {
1375 l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour, 1377 l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, neigh->dev, 0);
1376 dst->neighbour->dev, 0);
1377 mtu = dst_mtu(dst); 1378 mtu = dst_mtu(dst);
1378 tx_chan = cxgb4_port_chan(dst->neighbour->dev); 1379 tx_chan = cxgb4_port_chan(neigh->dev);
1379 smac_idx = (cxgb4_port_viid(dst->neighbour->dev) & 0x7F) << 1; 1380 smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
1380 step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan; 1381 step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;
1381 txq_idx = cxgb4_port_idx(dst->neighbour->dev) * step; 1382 txq_idx = cxgb4_port_idx(neigh->dev) * step;
1382 ctrlq_idx = cxgb4_port_idx(dst->neighbour->dev); 1383 ctrlq_idx = cxgb4_port_idx(neigh->dev);
1383 step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan; 1384 step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
1384 rss_qid = dev->rdev.lldi.rxq_ids[ 1385 rss_qid = dev->rdev.lldi.rxq_ids[
1385 cxgb4_port_idx(dst->neighbour->dev) * step]; 1386 cxgb4_port_idx(neigh->dev) * step];
1386 } 1387 }
1388 rcu_read_unlock();
1387 if (!l2t) { 1389 if (!l2t) {
1388 printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", 1390 printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
1389 __func__); 1391 __func__);
@@ -1847,6 +1849,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
1847 struct c4iw_ep *ep; 1849 struct c4iw_ep *ep;
1848 struct rtable *rt; 1850 struct rtable *rt;
1849 struct net_device *pdev; 1851 struct net_device *pdev;
1852 struct neighbour *neigh;
1850 int step; 1853 int step;
1851 1854
1852 if ((conn_param->ord > c4iw_max_read_depth) || 1855 if ((conn_param->ord > c4iw_max_read_depth) ||
@@ -1908,14 +1911,16 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
1908 } 1911 }
1909 ep->dst = &rt->dst; 1912 ep->dst = &rt->dst;
1910 1913
1914 rcu_read_lock();
1915 neigh = dst_get_neighbour(ep->dst);
1916
1911 /* get a l2t entry */ 1917 /* get a l2t entry */
1912 if (ep->dst->neighbour->dev->flags & IFF_LOOPBACK) { 1918 if (neigh->dev->flags & IFF_LOOPBACK) {
1913 PDBG("%s LOOPBACK\n", __func__); 1919 PDBG("%s LOOPBACK\n", __func__);
1914 pdev = ip_dev_find(&init_net, 1920 pdev = ip_dev_find(&init_net,
1915 cm_id->remote_addr.sin_addr.s_addr); 1921 cm_id->remote_addr.sin_addr.s_addr);
1916 ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t, 1922 ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
1917 ep->dst->neighbour, 1923 neigh, pdev, 0);
1918 pdev, 0);
1919 ep->mtu = pdev->mtu; 1924 ep->mtu = pdev->mtu;
1920 ep->tx_chan = cxgb4_port_chan(pdev); 1925 ep->tx_chan = cxgb4_port_chan(pdev);
1921 ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1; 1926 ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
@@ -1930,21 +1935,20 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
1930 dev_put(pdev); 1935 dev_put(pdev);
1931 } else { 1936 } else {
1932 ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t, 1937 ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
1933 ep->dst->neighbour, 1938 neigh, neigh->dev, 0);
1934 ep->dst->neighbour->dev, 0);
1935 ep->mtu = dst_mtu(ep->dst); 1939 ep->mtu = dst_mtu(ep->dst);
1936 ep->tx_chan = cxgb4_port_chan(ep->dst->neighbour->dev); 1940 ep->tx_chan = cxgb4_port_chan(neigh->dev);
1937 ep->smac_idx = (cxgb4_port_viid(ep->dst->neighbour->dev) & 1941 ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
1938 0x7F) << 1;
1939 step = ep->com.dev->rdev.lldi.ntxq / 1942 step = ep->com.dev->rdev.lldi.ntxq /
1940 ep->com.dev->rdev.lldi.nchan; 1943 ep->com.dev->rdev.lldi.nchan;
1941 ep->txq_idx = cxgb4_port_idx(ep->dst->neighbour->dev) * step; 1944 ep->txq_idx = cxgb4_port_idx(neigh->dev) * step;
1942 ep->ctrlq_idx = cxgb4_port_idx(ep->dst->neighbour->dev); 1945 ep->ctrlq_idx = cxgb4_port_idx(neigh->dev);
1943 step = ep->com.dev->rdev.lldi.nrxq / 1946 step = ep->com.dev->rdev.lldi.nrxq /
1944 ep->com.dev->rdev.lldi.nchan; 1947 ep->com.dev->rdev.lldi.nchan;
1945 ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[ 1948 ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
1946 cxgb4_port_idx(ep->dst->neighbour->dev) * step]; 1949 cxgb4_port_idx(neigh->dev) * step];
1947 } 1950 }
1951 rcu_read_unlock();
1948 if (!ep->l2t) { 1952 if (!ep->l2t) {
1949 printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); 1953 printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
1950 err = -ENOMEM; 1954 err = -ENOMEM;
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 2001f20a436..23c04ff6519 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1301,7 +1301,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
1301 int is_eth; 1301 int is_eth;
1302 int is_vlan = 0; 1302 int is_vlan = 0;
1303 int is_grh; 1303 int is_grh;
1304 u16 vlan; 1304 u16 vlan = 0;
1305 1305
1306 send_size = 0; 1306 send_size = 0;
1307 for (i = 0; i < wr->num_sge; ++i) 1307 for (i = 0; i < wr->num_sge; ++i)
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index e74cdf9ef47..a1f74f6381b 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -1150,9 +1150,11 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
1150 neigh_release(neigh); 1150 neigh_release(neigh);
1151 } 1151 }
1152 1152
1153 if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) 1153 if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) {
1154 neigh_event_send(rt->dst.neighbour, NULL); 1154 rcu_read_lock();
1155 1155 neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
1156 rcu_read_unlock();
1157 }
1156 ip_rt_put(rt); 1158 ip_rt_put(rt);
1157 return rc; 1159 return rc;
1158} 1160}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 86addca9ddf..a98c414978e 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -555,14 +555,17 @@ static int path_rec_start(struct net_device *dev,
555 return 0; 555 return 0;
556} 556}
557 557
558/* called with rcu_read_lock */
558static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) 559static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
559{ 560{
560 struct ipoib_dev_priv *priv = netdev_priv(dev); 561 struct ipoib_dev_priv *priv = netdev_priv(dev);
561 struct ipoib_path *path; 562 struct ipoib_path *path;
562 struct ipoib_neigh *neigh; 563 struct ipoib_neigh *neigh;
564 struct neighbour *n;
563 unsigned long flags; 565 unsigned long flags;
564 566
565 neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev); 567 n = dst_get_neighbour(skb_dst(skb));
568 neigh = ipoib_neigh_alloc(n, skb->dev);
566 if (!neigh) { 569 if (!neigh) {
567 ++dev->stats.tx_dropped; 570 ++dev->stats.tx_dropped;
568 dev_kfree_skb_any(skb); 571 dev_kfree_skb_any(skb);
@@ -571,9 +574,9 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
571 574
572 spin_lock_irqsave(&priv->lock, flags); 575 spin_lock_irqsave(&priv->lock, flags);
573 576
574 path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4); 577 path = __path_find(dev, n->ha + 4);
575 if (!path) { 578 if (!path) {
576 path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4); 579 path = path_rec_create(dev, n->ha + 4);
577 if (!path) 580 if (!path)
578 goto err_path; 581 goto err_path;
579 582
@@ -607,7 +610,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
607 } 610 }
608 } else { 611 } else {
609 spin_unlock_irqrestore(&priv->lock, flags); 612 spin_unlock_irqrestore(&priv->lock, flags);
610 ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha)); 613 ipoib_send(dev, skb, path->ah, IPOIB_QPN(n->ha));
611 return; 614 return;
612 } 615 }
613 } else { 616 } else {
@@ -634,20 +637,24 @@ err_drop:
634 spin_unlock_irqrestore(&priv->lock, flags); 637 spin_unlock_irqrestore(&priv->lock, flags);
635} 638}
636 639
640/* called with rcu_read_lock */
637static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) 641static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
638{ 642{
639 struct ipoib_dev_priv *priv = netdev_priv(skb->dev); 643 struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
644 struct dst_entry *dst = skb_dst(skb);
645 struct neighbour *n;
640 646
641 /* Look up path record for unicasts */ 647 /* Look up path record for unicasts */
642 if (skb_dst(skb)->neighbour->ha[4] != 0xff) { 648 n = dst_get_neighbour(dst);
649 if (n->ha[4] != 0xff) {
643 neigh_add_path(skb, dev); 650 neigh_add_path(skb, dev);
644 return; 651 return;
645 } 652 }
646 653
647 /* Add in the P_Key for multicasts */ 654 /* Add in the P_Key for multicasts */
648 skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff; 655 n->ha[8] = (priv->pkey >> 8) & 0xff;
649 skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff; 656 n->ha[9] = priv->pkey & 0xff;
650 ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb); 657 ipoib_mcast_send(dev, n->ha + 4, skb);
651} 658}
652 659
653static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, 660static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
@@ -712,18 +719,23 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
712{ 719{
713 struct ipoib_dev_priv *priv = netdev_priv(dev); 720 struct ipoib_dev_priv *priv = netdev_priv(dev);
714 struct ipoib_neigh *neigh; 721 struct ipoib_neigh *neigh;
722 struct neighbour *n = NULL;
715 unsigned long flags; 723 unsigned long flags;
716 724
717 if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) { 725 rcu_read_lock();
718 if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) { 726 if (likely(skb_dst(skb)))
727 n = dst_get_neighbour(skb_dst(skb));
728
729 if (likely(n)) {
730 if (unlikely(!*to_ipoib_neigh(n))) {
719 ipoib_path_lookup(skb, dev); 731 ipoib_path_lookup(skb, dev);
720 return NETDEV_TX_OK; 732 goto unlock;
721 } 733 }
722 734
723 neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour); 735 neigh = *to_ipoib_neigh(n);
724 736
725 if (unlikely((memcmp(&neigh->dgid.raw, 737 if (unlikely((memcmp(&neigh->dgid.raw,
726 skb_dst(skb)->neighbour->ha + 4, 738 n->ha + 4,
727 sizeof(union ib_gid))) || 739 sizeof(union ib_gid))) ||
728 (neigh->dev != dev))) { 740 (neigh->dev != dev))) {
729 spin_lock_irqsave(&priv->lock, flags); 741 spin_lock_irqsave(&priv->lock, flags);
@@ -740,17 +752,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
740 ipoib_neigh_free(dev, neigh); 752 ipoib_neigh_free(dev, neigh);
741 spin_unlock_irqrestore(&priv->lock, flags); 753 spin_unlock_irqrestore(&priv->lock, flags);
742 ipoib_path_lookup(skb, dev); 754 ipoib_path_lookup(skb, dev);
743 return NETDEV_TX_OK; 755 goto unlock;
744 } 756 }
745 757
746 if (ipoib_cm_get(neigh)) { 758 if (ipoib_cm_get(neigh)) {
747 if (ipoib_cm_up(neigh)) { 759 if (ipoib_cm_up(neigh)) {
748 ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); 760 ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
749 return NETDEV_TX_OK; 761 goto unlock;
750 } 762 }
751 } else if (neigh->ah) { 763 } else if (neigh->ah) {
752 ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha)); 764 ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
753 return NETDEV_TX_OK; 765 goto unlock;
754 } 766 }
755 767
756 if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { 768 if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
@@ -784,13 +796,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
784 phdr->hwaddr + 4); 796 phdr->hwaddr + 4);
785 dev_kfree_skb_any(skb); 797 dev_kfree_skb_any(skb);
786 ++dev->stats.tx_dropped; 798 ++dev->stats.tx_dropped;
787 return NETDEV_TX_OK; 799 goto unlock;
788 } 800 }
789 801
790 unicast_arp_send(skb, dev, phdr); 802 unicast_arp_send(skb, dev, phdr);
791 } 803 }
792 } 804 }
793 805unlock:
806 rcu_read_unlock();
794 return NETDEV_TX_OK; 807 return NETDEV_TX_OK;
795} 808}
796 809
@@ -812,6 +825,8 @@ static int ipoib_hard_header(struct sk_buff *skb,
812 const void *daddr, const void *saddr, unsigned len) 825 const void *daddr, const void *saddr, unsigned len)
813{ 826{
814 struct ipoib_header *header; 827 struct ipoib_header *header;
828 struct dst_entry *dst;
829 struct neighbour *n;
815 830
816 header = (struct ipoib_header *) skb_push(skb, sizeof *header); 831 header = (struct ipoib_header *) skb_push(skb, sizeof *header);
817 832
@@ -823,7 +838,11 @@ static int ipoib_hard_header(struct sk_buff *skb,
823 * destination address onto the front of the skb so we can 838 * destination address onto the front of the skb so we can
824 * figure out where to send the packet later. 839 * figure out where to send the packet later.
825 */ 840 */
826 if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) { 841 dst = skb_dst(skb);
842 n = NULL;
843 if (dst)
844 n = dst_get_neighbour_raw(dst);
845 if ((!dst || !n) && daddr) {
827 struct ipoib_pseudoheader *phdr = 846 struct ipoib_pseudoheader *phdr =
828 (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); 847 (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
829 memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN); 848 memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 3871ac66355..a8d2a891b84 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -258,11 +258,15 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
258 netif_tx_lock_bh(dev); 258 netif_tx_lock_bh(dev);
259 while (!skb_queue_empty(&mcast->pkt_queue)) { 259 while (!skb_queue_empty(&mcast->pkt_queue)) {
260 struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue); 260 struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
261 struct dst_entry *dst = skb_dst(skb);
262 struct neighbour *n = NULL;
263
261 netif_tx_unlock_bh(dev); 264 netif_tx_unlock_bh(dev);
262 265
263 skb->dev = dev; 266 skb->dev = dev;
264 267 if (dst)
265 if (!skb_dst(skb) || !skb_dst(skb)->neighbour) { 268 n = dst_get_neighbour_raw(dst);
269 if (!dst || !n) {
266 /* put pseudoheader back on for next time */ 270 /* put pseudoheader back on for next time */
267 skb_push(skb, sizeof (struct ipoib_pseudoheader)); 271 skb_push(skb, sizeof (struct ipoib_pseudoheader));
268 } 272 }
@@ -715,11 +719,15 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
715 719
716out: 720out:
717 if (mcast && mcast->ah) { 721 if (mcast && mcast->ah) {
718 if (skb_dst(skb) && 722 struct dst_entry *dst = skb_dst(skb);
719 skb_dst(skb)->neighbour && 723 struct neighbour *n = NULL;
720 !*to_ipoib_neigh(skb_dst(skb)->neighbour)) { 724
721 struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, 725 rcu_read_lock();
722 skb->dev); 726 if (dst)
727 n = dst_get_neighbour(dst);
728 if (n && !*to_ipoib_neigh(n)) {
729 struct ipoib_neigh *neigh = ipoib_neigh_alloc(n,
730 skb->dev);
723 731
724 if (neigh) { 732 if (neigh) {
725 kref_get(&mcast->ah->ref); 733 kref_get(&mcast->ah->ref);
@@ -727,7 +735,7 @@ out:
727 list_add_tail(&neigh->list, &mcast->neigh_list); 735 list_add_tail(&neigh->list, &mcast->neigh_list);
728 } 736 }
729 } 737 }
730 738 rcu_read_unlock();
731 spin_unlock_irqrestore(&priv->lock, flags); 739 spin_unlock_irqrestore(&priv->lock, flags);
732 ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN); 740 ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
733 return; 741 return;