Merge tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[cascardo/linux.git] / drivers / infiniband / hw / cxgb4 / qp.c
index 60cfc11..41cd688 100644 (file)
@@ -58,6 +58,31 @@ static int max_fr_immd = T4_MAX_FR_IMMD;
 module_param(max_fr_immd, int, 0644);
 MODULE_PARM_DESC(max_fr_immd, "fastreg threshold for using DSGL instead of immedate");
 
+static int alloc_ird(struct c4iw_dev *dev, u32 ird)
+{
+       int ret = 0;
+
+       spin_lock_irq(&dev->lock);
+       if (ird <= dev->avail_ird)
+               dev->avail_ird -= ird;
+       else
+               ret = -ENOMEM;
+       spin_unlock_irq(&dev->lock);
+
+       if (ret)
+               dev_warn(&dev->rdev.lldi.pdev->dev,
+                        "device IRD resources exhausted\n");
+
+       return ret;
+}
+
+static void free_ird(struct c4iw_dev *dev, int ird)
+{
+       spin_lock_irq(&dev->lock);
+       dev->avail_ird += ird;
+       spin_unlock_irq(&dev->lock);
+}
+
 static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)
 {
        unsigned long flag;
@@ -180,9 +205,9 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
        }
 
        /*
-        * RQT must be a power of 2.
+        * RQT must be a power of 2 and at least 16 deep.
         */
