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