Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 6 May 2008 00:31:41 +0000 (17:31 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 6 May 2008 00:31:41 +0000 (17:31 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
  mlx4_core: Support creation of FMRs with pages smaller than 4K
  IB/ehca: Fix function return types
  RDMA/cxgb3: Bump up the MPA connection setup timeout.
  RDMA/cxgb3: Silently ignore close reply after abort.
  RDMA/cxgb3: QP flush fixes
  IB/ipoib: Fix transmit queue stalling forever
  IB/mlx4: Fix off-by-one errors in calls to mlx4_ib_free_cq_buf()

drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb3/cxio_hal.h
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/infiniband/hw/ehca/ehca_hca.c
drivers/infiniband/hw/mlx4/cq.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_verbs.c
drivers/net/mlx4/mr.c

index ed2ee4ba4b7c3e9e50ed8d162fbc40b5482945ca..5fd8506a865735a87df96738a4677ad227e8e381 100644 (file)
@@ -359,9 +359,10 @@ static void insert_recv_cqe(struct t3_wq *wq, struct t3_cq *cq)
        cq->sw_wptr++;
 }
 
-void cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count)
+int cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count)
 {
        u32 ptr;
+       int flushed = 0;
 
        PDBG("%s wq %p cq %p\n", __func__, wq, cq);
 
@@ -369,8 +370,11 @@ void cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count)
        PDBG("%s rq_rptr %u rq_wptr %u skip count %u\n", __func__,
            wq->rq_rptr, wq->rq_wptr, count);
        ptr = wq->rq_rptr + count;
-       while (ptr++ != wq->rq_wptr)
+       while (ptr++ != wq->rq_wptr) {
                insert_recv_cqe(wq, cq);
+               flushed++;
+       }
+       return flushed;
 }
 
 static void insert_sq_cqe(struct t3_wq *wq, struct t3_cq *cq,
@@ -394,9 +398,10 @@ static void insert_sq_cqe(struct t3_wq *wq, struct t3_cq *cq,
        cq->sw_wptr++;
 }
 
-void cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count)
+int cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count)
 {
        __u32 ptr;
+       int flushed = 0;
        struct t3_swsq *sqp = wq->sq + Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2);
 
        ptr = wq->sq_rptr + count;
@@ -405,7 +410,9 @@ void cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count)
                insert_sq_cqe(wq, cq, sqp);
                sqp++;
                ptr++;
+               flushed++;
        }
+       return flushed;
 }
 
 /*
index 2bcff7f5046e3a00c10675643f40872319bb51ef..69ab08ebc680166292ffe8f4b040f96b21dcabb3 100644 (file)
@@ -173,8 +173,8 @@ u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp);
 void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid);
 int __init cxio_hal_init(void);
 void __exit cxio_hal_exit(void);
-void cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count);
-void cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count);
+int cxio_flush_rq(struct t3_wq *wq, struct t3_cq *cq, int count);
+int cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count);
 void cxio_count_rcqes(struct t3_cq *cq, struct t3_wq *wq, int *count);
 void cxio_count_scqes(struct t3_cq *cq, struct t3_wq *wq, int *count);
 void cxio_flush_hw_cq(struct t3_cq *cq);
index d44a6df9ad8c4a7ebd915b00817a8a980ae2f237..c325c44807e8226b1744796a7463e6aab384e950 100644 (file)
@@ -67,10 +67,10 @@ int peer2peer = 0;
 module_param(peer2peer, int, 0644);
 MODULE_PARM_DESC(peer2peer, "Support peer2peer ULPs (default=0)");
 
-static int ep_timeout_secs = 10;
+static int ep_timeout_secs = 60;
 module_param(ep_timeout_secs, int, 0644);
 MODULE_PARM_DESC(ep_timeout_secs, "CM Endpoint operation timeout "
-                                  "in seconds (default=10)");
+                                  "in seconds (default=60)");
 
 static int mpa_rev = 1;
 module_param(mpa_rev, int, 0644);
@@ -1650,8 +1650,8 @@ static int close_con_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                release = 1;
                break;
        case ABORTING:
-               break;
        case DEAD:
+               break;
        default:
                BUG_ON(1);
                break;
index 9b4be889c58ea8d9d378200e0297958a337ef16c..79dbe5beae52b3ee3095ac24aa78f12ee0217b4e 100644 (file)
@@ -655,6 +655,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
 {
        struct iwch_cq *rchp, *schp;
        int count;
+       int flushed;
 
        rchp = get_chp(qhp->rhp, qhp->attr.rcq);
        schp = get_chp(qhp->rhp, qhp->attr.scq);
@@ -669,20 +670,22 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
        spin_lock(&qhp->lock);
        cxio_flush_hw_cq(&rchp->cq);
        cxio_count_rcqes(&rchp->cq, &qhp->wq, &count);
-       cxio_flush_rq(&qhp->wq, &rchp->cq, count);
+       flushed = cxio_flush_rq(&qhp->wq, &rchp->cq, count);
        spin_unlock(&qhp->lock);
        spin_unlock_irqrestore(&rchp->lock, *flag);
-       (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+       if (flushed)
+               (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
 
        /* locking heirarchy: cq lock first, then qp lock. */
        spin_lock_irqsave(&schp->lock, *flag);
        spin_lock(&qhp->lock);
        cxio_flush_hw_cq(&schp->cq);
        cxio_count_scqes(&schp->cq, &qhp->wq, &count);
