Commit 11d814a2 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
  IB: Fix RCU lockdep splats
  IB/ipoib: Prevent hung task or softlockup processing multicast response
  IB/qib: Fix over-scheduling of QSFP work
  RDMA/cxgb4: Fix retry with MPAv1 logic for MPAv2
  RDMA/cxgb4: Fix iw_cxgb4 count_rcqes() logic
  IB/qib: Don't use schedule_work()
parents c290b2f2 a493f1a2
...@@ -216,7 +216,9 @@ static int addr4_resolve(struct sockaddr_in *src_in, ...@@ -216,7 +216,9 @@ static int addr4_resolve(struct sockaddr_in *src_in,
neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev); neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
if (!neigh || !(neigh->nud_state & NUD_VALID)) { if (!neigh || !(neigh->nud_state & NUD_VALID)) {
rcu_read_lock();
neigh_event_send(dst_get_neighbour(&rt->dst), NULL); neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
rcu_read_unlock();
ret = -ENODATA; ret = -ENODATA;
if (neigh) if (neigh)
goto release; goto release;
...@@ -274,15 +276,16 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, ...@@ -274,15 +276,16 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
goto put; goto put;
} }
rcu_read_lock();
neigh = dst_get_neighbour(dst); neigh = dst_get_neighbour(dst);
if (!neigh || !(neigh->nud_state & NUD_VALID)) { if (!neigh || !(neigh->nud_state & NUD_VALID)) {
if (neigh) if (neigh)
neigh_event_send(neigh, NULL); neigh_event_send(neigh, NULL);
ret = -ENODATA; 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: put:
dst_release(dst); dst_release(dst);
return ret; return ret;
......
...@@ -1375,8 +1375,10 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx) ...@@ -1375,8 +1375,10 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
goto reject; goto reject;
} }
dst = &rt->dst; dst = &rt->dst;
rcu_read_lock();
neigh = dst_get_neighbour(dst); neigh = dst_get_neighbour(dst);
l2t = t3_l2t_get(tdev, neigh, neigh->dev); l2t = t3_l2t_get(tdev, neigh, neigh->dev);
rcu_read_unlock();
if (!l2t) { if (!l2t) {
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
__func__); __func__);
...@@ -1946,10 +1948,12 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) ...@@ -1946,10 +1948,12 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
} }
ep->dst = &rt->dst; ep->dst = &rt->dst;
rcu_read_lock();
neigh = dst_get_neighbour(ep->dst); neigh = dst_get_neighbour(ep->dst);
/* get a l2t entry */ /* get a l2t entry */
ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev); ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
rcu_read_unlock();
if (!ep->l2t) { if (!ep->l2t) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
err = -ENOMEM; err = -ENOMEM;
......
...@@ -542,8 +542,10 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb, ...@@ -542,8 +542,10 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
(mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0); (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0);
mpa->private_data_size = htons(ep->plen); mpa->private_data_size = htons(ep->plen);
mpa->revision = mpa_rev_to_use; mpa->revision = mpa_rev_to_use;
if (mpa_rev_to_use == 1) if (mpa_rev_to_use == 1) {
ep->tried_with_mpa_v1 = 1; ep->tried_with_mpa_v1 = 1;
ep->retry_with_mpa_v1 = 0;
}
if (mpa_rev_to_use == 2) { if (mpa_rev_to_use == 2) {
mpa->private_data_size += mpa->private_data_size +=
...@@ -1594,6 +1596,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1594,6 +1596,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
goto reject; goto reject;
} }
dst = &rt->dst; dst = &rt->dst;
rcu_read_lock();
neigh = dst_get_neighbour(dst); neigh = dst_get_neighbour(dst);
if (neigh->dev->flags & IFF_LOOPBACK) { if (neigh->dev->flags & IFF_LOOPBACK) {
pdev = ip_dev_find(&init_net, peer_ip); pdev = ip_dev_find(&init_net, peer_ip);
...@@ -1620,6 +1623,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb) ...@@ -1620,6 +1623,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
rss_qid = dev->rdev.lldi.rxq_ids[ rss_qid = dev->rdev.lldi.rxq_ids[
cxgb4_port_idx(neigh->dev) * step]; cxgb4_port_idx(neigh->dev) * step];
} }
rcu_read_unlock();
if (!l2t) { if (!l2t) {
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n", printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
__func__); __func__);
...@@ -1820,6 +1824,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep) ...@@ -1820,6 +1824,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
} }
ep->dst = &rt->dst; ep->dst = &rt->dst;
rcu_read_lock();
neigh = dst_get_neighbour(ep->dst); neigh = dst_get_neighbour(ep->dst);
/* get a l2t entry */ /* get a l2t entry */
...@@ -1856,6 +1861,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep) ...@@ -1856,6 +1861,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[ ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
cxgb4_port_idx(neigh->dev) * step]; cxgb4_port_idx(neigh->dev) * step];
} }
rcu_read_unlock();
if (!ep->l2t) { if (!ep->l2t) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
err = -ENOMEM; err = -ENOMEM;
...@@ -2301,6 +2307,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) ...@@ -2301,6 +2307,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
} }
ep->dst = &rt->dst; ep->dst = &rt->dst;
rcu_read_lock();
neigh = dst_get_neighbour(ep->dst); neigh = dst_get_neighbour(ep->dst);
/* get a l2t entry */ /* get a l2t entry */
...@@ -2339,6 +2346,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) ...@@ -2339,6 +2346,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ep->retry_with_mpa_v1 = 0; ep->retry_with_mpa_v1 = 0;
ep->tried_with_mpa_v1 = 0; ep->tried_with_mpa_v1 = 0;
} }
rcu_read_unlock();
if (!ep->l2t) { if (!ep->l2t) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__); printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
err = -ENOMEM; err = -ENOMEM;
......
...@@ -311,7 +311,7 @@ void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count) ...@@ -311,7 +311,7 @@ void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count)
while (ptr != cq->sw_pidx) { while (ptr != cq->sw_pidx) {
cqe = &cq->sw_queue[ptr]; cqe = &cq->sw_queue[ptr];
if (RQ_TYPE(cqe) && (CQE_OPCODE(cqe) != FW_RI_READ_RESP) && if (RQ_TYPE(cqe) && (CQE_OPCODE(cqe) != FW_RI_READ_RESP) &&
(CQE_QPID(cqe) == wq->rq.qid) && cqe_completes_wr(cqe, wq)) (CQE_QPID(cqe) == wq->sq.qid) && cqe_completes_wr(cqe, wq))
(*count)++; (*count)++;
if (++ptr == cq->size) if (++ptr == cq->size)
ptr = 0; ptr = 0;
......
...@@ -1377,9 +1377,11 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi ...@@ -1377,9 +1377,11 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
neigh_release(neigh); neigh_release(neigh);
} }
if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) {
rcu_read_lock();
neigh_event_send(dst_get_neighbour(&rt->dst), NULL); neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
rcu_read_unlock();
}
ip_rt_put(rt); ip_rt_put(rt);
return rc; return rc;
} }
......
...@@ -2307,19 +2307,11 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd) ...@@ -2307,19 +2307,11 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
SYM_LSB(IBCCtrlA_0, MaxPktLen); SYM_LSB(IBCCtrlA_0, MaxPktLen);
ppd->cpspec->ibcctrl_a = ibc; /* without linkcmd or linkinitcmd! */ ppd->cpspec->ibcctrl_a = ibc; /* without linkcmd or linkinitcmd! */
/* initially come up waiting for TS1, without sending anything. */
val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
ppd->cpspec->ibcctrl_a = val;
/* /*
* Reset the PCS interface to the serdes (and also ibc, which is still * Reset the PCS interface to the serdes (and also ibc, which is still
* in reset from above). Writes new value of ibcctrl_a as last step. * in reset from above). Writes new value of ibcctrl_a as last step.
*/ */
qib_7322_mini_pcs_reset(ppd); qib_7322_mini_pcs_reset(ppd);
qib_write_kreg(dd, kr_scratch, 0ULL);
/* clear the linkinit cmds */
ppd->cpspec->ibcctrl_a &= ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
if (!ppd->cpspec->ibcctrl_b) { if (!ppd->cpspec->ibcctrl_b) {
unsigned lse = ppd->link_speed_enabled; unsigned lse = ppd->link_speed_enabled;
...@@ -2385,6 +2377,14 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd) ...@@ -2385,6 +2377,14 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn); ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn);
set_vls(ppd); set_vls(ppd);
/* initially come up DISABLED, without sending anything. */
val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
qib_write_kreg_port(ppd, krp_ibcctrl_a, val);
qib_write_kreg(dd, kr_scratch, 0ULL);
/* clear the linkinit cmds */
ppd->cpspec->ibcctrl_a = val & ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
/* be paranoid against later code motion, etc. */ /* be paranoid against later code motion, etc. */
spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags); spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags);
ppd->p_rcvctrl |= SYM_MASK(RcvCtrl_0, RcvIBPortEnable); ppd->p_rcvctrl |= SYM_MASK(RcvCtrl_0, RcvIBPortEnable);
...@@ -5241,7 +5241,7 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs) ...@@ -5241,7 +5241,7 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
off */ off */
if (ppd->dd->flags & QIB_HAS_QSFP) { if (ppd->dd->flags & QIB_HAS_QSFP) {
qd->t_insert = get_jiffies_64(); qd->t_insert = get_jiffies_64();
schedule_work(&qd->work); queue_work(ib_wq, &qd->work);
} }
spin_lock_irqsave(&ppd->sdma_lock, flags); spin_lock_irqsave(&ppd->sdma_lock, flags);
if (__qib_sdma_running(ppd)) if (__qib_sdma_running(ppd))
......
...@@ -480,18 +480,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd, ...@@ -480,18 +480,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
udelay(20); /* Generous RST dwell */ udelay(20); /* Generous RST dwell */
dd->f_gpio_mod(dd, mask, mask, mask); dd->f_gpio_mod(dd, mask, mask, mask);
/* Spec says module can take up to two seconds! */
mask = QSFP_GPIO_MOD_PRS_N;
if (qd->ppd->hw_pidx)
mask <<= QSFP_GPIO_PORT2_SHIFT;
/* Do not try to wait here. Better to let event handle it */
if (!qib_qsfp_mod_present(qd->ppd))
goto bail;
/* We see a module, but it may be unwise to look yet. Just schedule */
qd->t_insert = get_jiffies_64();
queue_work(ib_wq, &qd->work);
bail:
return; return;
} }
......
...@@ -57,21 +57,24 @@ struct ipoib_ah *ipoib_create_ah(struct net_device *dev, ...@@ -57,21 +57,24 @@ struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
struct ib_pd *pd, struct ib_ah_attr *attr) struct ib_pd *pd, struct ib_ah_attr *attr)
{ {
struct ipoib_ah *ah; struct ipoib_ah *ah;
struct ib_ah *vah;
ah = kmalloc(sizeof *ah, GFP_KERNEL); ah = kmalloc(sizeof *ah, GFP_KERNEL);
if (!ah) if (!ah)
return NULL; return ERR_PTR(-ENOMEM);
ah->dev = dev; ah->dev = dev;
ah->last_send = 0; ah->last_send = 0;
kref_init(&ah->ref); kref_init(&ah->ref);
ah->ah = ib_create_ah(pd, attr); vah = ib_create_ah(pd, attr);
if (IS_ERR(ah->ah)) { if (IS_ERR(vah)) {
kfree(ah); kfree(ah);
ah = NULL; ah = (struct ipoib_ah *)vah;
} else } else {
ah->ah = vah;
ipoib_dbg(netdev_priv(dev), "Created ah %p\n", ah->ah); ipoib_dbg(netdev_priv(dev), "Created ah %p\n", ah->ah);
}
return ah; return ah;
} }
......
...@@ -432,7 +432,7 @@ static void path_rec_completion(int status, ...@@ -432,7 +432,7 @@ static void path_rec_completion(int status,
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
if (ah) { if (!IS_ERR_OR_NULL(ah)) {
path->pathrec = *pathrec; path->pathrec = *pathrec;
old_ah = path->ah; old_ah = path->ah;
...@@ -555,6 +555,7 @@ static int path_rec_start(struct net_device *dev, ...@@ -555,6 +555,7 @@ static int path_rec_start(struct net_device *dev,
return 0; return 0;
} }
/* called with rcu_read_lock */
static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
{ {
struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_dev_priv *priv = netdev_priv(dev);
...@@ -636,6 +637,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) ...@@ -636,6 +637,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
} }
/* called with rcu_read_lock */
static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev) static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
{ {
struct ipoib_dev_priv *priv = netdev_priv(skb->dev); struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
...@@ -720,13 +722,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -720,13 +722,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
struct neighbour *n = NULL; struct neighbour *n = NULL;
unsigned long flags; unsigned long flags;
rcu_read_lock();
if (likely(skb_dst(skb))) if (likely(skb_dst(skb)))
n = dst_get_neighbour(skb_dst(skb)); n = dst_get_neighbour(skb_dst(skb));
if (likely(n)) { if (likely(n)) {
if (unlikely(!*to_ipoib_neigh(n))) { if (unlikely(!*to_ipoib_neigh(n))) {
ipoib_path_lookup(skb, dev); ipoib_path_lookup(skb, dev);
return NETDEV_TX_OK; goto unlock;
} }
neigh = *to_ipoib_neigh(n); neigh = *to_ipoib_neigh(n);
...@@ -749,17 +752,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -749,17 +752,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
ipoib_neigh_free(dev, neigh); ipoib_neigh_free(dev, neigh);
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
ipoib_path_lookup(skb, dev); ipoib_path_lookup(skb, dev);
return NETDEV_TX_OK; goto unlock;
} }
if (ipoib_cm_get(neigh)) { if (ipoib_cm_get(neigh)) {
if (ipoib_cm_up(neigh)) { if (ipoib_cm_up(neigh)) {
ipoib_cm_send(dev, skb, ipoib_cm_get(neigh)); ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
return NETDEV_TX_OK; goto unlock;
} }
} else if (neigh->ah) { } else if (neigh->ah) {
ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha)); ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
return NETDEV_TX_OK; goto unlock;
} }
if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) { if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
...@@ -793,13 +796,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -793,13 +796,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
phdr->hwaddr + 4); phdr->hwaddr + 4);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
++dev->stats.tx_dropped; ++dev->stats.tx_dropped;
return NETDEV_TX_OK; goto unlock;
} }
unicast_arp_send(skb, dev, phdr); unicast_arp_send(skb, dev, phdr);
} }
} }
unlock:
rcu_read_unlock();
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
...@@ -837,7 +841,7 @@ static int ipoib_hard_header(struct sk_buff *skb, ...@@ -837,7 +841,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
dst = skb_dst(skb); dst = skb_dst(skb);
n = NULL; n = NULL;
if (dst) if (dst)
n = dst_get_neighbour(dst); n = dst_get_neighbour_raw(dst);
if ((!dst || !n) && daddr) { if ((!dst || !n) && daddr) {
struct ipoib_pseudoheader *phdr = struct ipoib_pseudoheader *phdr =
(struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr); (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
......
...@@ -240,8 +240,11 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, ...@@ -240,8 +240,11 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
av.grh.dgid = mcast->mcmember.mgid; av.grh.dgid = mcast->mcmember.mgid;
ah = ipoib_create_ah(dev, priv->pd, &av); ah = ipoib_create_ah(dev, priv->pd, &av);
if (!ah) { if (IS_ERR(ah)) {
ipoib_warn(priv, "ib_address_create failed\n"); ipoib_warn(priv, "ib_address_create failed %ld\n",
-PTR_ERR(ah));
/* use original error */
return PTR_ERR(ah);
} else { } else {
spin_lock_irq(&priv->lock); spin_lock_irq(&priv->lock);
mcast->ah = ah; mcast->ah = ah;
...@@ -266,7 +269,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, ...@@ -266,7 +269,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
skb->dev = dev; skb->dev = dev;
if (dst) if (dst)
n = dst_get_neighbour(dst); n = dst_get_neighbour_raw(dst);
if (!dst || !n) { if (!dst || !n) {
/* put pseudoheader back on for next time */ /* put pseudoheader back on for next time */
skb_push(skb, sizeof (struct ipoib_pseudoheader)); skb_push(skb, sizeof (struct ipoib_pseudoheader));
...@@ -722,6 +725,8 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) ...@@ -722,6 +725,8 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
if (mcast && mcast->ah) { if (mcast && mcast->ah) {
struct dst_entry *dst = skb_dst(skb); struct dst_entry *dst = skb_dst(skb);
struct neighbour *n = NULL; struct neighbour *n = NULL;
rcu_read_lock();
if (dst) if (dst)
n = dst_get_neighbour(dst); n = dst_get_neighbour(dst);
if (n && !*to_ipoib_neigh(n)) { if (n && !*to_ipoib_neigh(n)) {
...@@ -734,7 +739,7 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb) ...@@ -734,7 +739,7 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
list_add_tail(&neigh->list, &mcast->neigh_list); list_add_tail(&neigh->list, &mcast->neigh_list);
} }
} }
rcu_read_unlock();
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN); ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment