dapl/cma: fix referencing freed address
[mirror/winof/.git] / ulp / dapl2 / dapl / openib_common / qp.c
1 /*\r
2  * This Software is licensed under one of the following licenses:\r
3  *\r
4  * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
5  *    available from the Open Source Initiative, see\r
6  *    http://www.opensource.org/licenses/cpl.php.\r
7  *\r
8  * 2) under the terms of the "The BSD License" a copy of which is\r
9  *    available from the Open Source Initiative, see\r
10  *    http://www.opensource.org/licenses/bsd-license.php.\r
11  *\r
12  * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
13  *    copy of which is available from the Open Source Initiative, see\r
14  *    http://www.opensource.org/licenses/gpl-license.php.\r
15  *\r
16  * Licensee has the right to choose one of the above licenses.\r
17  *\r
18  * Redistributions of source code must retain the above copyright\r
19  * notice and one of the license notices.\r
20  *\r
21  * Redistributions in binary form must reproduce both the above copyright\r
22  * notice, one of the license notices in the documentation\r
23  * and/or other materials provided with the distribution.\r
24  */\r
25 #include "dapl.h"\r
26 #include "dapl_adapter_util.h"\r
27 \r
28 /*\r
29  * dapl_ib_qp_alloc\r
30  *\r
31  * Alloc a QP\r
32  *\r
33  * Input:\r
34  *      *ep_ptr         pointer to EP INFO\r
35  *      ib_hca_handle   provider HCA handle\r
36  *      ib_pd_handle    provider protection domain handle\r
37  *      cq_recv         provider recv CQ handle\r
38  *      cq_send         provider send CQ handle\r
39  *\r
40  * Output:\r
41  *      none\r
42  *\r
43  * Returns:\r
44  *      DAT_SUCCESS\r
45  *      DAT_INSUFFICIENT_RESOURCES\r
46  *      DAT_INTERNAL_ERROR\r
47  *\r
48  */\r
49 DAT_RETURN\r
50 dapls_ib_qp_alloc(IN DAPL_IA * ia_ptr,\r
51                   IN DAPL_EP * ep_ptr, IN DAPL_EP * ep_ctx_ptr)\r
52 {\r
53         DAT_EP_ATTR *attr;\r
54         DAPL_EVD *rcv_evd, *req_evd;\r
55         ib_cq_handle_t rcv_cq, req_cq;\r
56         ib_pd_handle_t ib_pd_handle;\r
57         struct ibv_qp_init_attr qp_create;\r
58 #ifdef _OPENIB_CMA_\r
59         dp_ib_cm_handle_t conn;\r
60 #endif\r
61         dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
62                      " qp_alloc: ia_ptr %p ep_ptr %p ep_ctx_ptr %p\n",\r
63                      ia_ptr, ep_ptr, ep_ctx_ptr);\r
64 \r
65         attr = &ep_ptr->param.ep_attr;\r
66         ib_pd_handle = ((DAPL_PZ *) ep_ptr->param.pz_handle)->pd_handle;\r
67         rcv_evd = (DAPL_EVD *) ep_ptr->param.recv_evd_handle;\r
68         req_evd = (DAPL_EVD *) ep_ptr->param.request_evd_handle;\r
69 \r
70         /* \r
71          * DAT allows usage model of EP's with no EVD's but IB does not. \r
72          * Create a CQ with zero entries under the covers to support and \r
73          * catch any invalid posting. \r
74          */\r
75         if (rcv_evd != DAT_HANDLE_NULL)\r
76                 rcv_cq = rcv_evd->ib_cq_handle;\r
77         else if (!ia_ptr->hca_ptr->ib_trans.ib_cq_empty)\r
78                 rcv_cq = ia_ptr->hca_ptr->ib_trans.ib_cq_empty;\r
79         else {\r
80                 struct ibv_comp_channel *channel;\r
81 \r
82                 channel = ibv_create_comp_channel(ia_ptr->hca_ptr->ib_hca_handle);\r
83                 if (!channel)\r
84                         return (dapl_convert_errno(ENOMEM, "create_cq"));\r
85                   \r
86                 /* Call IB verbs to create CQ */\r
87                 rcv_cq = ibv_create_cq(ia_ptr->hca_ptr->ib_hca_handle,\r
88                                        0, NULL, channel, 0);\r
89 \r
90                 if (rcv_cq == IB_INVALID_HANDLE) {\r
91                         ibv_destroy_comp_channel(channel);\r
92                         return (dapl_convert_errno(ENOMEM, "create_cq"));\r
93                 }\r
94 \r
95                 ia_ptr->hca_ptr->ib_trans.ib_cq_empty = rcv_cq;\r
96         }\r
97         if (req_evd != DAT_HANDLE_NULL)\r
98                 req_cq = req_evd->ib_cq_handle;\r
99         else\r
100                 req_cq = ia_ptr->hca_ptr->ib_trans.ib_cq_empty;\r
101 \r
102         /* \r
103          * IMPLEMENTATION NOTE:\r
104          * uDAPL allows consumers to post buffers on the EP after creation\r
105          * and before a connect request (outbound and inbound). This forces\r
106          * a binding to a device during the hca_open call and requires the\r
107          * consumer to predetermine which device to listen on or connect from.\r
108          * This restriction eliminates any option of listening or connecting \r
109          * over multiple devices. uDAPL should add API's to resolve addresses \r
110          * and bind to the device at the approriate time (before connect \r
111          * and after CR arrives). Discovery should happen at connection time \r
112          * based on addressing and not on static configuration during open.\r
113          */\r
114 \r
115 #ifdef _OPENIB_CMA_\r
116         /* Allocate CM and initialize lock */\r
117         if ((conn = dapls_ib_cm_create(ep_ptr)) == NULL)\r
118                 return (dapl_convert_errno(ENOMEM, "create_cq"));\r
119 \r
120         /* open identifies the local device; per DAT specification */\r
121         if (rdma_bind_addr(conn->cm_id,\r
122                            (struct sockaddr *)&ia_ptr->hca_ptr->hca_address))\r
123                 return (dapl_convert_errno(EAFNOSUPPORT, "create_cq"));\r
124 #endif\r
125         /* Setup attributes and create qp */\r
126         dapl_os_memzero((void *)&qp_create, sizeof(qp_create));\r
127         qp_create.send_cq = req_cq;\r
128         qp_create.cap.max_send_wr = attr->max_request_dtos;\r
129         qp_create.cap.max_send_sge = attr->max_request_iov;\r
130         qp_create.cap.max_inline_data =\r
131             ia_ptr->hca_ptr->ib_trans.max_inline_send;\r
132         qp_create.qp_type = IBV_QPT_RC;\r
133         qp_create.qp_context = (void *)ep_ptr;\r
134 \r
135 #ifdef DAT_EXTENSIONS \r
136         if (attr->service_type == DAT_IB_SERVICE_TYPE_UD) {\r
137 #ifdef _OPENIB_CMA_\r
138                 return (DAT_NOT_IMPLEMENTED);\r
139 #endif\r
140                 qp_create.qp_type = IBV_QPT_UD;\r
141                 if (attr->max_message_size >\r
142                     (128 << ia_ptr->hca_ptr->ib_trans.mtu)) {\r
143                         return (DAT_INVALID_PARAMETER | DAT_INVALID_ARG6);\r
144                 }\r
145         }\r
146 #endif\r
147         \r
148         /* ibv assumes rcv_cq is never NULL, set to req_cq */\r
149         if (rcv_cq == NULL) {\r
150                 qp_create.recv_cq = req_cq;\r
151                 qp_create.cap.max_recv_wr = 0;\r
152                 qp_create.cap.max_recv_sge = 0;\r
153         } else {\r
154                 qp_create.recv_cq = rcv_cq;\r
155                 qp_create.cap.max_recv_wr = attr->max_recv_dtos;\r
156                 qp_create.cap.max_recv_sge = attr->max_recv_iov;\r
157         }\r
158 \r
159 #ifdef _OPENIB_CMA_\r
160         if (rdma_create_qp(conn->cm_id, ib_pd_handle, &qp_create)) {\r
161                 dapls_ib_cm_free(conn, ep_ptr);\r
162                 return (dapl_convert_errno(errno, "create_qp"));\r
163         }\r
164         ep_ptr->qp_handle = conn->cm_id->qp;\r
165         ep_ptr->cm_handle = conn;\r
166         ep_ptr->qp_state = IBV_QPS_INIT;\r
167 \r
168         ep_ptr->param.local_port_qual = rdma_get_src_port(conn->cm_id);\r
169 #else\r
170         ep_ptr->qp_handle = ibv_create_qp(ib_pd_handle, &qp_create);\r
171         if (!ep_ptr->qp_handle)\r
172                 return (dapl_convert_errno(ENOMEM, "create_qp"));\r
173                 \r
174         /* Setup QP attributes for INIT state on the way out */\r
175         if (dapls_modify_qp_state(ep_ptr->qp_handle,\r
176                                   IBV_QPS_INIT, 0, 0, 0) != DAT_SUCCESS) {\r
177                 ibv_destroy_qp(ep_ptr->qp_handle);\r
178                 ep_ptr->qp_handle = IB_INVALID_HANDLE;\r
179                 return DAT_INTERNAL_ERROR;\r
180         }\r
181 #endif\r
182         dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
183                      " qp_alloc: qpn %p sq %d,%d rq %d,%d\n",\r
184                      ep_ptr->qp_handle->qp_num,\r
185                      qp_create.cap.max_send_wr, qp_create.cap.max_send_sge,\r
186                      qp_create.cap.max_recv_wr, qp_create.cap.max_recv_sge);\r
187 \r
188         return DAT_SUCCESS;\r
189 }\r
190 \r
191 /*\r
192  * dapl_ib_qp_free\r
193  *\r
194  * Free a QP\r
195  *\r
196  * Input:\r
197  *      ia_handle       IA handle\r
198  *      *ep_ptr         pointer to EP INFO\r
199  *\r
200  * Output:\r
201  *      none\r
202  *\r
203  * Returns:\r
204  *      DAT_SUCCESS\r
205  *  dapl_convert_errno\r
206  *\r
207  */\r
208 DAT_RETURN dapls_ib_qp_free(IN DAPL_IA * ia_ptr, IN DAPL_EP * ep_ptr)\r
209 {\r
210         dapl_dbg_log(DAPL_DBG_TYPE_EP, " qp_free:  ep_ptr %p qp %p\n",\r
211                      ep_ptr, ep_ptr->qp_handle);\r
212 \r
213         if (ep_ptr->cm_handle != NULL) {\r
214                 dapls_ib_cm_free(ep_ptr->cm_handle, ep_ptr);\r
215         }\r
216         \r
217         if (ep_ptr->qp_handle != NULL) {\r
218                 /* force error state to flush queue, then destroy */\r
219                 dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_ERR, 0,0,0);\r
220 \r
221                 if (ibv_destroy_qp(ep_ptr->qp_handle))\r
222                         return (dapl_convert_errno(errno, "destroy_qp"));\r
223 \r
224                 ep_ptr->qp_handle = NULL;\r
225         }\r
226 \r
227 #ifdef DAT_EXTENSIONS\r
228         /* UD endpoints can have many CR associations and will not\r
229          * set ep->cm_handle. Call provider with cm_ptr null to incidate\r
230          * UD type multi CR's for this EP. It will parse internal list\r
231          * and cleanup all associations.\r
232          */\r
233         if (ep_ptr->param.ep_attr.service_type == DAT_IB_SERVICE_TYPE_UD) \r
234                 dapls_ib_cm_free(NULL, ep_ptr);\r
235 #endif\r
236 \r
237         return DAT_SUCCESS;\r
238 }\r
239 \r
240 /*\r
241  * dapl_ib_qp_modify\r
242  *\r
243  * Set the QP to the parameters specified in an EP_PARAM\r
244  *\r
245  * The EP_PARAM structure that is provided has been\r
246  * sanitized such that only non-zero values are valid.\r
247  *\r
248  * Input:\r
249  *      ib_hca_handle           HCA handle\r
250  *      qp_handle               QP handle\r
251  *      ep_attr                 Sanitized EP Params\r
252  *\r
253  * Output:\r
254  *      none\r
255  *\r
256  * Returns:\r
257  *      DAT_SUCCESS\r
258  *      DAT_INSUFFICIENT_RESOURCES\r
259  *      DAT_INVALID_PARAMETER\r
260  *\r
261  */\r
262 DAT_RETURN\r
263 dapls_ib_qp_modify(IN DAPL_IA * ia_ptr,\r
264                    IN DAPL_EP * ep_ptr, IN DAT_EP_ATTR * attr)\r
265 {\r
266         struct ibv_qp_attr qp_attr;\r
267 \r
268         if (ep_ptr->qp_handle == IB_INVALID_HANDLE)\r
269                 return DAT_INVALID_PARAMETER;\r
270 \r
271         /* \r
272          * EP state, qp_handle state should be an indication\r
273          * of current state but the only way to be sure is with\r
274          * a user mode ibv_query_qp call which is NOT available \r
275          */\r
276 \r
277         /* move to error state if necessary */\r
278         if ((ep_ptr->qp_state == IB_QP_STATE_ERROR) &&\r
279             (ep_ptr->qp_handle->state != IBV_QPS_ERR)) {\r
280                 return (dapls_modify_qp_state(ep_ptr->qp_handle, \r
281                                               IBV_QPS_ERR, 0, 0, 0));\r
282         }\r
283 \r
284         /*\r
285          * Check if we have the right qp_state to modify attributes\r
286          */\r
287         if ((ep_ptr->qp_handle->state != IBV_QPS_RTR) &&\r
288             (ep_ptr->qp_handle->state != IBV_QPS_RTS))\r
289                 return DAT_INVALID_STATE;\r
290 \r
291         /* Adjust to current EP attributes */\r
292         dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
293         qp_attr.cap.max_send_wr = attr->max_request_dtos;\r
294         qp_attr.cap.max_recv_wr = attr->max_recv_dtos;\r
295         qp_attr.cap.max_send_sge = attr->max_request_iov;\r
296         qp_attr.cap.max_recv_sge = attr->max_recv_iov;\r
297 \r
298         dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
299                      "modify_qp: qp %p sq %d,%d, rq %d,%d\n",\r
300                      ep_ptr->qp_handle,\r
301                      qp_attr.cap.max_send_wr, qp_attr.cap.max_send_sge,\r
302                      qp_attr.cap.max_recv_wr, qp_attr.cap.max_recv_sge);\r
303 \r
304         if (ibv_modify_qp(ep_ptr->qp_handle, &qp_attr, IBV_QP_CAP)) {\r
305                 dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
306                              "modify_qp: modify ep %p qp %p failed\n",\r
307                              ep_ptr, ep_ptr->qp_handle);\r
308                 return (dapl_convert_errno(errno, "modify_qp_state"));\r
309         }\r
310 \r
311         return DAT_SUCCESS;\r
312 }\r
313 \r
314 /*\r
315  * dapls_ib_reinit_ep\r
316  *\r
317  * Move the QP to INIT state again.\r
318  *\r
319  * Input:\r
320  *      ep_ptr          DAPL_EP\r
321  *\r
322  * Output:\r
323  *      none\r
324  *\r
325  * Returns:\r
326  *      void\r
327  *\r
328  */\r
329 #if defined(_WIN32) || defined(_WIN64) || defined(_OPENIB_CMA_)\r
330 void dapls_ib_reinit_ep(IN DAPL_EP * ep_ptr)\r
331 {\r
332         /* work around bug in low level driver - 3/24/09 */\r
333         /* RTS -> RESET -> INIT -> ERROR QP transition crashes system */\r
334         if (ep_ptr->qp_handle != IB_INVALID_HANDLE) {\r
335                 dapls_ib_qp_free(ep_ptr->header.owner_ia, ep_ptr);\r
336                 dapls_ib_qp_alloc(ep_ptr->header.owner_ia, ep_ptr, ep_ptr);\r
337         }\r
338 }\r
339 #else                           // _WIN32 || _WIN64\r
340 void dapls_ib_reinit_ep(IN DAPL_EP * ep_ptr)\r
341 {\r
342         if (ep_ptr->qp_handle != IB_INVALID_HANDLE &&\r
343             ep_ptr->qp_handle->qp_type != IBV_QPT_UD) {\r
344                 /* move to RESET state and then to INIT */\r
345                 dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_RESET,0,0,0);\r
346                 dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_INIT,0,0,0);\r
347         }\r
348 }\r
349 #endif                          // _WIN32 || _WIN64\r
350 \r
351 /* \r
352  * Generic QP modify for init, reset, error, RTS, RTR\r
353  * For UD, create_ah on RTR, qkey on INIT\r
354  * CM msg provides QP attributes, info in network order\r
355  */\r
356 DAT_RETURN\r
357 dapls_modify_qp_state(IN ib_qp_handle_t         qp_handle,\r
358                       IN ib_qp_state_t          qp_state, \r
359                       IN uint32_t               qpn,\r
360                       IN uint16_t               lid,\r
361                       IN ib_gid_handle_t        gid)\r
362 {\r
363         struct ibv_qp_attr qp_attr;\r
364         enum ibv_qp_attr_mask mask = IBV_QP_STATE;\r
365         DAPL_EP *ep_ptr = (DAPL_EP *) qp_handle->qp_context;\r
366         DAPL_IA *ia_ptr = ep_ptr->header.owner_ia;\r
367         int ret;\r
368 \r
369         dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
370         qp_attr.qp_state = qp_state;\r
371         \r
372         switch (qp_state) {\r
373         case IBV_QPS_RTR:\r
374                 dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
375                                 " QPS_RTR: type %d qpn 0x%x lid 0x%x"\r
376                                 " port %d ep %p qp_state %d \n",\r
377                                 qp_handle->qp_type, \r
378                                 ntohl(qpn), ntohs(lid), \r
379                                 ia_ptr->hca_ptr->port_num,\r
380                                 ep_ptr, ep_ptr->qp_state);\r
381 \r
382                 mask |= IBV_QP_AV |\r
383                         IBV_QP_PATH_MTU |\r
384                         IBV_QP_DEST_QPN |\r
385                         IBV_QP_RQ_PSN |\r
386                         IBV_QP_MAX_DEST_RD_ATOMIC | IBV_QP_MIN_RNR_TIMER;\r
387 \r
388                 qp_attr.dest_qp_num = ntohl(qpn);\r
389                 qp_attr.rq_psn = 1;\r
390                 qp_attr.path_mtu = ia_ptr->hca_ptr->ib_trans.mtu;\r
391                 qp_attr.max_dest_rd_atomic =\r
392                         ep_ptr->param.ep_attr.max_rdma_read_out;\r
393                 qp_attr.min_rnr_timer =\r
394                         ia_ptr->hca_ptr->ib_trans.rnr_timer;\r
395 \r
396                 /* address handle. RC and UD */\r
397                 qp_attr.ah_attr.dlid = ntohs(lid);\r
398                 if (ia_ptr->hca_ptr->ib_trans.global) {\r
399                         qp_attr.ah_attr.is_global = 1;\r
400                         qp_attr.ah_attr.grh.dgid.global.subnet_prefix = \r
401                                 ntohll(gid->global.subnet_prefix);\r
402                         qp_attr.ah_attr.grh.dgid.global.interface_id = \r
403                                 ntohll(gid->global.interface_id);\r
404                         qp_attr.ah_attr.grh.hop_limit =\r
405                                 ia_ptr->hca_ptr->ib_trans.hop_limit;\r
406                         qp_attr.ah_attr.grh.traffic_class =\r
407                                 ia_ptr->hca_ptr->ib_trans.tclass;\r
408                 }\r
409                 qp_attr.ah_attr.sl = 0;\r
410                 qp_attr.ah_attr.src_path_bits = 0;\r
411                 qp_attr.ah_attr.port_num = ia_ptr->hca_ptr->port_num;\r
412 \r
413                 /* UD: already in RTR, RTS state */\r
414                 if (qp_handle->qp_type == IBV_QPT_UD) {\r
415                         mask = IBV_QP_STATE;\r
416                         if (ep_ptr->qp_state == IBV_QPS_RTR ||\r
417                                 ep_ptr->qp_state == IBV_QPS_RTS)\r
418                                 return DAT_SUCCESS;\r
419                 }\r
420                 break;\r
421         case IBV_QPS_RTS:\r
422                 if (qp_handle->qp_type == IBV_QPT_RC) {\r
423                         mask |= IBV_QP_SQ_PSN |\r
424                                 IBV_QP_TIMEOUT |\r
425                                 IBV_QP_RETRY_CNT |\r
426                                 IBV_QP_RNR_RETRY | IBV_QP_MAX_QP_RD_ATOMIC;\r
427                         qp_attr.timeout =\r
428                                 ia_ptr->hca_ptr->ib_trans.ack_timer;\r
429                         qp_attr.retry_cnt =\r
430                                 ia_ptr->hca_ptr->ib_trans.ack_retry;\r
431                         qp_attr.rnr_retry =\r
432                                 ia_ptr->hca_ptr->ib_trans.rnr_retry;\r
433                         qp_attr.max_rd_atomic =\r
434                                 ep_ptr->param.ep_attr.max_rdma_read_out;\r
435                 }\r
436                 /* RC and UD */\r
437                 qp_attr.qp_state = IBV_QPS_RTS;\r
438                 qp_attr.sq_psn = 1;\r
439 \r
440                 dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
441                                 " QPS_RTS: psn %x rd_atomic %d ack %d "\r
442                                 " retry %d rnr_retry %d ep %p qp_state %d\n",\r
443                                 qp_attr.sq_psn, qp_attr.max_rd_atomic,\r
444                                 qp_attr.timeout, qp_attr.retry_cnt,\r
445                                 qp_attr.rnr_retry, ep_ptr,\r
446                                 ep_ptr->qp_state);\r
447 \r
448                 if (qp_handle->qp_type == IBV_QPT_UD) {\r
449                         /* already RTS, multi remote AH's on QP */\r
450                         if (ep_ptr->qp_state == IBV_QPS_RTS)\r
451                                 return DAT_SUCCESS;\r
452                         else\r
453                                 mask = IBV_QP_STATE | IBV_QP_SQ_PSN;\r
454                 }\r
455                 break;\r
456         case IBV_QPS_INIT:\r
457                 mask |= IBV_QP_PKEY_INDEX | IBV_QP_PORT;\r
458                 if (qp_handle->qp_type == IBV_QPT_RC) {\r
459                         mask |= IBV_QP_ACCESS_FLAGS;\r
460                         qp_attr.qp_access_flags =\r
461                                 IBV_ACCESS_LOCAL_WRITE |\r
462                                 IBV_ACCESS_REMOTE_WRITE |\r
463                                 IBV_ACCESS_REMOTE_READ |\r
464                                 IBV_ACCESS_REMOTE_ATOMIC |\r
465                                 IBV_ACCESS_MW_BIND;\r
466                 }\r
467 \r
468                 if (qp_handle->qp_type == IBV_QPT_UD) {\r
469                         /* already INIT, multi remote AH's on QP */\r
470                         if (ep_ptr->qp_state == IBV_QPS_INIT)\r
471                                 return DAT_SUCCESS;\r
472                         mask |= IBV_QP_QKEY;\r
473                         qp_attr.qkey = DAT_UD_QKEY;\r
474                 }\r
475 \r
476                 qp_attr.pkey_index = 0;\r
477                 qp_attr.port_num = ia_ptr->hca_ptr->port_num;\r
478 \r
479                 dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
480                                 " QPS_INIT: pi %x port %x acc %x qkey 0x%x\n",\r
481                                 qp_attr.pkey_index, qp_attr.port_num,\r
482                                 qp_attr.qp_access_flags, qp_attr.qkey);\r
483                 break;\r
484         default:\r
485                 break;\r
486         }\r
487 \r
488         ret = ibv_modify_qp(qp_handle, &qp_attr, mask);\r
489         if (ret == 0) {\r
490                 ep_ptr->qp_state = qp_state;\r
491                 return DAT_SUCCESS;\r
492         } else {\r
493                 return (dapl_convert_errno(errno, "modify_qp_state"));\r
494         }\r
495 }\r
496 \r
497 /* Modify UD type QP from init, rtr, rts, info network order */\r
498 DAT_RETURN \r
499 dapls_modify_qp_ud(IN DAPL_HCA *hca, IN ib_qp_handle_t qp)\r
500 {\r
501         struct ibv_qp_attr qp_attr;\r
502 \r
503         /* modify QP, setup and prepost buffers */\r
504         dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
505         qp_attr.qp_state = IBV_QPS_INIT;\r
506         qp_attr.pkey_index = 0;\r
507         qp_attr.port_num = hca->port_num;\r
508         qp_attr.qkey = DAT_UD_QKEY;\r
509         if (ibv_modify_qp(qp, &qp_attr, \r
510                           IBV_QP_STATE          |\r
511                           IBV_QP_PKEY_INDEX     |\r
512                           IBV_QP_PORT           |\r
513                           IBV_QP_QKEY)) {\r
514                 dapl_log(DAPL_DBG_TYPE_ERR,\r
515                         " modify_ud_qp INIT: ERR %s\n", strerror(errno));\r
516                 return (dapl_convert_errno(errno, "modify_qp"));\r
517         }\r
518         dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
519         qp_attr.qp_state = IBV_QPS_RTR;\r
520         if (ibv_modify_qp(qp, &qp_attr,IBV_QP_STATE)) {\r
521                 dapl_log(DAPL_DBG_TYPE_ERR, \r
522                         " modify_ud_qp RTR: ERR %s\n", strerror(errno));\r
523                 return (dapl_convert_errno(errno, "modify_qp"));\r
524         }\r
525         dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
526         qp_attr.qp_state = IBV_QPS_RTS;\r
527         qp_attr.sq_psn = 1;\r
528         if (ibv_modify_qp(qp, &qp_attr, \r
529                           IBV_QP_STATE | IBV_QP_SQ_PSN)) {\r
530                 dapl_log(DAPL_DBG_TYPE_ERR,\r
531                         " modify_ud_qp RTS: ERR %s\n", strerror(errno));\r
532                 return (dapl_convert_errno(errno, "modify_qp"));\r
533         }\r
534         return DAT_SUCCESS;\r
535 }\r
536 \r
537 /* Create address handle for remote QP, info in network order */\r
538 ib_ah_handle_t \r
539 dapls_create_ah(IN DAPL_HCA             *hca,\r
540                 IN ib_pd_handle_t       pd,\r
541                 IN ib_qp_handle_t       qp,\r
542                 IN uint16_t             lid,\r
543                 IN ib_gid_handle_t      gid)\r
544 {\r
545         struct ibv_qp_attr qp_attr;\r
546         ib_ah_handle_t  ah;\r
547 \r
548         if (qp->qp_type != IBV_QPT_UD)\r
549                 return NULL;\r
550 \r
551         dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
552         qp_attr.qp_state = IBV_QP_STATE;\r
553 \r
554         /* address handle. RC and UD */\r
555         qp_attr.ah_attr.dlid = ntohs(lid);\r
556         if (gid != NULL) {\r
557                 dapl_log(DAPL_DBG_TYPE_CM, "dapl_create_ah: with GID\n");\r
558                 qp_attr.ah_attr.is_global = 1;\r
559                 qp_attr.ah_attr.grh.dgid.global.subnet_prefix = \r
560                                 ntohll(gid->global.subnet_prefix);\r
561                 qp_attr.ah_attr.grh.dgid.global.interface_id = \r
562                                 ntohll(gid->global.interface_id);\r
563                 qp_attr.ah_attr.grh.hop_limit = hca->ib_trans.hop_limit;\r
564                 qp_attr.ah_attr.grh.traffic_class = hca->ib_trans.tclass;\r
565         }\r
566         qp_attr.ah_attr.sl = 0;\r
567         qp_attr.ah_attr.src_path_bits = 0;\r
568         qp_attr.ah_attr.port_num = hca->port_num;\r
569 \r
570         dapl_log(DAPL_DBG_TYPE_CM, \r
571                         " dapls_create_ah: port %x lid %x pd %p ctx %p handle 0x%x\n", \r
572                         hca->port_num,qp_attr.ah_attr.dlid, pd, pd->context, pd->handle);\r
573 \r
574         /* UD: create AH for remote side */\r
575         ah = ibv_create_ah(pd, &qp_attr.ah_attr);\r
576         if (!ah) {\r
577                 dapl_log(DAPL_DBG_TYPE_ERR,\r
578                         " create_ah: ERR %s\n", strerror(errno));\r
579                 return NULL;\r
580         }\r
581 \r
582         dapl_log(DAPL_DBG_TYPE_CM, \r
583                         " dapls_create_ah: AH %p for lid %x\n", \r
584                         ah, qp_attr.ah_attr.dlid);\r
585 \r
586         return ah;\r
587 }\r
588 \r
589 /*\r
590  * Local variables:\r
591  *  c-indent-level: 4\r
592  *  c-basic-offset: 4\r
593  *  tab-width: 8\r
594  * End:\r
595  */\r