-       cxio_flush_sq(&qhp->wq, &schp->cq, count);
+       flushed = cxio_flush_sq(&qhp->wq, &schp->cq, count);
        spin_unlock(&qhp->lock);
        spin_unlock_irqrestore(&schp->lock, *flag);
-       (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
+       if (flushed)
+               (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
 
        /* deref */
        if (atomic_dec_and_test(&qhp->refcnt))
@@ -880,7 +883,6 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
                                ep = qhp->ep;
                                get_ep(&ep->com);
                        }
-                       flush_qp(qhp, &flag);
                        break;
                case IWCH_QP_STATE_TERMINATE:
                        qhp->attr.state = IWCH_QP_STATE_TERMINATE;
@@ -911,6 +913,7 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
                }
                switch (attrs->next_state) {
                        case IWCH_QP_STATE_IDLE:
+                               flush_qp(qhp, &flag);
                                qhp->attr.state = IWCH_QP_STATE_IDLE;
                                qhp->attr.llp_stream_handle = NULL;
                                put_ep(&qhp->ep->com);
index 2515cbde7e65449e1a54fafd507ac57cabf482cd..bc3b37d2070f338b6a41003ad1e6a6c125e1d555 100644 (file)
@@ -101,7 +101,6 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
        props->max_ee          = limit_uint(rblock->max_rd_ee_context);
        props->max_rdd         = limit_uint(rblock->max_rd_domain);
        props->max_fmr         = limit_uint(rblock->max_mr);
-       props->local_ca_ack_delay  = limit_uint(rblock->local_ca_ack_delay);
        props->max_qp_rd_atom  = limit_uint(rblock->max_rr_qp);
        props->max_ee_rd_atom  = limit_uint(rblock->max_rr_ee_context);
        props->max_res_rd_atom = limit_uint(rblock->max_rr_hca);
@@ -115,7 +114,7 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
        }
 
        props->max_pkeys           = 16;
-       props->local_ca_ack_delay  = limit_uint(rblock->local_ca_ack_delay);
+       props->local_ca_ack_delay  = min_t(u8, rblock->local_ca_ack_delay, 255);
        props->max_raw_ipv6_qp     = limit_uint(rblock->max_raw_ipv6_qp);
        props->max_raw_ethy_qp     = limit_uint(rblock->max_raw_ethy_qp);
        props->max_mcast_grp       = limit_uint(rblock->max_mcast_grp);
@@ -136,7 +135,7 @@ query_device1:
        return ret;
 }
 
-static int map_mtu(struct ehca_shca *shca, u32 fw_mtu)
+static enum ib_mtu map_mtu(struct ehca_shca *shca, u32 fw_mtu)
 {
        switch (fw_mtu) {
        case 0x1:
@@ -156,7 +155,7 @@ static int map_mtu(struct ehca_shca *shca, u32 fw_mtu)
        }
 }
 
-static int map_number_of_vls(struct ehca_shca *shca, u32 vl_cap)
+static u8 map_number_of_vls(struct ehca_shca *shca, u32 vl_cap)
 {
        switch (vl_cap) {
        case 0x1:
index 2f199c5c4a724320a8e517a5a37046d7d740923d..4521319b14067c22d576044c35bea72bcb2e3720 100644 (file)
@@ -246,7 +246,7 @@ err_mtt:
        if (context)
                ib_umem_release(cq->umem);
        else
-               mlx4_ib_free_cq_buf(dev, &cq->buf, entries);
+               mlx4_ib_free_cq_buf(dev, &cq->buf, cq->ibcq.cqe);
 
 err_db:
        if (!context)
@@ -434,7 +434,7 @@ int mlx4_ib_destroy_cq(struct ib_cq *cq)
                mlx4_ib_db_unmap_user(to_mucontext(cq->uobject->context), &mcq->db);
                ib_umem_release(mcq->umem);
        } else {
-               mlx4_ib_free_cq_buf(dev, &mcq->buf, cq->cqe + 1);
+               mlx4_ib_free_cq_buf(dev, &mcq->buf, cq->cqe);
                mlx4_db_free(dev->dev, &mcq->db);
        }
 
index 9044f8803532e035e264e2b166644b05d84563e4..ca126fc2b853c14a3d61f24e731f2f304ad9530d 100644 (file)
@@ -334,6 +334,7 @@ struct ipoib_dev_priv {
 #endif
        int     hca_caps;
        struct ipoib_ethtool_st ethtool;
+       struct timer_list poll_timer;
 };
 
 struct ipoib_ah {
@@ -404,6 +405,7 @@ extern struct workqueue_struct *ipoib_workqueue;
 
 int ipoib_poll(struct napi_struct *napi, int budget);
 void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr);
+void ipoib_send_comp_handler(struct ib_cq *cq, void *dev_ptr);
 
 struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
                                 struct ib_pd *pd, struct ib_ah_attr *attr);
