Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Dec 2011 00:25:02 +0000 (16:25 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Dec 2011 00:25:02 +0000 (16:25 -0800)
* '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()

drivers/infiniband/core/addr.c
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/cq.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/qib/qib_iba7322.c
drivers/infiniband/hw/qib/qib_qsfp.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c

index 691276b..e9cf51b 100644 (file)
@@ -216,7 +216,9 @@ static int addr4_resolve(struct sockaddr_in *src_in,
 
        neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
        if (!neigh || !(neigh->nud_state & NUD_VALID)) {
+               rcu_read_lock();
                neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
+               rcu_read_unlock();
                ret = -ENODATA;
                if (neigh)
                        goto release;
@@ -274,15 +276,16 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
                goto put;
        }
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(dst);
        if (!neigh || !(neigh->nud_state & NUD_VALID)) {
                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 de6d077..c88b12b 100644 (file)
@@ -1375,8 +1375,10 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                goto reject;
        }
        dst = &rt->dst;
+       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__);
@@ -1946,10 +1948,12 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        }
        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, neigh, neigh->dev);
+       rcu_read_unlock();
        if (!ep->l2t) {
                printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
                err = -ENOMEM;
index b36cdac..0747004 100644 (file)
@@ -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->private_data_size = htons(ep->plen);
        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->retry_with_mpa_v1 = 0;
+       }
 
        if (mpa_rev_to_use == 2) {
                mpa->private_data_size +=
@@ -1594,6 +1596,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
                goto reject;
        }
        dst = &rt->dst;
+       rcu_read_lock();
        neigh = dst_get_neighbour(dst);
        if (neigh->dev->flags & IFF_LOOPBACK) {
                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)
                rss_qid = dev->rdev.lldi.rxq_ids[
                          cxgb4_port_idx(neigh->dev) * step];
        }
+       rcu_read_unlock();
        if (!l2t) {
                printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
                       __func__);
@@ -1820,6 +1824,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
        }
        ep->dst = &rt->dst;
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(ep->dst);
 
        /* get a l2t entry */
@@ -1856,6 +1861,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
                ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
                        cxgb4_port_idx(neigh->dev) * step];
        }
+       rcu_read_unlock();
        if (!ep->l2t) {
                printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
                err = -ENOMEM;
@@ -2301,6 +2307,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        }
        ep->dst = &rt->dst;
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(ep->dst);
 
        /* get a l2t entry */
@@ -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->tried_with_mpa_v1 = 0;
        }
+       rcu_read_unlock();
        if (!ep->l2t) {
                printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
                err = -ENOMEM;
index f35a935..0f1607c 100644 (file)
@@ -311,7 +311,7 @@ void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count)
        while (ptr != cq->sw_pidx) {
                cqe = &cq->sw_queue[ptr];
                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)++;
                if (++ptr == cq->size)
                        ptr = 0;
index dfce9ea..0a52d72 100644 (file)
@@ -1377,9 +1377,11 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
                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);
-
+               rcu_read_unlock();
+       }
        ip_rt_put(rt);
        return rc;
 }
index 5bd2162..1d58959 100644 (file)
@@ -2307,19 +2307,11 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
                SYM_LSB(IBCCtrlA_0, MaxPktLen);
        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
         * in reset from above).  Writes new value of ibcctrl_a as last step.
         */
        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) {
                unsigned lse = ppd->link_speed_enabled;
@@ -2385,6 +2377,14 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
        ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn);
        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. */
        spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags);
        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)
                           off */
                        if (ppd->dd->flags & QIB_HAS_QSFP) {
                                qd->t_insert = get_jiffies_64();
-                               schedule_work(&qd->work);
+                               queue_work(ib_wq, &qd->work);
                        }
                        spin_lock_irqsave(&ppd->sdma_lock, flags);
                        if (__qib_sdma_running(ppd))
index e06c4ed..fa71b1e 100644 (file)
@@ -480,18 +480,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
        udelay(20); /* Generous RST dwell */
 
        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;
 }
 
index 0ef9af9..4115be5 100644 (file)
@@ -57,21 +57,24 @@ struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
                                 struct ib_pd *pd, struct ib_ah_attr *attr)
 {
        struct ipoib_ah *ah;
+       struct ib_ah *vah;
 
        ah = kmalloc(sizeof *ah, GFP_KERNEL);
        if (!ah)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        ah->dev       = dev;
        ah->last_send = 0;
        kref_init(&ah->ref);
 
-       ah->ah = ib_create_ah(pd, attr);
-       if (IS_ERR(ah->ah)) {
+       vah = ib_create_ah(pd, attr);
+       if (IS_ERR(vah)) {
                kfree(ah);
-               ah = NULL;
-       } else
+               ah = (struct ipoib_ah *)vah;
+       } else {
+               ah->ah = vah;
                ipoib_dbg(netdev_priv(dev), "Created ah %p\n", ah->ah);
+       }
 
        return ah;
 }
index 7567b60..83695b4 100644 (file)
@@ -432,7 +432,7 @@ static void path_rec_completion(int status,
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       if (ah) {
+       if (!IS_ERR_OR_NULL(ah)) {
                path->pathrec = *pathrec;
 
                old_ah   = path->ah;
@@ -555,6 +555,7 @@ static int path_rec_start(struct net_device *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);
@@ -636,6 +637,7 @@ 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);
@@ -720,13 +722,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct neighbour *n = NULL;
        unsigned long flags;
 
+       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(n);
@@ -749,17 +752,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        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(n->ha));
-                       return NETDEV_TX_OK;
+                       goto unlock;
                }
 
                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)
                                           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;
 }
 
@@ -837,7 +841,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
        dst = skb_dst(skb);
        n = NULL;
        if (dst)
-               n = dst_get_neighbour(dst);
+               n = dst_get_neighbour_raw(dst);
        if ((!dst || !n) && daddr) {
                struct ipoib_pseudoheader *phdr =
                        (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
index 1b7a976..873bff9 100644 (file)
@@ -240,8 +240,11 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
                av.grh.dgid = mcast->mcmember.mgid;
 
                ah = ipoib_create_ah(dev, priv->pd, &av);
-               if (!ah) {
-                       ipoib_warn(priv, "ib_address_create failed\n");
+               if (IS_ERR(ah)) {
+                       ipoib_warn(priv, "ib_address_create failed %ld\n",
+                               -PTR_ERR(ah));
+                       /* use original error */
+                       return PTR_ERR(ah);
                } else {
                        spin_lock_irq(&priv->lock);
                        mcast->ah = ah;
@@ -266,7 +269,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
 
                skb->dev = dev;
                if (dst)
-                       n = dst_get_neighbour(dst);
+                       n = dst_get_neighbour_raw(dst);
                if (!dst || !n) {
                        /* put pseudoheader back on for next time */
                        skb_push(skb, sizeof (struct ipoib_pseudoheader));
@@ -722,6 +725,8 @@ out:
        if (mcast && mcast->ah) {
                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)) {
@@ -734,7 +739,7 @@ out:
                                list_add_tail(&neigh->list, &mcast->neigh_list);
                        }
                }
-
+               rcu_read_unlock();
                spin_unlock_irqrestore(&priv->lock, flags);
                ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
                return;