bcd2f5ae9b0cab96e91528ac5326318f8bdaac84
[mirror/winof/.git] / core / al / al_qp.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\r
8  *     Redistribution and use in source and binary forms, with or\r
9  *     without modification, are permitted provided that the following\r
10  *     conditions are met:\r
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\r
16  *      - Redistributions in binary form must reproduce the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer in the documentation and/or other materials\r
19  *        provided with the distribution.\r
20  *\r
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
28  * SOFTWARE.\r
29  *\r
30  * $Id$\r
31  */\r
32 \r
33 #include <complib/cl_async_proc.h>\r
34 #include <complib/cl_memory.h>\r
35 #include <complib/cl_timer.h>\r
36 \r
37 #include "al.h"\r
38 #include "al_av.h"\r
39 #include "al_ca.h"\r
40 #include "al_cm_cep.h"\r
41 #include "al_cq.h"\r
42 #include "al_debug.h"\r
43 #if defined(EVENT_TRACING)\r
44 #ifdef offsetof\r
45 #undef offsetof\r
46 #endif\r
47 #include "al_qp.tmh"\r
48 #endif\r
49 #include "al_mad.h"\r
50 #include "al_mad_pool.h"\r
51 #include "al_mcast.h"\r
52 #include "al_mgr.h"\r
53 #include "al_mr.h"\r
54 #include "al_mw.h"\r
55 #include "al_pd.h"\r
56 #include "al_qp.h"\r
57 #include "al_query.h"\r
58 #ifdef CL_KERNEL\r
59 #include "al_smi.h"\r
60 #endif  /* CL_KERNEL */\r
61 #include "al_verbs.h"\r
62 \r
63 #include "ib_common.h"\r
64 \r
65 \r
66 #define UNBOUND_PORT_GUID               0\r
67 \r
68 \r
69 extern ib_pool_handle_t                 gh_mad_pool;\r
70 \r
71 \r
72 /*\r
73  * Function prototypes.\r
74  */\r
75 void\r
76 destroying_qp(\r
77         IN                              al_obj_t                                        *p_obj );\r
78 \r
79 void\r
80 cleanup_qp(\r
81         IN                              al_obj_t                                        *p_obj );\r
82 \r
83 void\r
84 free_qp(\r
85         IN                              al_obj_t                                        *p_obj );\r
86 \r
87 \r
88 \r
89 ib_api_status_t\r
90 init_base_qp(\r
91         IN                              ib_qp_t* const                          p_qp,\r
92         IN              const   void* const                                     qp_context,\r
93         IN              const   ib_pfn_event_cb_t                       pfn_qp_event_cb,\r
94         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf );\r
95 \r
96 ib_api_status_t\r
97 init_raw_qp(\r
98         IN              const   ib_qp_handle_t                          h_qp,\r
99         IN              const   ib_pd_handle_t                          h_pd,\r
100         IN              const   ib_net64_t                                      port_guid OPTIONAL,\r
101         IN              const   ib_qp_create_t* const           p_qp_create,\r
102         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf );\r
103 \r
104 ib_api_status_t\r
105 init_conn_qp(\r
106         IN                              al_conn_qp_t* const                     p_conn_qp,\r
107         IN              const   ib_pd_handle_t                          h_pd,\r
108         IN              const   ib_qp_create_t* const           p_qp_create,\r
109         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf );\r
110 \r
111 ib_api_status_t\r
112 init_dgrm_qp(\r
113         IN                              al_dgrm_qp_t* const                     p_dgrm_qp,\r
114         IN              const   ib_pd_handle_t                          h_pd,\r
115         IN              const   ib_qp_create_t* const           p_qp_create,\r
116         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf );\r
117 \r
118 ib_api_status_t\r
119 init_special_qp(\r
120         IN                              al_special_qp_t* const          p_special_qp,\r
121         IN              const   ib_pd_handle_t                          h_pd,\r
122         IN              const   ib_net64_t                                      port_guid,\r
123         IN              const   ib_qp_create_t* const           p_qp_create );\r
124 \r
125 ib_api_status_t\r
126 init_qp_alias(\r
127         IN                              al_qp_alias_t* const            p_qp_alias,\r
128         IN              const   ib_pd_handle_t                          h_pd,\r
129         IN              const   ib_net64_t                                      port_guid,\r
130         IN              const   ib_qp_create_t* const           p_qp_create );\r
131 \r
132 ib_api_status_t\r
133 init_mad_qp(\r
134         IN                              al_mad_qp_t* const                      p_mad_qp,\r
135         IN              const   ib_pd_handle_t                          h_pd,\r
136         IN              const   ib_qp_create_t* const           p_qp_create,\r
137         IN              const   ib_pfn_event_cb_t                       pfn_qp_event_cb );\r
138 \r
139 ib_api_status_t\r
140 init_mad_dgrm_svc(\r
141         IN              const   ib_qp_handle_t                          h_qp,\r
142         IN              const   ib_dgrm_info_t* const           p_dgrm_info );\r
143 \r
144 \r
145 ib_api_status_t\r
146 al_modify_qp(\r
147         IN              const   ib_qp_handle_t                          h_qp,\r
148         IN              const   ib_qp_mod_t* const                      p_qp_mod,\r
149         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf );\r
150 \r
151 \r
152 ib_api_status_t\r
153 init_dgrm_svc(\r
154         IN              const   ib_qp_handle_t                          h_qp,\r
155         IN              const   ib_dgrm_info_t* const           p_dgrm_info );\r
156 \r
157 ib_api_status_t\r
158 mad_qp_post_recvs(\r
159         IN                              al_mad_qp_t*    const           p_mad_qp );\r
160 \r
161 ib_api_status_t\r
162 ud_post_send(\r
163         IN              const   ib_qp_handle_t                          h_qp,\r
164         IN                              ib_send_wr_t* const                     p_send_wr,\r
165                 OUT                     ib_send_wr_t                            **pp_send_failure );\r
166 \r
167 ib_api_status_t\r
168 special_qp_post_send(\r
169         IN              const   ib_qp_handle_t                          h_qp,\r
170         IN                              ib_send_wr_t* const                     p_send_wr,\r
171                 OUT                     ib_send_wr_t                            **pp_send_failure );\r
172 \r
173 void\r
174 mad_qp_queue_mad(\r
175         IN              const   ib_qp_handle_t                          h_qp,\r
176         IN                              al_mad_wr_t* const                      p_mad_wr );\r
177 \r
178 void\r
179 mad_qp_resume_sends(\r
180         IN                              ib_qp_handle_t                          h_qp );\r
181 \r
182 void\r
183 mad_qp_flush_send(\r
184         IN                              al_mad_qp_t*                            p_mad_qp,\r
185         IN                              al_mad_wr_t* const                      p_mad_wr );\r
186 \r
187 void\r
188 mad_recv_comp_cb(\r
189         IN              const   ib_cq_handle_t                          h_cq,\r
190         IN                              void                                            *cq_context );\r
191 \r
192 void\r
193 mad_send_comp_cb(\r
194         IN              const   ib_cq_handle_t                          h_cq,\r
195         IN                              void                                            *cq_context );\r
196 \r
197 void\r
198 mad_qp_comp(\r
199         IN                              al_mad_qp_t*                            p_mad_qp,\r
200         IN              const   ib_cq_handle_t                          h_cq,\r
201         IN                              ib_wc_type_t                            wc_type );\r
202 \r
203 void\r
204 mad_qp_cq_event_cb(\r
205         IN                              ib_async_event_rec_t            *p_event_rec );\r
206 \r
207 \r
208 \r
209 /*\r
210  * Allocates a structure to store QP information.\r
211  */\r
212 ib_api_status_t\r
213 alloc_qp(\r
214         IN              const   ib_qp_type_t                            qp_type,\r
215                 OUT                     ib_qp_handle_t* const           ph_qp )\r
216 {\r
217         ib_qp_handle_t                          h_qp;\r
218 \r
219         switch( qp_type )\r
220         {\r
221         case IB_QPT_RELIABLE_CONN:\r
222         case IB_QPT_UNRELIABLE_CONN:\r
223                 h_qp = (ib_qp_handle_t)cl_zalloc( sizeof( al_conn_qp_t ) );\r
224                 break;\r
225 \r
226         case IB_QPT_UNRELIABLE_DGRM:\r
227                 h_qp = (ib_qp_handle_t)cl_zalloc( sizeof( al_dgrm_qp_t ) );\r
228                 break;\r
229 \r
230         case IB_QPT_QP0:\r
231         case IB_QPT_QP1:\r
232                 h_qp = (ib_qp_handle_t)cl_zalloc( sizeof( al_special_qp_t ) );\r
233                 break;\r
234 \r
235         case IB_QPT_RAW_IPV6:\r
236         case IB_QPT_RAW_ETHER:\r
237                 h_qp = (ib_qp_handle_t)cl_zalloc( sizeof( ib_qp_t ) );\r
238                 break;\r
239 \r
240         case IB_QPT_MAD:\r
241                 h_qp = (ib_qp_handle_t)cl_zalloc( sizeof( al_mad_qp_t ) );\r
242                 break;\r
243 \r
244         case IB_QPT_QP0_ALIAS:\r
245         case IB_QPT_QP1_ALIAS:\r
246                 h_qp = (ib_qp_handle_t)cl_zalloc( sizeof( al_qp_alias_t ) );\r
247                 break;\r
248 \r
249         default:\r
250                 CL_ASSERT( qp_type == IB_QPT_RELIABLE_CONN ||\r
251                         qp_type == IB_QPT_UNRELIABLE_CONN ||\r
252                         qp_type == IB_QPT_UNRELIABLE_DGRM ||\r
253                         qp_type == IB_QPT_QP0 ||\r
254                         qp_type == IB_QPT_QP1 ||\r
255                         qp_type == IB_QPT_RAW_IPV6 ||\r
256                         qp_type == IB_QPT_RAW_ETHER ||\r
257                         qp_type == IB_QPT_MAD ||\r
258                         qp_type == IB_QPT_QP0_ALIAS ||\r
259                         qp_type == IB_QPT_QP1_ALIAS );\r
260                 return IB_INVALID_SETTING;\r
261         }\r
262 \r
263         if( !h_qp )\r
264         {\r
265                 return IB_INSUFFICIENT_MEMORY;\r
266         }\r
267 \r
268         h_qp->type = qp_type;\r
269 \r
270         *ph_qp = h_qp;\r
271         return IB_SUCCESS;\r
272 }\r
273 \r
274 \r
275 \r
276 /*\r
277  * Initializes the QP information structure.\r
278  */\r
279 ib_api_status_t\r
280 create_qp(\r
281         IN              const   ib_pd_handle_t                          h_pd,\r
282         IN              const   ib_qp_create_t* const           p_qp_create,\r
283         IN              const   void* const                                     qp_context,\r
284         IN              const   ib_pfn_event_cb_t                       pfn_qp_event_cb,\r
285                 OUT                     ib_qp_handle_t* const           ph_qp,\r
286         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
287 {\r
288         ib_api_status_t                 status;\r
289         ib_qp_handle_t                  h_qp;\r
290 \r
291         if( !p_qp_create || !ph_qp )\r
292         {\r
293                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
294                 return IB_INVALID_PARAMETER;\r
295         }\r
296 \r
297         /* Allocate a QP. */\r
298         status = alloc_qp( p_qp_create->qp_type, &h_qp );\r
299         if( status != IB_SUCCESS )\r
300         {\r
301                 return status;\r
302         }\r
303 \r
304         /* Init the base QP first. */\r
305         status = init_base_qp( h_qp, qp_context, pfn_qp_event_cb, p_umv_buf );\r
306         if( status != IB_SUCCESS )\r
307                 return status;\r
308 \r
309         /* Initialize the QP based on its type. */\r
310         switch( h_qp->type )\r
311         {\r
312         case IB_QPT_RELIABLE_CONN:\r
313         case IB_QPT_UNRELIABLE_CONN:\r
314                 if( AL_OBJ_INVALID_HANDLE( p_qp_create->h_sq_cq, AL_OBJ_TYPE_H_CQ ) ||\r
315                         AL_OBJ_INVALID_HANDLE( p_qp_create->h_rq_cq, AL_OBJ_TYPE_H_CQ ) )\r
316                 {\r
317                         status = IB_INVALID_CQ_HANDLE;\r
318                         break;\r
319                 }\r
320                 status = init_conn_qp( (al_conn_qp_t*)h_qp, h_pd, p_qp_create, p_umv_buf );\r
321                 break;\r
322 \r
323         case IB_QPT_UNRELIABLE_DGRM:\r
324                 if( AL_OBJ_INVALID_HANDLE( p_qp_create->h_sq_cq, AL_OBJ_TYPE_H_CQ ) ||\r
325                         AL_OBJ_INVALID_HANDLE( p_qp_create->h_rq_cq, AL_OBJ_TYPE_H_CQ ) )\r
326                 {\r
327                         status = IB_INVALID_CQ_HANDLE;\r
328                         break;\r
329                 }\r
330                 status = init_dgrm_qp( (al_dgrm_qp_t*)h_qp, h_pd, p_qp_create, p_umv_buf );\r
331                 break;\r
332 \r
333         case IB_QPT_MAD:\r
334                 if( p_qp_create->h_sq_cq || p_qp_create->h_rq_cq )\r
335                 {\r
336                         status = IB_INVALID_CQ_HANDLE;\r
337                         break;\r
338                 }\r
339                 status = init_mad_qp( (al_mad_qp_t*)h_qp, h_pd, p_qp_create,\r
340                         pfn_qp_event_cb );\r
341                 break;\r
342 \r
343         default:\r
344                 CL_ASSERT( h_qp->type == IB_QPT_RELIABLE_CONN ||\r
345                         h_qp->type == IB_QPT_UNRELIABLE_CONN ||\r
346                         h_qp->type == IB_QPT_UNRELIABLE_DGRM ||\r
347                         h_qp->type == IB_QPT_MAD );\r
348                 status = IB_INVALID_SETTING;\r
349                 break;\r
350         }\r
351 \r
352         if( status != IB_SUCCESS )\r
353         {\r
354                 h_qp->obj.pfn_destroy( &h_qp->obj, NULL );\r
355                 return status;\r
356         }\r
357 \r
358         *ph_qp = h_qp;\r
359 \r
360         /*\r
361          * Note that we don't release the reference taken in init_al_obj here.\r
362          * For kernel clients, it is release in ib_create_qp.  For user-mode\r
363          * clients is is released by the proxy after the handle is extracted.\r
364          */\r
365         return IB_SUCCESS;\r
366 }\r
367 \r
368 \r
369 \r
370 ib_api_status_t\r
371 get_spl_qp(\r
372         IN              const   ib_pd_handle_t                          h_pd,\r
373         IN              const   ib_net64_t                                      port_guid,\r
374         IN              const   ib_qp_create_t* const           p_qp_create,\r
375         IN              const   void* const                                     qp_context,\r
376         IN              const   ib_pfn_event_cb_t                       pfn_qp_event_cb,\r
377                 OUT                     ib_pool_key_t* const            p_pool_key OPTIONAL,\r
378                 OUT                     ib_qp_handle_t* const           ph_qp,\r
379         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
380 {\r
381         ib_api_status_t                 status;\r
382         ib_qp_handle_t                  h_qp;\r
383 \r
384         if( !p_qp_create || !ph_qp )\r
385         {\r
386                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
387                 return IB_INVALID_PARAMETER;\r
388         }\r
389 \r
390         /* Only allow creation of the special QP types. */\r
391         switch( p_qp_create->qp_type )\r
392         {\r
393 #ifdef CL_KERNEL\r
394         case IB_QPT_QP0:\r
395         case IB_QPT_QP1:\r
396 #endif\r
397         case IB_QPT_QP0_ALIAS:\r
398         case IB_QPT_QP1_ALIAS:\r
399         case IB_QPT_RAW_IPV6:\r
400         case IB_QPT_RAW_ETHER:\r
401                 break;                          /* The QP type is valid. */\r
402 \r
403         default:\r
404                 return IB_INVALID_SETTING;\r
405         }\r
406 \r
407         /* Allocate a QP. */\r
408         status = alloc_qp( p_qp_create->qp_type, &h_qp );\r
409         if( status != IB_SUCCESS )\r
410         {\r
411                 return status;\r
412         }\r
413 \r
414         /* Init the base QP first. */\r
415         status = init_base_qp( h_qp, qp_context, pfn_qp_event_cb, p_umv_buf );\r
416         if( status != IB_SUCCESS )\r
417                 return status;\r
418 \r
419         /* Initialize the QP based on its type. */\r
420         switch( h_qp->type )\r
421         {\r
422 #ifdef CL_KERNEL\r
423         case IB_QPT_QP0:\r
424         case IB_QPT_QP1:\r
425                 if( AL_OBJ_INVALID_HANDLE( p_qp_create->h_sq_cq, AL_OBJ_TYPE_H_CQ ) ||\r
426                         AL_OBJ_INVALID_HANDLE( p_qp_create->h_rq_cq, AL_OBJ_TYPE_H_CQ ) )\r
427                 {\r
428                         status = IB_INVALID_CQ_HANDLE;\r
429                         break;\r
430                 }\r
431                 status = init_special_qp( (al_special_qp_t*)h_qp, h_pd, port_guid,\r
432                         p_qp_create );\r
433                 break;\r
434 #endif  /* CL_KERNEL */\r
435 \r
436         case IB_QPT_QP0_ALIAS:\r
437         case IB_QPT_QP1_ALIAS:\r
438                 if( p_qp_create->h_sq_cq || p_qp_create->h_rq_cq )\r
439                 {\r
440                         status = IB_INVALID_CQ_HANDLE;\r
441                         break;\r
442                 }\r
443                 status = init_alias_qp( (al_qp_alias_t*)h_qp, h_pd, port_guid,\r
444                         p_qp_create );\r
445                 if( status == IB_SUCCESS && p_pool_key )\r
446                 {\r
447                         /* Create a pool_key to access to the global MAD pool. */\r
448                         status = ib_reg_mad_pool( gh_mad_pool, h_pd,\r
449                                 &((al_qp_alias_t*)h_qp)->pool_key );\r
450                         if( status == IB_SUCCESS )\r
451                                 *p_pool_key = ((al_qp_alias_t*)h_qp)->pool_key;\r
452                 }\r
453                 break;\r
454 \r
455         case IB_QPT_RAW_IPV6:\r
456         case IB_QPT_RAW_ETHER:\r
457                 if( AL_OBJ_INVALID_HANDLE( p_qp_create->h_sq_cq, AL_OBJ_TYPE_H_CQ ) ||\r
458                         AL_OBJ_INVALID_HANDLE( p_qp_create->h_rq_cq, AL_OBJ_TYPE_H_CQ ) )\r
459                 {\r
460                         status = IB_INVALID_CQ_HANDLE;\r
461                         break;\r
462                 }\r
463                 status = init_raw_qp( h_qp, h_pd, port_guid, p_qp_create, p_umv_buf );\r
464                 break;\r
465 \r
466         default:\r
467                 CL_ASSERT( h_qp->type == IB_QPT_QP0 ||\r
468                         h_qp->type == IB_QPT_QP1 ||\r
469                         h_qp->type == IB_QPT_QP0_ALIAS ||\r
470                         h_qp->type == IB_QPT_QP1_ALIAS ||\r
471                         h_qp->type == IB_QPT_RAW_IPV6 ||\r
472                         h_qp->type == IB_QPT_RAW_ETHER );\r
473 \r
474                 status = IB_INVALID_SETTING;\r
475                 break;\r
476         }\r
477 \r
478         if( status != IB_SUCCESS )\r
479         {\r
480                 h_qp->obj.pfn_destroy( &h_qp->obj, NULL );\r
481                 return status;\r
482         }\r
483 \r
484         *ph_qp = h_qp;\r
485 \r
486         return IB_SUCCESS;\r
487 }\r
488 \r
489 \r
490 static ib_api_status_t\r
491 al_bad_modify_qp(\r
492         IN              const   ib_qp_handle_t                          h_qp,\r
493         IN              const   ib_qp_mod_t* const                      p_qp_mod,\r
494         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
495 {\r
496         UNUSED_PARAM( h_qp );\r
497         UNUSED_PARAM( p_qp_mod );\r
498         UNUSED_PARAM( p_umv_buf );\r
499         return IB_INVALID_PARAMETER;\r
500 }\r
501 \r
502 \r
503 static ib_api_status_t\r
504 al_bad_post_send(\r
505         IN              const   ib_qp_handle_t                          h_qp,\r
506         IN                              ib_send_wr_t* const                     p_send_wr,\r
507         IN                              ib_send_wr_t                            **pp_send_failure OPTIONAL )\r
508 {\r
509         UNUSED_PARAM( h_qp );\r
510         UNUSED_PARAM( p_send_wr );\r
511         UNUSED_PARAM( pp_send_failure );\r
512         return IB_INVALID_PARAMETER;\r
513 }\r
514 \r
515 \r
516 static ib_api_status_t\r
517 al_bad_post_recv(\r
518         IN              const   ib_qp_handle_t                          h_qp,\r
519         IN                              ib_recv_wr_t* const                     p_recv_wr,\r
520         IN                              ib_recv_wr_t                            **p_recv_failure OPTIONAL )\r
521 {\r
522         UNUSED_PARAM( h_qp );\r
523         UNUSED_PARAM( p_recv_wr );\r
524         UNUSED_PARAM( p_recv_failure );\r
525         return IB_INVALID_PARAMETER;\r
526 }\r
527 \r
528 \r
529 static ib_api_status_t\r
530 al_bad_init_dgrm_svc(\r
531         IN              const   ib_qp_handle_t                          h_qp,\r
532         IN              const   ib_dgrm_info_t* const           p_dgrm_info )\r
533 {\r
534         UNUSED_PARAM( h_qp );\r
535         UNUSED_PARAM( p_dgrm_info );\r
536         return IB_INVALID_PARAMETER;\r
537 }\r
538 \r
539 \r
540 static ib_api_status_t\r
541 al_bad_reg_mad_svc(\r
542         IN              const   ib_qp_handle_t                          h_qp,\r
543         IN              const   ib_mad_svc_t* const                     p_mad_svc,\r
544                 OUT                     ib_mad_svc_handle_t* const      ph_mad_svc )\r
545 {\r
546         UNUSED_PARAM( h_qp );\r
547         UNUSED_PARAM( p_mad_svc );\r
548         UNUSED_PARAM( ph_mad_svc );\r
549         return IB_INVALID_PARAMETER;\r
550 }\r
551 \r
552 \r
553 static ib_api_status_t\r
554 al_bad_dereg_mad_svc(\r
555         IN              const   ib_mad_svc_handle_t                     h_mad_svc )\r
556 {\r
557         UNUSED_PARAM( h_mad_svc );\r
558         return IB_INVALID_PARAMETER;\r
559 }\r
560 \r
561 \r
562 static void\r
563 al_bad_queue_mad(\r
564         IN              const   ib_qp_handle_t                          h_qp,\r
565         IN                              al_mad_wr_t* const                      p_mad_wr )\r
566 {\r
567         UNUSED_PARAM( h_qp );\r
568         UNUSED_PARAM( p_mad_wr );\r
569 }\r
570 \r
571 \r
572 static void\r
573 al_bad_resume_mad(\r
574         IN              const   ib_qp_handle_t                          h_qp )\r
575 {\r
576         UNUSED_PARAM( h_qp );\r
577         return;\r
578 }\r
579 \r
580 \r
581 static ib_api_status_t\r
582 al_bad_join_mcast(\r
583         IN              const   ib_qp_handle_t                          h_qp,\r
584         IN              const   ib_mcast_req_t* const           p_mcast_req )\r
585 {\r
586         UNUSED_PARAM( h_qp );\r
587         UNUSED_PARAM( p_mcast_req );\r
588         return IB_INVALID_PARAMETER;\r
589 }\r
590 \r
591 \r
592 ib_api_status_t\r
593 init_base_qp(\r
594         IN                              ib_qp_t* const                          p_qp,\r
595         IN              const   void* const                                     qp_context,\r
596         IN              const   ib_pfn_event_cb_t                       pfn_qp_event_cb,\r
597         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
598 {\r
599         ib_api_status_t                 status;\r
600         al_obj_type_t                   obj_type = AL_OBJ_TYPE_H_QP;\r
601 \r
602         CL_ASSERT( p_qp );\r
603 \r
604         if( p_umv_buf )\r
605                 obj_type |= AL_OBJ_SUBTYPE_UM_EXPORT;\r
606 \r
607         construct_al_obj( &p_qp->obj, obj_type );\r
608         status = init_al_obj( &p_qp->obj, qp_context, TRUE,\r
609                 destroying_qp, cleanup_qp, free_qp );\r
610         if( status != IB_SUCCESS )\r
611         {\r
612                 free_qp( &p_qp->obj );\r
613                 return status;\r
614         }\r
615 \r
616         p_qp->pfn_event_cb = pfn_qp_event_cb;\r
617 \r
618         /*\r
619          * All function pointers should be invalid.  They will be set by\r
620          * derived QP types where appropriate.\r
621          */\r
622         p_qp->pfn_modify_qp = al_bad_modify_qp;\r
623         p_qp->pfn_post_recv = al_bad_post_recv;\r
624         p_qp->pfn_post_send = al_bad_post_send;\r
625         p_qp->pfn_reg_mad_svc = al_bad_reg_mad_svc;\r
626         p_qp->pfn_dereg_mad_svc = al_bad_dereg_mad_svc;\r
627         p_qp->pfn_queue_mad = al_bad_queue_mad;\r
628         p_qp->pfn_resume_mad = al_bad_resume_mad;\r
629         p_qp->pfn_init_dgrm_svc = al_bad_init_dgrm_svc;\r
630         p_qp->pfn_join_mcast = al_bad_join_mcast;\r
631 \r
632         if( p_qp->type == IB_QPT_RELIABLE_CONN ||\r
633                 p_qp->type == IB_QPT_UNRELIABLE_CONN )\r
634         {\r
635                 ((al_conn_qp_t*)p_qp)->cid = AL_INVALID_CID;\r
636         }\r
637 \r
638         return status;\r
639 }\r
640 \r
641 \r
642 \r
643 ib_api_status_t\r
644 init_raw_qp(\r
645         IN              const   ib_qp_handle_t                          h_qp,\r
646         IN              const   ib_pd_handle_t                          h_pd,\r
647         IN              const   ib_net64_t                                      port_guid OPTIONAL,\r
648         IN              const   ib_qp_create_t* const           p_qp_create,\r
649         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
650 {\r
651         ib_api_status_t                         status;\r
652         ib_qp_create_t                          qp_create;\r
653         ib_qp_attr_t                            qp_attr;\r
654         uint8_t                                         port_num;\r
655 \r
656         status = attach_al_obj( &h_pd->obj, &h_qp->obj );\r
657         if( status != IB_SUCCESS )\r
658                 return status;\r
659 \r
660         /* Convert AL handles to CI handles. */\r
661         qp_create = *p_qp_create;\r
662         convert_qp_handle( qp_create );\r
663 \r
664         /* Clear the QP attributes to ensure non-set values are 0. */\r
665         cl_memclr( &qp_attr, sizeof( ib_qp_attr_t ) );\r
666 \r
667         h_qp->port_guid = port_guid;\r
668 \r
669         /*\r
670          * Allocate a QP from the channel adapter.  Note that these calls\r
671          * set the send and receive pointers appropriately for posting\r
672          * work requests.\r
673          */\r
674         if( port_guid == UNBOUND_PORT_GUID )\r
675         {\r
676                 status =\r
677                         verbs_create_qp( h_pd, h_qp, &qp_create, &qp_attr, p_umv_buf );\r
678         }\r
679         else\r
680         {\r
681                 status = get_port_num( h_pd->obj.p_ci_ca, port_guid, &port_num );\r
682                 if( status == IB_SUCCESS )\r
683                 {\r
684                         status = verbs_get_spl_qp( h_pd, port_num, h_qp,\r
685                                 &qp_create, &qp_attr );\r
686                 }\r
687         }\r
688         if( status != IB_SUCCESS )\r
689         {\r
690                 return status;\r
691         }\r
692 \r
693         /* Override function pointers. */\r
694         h_qp->pfn_modify_qp = al_modify_qp;\r
695 \r
696         if( h_qp->type == IB_QPT_UNRELIABLE_DGRM ||\r
697                 h_qp->type == IB_QPT_QP0 ||\r
698                 h_qp->type == IB_QPT_QP1 )\r
699         {\r
700                 /* We have to mess with the AV handles. */\r
701                 h_qp->pfn_ud_post_send = h_qp->pfn_post_send;\r
702                 h_qp->h_ud_send_qp = h_qp->h_send_qp;\r
703 \r
704                 h_qp->pfn_post_send = ud_post_send;\r
705                 h_qp->h_send_qp = h_qp;\r
706         }\r
707 \r
708         h_qp->h_recv_cq = p_qp_create->h_rq_cq;\r
709         h_qp->h_send_cq = p_qp_create->h_sq_cq;\r
710 \r
711         h_qp->recv_cq_rel.p_child_obj = (cl_obj_t*)h_qp;\r
712         h_qp->send_cq_rel.p_child_obj = (cl_obj_t*)h_qp;\r
713 \r
714         cq_attach_qp( h_qp->h_recv_cq, &h_qp->recv_cq_rel );\r
715         cq_attach_qp( h_qp->h_send_cq, &h_qp->send_cq_rel );\r
716 \r
717         h_qp->num = qp_attr.num;\r
718 \r
719         return IB_SUCCESS;\r
720 }\r
721 \r
722 \r
723 \r
724 ib_api_status_t\r
725 init_conn_qp(\r
726         IN                              al_conn_qp_t* const                     p_conn_qp,\r
727         IN              const   ib_pd_handle_t                          h_pd,\r
728         IN              const   ib_qp_create_t* const           p_qp_create,\r
729         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
730 {\r
731         ib_api_status_t                         status;\r
732         CL_ASSERT( p_conn_qp );\r
733 \r
734         /* Initialize the inherited QP first. */\r
735         status = init_raw_qp( &p_conn_qp->qp, h_pd, UNBOUND_PORT_GUID,\r
736                 p_qp_create, p_umv_buf );\r
737 \r
738 \r
739         return status;\r
740 }\r
741 \r
742 \r
743 \r
744 ib_api_status_t\r
745 init_dgrm_qp(\r
746         IN                              al_dgrm_qp_t* const                     p_dgrm_qp,\r
747         IN              const   ib_pd_handle_t                          h_pd,\r
748         IN              const   ib_qp_create_t* const           p_qp_create,\r
749         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
750 {\r
751         ib_api_status_t                         status;\r
752         CL_ASSERT( p_dgrm_qp );\r
753 \r
754         /* Initialize the inherited QP first. */\r
755         status = init_raw_qp( p_dgrm_qp, h_pd, UNBOUND_PORT_GUID,\r
756                 p_qp_create, p_umv_buf );\r
757         if( status != IB_SUCCESS )\r
758         {\r
759                 return status;\r
760         }\r
761 \r
762         /* Override function pointers. */\r
763         p_dgrm_qp->pfn_init_dgrm_svc = init_dgrm_svc;\r
764         p_dgrm_qp->pfn_join_mcast = al_join_mcast;\r
765 \r
766         return IB_SUCCESS;\r
767 }\r
768 \r
769 \r
770 #ifdef CL_KERNEL\r
771 ib_api_status_t\r
772 init_special_qp(\r
773         IN                              al_special_qp_t* const          p_special_qp,\r
774         IN              const   ib_pd_handle_t                          h_pd,\r
775         IN              const   ib_net64_t                                      port_guid,\r
776         IN              const   ib_qp_create_t* const           p_qp_create )\r
777 {\r
778         ib_api_status_t                         status;\r
779         CL_ASSERT( p_special_qp );\r
780 \r
781         /* Construct the special QP. */\r
782         cl_qlist_init( &p_special_qp->to_send_queue );\r
783 \r
784         /* Initialize the inherited QP first. */\r
785         status =\r
786                 init_raw_qp( &p_special_qp->qp, h_pd, port_guid, p_qp_create, NULL );\r
787         if( status != IB_SUCCESS )\r
788         {\r
789                 return status;\r
790         }\r
791 \r
792         /* Override function pointers. */\r
793         p_special_qp->qp.pfn_init_dgrm_svc = init_dgrm_svc;\r
794         p_special_qp->qp.pfn_queue_mad = special_qp_queue_mad;\r
795         p_special_qp->qp.pfn_resume_mad = special_qp_resume_sends;\r
796 \r
797         return IB_SUCCESS;\r
798 }\r
799 \r
800 \r
801 ib_api_status_t\r
802 init_qp_alias(\r
803         IN                              al_qp_alias_t* const            p_qp_alias,\r
804         IN              const   ib_pd_handle_t                          h_pd,\r
805         IN              const   ib_net64_t                                      port_guid,\r
806         IN              const   ib_qp_create_t* const           p_qp_create )\r
807 {\r
808         ib_api_status_t                         status;\r
809 \r
810         CL_ASSERT( p_qp_alias );\r
811         UNUSED_PARAM( p_qp_create );\r
812 \r
813         if( h_pd->type != IB_PDT_ALIAS )\r
814         {\r
815                 return IB_INVALID_PD_HANDLE;\r
816         }\r
817 \r
818         status = attach_al_obj( &h_pd->obj, &p_qp_alias->qp.obj );\r
819         if( status != IB_SUCCESS )\r
820                 return status;\r
821 \r
822         switch( p_qp_alias->qp.type )\r
823         {\r
824         case IB_QPT_QP0_ALIAS:\r
825                 status = acquire_smi_disp( port_guid, &p_qp_alias->h_mad_disp );\r
826                 break;\r
827 \r
828         case IB_QPT_QP1_ALIAS:\r
829                 status = acquire_gsi_disp( port_guid, &p_qp_alias->h_mad_disp );\r
830                 break;\r
831 \r
832         default:\r
833                 CL_ASSERT( p_qp_alias->qp.type == IB_QPT_QP0_ALIAS ||\r
834                         p_qp_alias->qp.type == IB_QPT_QP1_ALIAS );\r
835                 return IB_ERROR;\r
836         }\r
837 \r
838         if( status != IB_SUCCESS )\r
839                 return status;\r
840 \r
841         /* Get a copy of the QP used by the MAD dispatcher. */\r
842         ref_al_obj( &p_qp_alias->h_mad_disp->h_qp->obj );\r
843         p_qp_alias->qp.h_ci_qp = p_qp_alias->h_mad_disp->h_qp->h_ci_qp;\r
844 \r
845         /* Override function pointers. */\r
846         p_qp_alias->qp.pfn_reg_mad_svc = reg_mad_svc;\r
847 \r
848         return IB_SUCCESS;\r
849 }\r
850 #endif  /* CL_KERNEL */\r
851 \r
852 \r
853 \r
854 ib_api_status_t\r
855 init_mad_qp(\r
856         IN                              al_mad_qp_t* const                      p_mad_qp,\r
857         IN              const   ib_pd_handle_t                          h_pd,\r
858         IN              const   ib_qp_create_t* const           p_qp_create,\r
859         IN              const   ib_pfn_event_cb_t                       pfn_qp_event_cb )\r
860 {\r
861         ib_cq_create_t                          cq_create;\r
862         ib_qp_create_t                          qp_create;\r
863         ib_al_handle_t                          h_al;\r
864         ib_ca_handle_t                          h_ca;\r
865         ib_api_status_t                         status;\r
866 \r
867         CL_ASSERT( p_mad_qp );\r
868 \r
869         /* Initialize the send and receive tracking queues. */\r
870         cl_qlist_init( &p_mad_qp->to_send_queue );\r
871         cl_qlist_init( &p_mad_qp->send_queue );\r
872         cl_qlist_init( &p_mad_qp->recv_queue );\r
873 \r
874         /* The CQ handles must be NULL when creating a MAD queue pair. */\r
875         if( p_qp_create->h_sq_cq || p_qp_create->h_rq_cq )\r
876         {\r
877                 return IB_INVALID_SETTING;\r
878         }\r
879 \r
880         /* Initialize the CQs used with the MAD QP. */\r
881         cl_memclr( &cq_create, sizeof( ib_cq_create_t ) );\r
882 \r
883         /* Create the send CQ. */\r
884         cq_create.size = p_qp_create->sq_depth;\r
885         cq_create.pfn_comp_cb = mad_send_comp_cb;\r
886 \r
887         status = ib_create_cq( h_pd->obj.p_ci_ca->h_ca, &cq_create,\r
888                 p_mad_qp, mad_qp_cq_event_cb, &p_mad_qp->h_send_cq );\r
889 \r
890         if( status != IB_SUCCESS )\r
891         {\r
892                 return status;\r
893         }\r
894 \r
895         /* Reference the MAD QP on behalf of ib_create_cq. */\r
896         ref_al_obj( &p_mad_qp->qp.obj );\r
897 \r
898         /* Create the receive CQ. */\r
899         cq_create.size = p_qp_create->rq_depth;\r
900         cq_create.pfn_comp_cb = mad_recv_comp_cb;\r
901 \r
902         h_ca = PARENT_STRUCT( h_pd->obj.p_parent_obj, ib_ca_t, obj );\r
903         status = ib_create_cq( h_ca, &cq_create, p_mad_qp, mad_qp_cq_event_cb,\r
904                 &p_mad_qp->h_recv_cq );\r
905 \r
906         if( status != IB_SUCCESS )\r
907         {\r
908                 return status;\r
909         }\r
910 \r
911         /* Reference the MAD QP on behalf of ib_create_cq. */\r
912         ref_al_obj( &p_mad_qp->qp.obj );\r
913 \r
914         /* Save the requested receive queue depth.  This is used to post MADs. */\r
915         p_mad_qp->max_rq_depth = p_qp_create->rq_depth;\r
916 \r
917         /* Allocate a datagram QP for the MAD QP. */\r
918         qp_create = *p_qp_create;\r
919         qp_create.qp_type = IB_QPT_UNRELIABLE_DGRM;\r
920         qp_create.sq_sge = 1;\r
921         qp_create.rq_sge = 1;\r
922         qp_create.h_rq_cq = p_mad_qp->h_recv_cq;\r
923         qp_create.h_sq_cq = p_mad_qp->h_send_cq;\r
924 \r
925         status = ib_create_qp( h_pd, &qp_create, p_mad_qp, pfn_qp_event_cb,\r
926                 &p_mad_qp->h_dgrm_qp );\r
927 \r
928         if( status != IB_SUCCESS )\r
929         {\r
930                 return status;\r
931         }\r
932 \r
933         /* Reference the MAD QP on behalf of ib_create_qp. */\r
934         ref_al_obj( &p_mad_qp->qp.obj );\r
935 \r
936         /* Create the MAD dispatch service. */\r
937         status = create_mad_disp( &p_mad_qp->qp.obj, &p_mad_qp->qp,\r
938                 &p_mad_qp->h_mad_disp );\r
939         if( status != IB_SUCCESS )\r
940         {\r
941                 return status;\r
942         }\r
943 \r
944         /* Override function pointers. */\r
945         p_mad_qp->qp.pfn_init_dgrm_svc = init_mad_dgrm_svc;\r
946         p_mad_qp->qp.pfn_queue_mad = mad_qp_queue_mad;\r
947         p_mad_qp->qp.pfn_resume_mad = mad_qp_resume_sends;\r
948         p_mad_qp->qp.pfn_reg_mad_svc = reg_mad_svc;\r
949 \r
950         /* The client's AL handle is the grandparent of the PD. */\r
951         h_al = PARENT_STRUCT( h_pd->obj.p_parent_obj->p_parent_obj, ib_al_t, obj );\r
952 \r
953         /* Create a receive MAD pool. */\r
954         status = ib_create_mad_pool( h_al, p_mad_qp->max_rq_depth + 16, 0, 16,\r
955                 &p_mad_qp->h_pool );\r
956 \r
957         if (status != IB_SUCCESS)\r
958         {\r
959                 return status;\r
960         }\r
961 \r
962         /*\r
963          * The MAD pool is a child of the client's AL instance.  If the client\r
964          * closes AL, the MAD pool will be destroyed before the MAD queue pair.\r
965          * Therefore, we hold a reference on the MAD pool to keep it from being\r
966          * destroyed until the MAD queue pair is destroyed.  Refer to the MAD\r
967          * queue pair cleanup code.\r
968          */\r
969         ref_al_obj( &p_mad_qp->h_pool->obj );\r
970 \r
971         /* Register the MAD pool with the PD. */\r
972         status = ib_reg_mad_pool( p_mad_qp->h_pool, h_pd, &p_mad_qp->pool_key );\r
973 \r
974         if (status != IB_SUCCESS)\r
975         {\r
976                 return status;\r
977         }\r
978 \r
979         /*\r
980          * Attach the MAD queue pair to the protection domain.  This must be\r
981          * done after creating the datagram queue pair and the MAD pool to set\r
982          * the correct order of object destruction.\r
983          */\r
984         status = attach_al_obj( &h_pd->obj, &p_mad_qp->qp.obj );\r
985         \r
986         /* Get a copy of the CI datagram QP for ib_query_qp. */\r
987         p_mad_qp->qp.h_ci_qp = p_mad_qp->h_dgrm_qp->h_ci_qp;\r
988 \r
989         return status;\r
990 }\r
991 \r
992 \r
993 \r
994 ib_api_status_t\r
995 ib_destroy_qp(\r
996         IN              const   ib_qp_handle_t                          h_qp,\r
997         IN              const   ib_pfn_destroy_cb_t                     pfn_destroy_cb OPTIONAL )\r
998 {\r
999         AL_ENTER( AL_DBG_QP );\r
1000 \r
1001         if( AL_OBJ_INVALID_HANDLE( h_qp, AL_OBJ_TYPE_H_QP ) )\r
1002         {\r
1003                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
1004                 return IB_INVALID_QP_HANDLE;\r
1005         }\r
1006 \r
1007         ref_al_obj( &h_qp->obj );\r
1008         h_qp->obj.pfn_destroy( &h_qp->obj, pfn_destroy_cb );\r
1009 \r
1010         AL_EXIT( AL_DBG_QP );\r
1011         return IB_SUCCESS;\r
1012 }\r
1013 \r
1014 \r
1015 \r
1016 /*\r
1017  * Release any resources that must be cleaned up immediately, such as\r
1018  * any AL resources acquired by calling through the main API.\r
1019  */\r
1020 void\r
1021 destroying_qp(\r
1022         IN                              al_obj_t                                        *p_obj )\r
1023 {\r
1024         ib_qp_handle_t                  h_qp;\r
1025         al_mad_qp_t                             *p_mad_qp;\r
1026         al_qp_alias_t                   *p_qp_alias;\r
1027         net32_t                                 cid;\r
1028 \r
1029         CL_ASSERT( p_obj );\r
1030         h_qp = PARENT_STRUCT( p_obj, ib_qp_t, obj );\r
1031 \r
1032         switch( h_qp->type )\r
1033         {\r
1034         case IB_QPT_MAD:\r
1035                 /* Destroy QP and CQ services required for MAD QP support. */\r
1036                 p_mad_qp = PARENT_STRUCT( h_qp, al_mad_qp_t, qp );\r
1037 \r
1038                 if( p_mad_qp->h_dgrm_qp )\r
1039                 {\r
1040                         ib_destroy_qp( p_mad_qp->h_dgrm_qp,\r
1041                                 (ib_pfn_destroy_cb_t)deref_al_obj );\r
1042                         p_mad_qp->qp.h_ci_qp = NULL;\r
1043                 }\r
1044 \r
1045                 if( p_mad_qp->h_recv_cq )\r
1046                 {\r
1047                         ib_destroy_cq( p_mad_qp->h_recv_cq,\r
1048                                 (ib_pfn_destroy_cb_t)deref_al_obj );\r
1049                 }\r
1050 \r
1051                 if( p_mad_qp->h_send_cq )\r
1052                 {\r
1053                         ib_destroy_cq( p_mad_qp->h_send_cq,\r
1054                                 (ib_pfn_destroy_cb_t)deref_al_obj );\r
1055                 }\r
1056                 break;\r
1057 \r
1058         case IB_QPT_QP0_ALIAS:\r
1059         case IB_QPT_QP1_ALIAS:\r
1060                 p_qp_alias = PARENT_STRUCT( h_qp, al_qp_alias_t, qp );\r
1061 \r
1062                 if( p_qp_alias->pool_key )\r
1063                 {\r
1064                         ib_api_status_t         status;\r
1065                         /* Deregister the pool_key. */\r
1066                         ref_al_obj( &p_qp_alias->pool_key->obj );\r
1067                         status = dereg_mad_pool( p_qp_alias->pool_key, AL_KEY_ALIAS );\r
1068                         if( status != IB_SUCCESS )\r
1069                         {\r
1070                                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("dereg_mad_pool returned %s.\n",\r
1071                                         ib_get_err_str(status)) );\r
1072                                 deref_al_obj( &p_qp_alias->pool_key->obj );\r
1073                         }\r
1074                         p_qp_alias->pool_key = NULL;\r
1075                 }\r
1076 \r
1077                 if( p_qp_alias->qp.h_ci_qp )\r
1078                 {\r
1079                         deref_al_obj( &p_qp_alias->h_mad_disp->h_qp->obj );\r
1080                         p_qp_alias->qp.h_ci_qp = NULL;\r
1081                 }\r
1082 \r
1083                 /*\r
1084                  * If the pool_key still exists here, then the QP is being destroyed\r
1085                  * by destroying its parent (the PD).  Destruction of the PD will also\r
1086                  * destroy the pool_key.\r
1087                  */\r
1088 \r
1089                 if( p_qp_alias->h_mad_disp )\r
1090                         deref_al_obj( &p_qp_alias->h_mad_disp->obj );\r
1091                 break;\r
1092 \r
1093         case IB_QPT_RELIABLE_CONN:\r
1094         case IB_QPT_UNRELIABLE_CONN:\r
1095                 cid = cl_atomic_xchg(\r
1096                         &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID );\r
1097                 if( cid != AL_INVALID_CID )\r
1098                 {\r
1099                         ref_al_obj( &h_qp->obj );\r
1100                         if( al_destroy_cep(\r
1101                                 h_qp->obj.h_al, cid, deref_al_obj ) != IB_SUCCESS )\r
1102                         {\r
1103                                 deref_al_obj( &h_qp->obj );\r
1104                         }\r
1105                 }\r
1106 \r
1107                 /* Fall through. */\r
1108         case IB_QPT_UNRELIABLE_DGRM:\r
1109         default:\r
1110                 /* Multicast membership gets cleaned up by object hierarchy. */\r
1111                 cq_detach_qp( h_qp->h_recv_cq, &h_qp->recv_cq_rel );\r
1112                 cq_detach_qp( h_qp->h_send_cq, &h_qp->send_cq_rel );\r
1113         }\r
1114 }\r
1115 \r
1116 \r
1117 \r
1118 /*\r
1119  * Release any HW resources.\r
1120  */\r
1121 void\r
1122 cleanup_qp(\r
1123         IN                              al_obj_t                                        *p_obj )\r
1124 {\r
1125         ib_qp_handle_t                  h_qp;\r
1126         al_mad_qp_t*                    p_mad_qp;\r
1127         al_mad_wr_t*                    p_mad_wr;\r
1128         cl_list_item_t*                 p_list_item;\r
1129         al_mad_element_t*               p_al_mad;\r
1130         ib_api_status_t                 status;\r
1131 \r
1132         CL_ASSERT( p_obj );\r
1133         h_qp = PARENT_STRUCT( p_obj, ib_qp_t, obj );\r
1134 \r
1135         if( verbs_check_qp( h_qp ) )\r
1136         {\r
1137                 status = verbs_destroy_qp( h_qp );\r
1138                 if( status != IB_SUCCESS )\r
1139                 {\r
1140                         AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
1141                                 ("verbs_destroy_qp failed with status %s.\n",\r
1142                                 ib_get_err_str(status)) );\r
1143                 }\r
1144                 h_qp->h_ci_qp = NULL;\r
1145         }\r
1146 \r
1147         if( h_qp->type == IB_QPT_MAD )\r
1148         {\r
1149                 /* All MAD queue pair operations are complete. */\r
1150                 p_mad_qp = PARENT_STRUCT( h_qp, al_mad_qp_t, qp );\r
1151 \r
1152                 /* Append the pending MAD send queue to the posted MAD send queue. */\r
1153                 cl_qlist_insert_list_tail( &p_mad_qp->send_queue,\r
1154                         &p_mad_qp->to_send_queue );\r
1155 \r
1156                 /* Complete all MAD sends as "flushed". */\r
1157                 for( p_list_item = cl_qlist_remove_head( &p_mad_qp->send_queue );\r
1158                          p_list_item != cl_qlist_end( &p_mad_qp->send_queue );\r
1159                          p_list_item = cl_qlist_remove_head( &p_mad_qp->send_queue ) )\r
1160                 {\r
1161                         p_mad_wr = PARENT_STRUCT( p_list_item, al_mad_wr_t, list_item );\r
1162                         mad_qp_flush_send( p_mad_qp, p_mad_wr );\r
1163                 }\r
1164 \r
1165                 /* Return any posted receive MAD elements to the pool. */\r
1166                 for( p_list_item = cl_qlist_remove_head( &p_mad_qp->recv_queue );\r
1167                          p_list_item != cl_qlist_end( &p_mad_qp->recv_queue );\r
1168                          p_list_item = cl_qlist_remove_head( &p_mad_qp->recv_queue ) )\r
1169                 {\r
1170                         p_al_mad = PARENT_STRUCT( p_list_item, al_mad_element_t,\r
1171                                 list_item );\r
1172 \r
1173                         status = ib_put_mad( &p_al_mad->element );\r
1174                         CL_ASSERT( status == IB_SUCCESS );\r
1175                 }\r
1176 \r
1177                 if( p_mad_qp->h_pool )\r
1178                 {\r
1179                         /*\r
1180                          * Destroy the receive MAD pool.  If the client has closed the\r
1181                          * AL instance, the MAD pool should already be destroying.  In\r
1182                          * this case, we simply release our reference on the pool to\r
1183                          * allow it to cleanup and deallocate.  Otherwise, we initiate\r
1184                          * the destruction of the MAD pool and release our reference.\r
1185                          */\r
1186                         cl_spinlock_acquire( &p_mad_qp->h_pool->obj.lock );\r
1187                         if( p_mad_qp->h_pool->obj.state == CL_DESTROYING )\r
1188                         {\r
1189                                 cl_spinlock_release( &p_mad_qp->h_pool->obj.lock );\r
1190                         }\r
1191                         else\r
1192                         {\r
1193                                 cl_spinlock_release( &p_mad_qp->h_pool->obj.lock );\r
1194                                 ib_destroy_mad_pool( p_mad_qp->h_pool );\r
1195                         }\r
1196                         deref_al_obj( &p_mad_qp->h_pool->obj );\r
1197                 }\r
1198         }\r
1199         else\r
1200         {\r
1201                 if( h_qp->h_recv_cq )\r
1202                         deref_al_obj( &h_qp->h_recv_cq->obj );\r
1203                 if( h_qp->h_send_cq )\r
1204                         deref_al_obj( &h_qp->h_send_cq->obj );\r
1205         }\r
1206 }\r
1207 \r
1208 \r
1209 \r
1210 void\r
1211 free_qp(\r
1212         IN                              al_obj_t                                        *p_obj )\r
1213 {\r
1214         ib_qp_handle_t                  h_qp;\r
1215 \r
1216         CL_ASSERT( p_obj );\r
1217         h_qp = PARENT_STRUCT( p_obj, ib_qp_t, obj );\r
1218 \r
1219         destroy_al_obj( p_obj );\r
1220         cl_free( h_qp );\r
1221 }\r
1222 \r
1223 \r
1224 \r
1225 ib_api_status_t\r
1226 ib_query_qp(\r
1227         IN              const   ib_qp_handle_t                          h_qp,\r
1228                 OUT                     ib_qp_attr_t* const                     p_qp_attr )\r
1229 {\r
1230         return query_qp( h_qp, p_qp_attr, NULL );\r
1231 }\r
1232 \r
1233 \r
1234 ib_api_status_t\r
1235 query_qp(\r
1236         IN              const   ib_qp_handle_t                          h_qp,\r
1237                 OUT                     ib_qp_attr_t* const                     p_qp_attr,\r
1238         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
1239 {\r
1240         ib_api_status_t                 status;\r
1241 \r
1242         AL_ENTER( AL_DBG_QP );\r
1243 \r
1244         if( AL_OBJ_INVALID_HANDLE( h_qp, AL_OBJ_TYPE_H_QP ) )\r
1245         {\r
1246                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
1247                 return IB_INVALID_QP_HANDLE;\r
1248         }\r
1249         if( !p_qp_attr )\r
1250         {\r
1251                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
1252                 return IB_INVALID_PARAMETER;\r
1253         }\r
1254 \r
1255         status = verbs_query_qp( h_qp, p_qp_attr );\r
1256         if( status != IB_SUCCESS )\r
1257         {\r
1258                 AL_EXIT( AL_DBG_QP );\r
1259                 return status;\r
1260         }\r
1261 \r
1262         /* Convert to using AL's handles. */\r
1263         p_qp_attr->h_pd = PARENT_STRUCT( h_qp->obj.p_parent_obj, ib_pd_t, obj );\r
1264         p_qp_attr->h_rq_cq = h_qp->h_recv_cq;\r
1265         p_qp_attr->h_sq_cq = h_qp->h_send_cq;\r
1266         p_qp_attr->qp_type = h_qp->type;\r
1267 \r
1268         AL_EXIT( AL_DBG_QP );\r
1269         return IB_SUCCESS;\r
1270 }\r
1271 \r
1272 \r
1273 \r
1274 ib_api_status_t\r
1275 ib_modify_qp(\r
1276         IN              const   ib_qp_handle_t                          h_qp,\r
1277         IN              const   ib_qp_mod_t* const                      p_qp_mod )\r
1278 {\r
1279         return modify_qp( h_qp, p_qp_mod, NULL );\r
1280 }\r
1281 \r
1282 \r
1283 \r
1284 ib_api_status_t\r
1285 modify_qp(\r
1286         IN              const   ib_qp_handle_t                          h_qp,\r
1287         IN              const   ib_qp_mod_t* const                      p_qp_mod,\r
1288         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
1289 {\r
1290         ib_api_status_t                 status;\r
1291 \r
1292         AL_ENTER( AL_DBG_QP );\r
1293 \r
1294         if( AL_OBJ_INVALID_HANDLE( h_qp, AL_OBJ_TYPE_H_QP ) )\r
1295         {\r
1296                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
1297                 return IB_INVALID_QP_HANDLE;\r
1298         }\r
1299         if( !p_qp_mod )\r
1300         {\r
1301                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
1302                 return IB_INVALID_PARAMETER;\r
1303         }\r
1304 \r
1305         status = h_qp->pfn_modify_qp( h_qp, p_qp_mod, p_umv_buf );\r
1306 \r
1307         AL_EXIT( AL_DBG_QP );\r
1308         return status;\r
1309 }\r
1310 \r
1311 \r
1312 \r
1313 ib_api_status_t\r
1314 al_modify_qp(\r
1315         IN              const   ib_qp_handle_t                          h_qp,\r
1316         IN              const   ib_qp_mod_t* const                      p_qp_mod,\r
1317         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
1318 {\r
1319         ib_api_status_t                 status;\r
1320         ib_qp_attr_t                    qp_attr;\r
1321 \r
1322         CL_ASSERT( h_qp );\r
1323 \r
1324 #ifdef CL_KERNEL\r
1325         /* Only allow ERROR and RESET state changes during timewait. */\r
1326         if( (h_qp->type == IB_QPT_RELIABLE_CONN ||\r
1327                 h_qp->type == IB_QPT_UNRELIABLE_CONN) &&\r
1328                 p_qp_mod->req_state != IB_QPS_ERROR &&\r
1329                 p_qp_mod->req_state != IB_QPS_RESET &&\r
1330                 p_qp_mod->req_state != IB_QPS_INIT &&\r
1331                 cl_get_time_stamp() < h_qp->timewait )\r
1332         {\r
1333                 return IB_QP_IN_TIMEWAIT;\r
1334         }\r
1335 #endif  /* CL_KERNEL */\r
1336 \r
1337         /* Modify the actual QP attributes. */\r
1338         status = verbs_modify_qp( h_qp, p_qp_mod, qp_attr );\r
1339 \r
1340         /* Record the QP state if the modify was successful. */\r
1341         if( status == IB_SUCCESS )\r
1342                 h_qp->state = p_qp_mod->req_state;\r
1343 \r
1344         return status;\r
1345 }\r
1346 \r
1347 \r
1348 \r
1349 ib_api_status_t\r
1350 ib_init_dgrm_svc(\r
1351         IN              const   ib_qp_handle_t                          h_qp,\r
1352         IN              const   ib_dgrm_info_t* const           p_dgrm_info OPTIONAL )\r
1353 {\r
1354         ib_api_status_t                 status;\r
1355 \r
1356         AL_ENTER( AL_DBG_QP );\r
1357 \r
1358         if( AL_OBJ_INVALID_HANDLE( h_qp, AL_OBJ_TYPE_H_QP ) )\r
1359         {\r
1360                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
1361                 return IB_INVALID_QP_HANDLE;\r
1362         }\r
1363 \r
1364         switch( h_qp->type )\r
1365         {\r
1366         case IB_QPT_QP0:\r
1367         case IB_QPT_QP1:\r
1368         case IB_QPT_RAW_IPV6:\r
1369         case IB_QPT_RAW_ETHER:\r
1370                 break;\r
1371 \r
1372         case IB_QPT_UNRELIABLE_DGRM:\r
1373         case IB_QPT_MAD:\r
1374                 if( !p_dgrm_info )\r
1375                 {\r
1376                         AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
1377                                 ("IB_INVALID_PARAMETER\n") );\r
1378                         return IB_INVALID_PARAMETER;\r
1379                 }\r
1380                 break;\r
1381 \r
1382         default:\r
1383                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
1384                 return IB_INVALID_PARAMETER;\r
1385         }\r
1386 \r
1387         status = h_qp->pfn_init_dgrm_svc( h_qp, p_dgrm_info );\r
1388 \r
1389         AL_EXIT( AL_DBG_QP );\r
1390         return status;\r
1391 }\r
1392 \r
1393 \r
1394 \r
1395 /*\r
1396  * Initialize a datagram QP to send and receive datagrams.\r
1397  */\r
1398 ib_api_status_t\r
1399 init_dgrm_svc(\r
1400         IN              const   ib_qp_handle_t                          h_qp,\r
1401         IN              const   ib_dgrm_info_t* const           p_dgrm_info OPTIONAL )\r
1402 {\r
1403         al_dgrm_qp_t                    *p_dgrm_qp;\r
1404         ib_qp_mod_t                             qp_mod;\r
1405         ib_api_status_t                 status;\r
1406 \r
1407         CL_ASSERT( h_qp );\r
1408 \r
1409         p_dgrm_qp = (al_dgrm_qp_t*)h_qp;\r
1410 \r
1411         /* Change to the RESET state. */\r
1412         cl_memclr( &qp_mod, sizeof( ib_qp_mod_t ) );\r
1413         qp_mod.req_state = IB_QPS_RESET;\r
1414 \r
1415         status = ib_modify_qp( h_qp, &qp_mod );\r
1416         if( status != IB_SUCCESS )\r
1417         {\r
1418                 return status;\r
1419         }\r
1420 \r
1421         /* Change to the INIT state. */\r
1422         cl_memclr( &qp_mod, sizeof( ib_qp_mod_t ) );\r
1423         qp_mod.req_state = IB_QPS_INIT;\r
1424         if( p_dgrm_info )\r
1425         {\r
1426                 qp_mod.state.init.qkey = p_dgrm_info->qkey;\r
1427                 qp_mod.state.init.pkey_index = p_dgrm_info->pkey_index;\r
1428                 status = get_port_num( h_qp->obj.p_ci_ca, p_dgrm_info->port_guid,\r
1429                         &qp_mod.state.init.primary_port );\r
1430         }\r
1431         else\r
1432         {\r
1433                 if( h_qp->type == IB_QPT_QP0 )\r
1434                         qp_mod.state.init.qkey = 0;\r
1435                 else\r
1436                         qp_mod.state.init.qkey = IB_QP1_WELL_KNOWN_Q_KEY;\r
1437                 status = get_port_num( h_qp->obj.p_ci_ca, h_qp->port_guid,\r
1438                         &qp_mod.state.init.primary_port );\r
1439         }\r
1440         if( status != IB_SUCCESS )\r
1441         {\r
1442                 return status;\r
1443         }\r
1444 \r
1445         status = ib_modify_qp( h_qp, &qp_mod );\r
1446         if( status != IB_SUCCESS )\r
1447         {\r
1448                 return status;\r
1449         }\r
1450 \r
1451         /* Change to the RTR state. */\r
1452         cl_memclr( &qp_mod, sizeof( ib_qp_mod_t ) );\r
1453         qp_mod.req_state = IB_QPS_RTR;\r
1454 \r
1455         status = ib_modify_qp( h_qp, &qp_mod );\r
1456         if( status != IB_SUCCESS )\r
1457         {\r
1458                 return status;\r
1459         }\r
1460 \r
1461         /* Change to the RTS state. */\r
1462         cl_memclr( &qp_mod, sizeof( ib_qp_mod_t ) );\r
1463         qp_mod.req_state = IB_QPS_RTS;\r
1464         qp_mod.state.rts.sq_psn = CL_HTON32(cl_get_time_stamp_sec() & 0x00ffffff);\r
1465         status = ib_modify_qp( h_qp, &qp_mod );\r
1466 \r
1467         return status;\r
1468 }\r
1469 \r
1470 \r
1471 \r
1472 ib_api_status_t\r
1473 init_mad_dgrm_svc(\r
1474         IN              const   ib_qp_handle_t                          h_qp,\r
1475         IN              const   ib_dgrm_info_t* const           p_dgrm_info )\r
1476 {\r
1477         al_mad_qp_t                             *p_mad_qp;\r
1478         ib_api_status_t                 status;\r
1479 \r
1480         CL_ASSERT( h_qp );\r
1481 \r
1482         p_mad_qp = (al_mad_qp_t*)h_qp;\r
1483         status = ib_init_dgrm_svc( p_mad_qp->h_dgrm_qp, p_dgrm_info );\r
1484         if( status != IB_SUCCESS )\r
1485         {\r
1486                 return status;\r
1487         }\r
1488 \r
1489         /* Post receive buffers. */\r
1490         status = mad_qp_post_recvs( p_mad_qp );\r
1491         if (status != IB_SUCCESS)\r
1492         {\r
1493                 return status;\r
1494         }\r
1495 \r
1496         /* Force a completion callback to rearm the CQs. */\r
1497         mad_send_comp_cb( p_mad_qp->h_send_cq, p_mad_qp );\r
1498         mad_recv_comp_cb( p_mad_qp->h_recv_cq, p_mad_qp );\r
1499 \r
1500         return status;\r
1501 }\r
1502 \r
1503 \r
1504 \r
1505 ib_api_status_t\r
1506 ib_reg_mad_svc(\r
1507         IN              const   ib_qp_handle_t                          h_qp,\r
1508         IN              const   ib_mad_svc_t* const                     p_mad_svc,\r
1509                 OUT                     ib_mad_svc_handle_t* const      ph_mad_svc )\r
1510 {\r
1511         ib_api_status_t                 status;\r
1512 \r
1513         AL_ENTER( AL_DBG_MAD_SVC );\r
1514 \r
1515         if( AL_OBJ_INVALID_HANDLE( h_qp, AL_OBJ_TYPE_H_QP ) )\r
1516         {\r
1517                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
1518                 return IB_INVALID_QP_HANDLE;\r
1519         }\r
1520 \r
1521         status = h_qp->pfn_reg_mad_svc( h_qp, p_mad_svc, ph_mad_svc );\r
1522 \r
1523         /* Release the reference taken in init_al_obj. */\r
1524         if( status == IB_SUCCESS )\r
1525                 deref_al_obj( &(*ph_mad_svc)->obj );\r
1526 \r
1527         AL_EXIT( AL_DBG_MAD_SVC );\r
1528         return status;\r
1529 }\r
1530 \r
1531 \r
1532 ib_api_status_t\r
1533 ib_join_mcast(\r
1534         IN              const   ib_qp_handle_t                          h_qp,\r
1535         IN              const   ib_mcast_req_t* const           p_mcast_req )\r
1536 {\r
1537         ib_api_status_t                 status;\r
1538 \r
1539         AL_ENTER( AL_DBG_MCAST );\r
1540 \r
1541         if( AL_OBJ_INVALID_HANDLE( h_qp, AL_OBJ_TYPE_H_QP ) )\r
1542         {\r
1543                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
1544                 return IB_INVALID_QP_HANDLE;\r
1545         }\r
1546         if( !p_mcast_req )\r
1547         {\r
1548                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
1549                 return IB_INVALID_PARAMETER;\r
1550         }\r
1551 \r
1552         status = h_qp->pfn_join_mcast( h_qp, p_mcast_req );\r
1553 \r
1554         AL_EXIT( AL_DBG_MCAST );\r
1555         return status;\r
1556 }\r
1557 \r
1558 \r
1559 \r
1560 /*\r
1561  * Post a work request to the send queue of the QP.\r
1562  */\r
1563 ib_api_status_t\r
1564 ib_post_send(\r
1565         IN              const   ib_qp_handle_t                          h_qp,\r
1566         IN                              ib_send_wr_t* const                     p_send_wr,\r
1567                 OUT                     ib_send_wr_t                            **pp_send_failure OPTIONAL )\r
1568 {\r
1569         ib_api_status_t                 status;\r
1570         PERF_DECLARE( IbPostSend );\r
1571         PERF_DECLARE( PostSend );\r
1572 \r
1573         cl_perf_start( IbPostSend );\r
1574         AL_ENTER( AL_DBG_QP );\r
1575 \r
1576         if( AL_OBJ_INVALID_HANDLE( h_qp, AL_OBJ_TYPE_H_QP ) )\r
1577         {\r
1578                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
1579                 return IB_INVALID_QP_HANDLE;\r
1580         }\r
1581         if( !p_send_wr || ( p_send_wr->p_next && !pp_send_failure ) )\r
1582         {\r
1583                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
1584                 return IB_INVALID_PARAMETER;\r
1585         }\r
1586 \r
1587         cl_perf_start( PostSend );\r
1588         status =\r
1589                 h_qp->pfn_post_send( h_qp->h_send_qp, p_send_wr, pp_send_failure );\r
1590         cl_perf_stop( &g_perf, PostSend );\r
1591 \r
1592         AL_EXIT( AL_DBG_QP );\r
1593         cl_perf_stop( &g_perf, IbPostSend );\r
1594         return status;\r
1595 }\r
1596 \r
1597 \r
1598 \r
1599 ib_api_status_t\r
1600 ud_post_send(\r
1601         IN              const   ib_qp_handle_t                          h_qp,\r
1602         IN                              ib_send_wr_t* const                     p_send_wr,\r
1603                 OUT                     ib_send_wr_t                            **pp_send_failure )\r
1604 {\r
1605         ib_api_status_t                 status;\r
1606         ib_send_wr_t                    *p_wr;\r
1607 \r
1608         CL_ASSERT( h_qp );\r
1609 \r
1610         /* Convert all AV handles for verb provider usage. */\r
1611         for( p_wr = p_send_wr; p_wr; p_wr = p_wr->p_next )\r
1612         {\r
1613                 CL_ASSERT( p_wr->dgrm.ud.h_av );\r
1614                 p_wr->dgrm.ud.rsvd = p_wr->dgrm.ud.h_av;\r
1615                 p_wr->dgrm.ud.h_av = convert_av_handle( h_qp, p_wr->dgrm.ud.h_av );\r
1616         }\r
1617 \r
1618         status = h_qp->pfn_ud_post_send(\r
1619                 h_qp->h_ud_send_qp, p_send_wr, pp_send_failure );\r
1620 \r
1621         /* Restore all AV handles. */\r
1622         for( p_wr = p_send_wr; p_wr; p_wr = p_wr->p_next )\r
1623                 p_wr->dgrm.ud.h_av = (ib_av_handle_t)p_wr->dgrm.ud.rsvd;\r
1624 \r
1625         return status;\r
1626 }\r
1627 \r
1628 \r
1629 \r
1630 #ifdef CL_KERNEL\r
1631 /*\r
1632  * Post a work request to the send queue of a special QP.\r
1633  * The special QP is owned by the GSA or SMA, so care must be taken to prevent\r
1634  * overruning the QP by multiple owners.\r
1635  */\r
1636 void\r
1637 special_qp_queue_mad(\r
1638         IN              const   ib_qp_handle_t                          h_qp,\r
1639         IN                              al_mad_wr_t* const                      p_mad_wr )\r
1640 {\r
1641         al_special_qp_t*                p_special_qp;\r
1642 \r
1643         CL_ASSERT( h_qp );\r
1644         CL_ASSERT( p_mad_wr );\r
1645 \r
1646         p_special_qp = (al_special_qp_t*)h_qp;\r
1647 \r
1648         /* Queue the send work request. */\r
1649         cl_spinlock_acquire( &h_qp->obj.lock );\r
1650         cl_qlist_insert_tail( &p_special_qp->to_send_queue, &p_mad_wr->list_item );\r
1651         cl_spinlock_release( &h_qp->obj.lock );\r
1652 }\r
1653 \r
1654 \r
1655 \r
1656 void\r
1657 special_qp_resume_sends(\r
1658         IN              const   ib_qp_handle_t                          h_qp )\r
1659 {\r
1660         al_special_qp_t*                p_special_qp;\r
1661         cl_list_item_t*                 p_list_item;\r
1662         al_mad_wr_t*                    p_mad_wr;\r
1663         ib_api_status_t                 status;\r
1664 \r
1665         CL_ASSERT( h_qp );\r
1666         p_special_qp = (al_special_qp_t*)h_qp;\r
1667 \r
1668         cl_spinlock_acquire( &p_special_qp->qp.obj.lock );\r
1669 \r
1670         for( p_list_item = cl_qlist_remove_head( &p_special_qp->to_send_queue );\r
1671                  p_list_item != cl_qlist_end( &p_special_qp->to_send_queue );\r
1672                  p_list_item = cl_qlist_remove_head( &p_special_qp->to_send_queue ) )\r
1673         {\r
1674                 p_mad_wr = PARENT_STRUCT( p_list_item, al_mad_wr_t, list_item );\r
1675 \r
1676                 cl_spinlock_release( &p_special_qp->qp.obj.lock );\r
1677                 status = spl_qp_svc_send( &p_special_qp->qp, &p_mad_wr->send_wr );\r
1678                 cl_spinlock_acquire( &p_special_qp->qp.obj.lock );\r
1679 \r
1680                 if( status != IB_SUCCESS )\r
1681                 {\r
1682                         cl_qlist_insert_head( &p_special_qp->to_send_queue, p_list_item );\r
1683                         break;\r
1684                 }\r
1685         }\r
1686 \r
1687         cl_spinlock_release( &p_special_qp->qp.obj.lock );\r
1688 }\r
1689 #endif  /* CL_KERNEL */\r
1690 \r
1691 \r
1692 void\r
1693 mad_qp_queue_mad(\r
1694         IN              const   ib_qp_handle_t                          h_qp,\r
1695         IN                              al_mad_wr_t* const                      p_mad_wr )\r
1696 {\r
1697         al_mad_qp_t                             *p_mad_qp;\r
1698 \r
1699         CL_ASSERT( h_qp );\r
1700         p_mad_qp = (al_mad_qp_t*)h_qp;\r
1701 \r
1702         /* Queue the send work request on the to_send_queue. */\r
1703         cl_spinlock_acquire( &p_mad_qp->qp.obj.lock );\r
1704         cl_qlist_insert_tail( &p_mad_qp->to_send_queue, &p_mad_wr->list_item );\r
1705         cl_spinlock_release( &p_mad_qp->qp.obj.lock );\r
1706 }\r
1707 \r
1708 \r
1709 \r
1710 void\r
1711 mad_qp_resume_sends(\r
1712         IN                              ib_qp_handle_t                          h_qp )\r
1713 {\r
1714         al_mad_qp_t                             *p_mad_qp;\r
1715         cl_list_item_t*                 p_list_item;\r
1716         al_mad_wr_t*                    p_mad_wr;\r
1717         ib_api_status_t                 status;\r
1718 \r
1719         CL_ASSERT( h_qp );\r
1720 \r
1721         p_mad_qp = (al_mad_qp_t*)h_qp;\r
1722 \r
1723         cl_spinlock_acquire( &p_mad_qp->qp.obj.lock );\r
1724 \r
1725         /* Do not post sends if the MAD queue pair is being destroyed. */\r
1726         if( p_mad_qp->qp.obj.state == CL_DESTROYING )\r
1727         {\r
1728                 cl_spinlock_release( &p_mad_qp->qp.obj.lock );\r
1729                 return;\r
1730         }\r
1731 \r
1732         for( p_list_item = cl_qlist_remove_head( &p_mad_qp->to_send_queue );\r
1733                  p_list_item != cl_qlist_end( &p_mad_qp->to_send_queue );\r
1734                  p_list_item = cl_qlist_remove_head( &p_mad_qp->to_send_queue ) )\r
1735         {\r
1736                 p_mad_wr = PARENT_STRUCT( p_list_item, al_mad_wr_t, list_item );\r
1737 \r
1738                 /* Always generate send completions. */\r
1739                 p_mad_wr->send_wr.send_opt |= IB_SEND_OPT_SIGNALED;\r
1740 \r
1741                 status = ib_post_send( p_mad_qp->h_dgrm_qp, &p_mad_wr->send_wr, NULL );\r
1742 \r
1743                 if( status == IB_SUCCESS )\r
1744                 {\r
1745                         /* Queue the MAD work request on the send tracking queue. */\r
1746                         cl_qlist_insert_tail( &p_mad_qp->send_queue, &p_mad_wr->list_item );\r
1747                 }\r
1748                 else\r
1749                 {\r
1750                         /* Re-queue the send work request on the to_send_queue. */\r
1751                         cl_qlist_insert_head( &p_mad_qp->to_send_queue, p_list_item );\r
1752                         break;\r
1753                 }\r
1754         }\r
1755 \r
1756         cl_spinlock_release( &p_mad_qp->qp.obj.lock );\r
1757 }\r
1758 \r
1759 \r
1760 \r
1761 void\r
1762 mad_qp_flush_send(\r
1763         IN                              al_mad_qp_t*                            p_mad_qp,\r
1764         IN                              al_mad_wr_t* const                      p_mad_wr )\r
1765 {\r
1766         ib_wc_t                                 wc;\r
1767 \r
1768         cl_memclr( &wc, sizeof( ib_wc_t ) );\r
1769         wc.wr_id = p_mad_wr->send_wr.wr_id;\r
1770         wc.wc_type = IB_WC_SEND;\r
1771         wc.status = IB_WCS_WR_FLUSHED_ERR;\r
1772 \r
1773         mad_disp_send_done( p_mad_qp->h_mad_disp, p_mad_wr, &wc );\r
1774 }\r
1775 \r
1776 \r
1777 \r
1778 ib_api_status_t\r
1779 ib_post_recv(\r
1780         IN              const   ib_qp_handle_t                          h_qp,\r
1781         IN                              ib_recv_wr_t* const                     p_recv_wr,\r
1782                 OUT                     ib_recv_wr_t                            **pp_recv_failure OPTIONAL )\r
1783 {\r
1784         ib_api_status_t                 status;\r
1785 \r
1786         AL_ENTER( AL_DBG_QP );\r
1787 \r
1788         if( AL_OBJ_INVALID_HANDLE( h_qp, AL_OBJ_TYPE_H_QP ) )\r
1789         {\r
1790                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
1791                 return IB_INVALID_QP_HANDLE;\r
1792         }\r
1793         if( !p_recv_wr || ( p_recv_wr->p_next && !pp_recv_failure ) )\r
1794         {\r
1795                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
1796                 return IB_INVALID_PARAMETER;\r
1797         }\r
1798 \r
1799         status =\r
1800                 h_qp->pfn_post_recv( h_qp->h_recv_qp, p_recv_wr, pp_recv_failure );\r
1801 \r
1802         AL_EXIT( AL_DBG_QP );\r
1803         return status;\r
1804 }\r
1805 \r
1806 \r
1807 \r
1808 /*\r
1809  * Post receive buffers to a MAD QP.\r
1810  */\r
1811 ib_api_status_t\r
1812 mad_qp_post_recvs(\r
1813         IN                              al_mad_qp_t*    const           p_mad_qp )\r
1814 {\r
1815         ib_mad_element_t*               p_mad_element;\r
1816         al_mad_element_t*               p_al_element;\r
1817         ib_recv_wr_t                    recv_wr;\r
1818         ib_api_status_t                 status = IB_SUCCESS;\r
1819 \r
1820         CL_ASSERT( p_mad_qp );\r
1821 \r
1822         /* Attempt to post receive buffers up to the max_rq_depth limit. */\r
1823         cl_spinlock_acquire( &p_mad_qp->qp.obj.lock );\r
1824         while( p_mad_qp->cur_rq_depth < (int32_t)p_mad_qp->max_rq_depth )\r
1825         {\r
1826                 /* Get a MAD element from the pool. */\r
1827                 status = ib_get_mad( p_mad_qp->pool_key, MAD_BLOCK_SIZE,\r
1828                         &p_mad_element );\r
1829 \r
1830                 if( status != IB_SUCCESS ) break;\r
1831 \r
1832                 p_al_element = PARENT_STRUCT( p_mad_element, al_mad_element_t,\r
1833                         element );\r
1834 \r
1835                 /* Build the receive work request. */\r
1836                 recv_wr.p_next   = NULL;\r
1837                 recv_wr.wr_id    = (uintn_t)p_al_element;\r
1838                 recv_wr.num_ds = 1;\r
1839                 recv_wr.ds_array = &p_al_element->grh_ds;\r
1840 \r
1841                 /* Queue the receive on the service tracking list. */\r
1842                 cl_qlist_insert_tail( &p_mad_qp->recv_queue, &p_al_element->list_item );\r
1843 \r
1844                 /* Post the receive. */\r
1845                 status = ib_post_recv( p_mad_qp->h_dgrm_qp, &recv_wr, NULL );\r
1846 \r
1847                 if( status != IB_SUCCESS )\r
1848                 {\r
1849                         cl_qlist_remove_item( &p_mad_qp->recv_queue,\r
1850                                 &p_al_element->list_item );\r
1851 \r
1852                         ib_put_mad( p_mad_element );\r
1853                         break;\r
1854                 }\r
1855 \r
1856                 cl_atomic_inc( &p_mad_qp->cur_rq_depth );\r
1857         }\r
1858         cl_spinlock_release( &p_mad_qp->qp.obj.lock );\r
1859 \r
1860         return status;\r
1861 }\r
1862 \r
1863 \r
1864 \r
1865 void\r
1866 mad_recv_comp_cb(\r
1867         IN              const   ib_cq_handle_t                          h_cq,\r
1868         IN                              void                                            *cq_context )\r
1869 {\r
1870         al_mad_qp_t                             *p_mad_qp;\r
1871 \r
1872         CL_ASSERT( cq_context );\r
1873         p_mad_qp = (al_mad_qp_t*)cq_context;\r
1874 \r
1875         CL_ASSERT( h_cq == p_mad_qp->h_recv_cq );\r
1876         mad_qp_comp( p_mad_qp, h_cq, IB_WC_RECV );\r
1877 }\r
1878 \r
1879 \r
1880 \r
1881 void\r
1882 mad_send_comp_cb(\r
1883         IN              const   ib_cq_handle_t                          h_cq,\r
1884         IN                              void                                            *cq_context )\r
1885 {\r
1886         al_mad_qp_t                             *p_mad_qp;\r
1887 \r
1888         CL_ASSERT( cq_context );\r
1889         p_mad_qp = (al_mad_qp_t*)cq_context;\r
1890 \r
1891         CL_ASSERT( h_cq == p_mad_qp->h_send_cq );\r
1892         mad_qp_comp( p_mad_qp, h_cq, IB_WC_SEND );\r
1893 \r
1894         /* Continue processing any queued MADs on the QP. */\r
1895         mad_qp_resume_sends( &p_mad_qp->qp );\r
1896 }\r
1897 \r
1898 \r
1899 \r
1900 void\r
1901 mad_qp_comp(\r
1902         IN                              al_mad_qp_t*                            p_mad_qp,\r
1903         IN              const   ib_cq_handle_t                          h_cq,\r
1904         IN                              ib_wc_type_t                            wc_type )\r
1905 {\r
1906         ib_wc_t                                 wc;\r
1907         ib_wc_t*                                p_free_wc = &wc;\r
1908         ib_wc_t*                                p_done_wc;\r
1909         al_mad_wr_t*                    p_mad_wr;\r
1910         al_mad_element_t*               p_al_mad;\r
1911         ib_mad_element_t*               p_mad_element;\r
1912         ib_api_status_t                 status;\r
1913 \r
1914         CL_ASSERT( p_mad_qp );\r
1915         CL_ASSERT( h_cq );\r
1916 \r
1917         /* Rearm the CQ before polling to avoid missing completions. */\r
1918         status = ib_rearm_cq( h_cq, FALSE );\r
1919         CL_ASSERT( status == IB_SUCCESS );\r
1920 \r
1921         wc.p_next = NULL;\r
1922         /* Process work completions. */\r
1923         while( ib_poll_cq( h_cq, &p_free_wc, &p_done_wc ) == IB_SUCCESS )\r
1924         {\r
1925                 /* Process completions one at a time. */\r
1926 \r
1927                 /*\r
1928                  * Process the work completion.  Per IBA specification, the\r
1929                  * wc.wc_type is undefined if wc.status is not IB_WCS_SUCCESS.\r
1930                  * Use the wc_type function parameter instead of wc.wc_type.\r
1931                  */\r
1932                 switch( wc_type )\r
1933                 {\r
1934                 case IB_WC_SEND:\r
1935                         /* Get a pointer to the MAD work request. */\r
1936                         p_mad_wr = (al_mad_wr_t*)((uintn_t)wc.wr_id);\r
1937 \r
1938                         /* Remove the MAD work request from the send tracking queue. */\r
1939                         cl_spinlock_acquire( &p_mad_qp->qp.obj.lock );\r
1940                         cl_qlist_remove_item( &p_mad_qp->send_queue, &p_mad_wr->list_item );\r
1941                         cl_spinlock_release( &p_mad_qp->qp.obj.lock );\r
1942 \r
1943                         /* Report the send completion to the dispatcher. */\r
1944                         mad_disp_send_done( p_mad_qp->h_mad_disp, p_mad_wr, &wc );\r
1945                         break;\r
1946 \r
1947                 case IB_WC_RECV:\r
1948                         /* A receive buffer was consumed. */\r
1949                         cl_atomic_dec( &p_mad_qp->cur_rq_depth );\r
1950 \r
1951                         /* Replenish the receive buffer. */\r
1952                         mad_qp_post_recvs( p_mad_qp );\r
1953 \r
1954                         /* Initialize pointers to the MAD element. */\r
1955                         p_al_mad = (al_mad_element_t*)((uintn_t)wc.wr_id);\r
1956                         p_mad_element = &p_al_mad->element;\r
1957 \r
1958                         /* Remove the AL MAD element from the receive tracking queue. */\r
1959                         cl_spinlock_acquire( &p_mad_qp->qp.obj.lock );\r
1960                         cl_qlist_remove_item( &p_mad_qp->recv_queue, &p_al_mad->list_item );\r
1961                         cl_spinlock_release( &p_mad_qp->qp.obj.lock );\r
1962 \r
1963                         /* Construct the MAD element from the receive work completion. */\r
1964                         build_mad_recv( p_mad_element, &wc );\r
1965 \r
1966                         /* Process the received MAD. */\r
1967                         status = mad_disp_recv_done( p_mad_qp->h_mad_disp,\r
1968                                 p_mad_element );\r
1969 \r
1970                         /* Discard this MAD on error. */\r
1971                         if( status != IB_SUCCESS )\r
1972                         {\r
1973                                 status = ib_put_mad( p_mad_element );\r
1974                                 CL_ASSERT( status == IB_SUCCESS );\r
1975                         }\r
1976                         break;\r
1977 \r
1978                 default:\r
1979                         CL_ASSERT( wc_type == IB_WC_SEND || wc_type == IB_WC_RECV );\r
1980                         break;\r
1981                 }\r
1982                 p_free_wc = &wc;\r
1983         }\r
1984 }\r
1985 \r
1986 \r
1987 \r
1988 /*\r
1989  * Process an event on a CQ associated with a MAD QP.\r
1990  */\r
1991 void\r
1992 mad_qp_cq_event_cb(\r
1993         IN                              ib_async_event_rec_t            *p_event_rec )\r
1994 {\r
1995         al_mad_qp_t                             *p_mad_qp;\r
1996 \r
1997         CL_ASSERT( p_event_rec );\r
1998         CL_ASSERT( p_event_rec->context );\r
1999 \r
2000         if( p_event_rec->code == IB_AE_SQ_DRAINED )\r
2001                 return;\r
2002 \r
2003         p_mad_qp = (al_mad_qp_t* __ptr64)p_event_rec->context;\r
2004 \r
2005         /* Nothing to do here. */\r
2006 }\r
2007 \r
2008 \r
2009 \r
2010 /*\r
2011  * Process an asynchronous event on the QP.  Notify the user of the event.\r
2012  */\r
2013 void\r
2014 qp_async_event_cb(\r
2015         IN                              ib_async_event_rec_t* const     p_event_rec )\r
2016 {\r
2017         ib_qp_handle_t                  h_qp;\r
2018 \r
2019         CL_ASSERT( p_event_rec );\r
2020         h_qp = (ib_qp_handle_t)p_event_rec->context;\r
2021 \r
2022 #if defined(CL_KERNEL)\r
2023         switch( p_event_rec->code )\r
2024         {\r
2025         case IB_AE_QP_COMM:\r
2026                 al_cep_established( h_qp->obj.h_al, ((al_conn_qp_t*)h_qp)->cid );\r
2027                 break;\r
2028 \r
2029         case IB_AE_QP_APM:\r
2030                 al_cep_migrate( h_qp->obj.h_al, ((al_conn_qp_t*)h_qp)->cid );\r
2031                 break;\r
2032 \r
2033         case IB_AE_QP_APM_ERROR:\r
2034                 //***TODO: Figure out how to handle these errors.\r
2035                 break;\r
2036 \r
2037         default:\r
2038                 break;\r
2039         }\r
2040 #endif\r
2041 \r
2042         p_event_rec->context = (void*)h_qp->obj.context;\r
2043         p_event_rec->handle.h_qp = h_qp;\r
2044 \r
2045         if( h_qp->pfn_event_cb )\r
2046                 h_qp->pfn_event_cb( p_event_rec );\r
2047 }\r
2048 \r
2049 \r
2050 \r
2051 ib_api_status_t\r
2052 ib_bind_mw(\r
2053         IN              const   ib_mw_handle_t                          h_mw,\r
2054         IN              const   ib_qp_handle_t                          h_qp,\r
2055         IN                              ib_bind_wr_t * const            p_mw_bind,\r
2056                 OUT                     net32_t * const                         p_rkey )\r
2057 {\r
2058         ib_mr_handle_t                  h_mr;\r
2059         ib_api_status_t                 status;\r
2060 \r
2061         AL_ENTER( AL_DBG_MW );\r
2062 \r
2063         if( AL_OBJ_INVALID_HANDLE( h_mw, AL_OBJ_TYPE_H_MW ) )\r
2064         {\r
2065                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_MW_HANDLE\n") );\r
2066                 return IB_INVALID_MW_HANDLE;\r
2067         }\r
2068         if( AL_OBJ_INVALID_HANDLE( h_qp, AL_OBJ_TYPE_H_QP ) )\r
2069         {\r
2070                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
2071                 return IB_INVALID_QP_HANDLE;\r
2072         }\r
2073         if( !p_mw_bind || !p_rkey )\r
2074         {\r
2075                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
2076                 return IB_INVALID_PARAMETER;\r
2077         }\r
2078 \r
2079         /* Convert to the CI handles. */\r
2080         h_mr = p_mw_bind->h_mr;\r
2081         p_mw_bind->h_mr = convert_mr_handle( h_mr );\r
2082 \r
2083         status = verbs_bind_mw(h_mw, h_qp, p_mw_bind, p_rkey);\r
2084 \r
2085         p_mw_bind->h_mr = h_mr;\r
2086 \r
2087         AL_EXIT( AL_DBG_MW );\r
2088         return status;\r
2089 }\r