[ofa-general] [PATCH] Fixup handling of responder_resources in cmpost.c example
Jason Gunthorpe
jgunthorpe at obsidianresearch.com
Tue Apr 22 20:52:42 PDT 2008
Sean,
For better clarity, here is an example of what I am looking at. This
modifies the cmpost example of libibcm to handle responder resources
negotiation at the ULP level. So far, all of the in-kernel and example
user space CM and RDMA CM consumers I have looked at appear to need a
patch like this.
This is why I am wondering if moving this whole common process into the
kernel and sharing it with all ULPs might be more appropriate.
----
Show a more realistic example using maximum responder resources and
what is required for that to work:
- Limit the responder resources to device capability while producing the
REP
- Use the device capability values in generating the REQ
- Match the passive side QP configuration to the REQ
- Notes on initiator_depth and responder_resources value selection
Signed-off-by: Jason Gunthorpe <jgunthorpe at obsidianresearch.com>
---
examples/cmpost.c | 48 +++++++++++++++++++++++++++++++++++++++---------
1 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/examples/cmpost.c b/examples/cmpost.c
index a85264b..1d876dd 100644
--- a/examples/cmpost.c
+++ b/examples/cmpost.c
@@ -50,6 +50,7 @@ struct cmtest {
struct ib_cm_device *cm_dev;
struct ibv_context *verbs;
struct ibv_pd *pd;
+ struct ibv_device_attr dev_attr;
/* cm info */
struct ibv_sa_path_rec path_rec;
@@ -106,7 +107,8 @@ static int post_recvs(struct cmtest_node *node)
return ret;
}
-static int modify_to_rtr(struct cmtest_node *node)
+static int modify_to_rtr(struct cmtest_node *node,
+ struct ib_cm_rep_param *rep)
{
struct ibv_qp_attr qp_attr;
int qp_attr_mask, ret;
@@ -129,6 +131,10 @@ static int modify_to_rtr(struct cmtest_node *node)
return ret;
}
qp_attr.rq_psn = node->qp->qp_num;
+ if (rep != NULL) {
+ qp_attr.max_dest_rd_atomic = rep->responder_resources;
+ qp_attr.max_rd_atomic = rep->initiator_depth;
+ }
ret = ibv_modify_qp(node->qp, &qp_attr, qp_attr_mask);
if (ret) {
printf("failed to modify QP to RTR: %d\n", ret);
@@ -167,10 +173,27 @@ static void req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
goto error1;
node = &test.nodes[test.conn_index++];
+ req = &event->param.req_rcvd;
+ memset(&rep, 0, sizeof rep);
+
+ /* Limit the responder resources requested by the remote to our
+ capabilities. Note that the kernel swaps req->responder_resources
+ and req->initiator_depth, so that req->responder_resources
+ is actually the active side's initiator_depth. */
+ rep.responder_resources = req->responder_resources;
+ if (rep.responder_resources > test.dev_attr.max_qp_rd_atom)
+ rep.responder_resources = test.dev_attr.max_qp_rd_atom;
+
+ /* Note: If this side of the connection is never going to use
+ RDMA Read then initiator_depth can be set to 0 here. */
+ rep.initiator_depth = req->initiator_depth;
+ if (rep.initiator_depth > test.dev_attr.max_qp_init_rd_atom)
+ rep.initiator_depth = test.dev_attr.max_qp_init_rd_atom;
+
node->cm_id = cm_id;
cm_id->context = node;
- ret = modify_to_rtr(node);
+ ret = modify_to_rtr(node,&rep);
if (ret)
goto error2;
@@ -178,13 +201,9 @@ static void req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
if (ret)
goto error2;
- req = &event->param.req_rcvd;
- memset(&rep, 0, sizeof rep);
rep.qp_num = node->qp->qp_num;
rep.srq = (node->qp->srq != NULL);
rep.starting_psn = node->qp->qp_num;
- rep.responder_resources = req->responder_resources;
- rep.initiator_depth = req->initiator_depth;
rep.target_ack_delay = 20;
rep.flow_control = req->flow_control;
rep.rnr_retry_count = req->rnr_retry_count;
@@ -207,7 +226,7 @@ static void rep_handler(struct cmtest_node *node, struct ib_cm_event *event)
{
int ret;
- ret = modify_to_rtr(node);
+ ret = modify_to_rtr(node,0);
if (ret)
goto error;
@@ -428,6 +447,9 @@ static int init(void)
if (!test.verbs)
return -1;
+ if (ibv_query_device(test.verbs,&test.dev_attr) != 0)
+ return -1;
+
test.cm_dev = ib_cm_open_device(test.verbs);
if (!test.cm_dev)
return -1;
@@ -671,8 +693,16 @@ static void run_client(char *dst)
memset(&req, 0, sizeof req);
req.primary_path = &test.path_rec;
req.service_id = __cpu_to_be64(0x1000);
- req.responder_resources = 1;
- req.initiator_depth = 1;
+
+ /* When choosing the responder resources for a ULP, it is usually best
+ to use the maximum value of the HCA. If the other side is not going
+ to use RDMA READ then it should zero out initator_depth in the REP
+ which will zero out the local responder_resources when we program
+ the QP. Generally, initiator_depth should be either set to 0 or
+ min(max_qp_rd_atom,max_send_wr). Use 0 if RDMA READ is never going
+ to be sent from this side. */
+ req.responder_resources = test.dev_attr.max_qp_rd_atom;
+ req.initiator_depth = test.dev_attr.max_qp_init_rd_atom;
req.remote_cm_response_timeout = 20;
req.local_cm_response_timeout = 20;
req.retry_count = 5;
--
1.5.4.2
More information about the general
mailing list