-       wq->rq.rqt_size = roundup_pow_of_two(wq->rq.size);
+       wq->rq.rqt_size = roundup_pow_of_two(max_t(u16, wq->rq.size, 16));
        wq->rq.rqt_hwaddr = c4iw_rqtpool_alloc(rdev, wq->rq.rqt_size);
        if (!wq->rq.rqt_hwaddr) {
                ret = -ENOMEM;
@@ -258,7 +283,8 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
        /*
         * eqsize is the number of 64B entries plus the status page size.
         */
-       eqsize = wq->sq.size * T4_SQ_NUM_SLOTS + T4_EQ_STATUS_ENTRIES;
+       eqsize = wq->sq.size * T4_SQ_NUM_SLOTS +
+               rdev->hw_queue.t4_eq_status_entries;
 
        res->u.sqrq.fetchszm_to_iqid = cpu_to_be32(
                V_FW_RI_RES_WR_HOSTFCMODE(0) |  /* no host cidx updates */
@@ -283,7 +309,8 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
        /*
         * eqsize is the number of 64B entries plus the status page size.
         */
-       eqsize = wq->rq.size * T4_RQ_NUM_SLOTS + T4_EQ_STATUS_ENTRIES;
+       eqsize = wq->rq.size * T4_RQ_NUM_SLOTS +
+               rdev->hw_queue.t4_eq_status_entries;
        res->u.sqrq.fetchszm_to_iqid = cpu_to_be32(
                V_FW_RI_RES_WR_HOSTFCMODE(0) |  /* no host cidx updates */
                V_FW_RI_RES_WR_CPRIO(0) |       /* don't keep in chip cache */
@@ -796,6 +823,11 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                                  qhp->sq_sig_all;
                swsqe->flushed = 0;
                swsqe->wr_id = wr->wr_id;
+               if (c4iw_wr_log) {
+                       swsqe->sge_ts = cxgb4_read_sge_timestamp(
+                                       qhp->rhp->rdev.lldi.ports[0]);
+                       getnstimeofday(&swsqe->host_ts);
+               }
 
                init_wr_hdr(wqe, qhp->wq.sq.pidx, fw_opcode, fw_flags, len16);
 
@@ -859,6 +891,13 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
                }
 
                qhp->wq.rq.sw_rq[qhp->wq.rq.pidx].wr_id = wr->wr_id;
+               if (c4iw_wr_log) {
+                       qhp->wq.rq.sw_rq[qhp->wq.rq.pidx].sge_ts =
+                               cxgb4_read_sge_timestamp(
+                                               qhp->rhp->rdev.lldi.ports[0]);
+                       getnstimeofday(
+                               &qhp->wq.rq.sw_rq[qhp->wq.rq.pidx].host_ts);
+               }
 
                wqe->recv.opcode = FW_RI_RECV_WR;
                wqe->recv.r1 = 0;
@@ -1215,12 +1254,20 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
        int ret;
        struct sk_buff *skb;
 
-       PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
-            qhp->ep->hwtid);
+       PDBG("%s qhp %p qid 0x%x tid %u ird %u ord %u\n", __func__, qhp,
+            qhp->wq.sq.qid, qhp->ep->hwtid, qhp->ep->ird, qhp->ep->ord);
 
        skb = alloc_skb(sizeof *wqe, GFP_KERNEL);
-       if (!skb)
-               return -ENOMEM;
+       if (!skb) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       ret = alloc_ird(rhp, qhp->attr.max_ird);
+       if (ret) {
+               qhp->attr.max_ird = 0;
+               kfree_skb(skb);
+               goto out;
+       }
        set_wr_txq(skb, CPL_PRIORITY_DATA, qhp->ep->txq_idx);
 
        wqe = (struct fw_ri_wr *)__skb_put(skb, sizeof(*wqe));
@@ -1271,10 +1318,14 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
 
        ret = c4iw_ofld_send(&rhp->rdev, skb);
        if (ret)
-               goto out;
+               goto err1;
 
        ret = c4iw_wait_for_reply(&rhp->rdev, &qhp->ep->com.wr_wait,
                                  qhp->ep->hwtid, qhp->wq.sq.qid, __func__);
+       if (!ret)
+               goto out;
+err1:
+       free_ird(rhp, qhp->attr.max_ird);
 out:
        PDBG("%s ret %d\n", __func__, ret);
        return ret;
@@ -1319,7 +1370,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
                        newattr.max_ord = attrs->max_ord;
                }
                if (mask & C4IW_QP_ATTR_MAX_IRD) {
-                       if (attrs->max_ird > c4iw_max_read_depth) {
+                       if (attrs->max_ird > cur_max_read_depth(rhp)) {
                                ret = -EINVAL;
                                goto out;
                        }
@@ -1542,6 +1593,7 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
        if (!list_empty(&qhp->db_fc_entry))
                list_del_init(&qhp->db_fc_entry);
        spin_unlock_irq(&rhp->lock);
+       free_ird(rhp, qhp->attr.max_ird);
 
        ucontext = ib_qp->uobject ?
                   to_c4iw_ucontext(ib_qp->uobject->context) : NULL;
@@ -1582,13 +1634,17 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
        if (attrs->cap.max_inline_data > T4_MAX_SEND_INLINE)
                return ERR_PTR(-EINVAL);
 
-       rqsize = roundup(attrs->cap.max_recv_wr + 1, 16);
-       if (rqsize > T4_MAX_RQ_SIZE)
+       if (attrs->cap.max_recv_wr > rhp->rdev.hw_queue.t4_max_rq_size)
                return ERR_PTR(-E2BIG);
+       rqsize = attrs->cap.max_recv_wr + 1;
+       if (rqsize < 8)
+               rqsize = 8;
 
-       sqsize = roundup(attrs->cap.max_send_wr + 1, 16);
-       if (sqsize > T4_MAX_SQ_SIZE)
+       if (attrs->cap.max_send_wr > rhp->rdev.hw_queue.t4_max_sq_size)
                return ERR_PTR(-E2BIG);
+       sqsize = attrs->cap.max_send_wr + 1;
+       if (sqsize < 8)
+               sqsize = 8;
 
        ucontext = pd->uobject ? to_c4iw_ucontext(pd->uobject->context) : NULL;
 
@@ -1596,19 +1652,20 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
        if (!qhp)
                return ERR_PTR(-ENOMEM);
        qhp->wq.sq.size = sqsize;
-       qhp->wq.sq.memsize = (sqsize + 1) * sizeof *qhp->wq.sq.queue;
+       qhp->wq.sq.memsize =
+               (sqsize + rhp->rdev.hw_queue.t4_eq_status_entries) *
+               sizeof(*qhp->wq.sq.queue) + 16 * sizeof(__be64);
        qhp->wq.sq.flush_cidx = -1;
        qhp->wq.rq.size = rqsize;
-       qhp->wq.rq.memsize = (rqsize + 1) * sizeof *qhp->wq.rq.queue;
+       qhp->wq.rq.memsize =
+               (rqsize + rhp->rdev.hw_queue.t4_eq_status_entries) *
+               sizeof(*qhp->wq.rq.queue);
 
        if (ucontext) {
                qhp->wq.sq.memsize = roundup(qhp->wq.sq.memsize, PAGE_SIZE);
                qhp->wq.rq.memsize = roundup(qhp->wq.rq.memsize, PAGE_SIZE);
        }
 
-       PDBG("%s sqsize %u sqmemsize %zu rqsize %u rqmemsize %zu\n",
-            __func__, sqsize, qhp->wq.sq.memsize, rqsize, qhp->wq.rq.memsize);
-
        ret = create_qp(&rhp->rdev, &qhp->wq, &schp->cq, &rchp->cq,
                        ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
        if (ret)
@@ -1632,8 +1689,8 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
        qhp->attr.enable_rdma_read = 1;
        qhp->attr.enable_rdma_write = 1;
        qhp->attr.enable_bind = 1;
-       qhp->attr.max_ord = 1;
-       qhp->attr.max_ird = 1;
+       qhp->attr.max_ord = 0;
+       qhp->attr.max_ird = 0;
        qhp->sq_sig_all = attrs->sq_sig_type == IB_SIGNAL_ALL_WR;
        spin_lock_init(&qhp->lock);
        mutex_init(&qhp->mutex);
@@ -1727,9 +1784,11 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
        qhp->ibqp.qp_num = qhp->wq.sq.qid;
        init_timer(&(qhp->timer));
        INIT_LIST_HEAD(&qhp->db_fc_entry);
-       PDBG("%s qhp %p sq_num_entries %d, rq_num_entries %d qpid 0x%0x\n",
-            __func__, qhp, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
-            qhp->wq.sq.qid);
+       PDBG("%s sq id %u size %u memsize %zu num_entries %u "
+            "rq id %u size %u memsize %zu num_entries %u\n", __func__,
+            qhp->wq.sq.qid, qhp->wq.sq.size, qhp->wq.sq.memsize,
+            attrs->cap.max_send_wr, qhp->wq.rq.qid, qhp->wq.rq.size,
+            qhp->wq.rq.memsize, attrs->cap.max_recv_wr);
        return &qhp->ibqp;
 err8:
        kfree(mm5);
@@ -1817,5 +1876,11 @@ int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
        memset(attr, 0, sizeof *attr);
        memset(init_attr, 0, sizeof *init_attr);
        attr->qp_state = to_ib_qp_state(qhp->attr.state);
+       init_attr->cap.max_send_wr = qhp->attr.sq_num_entries;
+       init_attr->cap.max_recv_wr = qhp->attr.rq_num_entries;
+       init_attr->cap.max_send_sge = qhp->attr.sq_max_sges;
+       init_attr->cap.max_recv_sge = qhp->attr.sq_max_sges;
+       init_attr->cap.max_inline_data = T4_MAX_SEND_INLINE;
+       init_attr->sq_sig_type = qhp->sq_sig_all ? IB_SIGNAL_ALL_WR : 0;
        return 0;
 }