index 97b815c1a3fc0988a33129e47ace54748d9d9dbb..f429bce24c20b9be303e75b6dc4ad1cf112a7663 100644 (file)
@@ -461,6 +461,26 @@ void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
        netif_rx_schedule(dev, &priv->napi);
 }
 
+static void drain_tx_cq(struct net_device *dev)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->tx_lock, flags);
+       while (poll_tx(priv))
+               ; /* nothing */
+
+       if (netif_queue_stopped(dev))
+               mod_timer(&priv->poll_timer, jiffies + 1);
+
+       spin_unlock_irqrestore(&priv->tx_lock, flags);
+}
+
+void ipoib_send_comp_handler(struct ib_cq *cq, void *dev_ptr)
+{
+       drain_tx_cq((struct net_device *)dev_ptr);
+}
+
 static inline int post_send(struct ipoib_dev_priv *priv,
                            unsigned int wr_id,
                            struct ib_ah *address, u32 qpn,
@@ -555,12 +575,22 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
        else
                priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
 
+       if (++priv->tx_outstanding == ipoib_sendq_size) {
+               ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
+               if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP))
+                       ipoib_warn(priv, "request notify on send CQ failed\n");
+               netif_stop_queue(dev);
+       }
+
        if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
                               address->ah, qpn, tx_req, phead, hlen))) {
                ipoib_warn(priv, "post_send failed\n");
                ++dev->stats.tx_errors;
+               --priv->tx_outstanding;
                ipoib_dma_unmap_tx(priv->ca, tx_req);
                dev_kfree_skb_any(skb);
+               if (netif_queue_stopped(dev))
+                       netif_wake_queue(dev);
        } else {
                dev->trans_start = jiffies;
 
@@ -568,14 +598,11 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
                ++priv->tx_head;
                skb_orphan(skb);
 
-               if (++priv->tx_outstanding == ipoib_sendq_size) {
-                       ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
-                       netif_stop_queue(dev);
-               }
        }
 
        if (unlikely(priv->tx_outstanding > MAX_SEND_CQE))
-               poll_tx(priv);
+               while (poll_tx(priv))
+                       ; /* nothing */
 }
 
 static void __ipoib_reap_ah(struct net_device *dev)
@@ -609,6 +636,11 @@ void ipoib_reap_ah(struct work_struct *work)
                                   round_jiffies_relative(HZ));
 }
 
+static void ipoib_ib_tx_timer_func(unsigned long ctx)
+{
+       drain_tx_cq((struct net_device *)ctx);
+}
+
 int ipoib_ib_dev_open(struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -645,6 +677,10 @@ int ipoib_ib_dev_open(struct net_device *dev)
        queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task,
                           round_jiffies_relative(HZ));
 
+       init_timer(&priv->poll_timer);
+       priv->poll_timer.function = ipoib_ib_tx_timer_func;
+       priv->poll_timer.data = (unsigned long)dev;
+
        set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
 
        return 0;
@@ -810,6 +846,7 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
        ipoib_dbg(priv, "All sends and receives done.\n");
 
 timeout:
+       del_timer_sync(&priv->poll_timer);
        qp_attr.qp_state = IB_QPS_RESET;
        if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
                ipoib_warn(priv, "Failed to modify QP to RESET state\n");
index c1e7ece1fd440ffd61efc2260ade377cc87df47e..8766d29ce3b783275d6b6753620cdc0291855186 100644 (file)
@@ -187,7 +187,8 @@ int ipoib_transport_dev_init(struct net_device *dev, struct ib_device *ca)
                goto out_free_mr;
        }
 
-       priv->send_cq = ib_create_cq(priv->ca, NULL, NULL, dev, ipoib_sendq_size, 0);
+       priv->send_cq = ib_create_cq(priv->ca, ipoib_send_comp_handler, NULL,
+                                    dev, ipoib_sendq_size, 0);
        if (IS_ERR(priv->send_cq)) {
                printk(KERN_WARNING "%s: failed to create send CQ\n", ca->name);
                goto out_free_recv_cq;
index cb46446b2691b88a7db70ce08a482f9a09696e5a..03a9abcce5240bbe53be4783e25584b010dcd68b 100644 (file)
@@ -551,7 +551,7 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages,
        u64 mtt_seg;
        int err = -ENOMEM;
 
-       if (page_shift < 12 || page_shift >= 32)
+       if (page_shift < (ffs(dev->caps.page_size_cap) - 1) || page_shift >= 32)
                return -EINVAL;
 
        /* All MTTs must fit in the same page */