]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/sunrpc/xprtrdma/svc_rdma_transport.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / net / sunrpc / xprtrdma / svc_rdma_transport.c
index 1334de2715c28112bf4f4b77600e2e78218dc853..39652d390a9c60bc026199a7dcb5ef996bcd65ab 100644 (file)
@@ -41,6 +41,7 @@
  */
 
 #include <linux/sunrpc/svc_xprt.h>
+#include <linux/sunrpc/addr.h>
 #include <linux/sunrpc/debug.h>
 #include <linux/sunrpc/rpc_rdma.h>
 #include <linux/interrupt.h>
@@ -226,25 +227,22 @@ void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt)
        struct svcxprt_rdma *xprt = ctxt->xprt;
        struct ib_device *device = xprt->sc_cm_id->device;
        u32 lkey = xprt->sc_pd->local_dma_lkey;
-       unsigned int i, count;
+       unsigned int i;
 
-       for (count = 0, i = 0; i < ctxt->mapped_sges; i++) {
+       for (i = 0; i < ctxt->mapped_sges; i++) {
                /*
                 * Unmap the DMA addr in the SGE if the lkey matches
                 * the local_dma_lkey, otherwise, ignore it since it is
                 * an FRMR lkey and will be unmapped later when the
                 * last WR that uses it completes.
                 */
-               if (ctxt->sge[i].lkey == lkey) {
-                       count++;
+               if (ctxt->sge[i].lkey == lkey)
                        ib_dma_unmap_page(device,
                                            ctxt->sge[i].addr,
                                            ctxt->sge[i].length,
                                            ctxt->direction);
-               }
        }
        ctxt->mapped_sges = 0;
-       atomic_sub(count, &xprt->sc_dma_used);
 }
 
 void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages)
@@ -398,7 +396,6 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
 
        /* WARNING: Only wc->wr_cqe and wc->status are reliable */
        ctxt = container_of(cqe, struct svc_rdma_op_ctxt, cqe);
-       ctxt->wc_status = wc->status;
        svc_rdma_unmap_dma(ctxt);
 
        if (wc->status != IB_WC_SUCCESS)
