Merge tag 'nfs-for-4.18-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[linux-2.6-block.git] / net / sunrpc / xprtrdma / frwr_ops.c
index 2d2fefbb810b5d9150e9929ebe1dfd660b946743..c040de196e13a0b2fb7d71478500a34f3fcd6169 100644 (file)
@@ -204,12 +204,22 @@ out_release:
        frwr_op_release_mr(mr);
 }
 
+/* On success, sets:
+ *     ep->rep_attr.cap.max_send_wr
+ *     ep->rep_attr.cap.max_recv_wr
+ *     cdata->max_requests
+ *     ia->ri_max_segs
+ *
+ * And these FRWR-related fields:
+ *     ia->ri_max_frwr_depth
+ *     ia->ri_mrtype
+ */
 static int
 frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
             struct rpcrdma_create_data_internal *cdata)
 {
        struct ib_device_attr *attrs = &ia->ri_device->attrs;
-       int depth, delta;
+       int max_qp_wr, depth, delta;
 
        ia->ri_mrtype = IB_MR_TYPE_MEM_REG;
        if (attrs->device_cap_flags & IB_DEVICE_SG_GAPS_REG)
@@ -243,14 +253,26 @@ frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
                } while (delta > 0);
        }
 
-       ep->rep_attr.cap.max_send_wr *= depth;
-       if (ep->rep_attr.cap.max_send_wr > attrs->max_qp_wr) {
-               cdata->max_requests = attrs->max_qp_wr / depth;
+       max_qp_wr = ia->ri_device->attrs.max_qp_wr;
+       max_qp_wr -= RPCRDMA_BACKWARD_WRS;
+       max_qp_wr -= 1;
+       if (max_qp_wr < RPCRDMA_MIN_SLOT_TABLE)
+               return -ENOMEM;
+       if (cdata->max_requests > max_qp_wr)
+               cdata->max_requests = max_qp_wr;
+       ep->rep_attr.cap.max_send_wr = cdata->max_requests * depth;
+       if (ep->rep_attr.cap.max_send_wr > max_qp_wr) {
+               cdata->max_requests = max_qp_wr / depth;
                if (!cdata->max_requests)
                        return -EINVAL;
                ep->rep_attr.cap.max_send_wr = cdata->max_requests *
                                               depth;
        }
+       ep->rep_attr.cap.max_send_wr += RPCRDMA_BACKWARD_WRS;
+       ep->rep_attr.cap.max_send_wr += 1; /* for ib_drain_sq */
+       ep->rep_attr.cap.max_recv_wr = cdata->max_requests;
+       ep->rep_attr.cap.max_recv_wr += RPCRDMA_BACKWARD_WRS;
+       ep->rep_attr.cap.max_recv_wr += 1; /* for ib_drain_rq */
 
        ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS /
                                ia->ri_max_frwr_depth);
@@ -395,6 +417,7 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
        mr->mr_nents = ib_dma_map_sg(ia->ri_device, mr->mr_sg, i, mr->mr_dir);
        if (!mr->mr_nents)
                goto out_dmamap_err;
+       trace_xprtrdma_dma_map(mr);
 
        ibmr = frwr->fr_mr;
        n = ib_map_mr_sg(ibmr, mr->mr_sg, mr->mr_nents, NULL, PAGE_SIZE);