[IBAL, HCA] Provide HCA driver with UM CA handle for resource
[mirror/winof/.git] / core / al / al_cq.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 "al_cq.h"\r
34 #include "al_debug.h"\r
35 #include "al_ca.h"\r
36 #include "al_pd.h"\r
37 #include "al_qp.h"\r
38 #include "al_verbs.h"\r
39 \r
40 /*\r
41  * Function prototypes.\r
42  */\r
43 void\r
44 destroying_cq(\r
45         IN                              struct _al_obj                          *p_obj );\r
46 \r
47 void\r
48 cleanup_cq(\r
49         IN                              al_obj_t                                        *p_obj );\r
50 \r
51 void\r
52 free_cq(\r
53         IN                              al_obj_t                                        *p_obj );\r
54 \r
55 \r
56 \r
57 \r
58 /*\r
59  * Initializes the CQ information structure.\r
60  */\r
61 ib_api_status_t\r
62 create_cq(\r
63         IN              const   ib_ca_handle_t                          h_ca,\r
64         IN      OUT                     ib_cq_create_t* const           p_cq_create,\r
65         IN              const   void* const                                     cq_context,\r
66         IN              const   ib_pfn_event_cb_t                       pfn_cq_event_cb,\r
67                 OUT                     ib_cq_handle_t* const           ph_cq,\r
68         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
69 {\r
70         ib_cq_handle_t                  h_cq;\r
71         ib_api_status_t                 status;\r
72         al_obj_type_t                   obj_type = AL_OBJ_TYPE_H_CQ;\r
73 \r
74         if( !p_cq_create || !ph_cq )\r
75         {\r
76                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
77                 return IB_INVALID_PARAMETER;\r
78         }\r
79         if( (p_cq_create->pfn_comp_cb && p_cq_create->h_wait_obj) ||\r
80                 (!p_cq_create->pfn_comp_cb && !p_cq_create->h_wait_obj) )\r
81         {\r
82                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_SETTING\n") );\r
83                 return IB_INVALID_SETTING;\r
84         }\r
85 \r
86         h_cq = cl_zalloc( sizeof( ib_cq_t ) );\r
87         if( !h_cq )\r
88         {\r
89                 return IB_INSUFFICIENT_MEMORY;\r
90         }\r
91         \r
92         if( p_umv_buf )\r
93                 obj_type |= AL_OBJ_SUBTYPE_UM_EXPORT;\r
94 \r
95         /* Construct the CQ. */\r
96         construct_al_obj( &h_cq->obj, obj_type );\r
97 \r
98         cl_qlist_init( &h_cq->qp_list );\r
99 \r
100         /* Initialize the CQ. */\r
101         status = init_al_obj( &h_cq->obj, cq_context, TRUE,\r
102                 destroying_cq, cleanup_cq, free_cq );\r
103         if( status != IB_SUCCESS )\r
104         {\r
105                 free_cq( &h_cq->obj );\r
106                 return status;\r
107         }\r
108         status = attach_al_obj( &h_ca->obj, &h_cq->obj );\r
109         if( status != IB_SUCCESS )\r
110         {\r
111                 h_cq->obj.pfn_destroy( &h_cq->obj, NULL );\r
112                 return status;\r
113         }\r
114 \r
115         /*\r
116          * Record which completion routine will be used to notify the CQ of\r
117          * a completion.\r
118          */\r
119         h_cq->pfn_event_cb = pfn_cq_event_cb;\r
120         if( p_cq_create->pfn_comp_cb )\r
121         {\r
122                 CL_ASSERT( !p_cq_create->h_wait_obj );\r
123                 h_cq->pfn_user_comp_cb = p_cq_create->pfn_comp_cb;\r
124         }\r
125         else\r
126         {\r
127                 CL_ASSERT( p_cq_create->h_wait_obj );\r
128                 h_cq->h_wait_obj = p_cq_create->h_wait_obj;\r
129         }\r
130 \r
131         /*\r
132          * Note:\r
133          * Because an extra reference is not held on the object during creation,\r
134          * the h_cq handle may be destroryed by the client's asynchronous event\r
135          * callback routine before call to verbs returns.\r
136          */\r
137         status = verbs_create_cq( h_ca, p_cq_create, h_cq, p_umv_buf );\r
138         if( status != IB_SUCCESS )\r
139         {\r
140                 h_cq->obj.pfn_destroy( &h_cq->obj, NULL );\r
141                 return status;\r
142         }\r
143 \r
144         *ph_cq = h_cq;\r
145 \r
146         return IB_SUCCESS;\r
147 }\r
148 \r
149 \r
150 \r
151 ib_api_status_t\r
152 ib_destroy_cq(\r
153         IN              const   ib_cq_handle_t                          h_cq,\r
154         IN              const   ib_pfn_destroy_cb_t                     pfn_destroy_cb OPTIONAL )\r
155 {\r
156         CL_ENTER( AL_DBG_CQ, g_al_dbg_lvl );\r
157 \r
158         if( AL_OBJ_INVALID_HANDLE( h_cq, AL_OBJ_TYPE_H_CQ ) )\r
159         {\r
160                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CQ_HANDLE\n") );\r
161                 return IB_INVALID_CQ_HANDLE;\r
162         }\r
163 \r
164         ref_al_obj( &h_cq->obj );\r
165         h_cq->obj.pfn_destroy( &h_cq->obj, pfn_destroy_cb );\r
166 \r
167         CL_EXIT( AL_DBG_CQ, g_al_dbg_lvl );\r
168         return IB_SUCCESS;\r
169 }\r
170 \r
171 \r
172 \r
173 void\r
174 destroying_cq(\r
175         IN                              struct _al_obj                          *p_obj )\r
176 {\r
177         ib_cq_handle_t          h_cq;\r
178         cl_list_item_t          *p_item;\r
179         cl_obj_rel_t            *p_rel;\r
180         ib_qp_handle_t          h_qp;\r
181 \r
182         CL_ASSERT( p_obj );\r
183         h_cq = PARENT_STRUCT( p_obj, ib_cq_t, obj );\r
184 \r
185         /* Initiate destruction of all bound QPs. */\r
186         cl_spinlock_acquire( &h_cq->obj.lock );\r
187         for( p_item = cl_qlist_remove_tail( &h_cq->qp_list );\r
188                 p_item != cl_qlist_end( &h_cq->qp_list );\r
189                 p_item = cl_qlist_remove_tail( &h_cq->qp_list ) )\r
190         {\r
191                 p_rel = PARENT_STRUCT( p_item, cl_obj_rel_t, pool_item.list_item );\r
192                 p_rel->p_parent_obj = NULL;\r
193                 h_qp = (ib_qp_handle_t)p_rel->p_child_obj;\r
194                 if( h_qp )\r
195                 {\r
196                         /* Take a reference to prevent the QP from being destroyed. */\r
197                         ref_al_obj( &h_qp->obj );\r
198                         cl_spinlock_release( &h_cq->obj.lock );\r
199                         h_qp->obj.pfn_destroy( &h_qp->obj, NULL );\r
200                         cl_spinlock_acquire( &h_cq->obj.lock );\r
201                 }\r
202         }\r
203         cl_spinlock_release( &h_cq->obj.lock );\r
204 }\r
205 \r
206 \r
207 void\r
208 cleanup_cq(\r
209         IN                              struct _al_obj                          *p_obj )\r
210 {\r
211         ib_cq_handle_t                  h_cq;\r
212         ib_api_status_t                 status;\r
213 \r
214         CL_ASSERT( p_obj );\r
215         h_cq = PARENT_STRUCT( p_obj, ib_cq_t, obj );\r
216 \r
217         /* Deallocate the CI cq. */\r
218         if( verbs_check_cq( h_cq ) )\r
219         {\r
220                 status = verbs_destroy_cq( h_cq );\r
221                 CL_ASSERT( status == IB_SUCCESS );\r
222         }\r
223 }\r
224 \r
225 \r
226 \r
227 /*\r
228  * Release all resources associated with the completion queue.\r
229  */\r
230 void\r
231 free_cq(\r
232         IN                              al_obj_t                                        *p_obj )\r
233 {\r
234         ib_cq_handle_t                  h_cq;\r
235 \r
236         CL_ASSERT( p_obj );\r
237         h_cq = PARENT_STRUCT( p_obj, ib_cq_t, obj );\r
238 \r
239         destroy_al_obj( &h_cq->obj );\r
240         cl_free( h_cq );\r
241 }\r
242 \r
243 \r
244 void\r
245 cq_attach_qp(\r
246         IN              const   ib_cq_handle_t                          h_cq,\r
247         IN                              cl_obj_rel_t* const                     p_qp_rel )\r
248 {\r
249         p_qp_rel->p_parent_obj = (cl_obj_t*)h_cq;\r
250         ref_al_obj( &h_cq->obj );\r
251         cl_spinlock_acquire( &h_cq->obj.lock );\r
252         cl_qlist_insert_tail( &h_cq->qp_list, &p_qp_rel->pool_item.list_item );\r
253         cl_spinlock_release( &h_cq->obj.lock );\r
254 }\r
255 \r
256 \r
257 void\r
258 cq_detach_qp(\r
259         IN              const   ib_cq_handle_t                          h_cq,\r
260         IN                              cl_obj_rel_t* const                     p_qp_rel )\r
261 {\r
262         if( p_qp_rel->p_parent_obj )\r
263         {\r
264                 CL_ASSERT( p_qp_rel->p_parent_obj == (cl_obj_t*)h_cq );\r
265                 p_qp_rel->p_parent_obj = NULL;\r
266                 cl_spinlock_acquire( &h_cq->obj.lock );\r
267                 cl_qlist_remove_item( &h_cq->qp_list, &p_qp_rel->pool_item.list_item );\r
268                 cl_spinlock_release( &h_cq->obj.lock );\r
269         }\r
270 }\r
271 \r
272 \r
273 ib_api_status_t\r
274 ib_modify_cq(\r
275         IN              const   ib_cq_handle_t                          h_cq,\r
276         IN      OUT                     uint32_t* const                         p_size )\r
277 {\r
278         return modify_cq( h_cq, p_size, NULL );\r
279 }\r
280 \r
281 \r
282 ib_api_status_t\r
283 modify_cq(\r
284         IN              const   ib_cq_handle_t                          h_cq,\r
285         IN      OUT                     uint32_t* const                         p_size,\r
286         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
287 {\r
288         ib_api_status_t                 status;\r
289 \r
290         CL_ENTER( AL_DBG_CQ, g_al_dbg_lvl );\r
291 \r
292         if( AL_OBJ_INVALID_HANDLE( h_cq, AL_OBJ_TYPE_H_CQ ) )\r
293         {\r
294                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CQ_HANDLE\n") );\r
295                 return IB_INVALID_CQ_HANDLE;\r
296         }\r
297         if( !p_size )\r
298         {\r
299                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
300                 return IB_INVALID_PARAMETER;\r
301         }\r
302 \r
303         status = verbs_modify_cq( h_cq, p_size );\r
304 \r
305         CL_EXIT( AL_DBG_CQ, g_al_dbg_lvl );\r
306         return status;\r
307 }\r
308 \r
309 \r
310 \r
311 ib_api_status_t\r
312 ib_query_cq(\r
313         IN              const   ib_cq_handle_t                          h_cq,\r
314                 OUT                     uint32_t* const                         p_size )\r
315 {\r
316         return query_cq( h_cq, p_size, NULL );\r
317 }\r
318 \r
319 \r
320 \r
321 ib_api_status_t\r
322 query_cq(\r
323         IN              const   ib_cq_handle_t                          h_cq,\r
324                 OUT                     uint32_t* const                         p_size,\r
325         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
326 {\r
327         ib_api_status_t                 status;\r
328 \r
329         CL_ENTER( AL_DBG_CQ, g_al_dbg_lvl );\r
330 \r
331         if( AL_OBJ_INVALID_HANDLE( h_cq, AL_OBJ_TYPE_H_CQ ) )\r
332         {\r
333                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CQ_HANDLE\n") );\r
334                 return IB_INVALID_CQ_HANDLE;\r
335         }\r
336         if( !p_size )\r
337         {\r
338                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
339                 return IB_INVALID_PARAMETER;\r
340         }\r
341 \r
342         status = verbs_query_cq( h_cq, p_size );\r
343 \r
344         CL_EXIT( AL_DBG_CQ, g_al_dbg_lvl );\r
345         return status;\r
346 }\r
347 \r
348 \r
349 \r
350 ib_api_status_t\r
351 ib_peek_cq(\r
352         IN              const   ib_cq_handle_t                          h_cq,\r
353         OUT                             uint32_t* const                         p_n_cqes )\r
354 {\r
355         ib_api_status_t                 status;\r
356 \r
357         CL_ENTER( AL_DBG_CQ, g_al_dbg_lvl );\r
358 \r
359         if( AL_OBJ_INVALID_HANDLE( h_cq, AL_OBJ_TYPE_H_CQ ) )\r
360         {\r
361                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CQ_HANDLE\n") );\r
362                 return IB_INVALID_CQ_HANDLE;\r
363         }\r
364         if( !p_n_cqes )\r
365         {\r
366                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
367                 return IB_INVALID_PARAMETER;\r
368         }\r
369 \r
370         status = verbs_peek_cq( h_cq, p_n_cqes );\r
371 \r
372         CL_EXIT( AL_DBG_CQ, g_al_dbg_lvl );\r
373         return status;\r
374 }\r
375 \r
376 \r
377 \r
378 ib_api_status_t\r
379 ib_poll_cq(\r
380         IN              const   ib_cq_handle_t                          h_cq,\r
381         IN      OUT                     ib_wc_t** const                         pp_free_wclist,\r
382                 OUT                     ib_wc_t** const                         pp_done_wclist )\r
383 {\r
384         ib_api_status_t                 status;\r
385         PERF_DECLARE( IbPollCq );\r
386         PERF_DECLARE( VerbsPollCq );\r
387 \r
388         cl_perf_start( IbPollCq );\r
389         CL_ENTER( AL_DBG_CQ, g_al_dbg_lvl );\r
390 \r
391         if( AL_OBJ_INVALID_HANDLE( h_cq, AL_OBJ_TYPE_H_CQ ) )\r
392         {\r
393                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CQ_HANDLE\n") );\r
394                 return IB_INVALID_CQ_HANDLE;\r
395         }\r
396         if( !pp_free_wclist || !pp_done_wclist )\r
397         {\r
398                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
399                 return IB_INVALID_PARAMETER;\r
400         }\r
401 \r
402         cl_perf_start( VerbsPollCq );\r
403         status = verbs_poll_cq( h_cq, pp_free_wclist, pp_done_wclist );\r
404         cl_perf_stop( &g_perf, VerbsPollCq );\r
405 \r
406         CL_EXIT( AL_DBG_CQ, g_al_dbg_lvl );\r
407         cl_perf_stop( &g_perf, IbPollCq );\r
408         return status;\r
409 }\r
410 \r
411 \r
412 \r
413 ib_api_status_t\r
414 ib_rearm_cq(\r
415         IN              const   ib_cq_handle_t                          h_cq,\r
416         IN              const   boolean_t                                       solicited )\r
417 {\r
418         ib_api_status_t                 status;\r
419 \r
420         CL_ENTER( AL_DBG_CQ, g_al_dbg_lvl );\r
421 \r
422         if( AL_OBJ_INVALID_HANDLE( h_cq, AL_OBJ_TYPE_H_CQ ) )\r
423         {\r
424                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CQ_HANDLE\n") );\r
425                 return IB_INVALID_CQ_HANDLE;\r
426         }\r
427 \r
428         status = verbs_rearm_cq( h_cq, solicited );\r
429 \r
430         CL_EXIT( AL_DBG_CQ, g_al_dbg_lvl );\r
431         return status;\r
432 }\r
433 \r
434 \r
435 \r
436 ib_api_status_t\r
437 ib_rearm_n_cq(\r
438         IN              const   ib_cq_handle_t                          h_cq,\r
439         IN              const   uint32_t                                        n_cqes )\r
440 {\r
441         ib_api_status_t                 status;\r
442 \r
443         CL_ENTER( AL_DBG_CQ, g_al_dbg_lvl );\r
444 \r
445         if( AL_OBJ_INVALID_HANDLE( h_cq, AL_OBJ_TYPE_H_CQ ) )\r
446         {\r
447                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CQ_HANDLE\n") );\r
448                 return IB_INVALID_CQ_HANDLE;\r
449         }\r
450         if( !n_cqes )\r
451         {\r
452                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
453                 return IB_INVALID_PARAMETER;\r
454         }\r
455 \r
456         status = verbs_rearm_n_cq( h_cq, n_cqes );\r
457 \r
458         CL_EXIT( AL_DBG_CQ, g_al_dbg_lvl );\r
459         return status;\r
460 }\r
461 \r
462 \r
463 \r
464 /*\r
465  * Process an asynchronous event on the CQ.  Notify the user of the event.\r
466  */\r
467 void\r
468 cq_async_event_cb(\r
469         IN                              ib_async_event_rec_t* const     p_event_rec )\r
470 {\r
471         ib_cq_handle_t                  h_cq;\r
472 \r
473         CL_ASSERT( p_event_rec );\r
474         h_cq = (ib_cq_handle_t)p_event_rec->context;\r
475 \r
476         p_event_rec->context = (void*)h_cq->obj.context;\r
477         p_event_rec->handle.h_cq = h_cq;\r
478 \r
479         if( h_cq->pfn_event_cb )\r
480                 h_cq->pfn_event_cb( p_event_rec );\r
481 }\r