@@ -436,7 +433,7 @@ static void svc_rdma_send_wc_common(struct svcxprt_rdma *xprt,
                goto err;
 
 out:
-       atomic_dec(&xprt->sc_sq_count);
+       atomic_inc(&xprt->sc_sq_avail);
        wake_up(&xprt->sc_send_wait);
        return;
 
@@ -946,7 +943,6 @@ void svc_rdma_put_frmr(struct svcxprt_rdma *rdma,
        if (frmr) {
                ib_dma_unmap_sg(rdma->sc_cm_id->device,
                                frmr->sg, frmr->sg_nents, frmr->direction);
-               atomic_dec(&rdma->sc_dma_used);
                spin_lock_bh(&rdma->sc_frmr_q_lock);
                WARN_ON_ONCE(!list_empty(&frmr->frmr_list));
                list_add(&frmr->frmr_list, &rdma->sc_frmr_q);
@@ -973,6 +969,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
        struct rpcrdma_connect_private pmsg;
        struct ib_qp_init_attr qp_attr;
        struct ib_device *dev;
+       struct sockaddr *sap;
        unsigned int i;
        int ret = 0;
 
@@ -1010,6 +1007,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
        newxprt->sc_rq_depth = newxprt->sc_max_requests +
                               newxprt->sc_max_bc_requests;
        newxprt->sc_sq_depth = RPCRDMA_SQ_DEPTH_MULT * newxprt->sc_rq_depth;
+       atomic_set(&newxprt->sc_sq_avail, newxprt->sc_sq_depth);
 
        if (!svc_rdma_prealloc_ctxts(newxprt))
                goto errout;
@@ -1052,18 +1050,12 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
        qp_attr.qp_type = IB_QPT_RC;
        qp_attr.send_cq = newxprt->sc_sq_cq;
        qp_attr.recv_cq = newxprt->sc_rq_cq;
-       dprintk("svcrdma: newxprt->sc_cm_id=%p, newxprt->sc_pd=%p\n"
-               "    cm_id->device=%p, sc_pd->device=%p\n"
-               "    cap.max_send_wr = %d\n"
-               "    cap.max_recv_wr = %d\n"
-               "    cap.max_send_sge = %d\n"
-               "    cap.max_recv_sge = %d\n",
-               newxprt->sc_cm_id, newxprt->sc_pd,
-               dev, newxprt->sc_pd->device,
-               qp_attr.cap.max_send_wr,
-               qp_attr.cap.max_recv_wr,
-               qp_attr.cap.max_send_sge,
-               qp_attr.cap.max_recv_sge);
+       dprintk("svcrdma: newxprt->sc_cm_id=%p, newxprt->sc_pd=%p\n",
+               newxprt->sc_cm_id, newxprt->sc_pd);
+       dprintk("    cap.max_send_wr = %d, cap.max_recv_wr = %d\n",
+               qp_attr.cap.max_send_wr, qp_attr.cap.max_recv_wr);
+       dprintk("    cap.max_send_sge = %d, cap.max_recv_sge = %d\n",
+               qp_attr.cap.max_send_sge, qp_attr.cap.max_recv_sge);
 
        ret = rdma_create_qp(newxprt->sc_cm_id, newxprt->sc_pd, &qp_attr);
        if (ret) {
@@ -1146,31 +1138,16 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
                goto errout;
        }
 
-       dprintk("svcrdma: new connection %p accepted with the following "
-               "attributes:\n"
-               "    local_ip        : %pI4\n"
-               "    local_port      : %d\n"
-               "    remote_ip       : %pI4\n"
-               "    remote_port     : %d\n"
-               "    max_sge         : %d\n"
-               "    max_sge_rd      : %d\n"
-               "    sq_depth        : %d\n"
-               "    max_requests    : %d\n"
-               "    ord             : %d\n",
-               newxprt,
-               &((struct sockaddr_in *)&newxprt->sc_cm_id->
-                        route.addr.src_addr)->sin_addr.s_addr,
-               ntohs(((struct sockaddr_in *)&newxprt->sc_cm_id->
-                      route.addr.src_addr)->sin_port),
-               &((struct sockaddr_in *)&newxprt->sc_cm_id->
-                        route.addr.dst_addr)->sin_addr.s_addr,
-               ntohs(((struct sockaddr_in *)&newxprt->sc_cm_id->
-                      route.addr.dst_addr)->sin_port),
-               newxprt->sc_max_sge,
-               newxprt->sc_max_sge_rd,
-               newxprt->sc_sq_depth,
-               newxprt->sc_max_requests,
-               newxprt->sc_ord);
+       dprintk("svcrdma: new connection %p accepted:\n", newxprt);
+       sap = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.src_addr;
+       dprintk("    local address   : %pIS:%u\n", sap, rpc_get_port(sap));
+       sap = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.dst_addr;
+       dprintk("    remote address  : %pIS:%u\n", sap, rpc_get_port(sap));
+       dprintk("    max_sge         : %d\n", newxprt->sc_max_sge);
+       dprintk("    max_sge_rd      : %d\n", newxprt->sc_max_sge_rd);
+       dprintk("    sq_depth        : %d\n", newxprt->sc_sq_depth);
+       dprintk("    max_requests    : %d\n", newxprt->sc_max_requests);
+       dprintk("    ord             : %d\n", newxprt->sc_ord);
 
        return &newxprt->sc_xprt;
 
@@ -1224,9 +1201,9 @@ static void __svc_rdma_free(struct work_struct *work)
                ib_drain_qp(rdma->sc_qp);
 
        /* We should only be called from kref_put */
-       if (atomic_read(&xprt->xpt_ref.refcount) != 0)
+       if (kref_read(&xprt->xpt_ref) != 0)
                pr_err("svcrdma: sc_xprt still in use? (%d)\n",
-                      atomic_read(&xprt->xpt_ref.refcount));
+                      kref_read(&xprt->xpt_ref));
 
        /*
         * Destroy queued, but not processed read completions. Note
@@ -1257,9 +1234,6 @@ static void __svc_rdma_free(struct work_struct *work)
        if (rdma->sc_ctxt_used != 0)
                pr_err("svcrdma: ctxt still in use? (%d)\n",
                       rdma->sc_ctxt_used);
-       if (atomic_read(&rdma->sc_dma_used) != 0)
-               pr_err("svcrdma: dma still in use? (%d)\n",
-                      atomic_read(&rdma->sc_dma_used));
 
        /* Final put of backchannel client transport */
        if (xprt->xpt_bc_xprt) {
@@ -1339,15 +1313,13 @@ int svc_rdma_send(struct svcxprt_rdma *xprt, struct ib_send_wr *wr)
 
        /* If the SQ is full, wait until an SQ entry is available */
        while (1) {
-               spin_lock_bh(&xprt->sc_lock);
-               if (xprt->sc_sq_depth < atomic_read(&xprt->sc_sq_count) + wr_count) {
-                       spin_unlock_bh(&xprt->sc_lock);
+               if ((atomic_sub_return(wr_count, &xprt->sc_sq_avail) < 0)) {
                        atomic_inc(&rdma_stat_sq_starve);
 
                        /* Wait until SQ WR available if SQ still full */
+                       atomic_add(wr_count, &xprt->sc_sq_avail);
                        wait_event(xprt->sc_send_wait,
-                                  atomic_read(&xprt->sc_sq_count) <
-                                  xprt->sc_sq_depth);
+                                  atomic_read(&xprt->sc_sq_avail) > wr_count);
                        if (test_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags))
                                return -ENOTCONN;
                        continue;
@@ -1357,21 +1329,17 @@ int svc_rdma_send(struct svcxprt_rdma *xprt, struct ib_send_wr *wr)
                        svc_xprt_get(&xprt->sc_xprt);
 
                /* Bump used SQ WR count and post */
-               atomic_add(wr_count, &xprt->sc_sq_count);
                ret = ib_post_send(xprt->sc_qp, wr, &bad_wr);
                if (ret) {
                        set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags);
-                       atomic_sub(wr_count, &xprt->sc_sq_count);
                        for (i = 0; i < wr_count; i ++)
                                svc_xprt_put(&xprt->sc_xprt);
-                       dprintk("svcrdma: failed to post SQ WR rc=%d, "
-                              "sc_sq_count=%d, sc_sq_depth=%d\n",
-                              ret, atomic_read(&xprt->sc_sq_count),
-                              xprt->sc_sq_depth);
-               }
-               spin_unlock_bh(&xprt->sc_lock);
-               if (ret)
+                       dprintk("svcrdma: failed to post SQ WR rc=%d\n", ret);
+                       dprintk("    sc_sq_avail=%d, sc_sq_depth=%d\n",
+                               atomic_read(&xprt->sc_sq_avail),
+                               xprt->sc_sq_depth);
                        wake_up(&xprt->sc_send_wait);
+               }
                break;
        }
        return ret;