[DAPL2] Sync with OFED DAPL 2.0.21 src release
[mirror/winof/.git] / ulp / dapl2 / dapl / ibal / dapl_ibal_util.c
1 /*\r
2  * Copyright (c) 2005-2007 Intel Corporation. All rights reserved.  \r
3  * Copyright (c) 2002, Network Appliance, Inc. All rights reserved. \r
4  * \r
5  * This Software is licensed under the terms of the "Common Public\r
6  * License" a copy of which is in the file LICENSE.txt in the root\r
7  * directory. The license is also available from the Open Source\r
8  * Initiative, see http://www.opensource.org/licenses/cpl.php.\r
9  *\r
10  */\r
11 \r
12 /**********************************************************************\r
13  * \r
14  * MODULE: dapl_ibal_util.c\r
15  *\r
16  * PURPOSE: Utility routines for access to IBAL APIs\r
17  *\r
18  * $Id: dapl_ibal_util.c 33 2005-07-11 19:51:17Z ftillier $\r
19  *\r
20  **********************************************************************/\r
21 \r
22 #include "dapl.h"\r
23 #include "dapl_adapter_util.h"\r
24 #include "dapl_evd_util.h"\r
25 #include "dapl_cr_util.h"\r
26 #include "dapl_lmr_util.h"\r
27 #include "dapl_rmr_util.h"\r
28 #include "dapl_cookie.h"\r
29 #include "dapl_ring_buffer_util.h"\r
30 \r
31 #ifdef DAT_EXTENSIONS\r
32 #include <dat2\dat_ib_extensions.h>\r
33 #endif\r
34 \r
35 #ifndef NO_NAME_SERVICE\r
36 #include "dapl_name_service.h"\r
37 #endif /* NO_NAME_SERVICE */\r
38 \r
39 #include "dapl_ibal_name_service.h"\r
40 \r
41 #define DAPL_IBAL_MAX_CA 4\r
42 #define DAT_ADAPTER_NAME "InfiniHost (Tavor)"\r
43 #define DAT_VENDOR_NAME  "Mellanox Technolgy Inc."\r
44 \r
45 /*\r
46  *  Root data structure for DAPL_IIBA.\r
47  */\r
48 dapl_ibal_root_t        dapl_ibal_root;\r
49 DAPL_HCA_NAME           dapl_ibal_hca_name_array [DAPL_IBAL_MAX_CA] = \r
50                             {"IbalHca0", "IbalHca1", "IbalHca2", "IbalHca3"};\r
51 ib_net64_t              *gp_ibal_ca_guid_tbl = NULL;\r
52 \r
53 /*\r
54  * DAT spec does not tie max_mtu_size with IB MTU\r
55  *\r
56 static ib_net32_t dapl_ibal_mtu_table[6] = {0, 256, 512, 1024, 2048, 4096};\r
57  */\r
58     \r
59 int g_loopback_connection = 0;\r
60 \r
61 \r
62 static cl_status_t\r
63 dapli_init_root_ca_list(\r
64     IN    dapl_ibal_root_t *root )\r
65 {\r
66     cl_status_t status;\r
67 \r
68     cl_qlist_init (&root->ca_head);\r
69     status = cl_spinlock_init (&root->ca_lock);\r
70 \r
71     if (status == CL_SUCCESS)\r
72     {\r
73         /*\r
74          * Get the time ready to go but don't start here\r
75          */\r
76         root->shutdown = FALSE;\r
77         root->initialized = TRUE;\r
78     }\r
79     else\r
80     {\r
81         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
82                        "--> DiIRCL: cl_spinlock_init returned %d\n", status );\r
83         root->initialized = FALSE;\r
84     }\r
85     \r
86     root->h_al = NULL;\r
87 \r
88     return (status);\r
89 }\r
90 \r
91 \r
92 static cl_status_t\r
93 dapli_destroy_root_ca_list(\r
94     IN    dapl_ibal_root_t *root )\r
95 {\r
96 \r
97     root->initialized = FALSE;\r
98 \r
99     /* \r
100      * At this point the lock should not be necessary\r
101      */\r
102     if (!cl_is_qlist_empty (&root->ca_head) )\r
103     {\r
104         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
105                        "--> Destroying nonempty ca list (%s)\n", "DiDRCL");\r
106     }\r
107     cl_spinlock_destroy (&root->ca_lock);\r
108 \r
109     return CL_SUCCESS;\r
110 }\r
111 \r
112 \r
113 static void\r
114 dapli_shutdown_port_access(\r
115     IN    dapl_ibal_ca_t    *ca )\r
116 {\r
117     dapl_ibal_port_t    *p_port;\r
118 \r
119     TAKE_LOCK( ca->port_lock );\r
120     {\r
121         while ( ! cl_is_qlist_empty( &ca->port_head ) )\r
122         {\r
123             p_port = (dapl_ibal_port_t *)cl_qlist_remove_head( &ca->port_head );\r
124             RELEASE_LOCK( ca->port_lock );\r
125             {\r
126                 REMOVE_REFERENCE( &p_port->refs );\r
127                 REMOVE_REFERENCE( &p_port->ca->refs );\r
128 \r
129                 dapl_os_free (p_port, sizeof (dapl_ibal_port_t));\r
130             }\r
131             TAKE_LOCK( ca->port_lock );\r
132         }\r
133     }\r
134     RELEASE_LOCK( ca->port_lock );\r
135 }\r
136 \r
137 \r
138 static void dapli_shutdown_ca_access (void)\r
139 {\r
140     dapl_ibal_ca_t  *ca;\r
141 \r
142     if ( dapl_ibal_root.initialized == FALSE )\r
143     {\r
144         goto destroy_root;\r
145     }\r
146 \r
147     TAKE_LOCK (dapl_ibal_root.ca_lock);\r
148     {\r
149         while ( ! cl_is_qlist_empty (&dapl_ibal_root.ca_head) )\r
150         {\r
151             ca = (dapl_ibal_ca_t *)\r
152                                  cl_qlist_remove_head (&dapl_ibal_root.ca_head);\r
153 \r
154             if (ca->p_ca_attr)\r
155             {\r
156                 dapl_os_free (ca->p_ca_attr, sizeof (ib_ca_attr_t));\r
157             }\r
158 \r
159 \r
160             RELEASE_LOCK (dapl_ibal_root.ca_lock);\r
161             {\r
162                 dapli_shutdown_port_access (ca);\r
163                 REMOVE_REFERENCE (&ca->refs);\r
164             }\r
165             TAKE_LOCK (dapl_ibal_root.ca_lock);\r
166         }\r
167     }\r
168     RELEASE_LOCK (dapl_ibal_root.ca_lock);\r
169 \r
170 destroy_root:\r
171     /*\r
172      * Destroy the root CA list and list lock\r
173      */\r
174     dapli_destroy_root_ca_list (&dapl_ibal_root);\r
175 \r
176     /*\r
177      * Signal we're all done and wake any waiter\r
178      */\r
179     dapl_ibal_root.shutdown = FALSE;\r
180 }\r
181 \r
182 \r
183 dapl_ibal_evd_cb_t *\r
184 dapli_find_evd_cb_by_context(\r
185     IN    void           *context,\r
186     IN    dapl_ibal_ca_t *ca)\r
187 {\r
188     dapl_ibal_evd_cb_t *evd_cb = NULL;\r
189 \r
190     TAKE_LOCK( ca->evd_cb_lock );\r
191 \r
192     evd_cb = (dapl_ibal_evd_cb_t *) cl_qlist_head( &ca->evd_cb_head );\r
193     while ( &evd_cb->next != cl_qlist_end( &ca->evd_cb_head ) )\r
194     {\r
195         if ( context == evd_cb->context)\r
196         {\r
197             goto found;\r
198         }\r
199 \r
200         /*\r
201          *  Try again\r
202          */\r
203         evd_cb = (dapl_ibal_evd_cb_t *) cl_qlist_next( &evd_cb->next );\r
204     }\r
205     /*\r
206      *  No joy\r
207      */\r
208     evd_cb = NULL;\r
209 \r
210 found:\r
211 \r
212     RELEASE_LOCK( ca->evd_cb_lock );\r
213 \r
214     return ( evd_cb );\r
215 }\r
216 \r
217 \r
218 static cl_status_t\r
219 dapli_init_ca_evd_cb_list(\r
220     IN    dapl_ibal_ca_t    *ca )\r
221 {\r
222     cl_status_t    status;\r
223 \r
224     cl_qlist_init( &ca->evd_cb_head );\r
225     status = cl_spinlock_init( &ca->evd_cb_lock );\r
226     if ( status != CL_SUCCESS )\r
227         dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DiICECL: cl_spinlock_init returned %d\n", status);\r
228     return ( status );\r
229 }\r
230 \r
231 \r
232 static cl_status_t\r
233 dapli_init_ca_port_list(\r
234     IN    dapl_ibal_ca_t    *ca )\r
235 {\r
236     cl_status_t    status;\r
237 \r
238     cl_qlist_init( &ca->port_head );\r
239     status = cl_spinlock_init( &ca->port_lock );\r
240     if ( status != CL_SUCCESS )\r
241         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
242                        "--> DiICPL: cl_spinlock_init returned %d\n", status );\r
243     return ( status );\r
244 }\r
245 \r
246 dapl_ibal_port_t  *\r
247 dapli_ibal_get_port (\r
248     IN   dapl_ibal_ca_t    *p_ca,\r
249     IN   uint8_t           port_num)\r
250 {\r
251     cl_list_item_t    *p_active_port = NULL;\r
252     \r
253     TAKE_LOCK (p_ca->port_lock);\r
254     for ( p_active_port = cl_qlist_head( &p_ca->port_head );\r
255           p_active_port != cl_qlist_end ( &p_ca->port_head);\r
256           p_active_port =  cl_qlist_next ( p_active_port ) )\r
257     {\r
258         if (((dapl_ibal_port_t *)p_active_port)->p_attr->port_num == port_num)\r
259             break;      \r
260     }\r
261     RELEASE_LOCK (p_ca->port_lock);\r
262 \r
263     return (dapl_ibal_port_t *)p_active_port;\r
264 }\r
265 \r
266 \r
267 void\r
268 dapli_ibal_ca_async_error_callback( IN ib_async_event_rec_t  *p_err_rec )\r
269 {\r
270     dapl_ibal_ca_t      *p_ca = (dapl_ibal_ca_t*)((void *)p_err_rec->context);\r
271     dapl_ibal_evd_cb_t  *evd_cb;\r
272     DAPL_IA             *ia_ptr;\r
273                         \r
274     dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
275                        "--> DiCaAEC: CA error %d for context %p\n", \r
276                        p_err_rec->code, p_err_rec->context);\r
277 \r
278     if (p_ca == NULL)\r
279     {\r
280         dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> DiCaAEC: invalid p_ca"\r
281                               "(%p)in async event rec\n",p_ca);\r
282         return;\r
283     }\r
284         \r
285     ia_ptr = (DAPL_IA*)p_ca->ia_ptr;\r
286     if (ia_ptr == NULL)\r
287     {\r
288         dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
289                               "--> DiCaAEC: invalid ia_ptr in %p ca \n", p_ca );\r
290         return;\r
291     }\r
292 \r
293     if (ia_ptr->async_error_evd == NULL)\r
294     {\r
295         dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
296                       "--> DiCqAEC: can't find async_error_evd on %s HCA\n", \r
297                       (ia_ptr->header.provider)->device_name );\r
298         return;\r
299     }\r
300 \r
301     /* find QP error callback using p_ca for context */\r
302     evd_cb = dapli_find_evd_cb_by_context (ia_ptr->async_error_evd, p_ca);\r
303     if ((evd_cb == NULL) || (evd_cb->pfn_async_err_cb == NULL))\r
304     {\r
305         dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
306                               "--> DiCaAEC: no ERROR cb on %p found \n", p_ca);\r
307         return;\r
308     }\r
309 \r
310     /* maps to dapl_evd_un_async_error_callback(), context is async_evd */\r
311     evd_cb->pfn_async_err_cb( (ib_hca_handle_t)p_ca, \r
312                               (ib_error_record_t*)&p_err_rec->code, \r
313                               ia_ptr->async_error_evd );\r
314 \r
315 }\r
316 \r
317 \r
318 static dapl_ibal_port_t *\r
319 dapli_alloc_port(\r
320     IN    dapl_ibal_ca_t    *ca,\r
321     IN    ib_port_attr_t    *ib_port )\r
322 {\r
323     dapl_ibal_port_t    *p_port = NULL;\r
324 \r
325     if (ca->h_ca == NULL )\r
326     {\r
327         return NULL;\r
328     }\r
329 \r
330     /*\r
331      *  Allocate the port structure memory.  This will also deal with the\r
332      *  copying ib_port_attr_t including GID and P_Key tables\r
333      */\r
334     p_port = dapl_os_alloc ( sizeof(dapl_ibal_port_t ) );\r
335 \r
336     if ( p_port )\r
337     {\r
338         dapl_os_memzero (p_port, sizeof(dapl_ibal_port_t ) );\r
339 \r
340         /*\r
341          *  We're good to go after initializing reference.\r
342          */\r
343         INIT_REFERENCE( &p_port->refs, 1, p_port, NULL /* pfn_destructor */ );\r
344                 \r
345                 p_port->p_attr = ib_port;\r
346     }\r
347     return ( p_port );\r
348 }\r
349 \r
350 static void\r
351 dapli_add_active_port(\r
352     IN dapl_ibal_ca_t   *ca )\r
353 {\r
354     dapl_ibal_port_t     *p_port;\r
355     ib_port_attr_t       *p_port_attr;\r
356     ib_ca_attr_t         *p_ca_attr;\r
357     int                  i;\r
358 \r
359     p_ca_attr = ca->p_ca_attr;\r
360 \r
361     dapl_os_assert (p_ca_attr != NULL);\r
362 \r
363     for (i = 0; i < p_ca_attr->num_ports; i++)\r
364     {\r
365         p_port_attr = &p_ca_attr->p_port_attr[i];\r
366 \r
367         {\r
368             p_port = dapli_alloc_port( ca, p_port_attr );\r
369             if ( p_port )\r
370             {\r
371                 TAKE_REFERENCE (&ca->refs);\r
372 \r
373                 /*\r
374                  *  Record / update attribues\r
375                  */\r
376                 p_port->p_attr = p_port_attr;\r
377 \r
378                 /*\r
379                  *  Remember the parant CA keeping the reference we took above\r
380                  */\r
381                 p_port->ca = ca;\r
382 \r
383                 /*\r
384                  *  We're good to go - Add the new port to the list on the CA\r
385                  */\r
386                 LOCK_INSERT_TAIL( ca->port_lock, ca->port_head, p_port->next );\r
387             }\r
388             else\r
389             {\r
390                 dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
391                                "--> %s: Could not allocate dapl_ibal_port_t\n",\r
392                                "DiAAP");\r
393             }\r
394         }\r
395         dapl_dbg_log( DAPL_DBG_TYPE_UTIL,\r
396                       "--> DiAAP: Port %d logical link %s lid = %#x\n",\r
397                       p_port_attr->port_num,\r
398                       ( p_port_attr->link_state != IB_LINK_ACTIVE\r
399                            ?  "DOWN": "UP" ),\r
400                       CL_HTON16(p_port_attr->lid) );\r
401 \r
402     } /* for loop */\r
403 }\r
404 \r
405 static dapl_ibal_ca_t *\r
406 dapli_alloc_ca(\r
407     IN    ib_al_handle_t  h_al,\r
408     IN    ib_net64_t      ca_guid)\r
409 {\r
410     dapl_ibal_ca_t         *p_ca;\r
411     ib_api_status_t        status;\r
412     uint32_t               attr_size;\r
413 \r
414     /*\r
415      *  Allocate the CA structure\r
416      */\r
417     p_ca = dapl_os_alloc( sizeof(dapl_ibal_ca_t) );\r
418     dapl_os_memzero (p_ca, sizeof(dapl_ibal_ca_t) );\r
419 \r
420     if ( p_ca )\r
421     {\r
422         /*\r
423          *  Now we pass dapli_ibal_ca_async_error_callback as the \r
424          *  async error callback\r
425          */\r
426         status = ib_open_ca( h_al,\r
427                              ca_guid,\r
428                              dapli_ibal_ca_async_error_callback,\r
429                              p_ca,\r
430                              &p_ca->h_ca );\r
431         if ( status != IB_SUCCESS )\r
432         {\r
433             dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
434                            "--> DiAC: ib_open_ca returned %s\n",\r
435                            ib_get_err_str(status));\r
436             dapl_os_free (p_ca, sizeof (dapl_ibal_ca_t));\r
437             return (NULL);\r
438         }\r
439 \r
440         /*\r
441          *  Get port list lock and list head initialized\r
442          */\r
443         if (( dapli_init_ca_port_list( p_ca ) != CL_SUCCESS ) ||\r
444             ( dapli_init_ca_evd_cb_list( p_ca ) != CL_SUCCESS ))\r
445         { \r
446             dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
447                            "--> %s: dapli_init_ca_port_list returned failed\n",\r
448                            "DiAC");\r
449             goto close_and_free_ca;\r
450         }\r
451 \r
452         attr_size = 0;\r
453         status = ib_query_ca (p_ca->h_ca, NULL, &attr_size);\r
454         if (status != IB_INSUFFICIENT_MEMORY)\r
455         {\r
456             dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
457                           "--> DiAC: ib_query_ca returned failed status = %d\n",\r
458                           status);\r
459             goto close_and_free_ca;\r
460         }\r
461 \r
462         p_ca->p_ca_attr = dapl_os_alloc ((int)attr_size);\r
463         if (p_ca->p_ca_attr == NULL)\r
464         {\r
465             dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
466                            "--> %s: dapli_alloc_ca failed to alloc memory\n",\r
467                            "DiAC");\r
468             goto close_and_free_ca;\r
469         }\r
470 \r
471         status = ib_query_ca (\r
472                           p_ca->h_ca,\r
473                           p_ca->p_ca_attr,\r
474                           &attr_size);\r
475         if (status != IB_SUCCESS)\r
476         {\r
477             dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
478                            "--> ib_query_ca returned failed status = %d\n",\r
479                            status);\r
480             dapl_os_free (p_ca->p_ca_attr, (int)attr_size);\r
481             goto close_and_free_ca;\r
482         }\r
483        \r
484         p_ca->ca_attr_size = attr_size;\r
485 \r
486         INIT_REFERENCE( &p_ca->refs, 1, p_ca, NULL /* pfn_destructor */ );\r
487 \r
488         dapli_add_active_port (p_ca);\r
489 \r
490         /*\r
491          *  We're good to go\r
492          */\r
493         return ( p_ca );\r
494     }\r
495     else\r
496     {\r
497         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
498                        "--> %s: Error allocating CA structure\n","DiAC");\r
499         return ( NULL );\r
500     }\r
501 \r
502 close_and_free_ca:\r
503    /*\r
504     *  Close the CA.\r
505     */\r
506    (void) ib_close_ca ( p_ca->h_ca, NULL /* callback */);\r
507    dapl_os_free (p_ca, sizeof (dapl_ibal_ca_t));\r
508 \r
509     /*\r
510      *  If we get here, there was an initialization failure\r
511      */\r
512     return ( NULL );\r
513 }\r
514 \r
515 \r
516 static dapl_ibal_ca_t *\r
517 dapli_add_ca (\r
518     IN   ib_al_handle_t    h_al,\r
519     IN   ib_net64_t        ca_guid )\r
520 {\r
521     dapl_ibal_ca_t     *p_ca;\r
522 \r
523     /*\r
524      *  Allocate a CA structure\r
525      */\r
526     p_ca = dapli_alloc_ca( h_al, ca_guid );\r
527     if ( p_ca )\r
528     {\r
529         /*\r
530          *  Add the new CA to the list\r
531          */\r
532         LOCK_INSERT_TAIL( dapl_ibal_root.ca_lock, \r
533                           dapl_ibal_root.ca_head, p_ca->next );\r
534     }\r
535     else\r
536     {\r
537         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
538                        "--> %s: Could not allocate dapl_ibal_ca_t "\r
539                        " for CA guid " F64x "\n","DiAA",ca_guid);\r
540     }\r
541 \r
542     return ( p_ca );\r
543 }\r
544 \r
545 \r
546 int32_t\r
547 dapls_ib_init (void)\r
548 {\r
549     ib_api_status_t status;\r
550 \r
551     /*\r
552      * Initialize the root structure\r
553      */\r
554     if ( dapli_init_root_ca_list (&dapl_ibal_root) == CL_SUCCESS )\r
555     {\r
556         /*\r
557          * Register with the access layer\r
558          */\r
559         status = ib_open_al (&dapl_ibal_root.h_al);\r
560 \r
561         if (status == IB_SUCCESS)\r
562         {\r
563             intn_t             guid_count;\r
564 \r
565             status = ib_get_ca_guids ( dapl_ibal_root.h_al,\r
566                                        NULL,\r
567                                        &(size_t)guid_count );\r
568             if (status != IB_INSUFFICIENT_MEMORY)\r
569             {\r
570                 dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
571                                "--> %s: ib_get_ca_guids failed = %d\n",\r
572                                __FUNCTION__,status);\r
573                 return -1;\r
574             }\r
575 \r
576             if (guid_count == 0)\r
577             {\r
578                 dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
579                                "--> %s: found NO HCA in the system\n",\r
580                                __FUNCTION__);\r
581                 return -1;\r
582             }\r
583 \r
584             if (guid_count > DAPL_IBAL_MAX_CA)\r
585             {\r
586                 guid_count = DAPL_IBAL_MAX_CA;\r
587             }\r
588 \r
589             gp_ibal_ca_guid_tbl = (ib_net64_t*)\r
590                                   dapl_os_alloc ( (int)(guid_count * \r
591                                                   sizeof (ib_net64_t)) );\r
592 \r
593             if (gp_ibal_ca_guid_tbl == NULL)\r
594             {\r
595                 dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> %s() can not alloc "\r
596                                "gp_ibal_ca_guid_tbl\n", __FUNCTION__);\r
597                         \r
598                 return -1;\r
599             }\r
600 \r
601             status = ib_get_ca_guids ( dapl_ibal_root.h_al, \r
602                                        gp_ibal_ca_guid_tbl, \r
603                                        &(size_t)guid_count );\r
604                             \r
605 \r
606             if ( status != IB_SUCCESS )\r
607             {\r
608                 dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
609                                "--> %s: ib_get_ca_guids failed '%s'\n", \r
610                                __FUNCTION__, ib_get_err_str(status) );\r
611                 return -1;\r
612             }\r
613 \r
614             dapl_dbg_log ( DAPL_DBG_TYPE_UTIL, \r
615                            "--> %s: Success open AL & found %d HCA avail,\n",\r
616                            __FUNCTION__, guid_count);\r
617             return 0;\r
618         }\r
619         else\r
620         {        \r
621             dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
622                            "--> %s: ib_open_al() failed '%s'\n",\r
623                            __FUNCTION__, ib_get_err_str(status) );\r
624             /*\r
625              * Undo CA list\r
626              */\r
627             dapli_destroy_root_ca_list (&dapl_ibal_root);\r
628         }\r
629     }\r
630     return -1;\r
631 }\r
632 \r
633 \r
634 int32_t dapls_ib_release (void)\r
635 {\r
636     dapl_ibal_root.shutdown = TRUE;\r
637 \r
638     dapli_shutdown_ca_access();\r
639 \r
640     /*\r
641      * If shutdown not complete, wait for it\r
642      */\r
643     if (dapl_ibal_root.shutdown)\r
644     {\r
645         dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
646                         "--> DsIR: timeout waiting for completion\n");\r
647     }\r
648 \r
649     if ( dapl_ibal_root.h_al != NULL )\r
650     {\r
651         (void) ib_close_al (dapl_ibal_root.h_al);\r
652         dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIR: ib_close_al() returns\n");\r
653         dapl_ibal_root.h_al = NULL;\r
654     }\r
655 #ifdef DBG\r
656     dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> %s: Exit\n",__FUNCTION__);\r
657 #endif\r
658 \r
659     return 0;\r
660 }\r
661 \r
662 \r
663 /*\r
664  * dapls_ib_enum_hcas\r
665  *\r
666  * Enumerate all HCAs on the system\r
667  *\r
668  * Input:\r
669  *      none\r
670  *\r
671  * Output:\r
672  *      hca_names       Array of hca names\r
673  *      total_hca_count \r
674  *\r
675  * Returns:\r
676  *      DAT_SUCCESS\r
677  *      DAT_INSUFFICIENT_RESOURCES\r
678  *\r
679  */\r
680 DAT_RETURN\r
681 dapls_ib_enum_hcas (\r
682         IN   const char          *vendor,\r
683         OUT  DAPL_HCA_NAME       **hca_names,\r
684         OUT  DAT_COUNT           *total_hca_count )\r
685 {\r
686     intn_t             guid_count;\r
687     ib_api_status_t    ib_status;\r
688     UNREFERENCED_PARAMETER(vendor);\r
689 \r
690     ib_status = ib_get_ca_guids (dapl_ibal_root.h_al, NULL, &(size_t)guid_count);\r
691     if (ib_status != IB_INSUFFICIENT_MEMORY)\r
692     {\r
693         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
694                        "--> DsIEH: ib_get_ca_guids failed '%s'\n",\r
695                        ib_get_err_str(ib_status) );\r
696         return dapl_ib_status_convert (ib_status);\r
697     }\r
698 \r
699     if (guid_count == 0)\r
700     {\r
701         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
702                        "--> %s: ib_get_ca_guids no HCA in the system\n",\r
703                        "DsIEH");\r
704         return (DAT_PROVIDER_NOT_FOUND);\r
705     }\r
706 \r
707     if (guid_count > DAPL_IBAL_MAX_CA)\r
708     {\r
709         guid_count = DAPL_IBAL_MAX_CA;\r
710     }\r
711 \r
712     gp_ibal_ca_guid_tbl = (ib_net64_t *)dapl_os_alloc ((int)(guid_count * sizeof (ib_net64_t)) );\r
713 \r
714     if (gp_ibal_ca_guid_tbl == NULL)\r
715     {\r
716         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
717                        "--> %s: can not alloc resources @line%d\n", "DsIEH",\r
718                        __LINE__);\r
719         return (DAT_INSUFFICIENT_RESOURCES);\r
720     }\r
721 \r
722     ib_status = ib_get_ca_guids ( dapl_ibal_root.h_al,\r
723                                   gp_ibal_ca_guid_tbl,\r
724                                   &(size_t)guid_count);\r
725 \r
726     if (ib_status != IB_SUCCESS)\r
727     {\r
728         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
729                        "--> DsIEH: ib_get_ca_guids failed status = %s\n", \r
730                        ib_get_err_str(ib_status) );\r
731         return dapl_ib_status_convert (ib_status);\r
732     }\r
733 \r
734     *hca_names = (DAPL_HCA_NAME*)\r
735                      dapl_os_alloc ((int)(guid_count * sizeof (DAPL_HCA_NAME)));\r
736 \r
737     if (*hca_names == NULL)\r
738     {\r
739         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
740                        "--> %s: can not alloc resources @line%d\n",\r
741                        "DsIEH", __LINE__);\r
742         return (DAT_INSUFFICIENT_RESOURCES);\r
743     }\r
744 \r
745     dapl_os_memcpy (*hca_names, \r
746                     dapl_ibal_hca_name_array, \r
747                     (int)(guid_count * sizeof (DAPL_HCA_NAME)) );\r
748 \r
749     *total_hca_count = (DAT_COUNT)guid_count;\r
750 \r
751     {\r
752         int i;\r
753 \r
754         for (i = 0; i < guid_count; i++)\r
755             dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIEH: %d) hca_names = %s\n",\r
756                           i, dapl_ibal_hca_name_array[i]);\r
757     }\r
758 \r
759     return (DAT_SUCCESS);\r
760 }\r
761 \r
762 \r
763 \r
764 IB_HCA_NAME\r
765 dapl_ib_convert_name(\r
766     IN  char    *name)\r
767 {\r
768     int                i;\r
769 \r
770     if (gp_ibal_ca_guid_tbl  == NULL)\r
771     {\r
772         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
773                        "--> DICN: found no HCA with name %s\n", name );\r
774         return 0;\r
775     }\r
776 \r
777     for (i = 0; i < DAPL_IBAL_MAX_CA; i++)\r
778     {\r
779         if (strcmp (name, dapl_ibal_hca_name_array[i]) == 0)\r
780         {\r
781             break;\r
782         }\r
783     }\r
784 \r
785     if (i >= DAPL_IBAL_MAX_CA)\r
786     {\r
787         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
788                        "--> DICN: can't find any HCA with name %s\n", name);\r
789         return 0;\r
790     }\r
791    \r
792     return (gp_ibal_ca_guid_tbl[i]);\r
793 }\r
794 \r
795 \r
796 /*\r
797  * dapls_ib_open_hca\r
798  *\r
799  * Open HCA\r
800  *\r
801  * Input:\r
802  *      *hca_name         pointer to provider device name\r
803  *      *ib_hca_handle_p  pointer to provide HCA handle\r
804  *\r
805  * Output:\r
806  *      none\r
807  *\r
808  * Return:\r
809  *      DAT_SUCCESS\r
810  *      DAT_INSUFFICIENT_RESOURCES\r
811  *\r
812  */\r
813 DAT_RETURN dapls_ib_open_hca ( IN  char         *hca_name,\r
814                                IN  DAPL_HCA     *p_hca )\r
815 {\r
816     dapl_ibal_ca_t     *p_ca;\r
817     IB_HCA_NAME        ca_guid;\r
818 \r
819     dapl_dbg_log (DAPL_DBG_TYPE_UTIL," open_hca: %s - %p\n", hca_name, p_hca);\r
820 \r
821     if (gp_ibal_ca_guid_tbl  == NULL)\r
822     {\r
823         dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIOH: found no HCA with ca_guid"\r
824                        F64x "\n", hca_name);\r
825         return (DAT_PROVIDER_NOT_FOUND);\r
826     }\r
827 \r
828     ca_guid = dapl_ib_convert_name(hca_name);\r
829 \r
830     p_ca = dapli_add_ca (dapl_ibal_root.h_al, ca_guid);\r
831 \r
832     if (p_ca == NULL)\r
833     {\r
834         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
835                      "--> DsIOH: can not create ca for '%s' guid " F64x "\n",\r
836                      hca_name, ca_guid);\r
837         return (DAT_INSUFFICIENT_RESOURCES);\r
838     }\r
839 \r
840     p_hca->ib_hca_handle = (ib_hca_handle_t) p_ca;\r
841     p_hca->ib_trans.d_hca = p_hca; // back-link\r
842 \r
843     /* initialize hca wait object for uAT event */\r
844     dapl_os_wait_object_init(&p_hca->ib_trans.wait_object);\r
845 \r
846 #if SOCK_CM\r
847     {\r
848         DAT_RETURN    dat_status;\r
849 \r
850         dat_status = dapli_init_sock_cm(p_hca);\r
851         if ( dat_status != DAT_SUCCESS )\r
852         {\r
853                 dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
854                                 " %s() failed to init sock_CM\n", __FUNCTION__);\r
855                 return DAT_INTERNAL_ERROR;\r
856         }\r
857 \r
858         /* initialize cr_list lock */\r
859         dat_status = dapl_os_lock_init(&p_hca->ib_trans.lock);\r
860         if (dat_status != DAT_SUCCESS)\r
861         {\r
862                 dapl_dbg_log (DAPL_DBG_TYPE_ERR, " %s() failed to init lock\n",\r
863                                 __FUNCTION__);\r
864                 return DAT_INTERNAL_ERROR;\r
865         }\r
866 \r
867         /* initialize CM list for listens on this HCA */\r
868         dapl_llist_init_head((DAPL_LLIST_HEAD*)&p_hca->ib_trans.list);\r
869     }\r
870 #endif\r
871 \r
872     return (DAT_SUCCESS);\r
873 }\r
874 \r
875 \r
876 /*\r
877  * dapls_ib_close_hca\r
878  *\r
879  * Open HCA\r
880  *\r
881  * Input:\r
882  *      ib_hca_handle   provide HCA handle\r
883  *\r
884  * Output:\r
885  *      none\r
886  *\r
887  * Return:\r
888  *      DAT_SUCCESS\r
889  *      DAT_INSUFFICIENT_RESOURCES\r
890  *\r
891  */\r
892 DAT_RETURN dapls_ib_close_hca ( IN  DAPL_HCA  *p_hca )\r
893 {\r
894     dapl_ibal_ca_t     *p_ca;\r
895    \r
896     p_ca =  (dapl_ibal_ca_t *) p_hca->ib_hca_handle;\r
897    \r
898 #if SOCK_CM\r
899 #endif\r
900     /*\r
901      * Remove it from the list\r
902      */\r
903     TAKE_LOCK (dapl_ibal_root.ca_lock);\r
904     {\r
905         cl_qlist_remove_item (&dapl_ibal_root.ca_head, &p_ca->next);\r
906     }\r
907     RELEASE_LOCK (dapl_ibal_root.ca_lock);\r
908 \r
909     dapli_shutdown_port_access (p_ca);\r
910  \r
911     /*\r
912      * Remove the constructor reference\r
913      */\r
914     REMOVE_REFERENCE (&p_ca->refs);\r
915 \r
916     cl_spinlock_destroy (&p_ca->port_lock);\r
917     cl_spinlock_destroy (&p_ca->evd_cb_lock);\r
918 \r
919     if (p_ca->p_ca_attr)\r
920         dapl_os_free (p_ca->p_ca_attr, sizeof (ib_ca_attr_t));\r
921 \r
922     (void) ib_close_ca (p_ca->h_ca, NULL /* close_callback */);\r
923 \r
924     p_hca->ib_hca_handle = IB_INVALID_HANDLE;\r
925     dapl_os_free (p_ca, sizeof (dapl_ibal_ca_t));\r
926 \r
927     return (DAT_SUCCESS);\r
928 }\r
929 \r
930 \r
931 \r
932 /*\r
933  * dapl_ib_pd_alloc\r
934  *\r
935  * Alloc a PD\r
936  *\r
937  * Input:\r
938  *      ia_handle               IA handle\r
939  *      PZ_ptr                  pointer to PZEVD struct\r
940  *\r
941  * Output:\r
942  *      none\r
943  *\r
944  * Returns:\r
945  *      DAT_SUCCESS\r
946  *      DAT_INSUFFICIENT_RESOURCES\r
947  *\r
948  */\r
949 DAT_RETURN\r
950 dapls_ib_pd_alloc (\r
951         IN  DAPL_IA                 *ia,\r
952         IN  DAPL_PZ                 *pz)\r
953 {\r
954     ib_api_status_t         ib_status;\r
955     dapl_ibal_ca_t          *p_ca;\r
956 \r
957     p_ca = (dapl_ibal_ca_t *) ia->hca_ptr->ib_hca_handle;\r
958 \r
959     ib_status = ib_alloc_pd (\r
960                               p_ca->h_ca,\r
961                               IB_PDT_NORMAL,\r
962                               ia,\r
963                               &pz->pd_handle );\r
964 \r
965     return dapl_ib_status_convert (ib_status);\r
966 }\r
967 \r
968 \r
969 /*\r
970  * dapl_ib_pd_free\r
971  *\r
972  * Free a PD\r
973  *\r
974  * Input:\r
975  *      PZ_ptr                  pointer to PZ struct\r
976  *\r
977  * Output:\r
978  *      none\r
979  *\r
980  * Returns:\r
981  *      DAT_SUCCESS\r
982  *      DAT_INSUFFICIENT_RESOURCES\r
983  *\r
984  */\r
985 DAT_RETURN\r
986 dapls_ib_pd_free (\r
987         IN  DAPL_PZ                 *pz)\r
988 {\r
989     ib_api_status_t                 ib_status;\r
990 \r
991     ib_status = ib_dealloc_pd (pz->pd_handle, /* destroy_callback */ NULL);\r
992 \r
993     pz->pd_handle = IB_INVALID_HANDLE;\r
994 \r
995     return dapl_ib_status_convert (ib_status);\r
996 }\r
997 \r
998 \r
999 /*\r
1000  * dapl_ib_mr_register\r
1001  *\r
1002  * Register a virtual memory region\r
1003  *\r
1004  * Input:\r
1005  *      ia_handle               IA handle\r
1006  *      lmr                     pointer to dapl_lmr struct\r
1007  *      virt_addr               virtual address of beginning of mem region\r
1008  *      length                  length of memory region\r
1009  *\r
1010  * Output:\r
1011  *      none\r
1012  *\r
1013  * Returns:\r
1014  *      DAT_SUCCESS\r
1015  *      DAT_INSUFFICIENT_RESOURCES\r
1016  *\r
1017  */\r
1018 DAT_RETURN\r
1019 dapls_ib_mr_register (\r
1020         IN  DAPL_IA                 *ia,\r
1021         IN  DAPL_LMR                *lmr,\r
1022         IN  DAT_PVOID                virt_addr,\r
1023         IN  DAT_VLEN                length,\r
1024         IN  DAT_MEM_PRIV_FLAGS      privileges,\r
1025         IN  DAT_VA_TYPE             va_type)\r
1026 {\r
1027     ib_api_status_t     ib_status;\r
1028     ib_mr_handle_t      mr_handle;\r
1029     ib_mr_create_t      mr_create;\r
1030     uint32_t            l_key, r_key; \r
1031 \r
1032     if ( ia == NULL || ia->header.magic != DAPL_MAGIC_IA )\r
1033     {\r
1034         return DAT_INVALID_HANDLE;\r
1035     }\r
1036 \r
1037     /* IBAL does not support */\r
1038     if (va_type == DAT_VA_TYPE_ZB) {\r
1039         dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
1040                      "--> va_type == DAT_VA_TYPE_ZB: NOT SUPPORTED\n");    \r
1041         return DAT_ERROR (DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE);  \r
1042     }\r
1043 \r
1044     mr_create.vaddr         = (void *) virt_addr;\r
1045     mr_create.length        = (size_t)length;\r
1046     mr_create.access_ctrl   = dapl_lmr_convert_privileges (privileges);\r
1047     mr_create.access_ctrl   |= IB_AC_MW_BIND;\r
1048    \r
1049     if (lmr->param.mem_type == DAT_MEM_TYPE_SHARED_VIRTUAL)\r
1050     {\r
1051         ib_status = ib_reg_shmid (\r
1052                           ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,\r
1053                           (const uint8_t*)lmr->shmid,\r
1054                           &mr_create,\r
1055                           (uint64_t *)&virt_addr,\r
1056                           &l_key,\r
1057                           &r_key,\r
1058                           &mr_handle);\r
1059     }\r
1060     else \r
1061     {\r
1062         ib_status = ib_reg_mem ( ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,\r
1063                                  &mr_create,\r
1064                                  &l_key,\r
1065                                  &r_key,\r
1066                                  &mr_handle );\r
1067     }\r
1068     \r
1069     if (ib_status != IB_SUCCESS)\r
1070     {\r
1071         return (dapl_ib_status_convert (ib_status));\r
1072     }\r
1073     \r
1074     /* DAT/DAPL expects context in host order */\r
1075     l_key = cl_ntoh32(l_key);\r
1076     r_key = cl_ntoh32(r_key);\r
1077 \r
1078     dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIMR: lmr (%p) lkey = 0x%x "\r
1079                   "r_key= %#x mr_handle %p vaddr 0x%LX len 0x%LX\n", \r
1080                   lmr, l_key, r_key, mr_handle, virt_addr, length);\r
1081 \r
1082     lmr->param.lmr_context = l_key;\r
1083     lmr->param.rmr_context = r_key;\r
1084     lmr->param.registered_size = length;\r
1085     lmr->param.registered_address = (DAT_VADDR)virt_addr;\r
1086     lmr->mr_handle         = mr_handle;\r
1087 \r
1088     return (DAT_SUCCESS);\r
1089 }\r
1090 \r
1091 \r
1092 /*\r
1093  * dapl_ib_mr_deregister\r
1094  *\r
1095  * Free a memory region\r
1096  *\r
1097  * Input:\r
1098  *      lmr                     pointer to dapl_lmr struct\r
1099  *\r
1100  * Output:\r
1101  *      none\r
1102  *\r
1103  * Returns:\r
1104  *      DAT_SUCCESS\r
1105  *      DAT_INSUFFICIENT_RESOURCES\r
1106  *\r
1107  */\r
1108 DAT_RETURN\r
1109 dapls_ib_mr_deregister (\r
1110         IN  DAPL_LMR                *lmr)\r
1111 {\r
1112     ib_api_status_t                ib_status;\r
1113 \r
1114     ib_status = ib_dereg_mr (lmr->mr_handle);\r
1115 \r
1116     if (ib_status != IB_SUCCESS)\r
1117     {\r
1118         return dapl_ib_status_convert (ib_status);\r
1119     }\r
1120 \r
1121     lmr->param.lmr_context = 0;\r
1122     lmr->mr_handle         = IB_INVALID_HANDLE;\r
1123 \r
1124     return (DAT_SUCCESS);\r
1125 }\r
1126 \r
1127 \r
1128 /*\r
1129  * dapl_ib_mr_register_shared\r
1130  *\r
1131  * Register a virtual memory region\r
1132  *\r
1133  * Input:\r
1134  *      ia_handle               IA handle\r
1135  *      lmr                     pointer to dapl_lmr struct\r
1136  *      virt_addr               virtual address of beginning of mem region\r
1137  *      length                  length of memory region\r
1138  *\r
1139  * Output:\r
1140  *      none\r
1141  *\r
1142  * Returns:\r
1143  *      DAT_SUCCESS\r
1144  *      DAT_INSUFFICIENT_RESOURCES\r
1145  *\r
1146  */\r
1147 DAT_RETURN\r
1148 dapls_ib_mr_register_shared (\r
1149         IN  DAPL_IA                  *ia,\r
1150         IN  DAPL_LMR                 *lmr,\r
1151         IN  DAT_MEM_PRIV_FLAGS       privileges,\r
1152         IN  DAT_VA_TYPE              va_type )\r
1153 {\r
1154     DAT_VADDR                   virt_addr;\r
1155     ib_mr_handle_t              mr_handle;\r
1156     ib_api_status_t             ib_status;\r
1157     ib_mr_handle_t              new_mr_handle;\r
1158     ib_access_t                 access_ctrl;\r
1159     uint32_t                    l_key, r_key; \r
1160     ib_mr_create_t      mr_create;\r
1161     if ( ia == NULL || ia->header.magic != DAPL_MAGIC_IA )\r
1162     {\r
1163         return DAT_INVALID_HANDLE;\r
1164     }\r
1165 \r
1166     /* IBAL does not support?? */\r
1167     if (va_type == DAT_VA_TYPE_ZB) {\r
1168         dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
1169             " va_type == DAT_VA_TYPE_ZB: NOT SUPPORTED\n");    \r
1170         return DAT_ERROR (DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE);  \r
1171     }\r
1172 \r
1173     virt_addr = dapl_mr_get_address (lmr->param.region_desc,\r
1174                                      lmr->param.mem_type);\r
1175 \r
1176     access_ctrl   = dapl_lmr_convert_privileges (privileges);\r
1177     access_ctrl  |= IB_AC_MW_BIND;\r
1178 \r
1179     mr_create.vaddr         = (void *) virt_addr;\r
1180     mr_create.access_ctrl   = access_ctrl;\r
1181     mr_handle = (ib_mr_handle_t) lmr->mr_handle;\r
1182 \r
1183     dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
1184                        "--> DsIMRS: orig mr_handle %p vaddr %p\n", \r
1185                        mr_handle, virt_addr);\r
1186 \r
1187     if (lmr->param.mem_type == DAT_MEM_TYPE_SHARED_VIRTUAL)\r
1188     {\r
1189         ib_status = ib_reg_shmid ( ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,\r
1190                                    (const uint8_t*)lmr->shmid,\r
1191                                    &mr_create,\r
1192                                    &virt_addr,\r
1193                                    &l_key,\r
1194                                    &r_key,\r
1195                                    &new_mr_handle );\r
1196     }\r
1197     else\r
1198     { \r
1199 \r
1200         ib_status = ib_reg_shared ( mr_handle,\r
1201                                    ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,\r
1202                                    access_ctrl,\r
1203                                    /* in/out */(DAT_UINT64 *)&virt_addr,\r
1204                                    &l_key,\r
1205                                    &r_key,\r
1206                                    &new_mr_handle );\r
1207     }\r
1208 \r
1209     if (ib_status != IB_SUCCESS)\r
1210     {\r
1211         return dapl_ib_status_convert (ib_status);\r
1212     }\r
1213     /*\r
1214      * FIXME - Vu\r
1215      *    What if virt_addr as an OUTPUT having the actual virtual address\r
1216      *    assigned to the register region\r
1217      */\r
1218 \r
1219     /* DAT/DAPL expects context to be in host order */\r
1220     l_key = cl_ntoh32(l_key);\r
1221     r_key = cl_ntoh32(r_key);\r
1222 \r
1223     dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIMRS: lmr (%p) lkey = 0x%x "\r
1224                   "new mr_handle %p vaddr %p\n",\r
1225                   lmr, l_key, new_mr_handle, virt_addr);\r
1226 \r
1227     lmr->param.lmr_context = l_key;\r
1228     lmr->param.rmr_context = r_key;\r
1229     lmr->param.registered_address = (DAT_VADDR) (uintptr_t) virt_addr;\r
1230     lmr->mr_handle         = new_mr_handle;\r
1231 \r
1232     return (DAT_SUCCESS);\r
1233 }\r
1234 \r
1235 \r
1236 /*\r
1237  * dapls_ib_mw_alloc\r
1238  *\r
1239  * Bind a protection domain to a memory window\r
1240  *\r
1241  * Input:\r
1242  *      rmr                     Initialized rmr to hold binding handles\r
1243  *\r
1244  * Output:\r
1245  *      none\r
1246  *\r
1247  * Returns:\r
1248  *      DAT_SUCCESS\r
1249  *      DAT_INSUFFICIENT_RESOURCES\r
1250  *\r
1251  */\r
1252 DAT_RETURN\r
1253 dapls_ib_mw_alloc ( IN  DAPL_RMR    *rmr )\r
1254 {\r
1255     ib_api_status_t     ib_status;\r
1256     uint32_t            r_key;\r
1257     ib_mw_handle_t      mw_handle;\r
1258 \r
1259     ib_status = ib_create_mw (\r
1260                   ((DAPL_PZ *)rmr->param.pz_handle)->pd_handle,\r
1261                   &r_key,\r
1262                   &mw_handle);\r
1263 \r
1264     if (ib_status != IB_SUCCESS)\r
1265     {\r
1266         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
1267                        "--> DsIMA: create MW failed = %s\n",\r
1268                        ib_get_err_str(ib_status) );\r
1269         return dapl_ib_status_convert (ib_status);\r
1270     }\r
1271 \r
1272     rmr->mw_handle         = mw_handle;\r
1273     rmr->param.rmr_context = (DAT_RMR_CONTEXT) cl_ntoh32(r_key);\r
1274 \r
1275     dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
1276                        "--> DsIMA: mw_handle %p r_key = 0x%x\n", \r
1277                         mw_handle, rmr->param.rmr_context);\r
1278 \r
1279     return (DAT_SUCCESS);\r
1280 }\r
1281 \r
1282 \r
1283 /*\r
1284  * dapls_ib_mw_free\r
1285  *\r
1286  * Release bindings of a protection domain to a memory window\r
1287  *\r
1288  * Input:\r
1289  *      rmr                     Initialized rmr to hold binding handles\r
1290  *\r
1291  * Output:\r
1292  *      none\r
1293  *\r
1294  * Returns:\r
1295  *      DAT_SUCCESS\r
1296  *      DAT_INSUFFICIENT_RESOURCES\r
1297  *\r
1298  */\r
1299 DAT_RETURN\r
1300 dapls_ib_mw_free (\r
1301         IN  DAPL_RMR                         *rmr)\r
1302 {\r
1303     ib_api_status_t         ib_status;\r
1304 \r
1305     dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
1306                        "--> DsIMF: mw_handle %p\n", rmr->mw_handle);\r
1307 \r
1308     ib_status = ib_destroy_mw (rmr->mw_handle);\r
1309 \r
1310     if (ib_status != IB_SUCCESS)\r
1311     {\r
1312         dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIMF: Free MW failed = %s\n",\r
1313                        ib_get_err_str(ib_status));\r
1314         return dapl_ib_status_convert (ib_status);\r
1315     }\r
1316 \r
1317     rmr->param.rmr_context = 0;\r
1318     rmr->mw_handle         = IB_INVALID_HANDLE;\r
1319 \r
1320     return (DAT_SUCCESS);\r
1321 }\r
1322 \r
1323 /*\r
1324  * dapls_ib_mw_bind\r
1325  *\r
1326  * Bind a protection domain to a memory window\r
1327  *\r
1328  * Input:\r
1329  *      rmr                     Initialized rmr to hold binding handles\r
1330  *\r
1331  * Output:\r
1332  *      none\r
1333  *\r
1334  * Returns:\r
1335  *      DAT_SUCCESS\r
1336  *      DAT_INSUFFICIENT_RESOURCES\r
1337  *\r
1338  */\r
1339 DAT_RETURN\r
1340 dapls_ib_mw_bind (\r
1341         IN  DAPL_RMR                *rmr,\r
1342         IN  DAPL_LMR                *lmr,\r
1343         IN  DAPL_EP                 *ep,\r
1344         IN  DAPL_COOKIE             *cookie,\r
1345         IN  DAT_VADDR               virtual_address,\r
1346         IN  DAT_VLEN                length,\r
1347         IN  DAT_MEM_PRIV_FLAGS      mem_priv,\r
1348         IN  ib_bool_t               is_signaled)\r
1349 {\r
1350     ib_api_status_t       ib_status;\r
1351     ib_bind_wr_t          bind_wr_prop;\r
1352     uint32_t              new_rkey;\r
1353     \r
1354     bind_wr_prop.local_ds.vaddr   = virtual_address;\r
1355     bind_wr_prop.local_ds.length  = (uint32_t)length;\r
1356     bind_wr_prop.local_ds.lkey    = cl_hton32(lmr->param.lmr_context);\r
1357     bind_wr_prop.current_rkey     = cl_hton32(rmr->param.rmr_context);\r
1358     bind_wr_prop.access_ctrl      = dapl_rmr_convert_privileges (mem_priv);\r
1359     bind_wr_prop.send_opt         = (is_signaled == TRUE) ? \r
1360                                     IB_SEND_OPT_SIGNALED : 0;\r
1361     bind_wr_prop.wr_id            = (uint64_t) ((uintptr_t) cookie);\r
1362     bind_wr_prop.h_mr             = lmr->mr_handle;\r
1363 \r
1364     dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIMB: mr_handle %p, mw_handle %p "\r
1365                   "vaddr %#I64x length %#I64x\n", \r
1366                   lmr->mr_handle, rmr->mw_handle, virtual_address, length);\r
1367 \r
1368     ib_status = ib_bind_mw (\r
1369                     rmr->mw_handle,\r
1370                     ep->qp_handle,\r
1371                     &bind_wr_prop,\r
1372                     &new_rkey);\r
1373 \r
1374     if (ib_status != IB_SUCCESS)\r
1375     {\r
1376         dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIMB: Bind MW failed = %s\n", \r
1377                        ib_get_err_str(ib_status));\r
1378         return (dapl_ib_status_convert (ib_status));\r
1379     }\r
1380 \r
1381     rmr->param.rmr_context      = (DAT_RMR_CONTEXT) cl_ntoh32(new_rkey);\r
1382 \r
1383     dapl_dbg_log (DAPL_DBG_TYPE_UTIL,\r
1384                         "--> DsIMB: new_rkey = 0x%x\n", rmr->param.rmr_context);\r
1385 \r
1386     return (DAT_SUCCESS);\r
1387 }\r
1388 \r
1389 /*\r
1390  * dapls_ib_mw_unbind\r
1391  *\r
1392  * Unbind a memory window\r
1393  *\r
1394  * Input:\r
1395  *      rmr                     Initialized rmr to hold binding handles\r
1396  *\r
1397  * Output:\r
1398  *      none\r
1399  *\r
1400  * Returns:\r
1401  *      DAT_SUCCESS\r
1402  *      DAT_INSUFFICIENT_RESOURCES\r
1403  *\r
1404  */\r
1405 DAT_RETURN\r
1406 dapls_ib_mw_unbind (\r
1407         IN  DAPL_RMR            *rmr,\r
1408         IN  DAPL_EP             *ep,\r
1409         IN  DAPL_COOKIE         *cookie,\r
1410         IN  ib_bool_t           is_signaled)\r
1411 {\r
1412     ib_api_status_t       ib_status;\r
1413     ib_bind_wr_t          bind_wr_prop;\r
1414     uint32_t              new_rkey;\r
1415     \r
1416     bind_wr_prop.local_ds.vaddr   = 0;\r
1417     bind_wr_prop.local_ds.length  = 0;\r
1418     bind_wr_prop.local_ds.lkey    = 0;\r
1419     bind_wr_prop.access_ctrl      = 0;\r
1420     bind_wr_prop.send_opt         = (is_signaled == TRUE) ? \r
1421                                     IB_SEND_OPT_SIGNALED : 0;\r
1422     bind_wr_prop.wr_id            = (uint64_t) ((uintptr_t) cookie);\r
1423 \r
1424     dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
1425                        "--> DsIMU: mw_handle = %p\n", rmr->mw_handle);\r
1426 \r
1427     ib_status = ib_bind_mw (\r
1428                     rmr->mw_handle,\r
1429                     ep->qp_handle,\r
1430                     &bind_wr_prop,\r
1431                     &new_rkey);\r
1432 \r
1433     if (ib_status != IB_SUCCESS)\r
1434     {\r
1435         dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIMU: Unbind MW failed = %s\n", \r
1436                 ib_get_err_str(ib_status));\r
1437         return (dapl_ib_status_convert (ib_status));\r
1438     }\r
1439 \r
1440     rmr->param.rmr_context      = (DAT_RMR_CONTEXT) cl_ntoh32(new_rkey);\r
1441 \r
1442     dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
1443                   "--> DsIMU: unbind new_rkey 0x%x\n", rmr->param.rmr_context);\r
1444 \r
1445     return (DAT_SUCCESS);\r
1446 }\r
1447 \r
1448 \r
1449 /*\r
1450  * dapls_ib_setup_async_callback\r
1451  *\r
1452  * Set up an asynchronous callbacks of various kinds\r
1453  *\r
1454  * Input:\r
1455  *      ia_handle               IA handle\r
1456  *      handler_type            type of handler to set up\r
1457  *      callback_handle         handle param for completion callbacks\r
1458  *      callback                callback routine pointer\r
1459  *      context                 argument for callback routine\r
1460  *\r
1461  * Output:\r
1462  *      none\r
1463  *\r
1464  * Returns:\r
1465  *      DAT_SUCCESS\r
1466  *      DAT_INSUFFICIENT_RESOURCES\r
1467  *      DAT_INVALID_PARAMETER\r
1468  *\r
1469  */\r
1470 DAT_RETURN\r
1471 dapls_ib_setup_async_callback (\r
1472         IN  DAPL_IA                     *ia_ptr,\r
1473         IN  DAPL_ASYNC_HANDLER_TYPE     handler_type,\r
1474         IN  DAPL_EVD                    *evd_ptr,\r
1475         IN  ib_async_handler_t          callback,\r
1476         IN  void                        *context )\r
1477 {\r
1478     dapl_ibal_ca_t     *p_ca;\r
1479     dapl_ibal_evd_cb_t *evd_cb;\r
1480 \r
1481     dapl_dbg_log (DAPL_DBG_TYPE_UTIL,\r
1482                   " setup_async_cb: ia %p type %d hdl %p cb %p ctx %p\n",\r
1483                   ia_ptr, handler_type, evd_ptr, callback, context);\r
1484 \r
1485     p_ca = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;\r
1486 \r
1487     if (p_ca == NULL)\r
1488     {\r
1489         dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsISAC: can't find %s HCA\n", \r
1490                        (ia_ptr->header.provider)->device_name);\r
1491         return (DAT_INVALID_HANDLE);\r
1492     }\r
1493    \r
1494     if (handler_type != DAPL_ASYNC_CQ_COMPLETION)\r
1495     {\r
1496         evd_cb = dapli_find_evd_cb_by_context (context, p_ca);\r
1497            \r
1498         if (evd_cb == NULL)\r
1499         {\r
1500             /* \r
1501              * No record for this evd. We allocate one\r
1502              */\r
1503             evd_cb = dapl_os_alloc (sizeof (dapl_ibal_evd_cb_t));\r
1504             dapl_os_memzero (evd_cb, sizeof(dapl_ibal_evd_cb_t));\r
1505 \r
1506             if (evd_cb == NULL)\r
1507             {\r
1508                 dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
1509                                "--> %s: can't alloc res\n","DsISAC"); \r
1510                 return (DAT_INSUFFICIENT_RESOURCES);\r
1511             }\r
1512         \r
1513             evd_cb->context          = context;\r
1514         \r
1515             /*\r
1516              *  Add the new EVD CB to the list\r
1517              */\r
1518             LOCK_INSERT_TAIL( p_ca->evd_cb_lock, \r
1519                               p_ca->evd_cb_head,\r
1520                               evd_cb->next );\r
1521         }\r
1522 \r
1523         switch (handler_type)\r
1524         {\r
1525             case DAPL_ASYNC_UNAFILIATED:\r
1526                 evd_cb->pfn_async_err_cb = callback;\r
1527                 break;\r
1528             case DAPL_ASYNC_CQ_ERROR:\r
1529                 evd_cb->pfn_async_cq_err_cb = callback;\r
1530                 break;\r
1531             case DAPL_ASYNC_QP_ERROR:\r
1532                 evd_cb->pfn_async_qp_err_cb = callback;\r
1533                 break;\r
1534             default:\r
1535                 break;\r
1536         }\r
1537 \r
1538     }\r
1539 \r
1540     return DAT_SUCCESS;\r
1541 }\r
1542 \r
1543 \r
1544 /*\r
1545  * dapls_ib_query_gid\r
1546  *\r
1547  * Query the hca for the gid of the 1st active port.\r
1548  *\r
1549  * Input:\r
1550  *      hca_handl               hca handle      \r
1551  *      ep_attr                 attribute of the ep\r
1552  *\r
1553  * Output:\r
1554  *      none\r
1555  *\r
1556  * Returns:\r
1557  *      DAT_SUCCESS\r
1558  *      DAT_INVALID_HANDLE\r
1559  *      DAT_INVALID_PARAMETER\r
1560  */\r
1561 \r
1562 DAT_RETURN\r
1563 dapls_ib_query_gid( IN  DAPL_HCA        *hca_ptr,\r
1564                     IN  GID             *gid )\r
1565 {\r
1566     dapl_ibal_ca_t    *p_ca;\r
1567     ib_ca_attr_t      *p_hca_attr;\r
1568     ib_api_status_t   ib_status;\r
1569     ib_hca_port_t     port_num;\r
1570 \r
1571     p_ca = (dapl_ibal_ca_t *) hca_ptr->ib_hca_handle;\r
1572 \r
1573     if (p_ca == NULL)\r
1574     {\r
1575         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
1576                         "%s() invalid hca_ptr %p", __FUNCTION__, hca_ptr);\r
1577         return DAT_INVALID_HANDLE;\r
1578     }\r
1579 \r
1580     ib_status = ib_query_ca (\r
1581                           p_ca->h_ca,\r
1582                           p_ca->p_ca_attr,\r
1583                           &p_ca->ca_attr_size);\r
1584     if (ib_status != IB_SUCCESS)\r
1585     {\r
1586         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
1587                        "%s() ib_query_ca returned failed status = %s\n", \r
1588                        ib_get_err_str(ib_status));\r
1589         return dapl_ib_status_convert (ib_status);\r
1590     }\r
1591 \r
1592     p_hca_attr = p_ca->p_ca_attr;\r
1593     port_num = hca_ptr->port_num - 1;\r
1594 \r
1595     gid->gid_prefix = p_hca_attr->p_port_attr[port_num].p_gid_table->unicast.prefix;\r
1596     gid->guid = p_hca_attr->p_port_attr[port_num].p_gid_table->unicast.interface_id;\r
1597     return DAT_SUCCESS;\r
1598 }\r
1599 \r
1600 \r
1601 /*\r
1602  * dapls_ib_query_hca\r
1603  *\r
1604  * Query the hca attribute\r
1605  *\r
1606  * Input:\r
1607  *      hca_handl               hca handle      \r
1608  *      ep_attr                 attribute of the ep\r
1609  *\r
1610  * Output:\r
1611  *      none\r
1612  *\r
1613  * Returns:\r
1614  *      DAT_SUCCESS\r
1615  *      DAT_INVALID_PARAMETER\r
1616  */\r
1617 \r
1618 DAT_RETURN dapls_ib_query_hca (\r
1619         IN  DAPL_HCA                       *hca_ptr,\r
1620         OUT DAT_IA_ATTR                    *ia_attr,\r
1621         OUT DAT_EP_ATTR                    *ep_attr,\r
1622         OUT DAT_SOCK_ADDR6                 *ip_addr)\r
1623 {\r
1624     ib_ca_attr_t      *p_hca_attr;\r
1625     dapl_ibal_ca_t    *p_ca;\r
1626     ib_api_status_t   ib_status;\r
1627     ib_hca_port_t     port_num;\r
1628     GID gid;\r
1629     DAT_SOCK_ADDR6       *p_sock_addr;\r
1630     DAT_RETURN dat_status = DAT_SUCCESS;\r
1631     port_num = hca_ptr->port_num;\r
1632 \r
1633     p_ca = (dapl_ibal_ca_t *) hca_ptr->ib_hca_handle;\r
1634 \r
1635     if (p_ca == NULL)\r
1636     {\r
1637         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,  "--> %s: invalid handle %p",\r
1638                        "DsIQH", hca_ptr);\r
1639         return (DAT_INVALID_HANDLE);\r
1640     }\r
1641 \r
1642     ib_status = ib_query_ca (\r
1643                           p_ca->h_ca,\r
1644                           p_ca->p_ca_attr,\r
1645                           &p_ca->ca_attr_size);\r
1646     if (ib_status != IB_SUCCESS)\r
1647     {\r
1648         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
1649                        "--> DsIQH: ib_query_ca returned failed status = %s\n", \r
1650                        ib_get_err_str(ib_status));\r
1651         return (dapl_ib_status_convert (ib_status));\r
1652     }\r
1653 \r
1654     p_hca_attr = p_ca->p_ca_attr;\r
1655 \r
1656     if (ip_addr != NULL)\r
1657     {\r
1658         p_sock_addr = dapl_os_alloc(sizeof(DAT_SOCK_ADDR6));\r
1659         if ( !p_sock_addr )\r
1660         {\r
1661                 dat_status = DAT_INSUFFICIENT_RESOURCES;\r
1662                 dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
1663                                        " Query Hca alloc Err: status %d\n",\r
1664                                        dat_status);\r
1665                 return dat_status;\r
1666         }\r
1667         dapl_os_memzero(p_sock_addr, sizeof(DAT_SOCK_ADDR6));\r
1668 \r
1669         gid.gid_prefix = p_hca_attr->p_port_attr[port_num-1].p_gid_table->unicast.prefix;\r
1670         gid.guid = p_hca_attr->p_port_attr[port_num-1].p_gid_table->unicast.interface_id;\r
1671         \r
1672         dat_status = dapls_ns_map_ipaddr( hca_ptr,\r
1673                                           gid,\r
1674                                           (DAT_IA_ADDRESS_PTR)p_sock_addr);\r
1675         \r
1676         if ( dat_status != DAT_SUCCESS )\r
1677         {\r
1678             dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
1679                           " SA Query for local IP failed= %d\n", dat_status );\r
1680                         /* what to do next ? */\r
1681         }\r
1682         else\r
1683         {\r
1684             dapl_dbg_log (DAPL_DBG_TYPE_CM, "SA query GID for IP: ");\r
1685             dapl_dbg_log ( DAPL_DBG_TYPE_CM, "%0d:%d:%d:%d\n", \r
1686                 (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[2]&0xff,\r
1687                 (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[3]&0xff,\r
1688                 (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[4]&0xff,\r
1689                 (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[5]&0xff);\r
1690         }\r
1691 \r
1692         hca_ptr->hca_address = *p_sock_addr;\r
1693 \r
1694         /* if structure address not from our hca_ptr */\r
1695         if ( ip_addr  != &hca_ptr->hca_address )\r
1696         {\r
1697             *ip_addr = *p_sock_addr;\r
1698         }\r
1699 \r
1700         dapl_os_free (p_sock_addr, sizeof(DAT_SOCK_ADDR6));\r
1701 \r
1702     } /* ip_addr != NULL */\r
1703 \r
1704     if ( ia_attr != NULL )\r
1705     {\r
1706         dapl_os_memzero( ia_attr->adapter_name,\r
1707                          (int)sizeof(ia_attr->adapter_name ));\r
1708         dapl_os_memcpy(ia_attr->adapter_name,\r
1709                         DAT_ADAPTER_NAME, \r
1710                         min ( (int)dapl_os_strlen(DAT_ADAPTER_NAME),\r
1711                               (int)(DAT_NAME_MAX_LENGTH)-1 ) );\r
1712 \r
1713         dapl_os_memzero ( ia_attr->vendor_name,\r
1714                           (int)sizeof(ia_attr->vendor_name) );\r
1715         dapl_os_memcpy ( ia_attr->vendor_name, \r
1716                          DAT_VENDOR_NAME,\r
1717                         min ( (int)dapl_os_strlen(DAT_VENDOR_NAME),\r
1718                               (int)(DAT_NAME_MAX_LENGTH)-1 ) );\r
1719         \r
1720         /* FIXME : Vu\r
1721          *         this value should be revisited\r
1722          *         It can be set by DAT consumers\r
1723          */\r
1724         ia_attr->ia_address_ptr           = (DAT_PVOID)&hca_ptr->hca_address;\r
1725         ia_attr->hardware_version_major   = p_hca_attr->dev_id;\r
1726         ia_attr->hardware_version_minor   = p_hca_attr->revision;\r
1727         ia_attr->max_eps                  = p_hca_attr->max_qps;\r
1728         ia_attr->max_dto_per_ep           = p_hca_attr->max_wrs;\r
1729         ia_attr->max_rdma_read_per_ep     = p_hca_attr->max_qp_resp_res;\r
1730         ia_attr->max_evds                 = p_hca_attr->max_cqs;\r
1731         ia_attr->max_evd_qlen             = p_hca_attr->max_cqes;\r
1732         ia_attr->max_iov_segments_per_dto = p_hca_attr->max_sges;\r
1733         ia_attr->max_lmrs                 = p_hca_attr->init_regions;\r
1734         ia_attr->max_lmr_block_size       = p_hca_attr->init_region_size;\r
1735         ia_attr->max_rmrs                 = p_hca_attr->init_windows;\r
1736         ia_attr->max_lmr_virtual_address  = p_hca_attr->max_addr_handles;\r
1737         ia_attr->max_rmr_target_address   = p_hca_attr->max_addr_handles;\r
1738         ia_attr->max_pzs                  = p_hca_attr->max_pds;\r
1739         /*\r
1740          * DAT spec does not tie max_mtu_size with IB MTU\r
1741          *\r
1742         ia_attr->max_mtu_size             = \r
1743                         dapl_ibal_mtu_table[p_hca_attr->p_port_attr->mtu];\r
1744         */\r
1745         ia_attr->max_mtu_size             = \r
1746                         p_hca_attr->p_port_attr->max_msg_size;\r
1747         ia_attr->max_rdma_size            = \r
1748                         p_hca_attr->p_port_attr->max_msg_size;\r
1749         ia_attr->num_transport_attr       = 0;\r
1750         ia_attr->transport_attr           = NULL;\r
1751         ia_attr->num_vendor_attr          = 0;\r
1752         ia_attr->vendor_attr              = NULL;\r
1753         ia_attr->max_iov_segments_per_rdma_read = p_hca_attr->max_sges;\r
1754 \r
1755 #ifdef DAT_EXTENSIONS\r
1756         ia_attr->extension_supported = DAT_EXTENSION_IB;\r
1757         ia_attr->extension_version = DAT_IB_EXTENSION_VERSION;\r
1758 #endif\r
1759         \r
1760         dapl_dbg_log(DAPL_DBG_TYPE_UTIL, \r
1761                 " --> DsIMU_qHCA: (ver=%x) ep %d ep_q %d evd %d evd_q %d\n", \r
1762                         ia_attr->hardware_version_major,\r
1763                         ia_attr->max_eps, ia_attr->max_dto_per_ep,\r
1764                         ia_attr->max_evds, ia_attr->max_evd_qlen );\r
1765         dapl_dbg_log(DAPL_DBG_TYPE_UTIL, \r
1766                 " --> DsIMU_qHCA: mtu %llu rdma %llu iov %d lmr %d rmr %d"\r
1767                 " rdma_io %d\n", \r
1768                         ia_attr->max_mtu_size, ia_attr->max_rdma_size,\r
1769                         ia_attr->max_iov_segments_per_dto, ia_attr->max_lmrs, \r
1770                         ia_attr->max_rmrs, ia_attr->max_rdma_read_per_ep );\r
1771     }\r
1772 \r
1773     if ( ep_attr != NULL )\r
1774     {\r
1775        (void) dapl_os_memzero(ep_attr, sizeof(*ep_attr)); \r
1776         /*\r
1777          * DAT spec does not tie max_mtu_size with IB MTU\r
1778          *\r
1779         ep_attr->max_mtu_size     = \r
1780                         dapl_ibal_mtu_table[p_hca_attr->p_port_attr->mtu];\r
1781          */\r
1782         ep_attr->max_mtu_size     = p_hca_attr->p_port_attr->max_msg_size;\r
1783         ep_attr->max_rdma_size    = p_hca_attr->p_port_attr->max_msg_size;\r
1784         ep_attr->max_recv_dtos    = p_hca_attr->max_wrs;\r
1785         ep_attr->max_request_dtos = p_hca_attr->max_wrs;\r
1786         ep_attr->max_recv_iov     = p_hca_attr->max_sges;\r
1787         ep_attr->max_request_iov  = p_hca_attr->max_sges;\r
1788         ep_attr->max_rdma_read_in = p_hca_attr->max_qp_resp_res;\r
1789         ep_attr->max_rdma_read_out= p_hca_attr->max_qp_resp_res;\r
1790         \r
1791         dapl_dbg_log(DAPL_DBG_TYPE_UTIL, \r
1792                 " --> DsIMU_qHCA: msg %llu dto %d iov %d rdma i%d,o%d\n", \r
1793                         ep_attr->max_mtu_size,\r
1794                         ep_attr->max_recv_dtos, ep_attr->max_recv_iov,\r
1795                         ep_attr->max_rdma_read_in, ep_attr->max_rdma_read_out);\r
1796     }\r
1797         return DAT_SUCCESS;\r
1798 }\r
1799 \r
1800 \r
1801 DAT_RETURN\r
1802 dapls_ib_completion_poll ( IN DAPL_HCA                *p_hca,\r
1803                            IN DAPL_EVD                *p_evd,\r
1804                            IN ib_work_completion_t   *cqe_ptr )\r
1805 {\r
1806     ib_api_status_t        ib_status;\r
1807     ib_work_completion_t   *cqe_filled;\r
1808 \r
1809     /*\r
1810      * FIXME - Vu\r
1811      *     Now we only poll for one cqe. We can poll for more than\r
1812      *     one completions later for better. However, this requires\r
1813      *     to change the logic in dapl_evd_dto_callback function\r
1814      *     to process more than one completion.\r
1815      */\r
1816     cqe_ptr->p_next = NULL;\r
1817     cqe_filled      = NULL;\r
1818 \r
1819     if  ( !p_hca->ib_hca_handle )\r
1820     {\r
1821         return DAT_INVALID_HANDLE;\r
1822     }\r
1823 \r
1824     ib_status = ib_poll_cq (p_evd->ib_cq_handle, &cqe_ptr, &cqe_filled);\r
1825 \r
1826     if ( ib_status == IB_INVALID_CQ_HANDLE )\r
1827     {\r
1828         ib_status = IB_NOT_FOUND;\r
1829     }\r
1830 \r
1831     return dapl_ib_status_convert (ib_status);\r
1832 }\r
1833 \r
1834 \r
1835 DAT_RETURN\r
1836 dapls_ib_completion_notify ( IN ib_hca_handle_t         hca_handle,\r
1837                              IN DAPL_EVD                *p_evd,\r
1838                              IN ib_notification_type_t  type )\r
1839 {\r
1840     ib_api_status_t        ib_status;\r
1841     DAT_BOOLEAN            solic_notify;\r
1842 \r
1843     if  ( !hca_handle )\r
1844     {\r
1845         return DAT_INVALID_HANDLE;\r
1846     }\r
1847     solic_notify = (type == IB_NOTIFY_ON_SOLIC_COMP) ? DAT_TRUE : DAT_FALSE; \r
1848     ib_status = ib_rearm_cq ( p_evd->ib_cq_handle, solic_notify );\r
1849 \r
1850     return dapl_ib_status_convert (ib_status);\r
1851 }\r
1852 \r
1853 DAT_RETURN\r
1854 dapls_evd_dto_wakeup (\r
1855         IN DAPL_EVD                     *evd_ptr)\r
1856 {\r
1857         return dapl_os_wait_object_wakeup(&evd_ptr->wait_object);\r
1858 }\r
1859 \r
1860 DAT_RETURN\r
1861 dapls_evd_dto_wait (\r
1862         IN DAPL_EVD                     *evd_ptr,\r
1863         IN uint32_t                     timeout)\r
1864 {\r
1865         return dapl_os_wait_object_wait(&evd_ptr->wait_object, timeout);\r
1866 }\r
1867 \r
1868 /*\r
1869  * dapls_ib_get_async_event\r
1870  *\r
1871  * Translate an asynchronous event type to the DAT event.\r
1872  * Note that different providers have different sets of errors.\r
1873  *\r
1874  * Input:\r
1875  *      cause_ptr               provider event cause\r
1876  *\r
1877  * Output:\r
1878  *      async_event             DAT mapping of error\r
1879  *\r
1880  * Returns:\r
1881  *      DAT_SUCCESS\r
1882  *      DAT_NOT_IMPLEMENTED     Caller is not interested this event\r
1883  */\r
1884 \r
1885 DAT_RETURN dapls_ib_get_async_event(\r
1886         IN  ib_async_event_rec_t        *cause_ptr,\r
1887         OUT DAT_EVENT_NUMBER            *async_event)\r
1888 {\r
1889     ib_async_event_t            event_id;\r
1890     DAT_RETURN                  dat_status;\r
1891 \r
1892     dat_status = DAT_SUCCESS;\r
1893     event_id = cause_ptr->code;\r
1894 \r
1895     dapl_dbg_log (DAPL_DBG_TYPE_WARN, "--> DsAE: event_id = %d%d\n", event_id);\r
1896 \r
1897     switch (event_id )\r
1898     {\r
1899         case IB_AE_SQ_ERROR:\r
1900         case IB_AE_SQ_DRAINED:\r
1901         case IB_AE_RQ_ERROR:\r
1902         {\r
1903             *async_event = DAT_ASYNC_ERROR_EP_BROKEN;\r
1904             break;\r
1905         }\r
1906 \r
1907         /* INTERNAL errors */\r
1908         case IB_AE_QP_FATAL:\r
1909         case IB_AE_CQ_ERROR:\r
1910         case IB_AE_LOCAL_FATAL:\r
1911         case IB_AE_WQ_REQ_ERROR:\r
1912         case IB_AE_WQ_ACCESS_ERROR:\r
1913         {\r
1914             *async_event = DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR;\r
1915             break;\r
1916         }\r
1917 \r
1918         /* CATASTROPHIC errors */\r
1919         case IB_AE_FLOW_CTRL_ERROR:\r
1920         case IB_AE_BUF_OVERRUN:\r
1921         {\r
1922             *async_event = DAT_ASYNC_ERROR_IA_CATASTROPHIC;\r
1923             break;\r
1924         }\r
1925 \r
1926         default:\r
1927         {\r
1928             /*\r
1929              * Errors we are not interested in reporting:\r
1930              * IB_AE_QP_APM\r
1931              * IB_AE_PKEY_TRAP\r
1932              * IB_AE_QKEY_TRAP\r
1933              * IB_AE_MKEY_TRAP\r
1934              * IB_AE_PORT_TRAP\r
1935              * IB_AE_QP_APM_ERROR\r
1936              * IB_AE_PORT_ACTIVE\r
1937              * ...\r
1938              */\r
1939             dat_status = DAT_NOT_IMPLEMENTED;\r
1940         }\r
1941 \r
1942     }\r
1943   \r
1944     return dat_status;\r
1945 }\r
1946 \r
1947 /*\r
1948  * dapls_ib_get_dto_status\r
1949  *\r
1950  * Return the DAT status of a DTO operation\r
1951  *\r
1952  * Input:\r
1953  *      cqe_ptr                 pointer to completion queue entry\r
1954  *\r
1955  * Output:\r
1956  *      none\r
1957  *\r
1958  * Returns:\r
1959  *      Value from ib_status_map table above\r
1960  */\r
1961 \r
1962 DAT_DTO_COMPLETION_STATUS\r
1963 dapls_ib_get_dto_status(\r
1964         IN ib_work_completion_t         *cqe_ptr)\r
1965 {\r
1966     ib_uint32_t    ib_status;\r
1967 \r
1968     ib_status = DAPL_GET_CQE_STATUS (cqe_ptr);\r
1969 \r
1970     switch (ib_status)\r
1971     {\r
1972     case IB_COMP_ST_SUCCESS :\r
1973         return  DAT_DTO_SUCCESS;\r
1974 \r
1975     case IB_COMP_ST_LOCAL_LEN_ERR:\r
1976         return DAT_DTO_ERR_LOCAL_LENGTH;\r
1977 \r
1978     case IB_COMP_ST_LOCAL_OP_ERR:\r
1979         return DAT_DTO_ERR_LOCAL_EP;\r
1980 \r
1981     case IB_COMP_ST_LOCAL_PROTECT_ERR:\r
1982         return DAT_DTO_ERR_LOCAL_PROTECTION;\r
1983 \r
1984     case IB_COMP_ST_WR_FLUSHED_ERR:     \r
1985         return DAT_DTO_ERR_FLUSHED;\r
1986 \r
1987     case IB_COMP_ST_MW_BIND_ERR:\r
1988         return DAT_RMR_OPERATION_FAILED;\r
1989 \r
1990     case IB_COMP_ST_REM_ACC_ERR:\r
1991         return DAT_DTO_ERR_REMOTE_ACCESS;\r
1992 \r
1993     case IB_COMP_ST_REM_OP_ERR:\r
1994         return DAT_DTO_ERR_REMOTE_RESPONDER;\r
1995 \r
1996     case IB_COMP_ST_RNR_COUNTER:\r
1997         return DAT_DTO_ERR_RECEIVER_NOT_READY;\r
1998 \r
1999     case IB_COMP_ST_TRANSP_COUNTER:\r
2000         return DAT_DTO_ERR_TRANSPORT;\r
2001 \r
2002     case IB_COMP_ST_REM_REQ_ERR:\r
2003         return DAT_DTO_ERR_REMOTE_RESPONDER;\r
2004 \r
2005     case IB_COMP_ST_BAD_RESPONSE_ERR:\r
2006         return DAT_DTO_ERR_BAD_RESPONSE;\r
2007 \r
2008     case IB_COMP_ST_EE_STATE_ERR:\r
2009     case IB_COMP_ST_EE_CTX_NO_ERR:\r
2010         return DAT_DTO_ERR_TRANSPORT;\r
2011 \r
2012     default:\r
2013 #ifdef DAPL_DBG\r
2014     dapl_dbg_log (DAPL_DBG_TYPE_ERR,"%s() unknown IB_COMP_ST %x(0x%x)\n",\r
2015                   __FUNCTION__,ib_status,ib_status);\r
2016 #endif\r
2017         return DAT_DTO_FAILURE;\r
2018     }\r
2019 }\r
2020 \r
2021 \r
2022 /*\r
2023  * Map all IBAPI DTO completion codes to the DAT equivelent.\r
2024  *\r
2025  * dapls_ib_get_dat_event\r
2026  *\r
2027  * Return a DAT connection event given a provider CM event.\r
2028  *\r
2029  * N.B. Some architectures combine async and CM events into a\r
2030  *      generic async event. In that case, dapls_ib_get_dat_event()\r
2031  *      and dapls_ib_get_async_event() should be entry points that\r
2032  *      call into a common routine.\r
2033  *\r
2034  * Input:\r
2035  *      ib_cm_event     event provided to the dapl callback routine\r
2036  *      active          switch indicating active or passive connection\r
2037  *\r
2038  * Output:\r
2039  *      none\r
2040  *\r
2041  * Returns:\r
2042  *      DAT_EVENT_NUMBER of translated provider value\r
2043  */\r
2044 \r
2045 DAT_EVENT_NUMBER\r
2046 dapls_ib_get_dat_event (\r
2047         IN    const ib_cm_events_t      ib_cm_event,\r
2048         IN    DAT_BOOLEAN               active)\r
2049 {\r
2050     DAT_EVENT_NUMBER            dat_event_num = 0;\r
2051     UNREFERENCED_PARAMETER (active);\r
2052 \r
2053     switch ( ib_cm_event)\r
2054     {\r
2055       case IB_CME_CONNECTED:\r
2056           dat_event_num = DAT_CONNECTION_EVENT_ESTABLISHED;\r
2057           break;\r
2058       case IB_CME_DISCONNECTED:\r
2059            dat_event_num = DAT_CONNECTION_EVENT_DISCONNECTED;\r
2060            break;\r
2061       case IB_CME_DISCONNECTED_ON_LINK_DOWN:\r
2062            dat_event_num = DAT_CONNECTION_EVENT_DISCONNECTED;\r
2063            break;\r
2064       case IB_CME_CONNECTION_REQUEST_PENDING:\r
2065            dat_event_num = DAT_CONNECTION_REQUEST_EVENT;\r
2066            break;\r
2067       case IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA:\r
2068            dat_event_num = DAT_CONNECTION_REQUEST_EVENT;\r
2069            break;\r
2070       case IB_CME_DESTINATION_REJECT:\r
2071            dat_event_num = DAT_CONNECTION_EVENT_NON_PEER_REJECTED;\r
2072            break;\r
2073       case IB_CME_DESTINATION_REJECT_PRIVATE_DATA:\r
2074            dat_event_num = DAT_CONNECTION_EVENT_PEER_REJECTED;\r
2075            break;\r
2076       case IB_CME_DESTINATION_UNREACHABLE:\r
2077            dat_event_num = DAT_CONNECTION_EVENT_UNREACHABLE;\r
2078            break;\r
2079       case IB_CME_TOO_MANY_CONNECTION_REQUESTS:\r
2080            dat_event_num = DAT_CONNECTION_EVENT_NON_PEER_REJECTED;\r
2081            break;\r
2082       case IB_CME_LOCAL_FAILURE:\r
2083            dat_event_num = DAT_CONNECTION_EVENT_BROKEN;\r
2084            break;\r
2085       case IB_CME_REPLY_RECEIVED:\r
2086       case IB_CME_REPLY_RECEIVED_PRIVATE_DATA:\r
2087       default:\r
2088            break;\r
2089     }\r
2090 #if 0\r
2091     dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
2092                   " dapls_ib_get_dat_event: event translation: (%s) "\r
2093                   "ib_event 0x%x dat_event 0x%x\n",\r
2094                   active ? "active" : "passive",\r
2095                   ib_cm_event,\r
2096                   dat_event_num);\r
2097 #endif\r
2098     return dat_event_num;\r
2099 }\r
2100 \r
2101 \r
2102 /*\r
2103  * dapls_ib_get_dat_event\r
2104  *\r
2105  * Return a DAT connection event given a provider CM event.\r
2106  *\r
2107  * N.B. Some architectures combine async and CM events into a\r
2108  *      generic async event. In that case, dapls_ib_get_cm_event()\r
2109  *      and dapls_ib_get_async_event() should be entry points that\r
2110  *      call into a common routine.\r
2111  *\r
2112  *      WARNING: In this implementation, there are multiple CM\r
2113  *      events that map to a single DAT event. Be very careful\r
2114  *      with provider routines that depend on this reverse mapping,\r
2115  *      they may have to accomodate more CM events than they\r
2116  *      'naturally' would.\r
2117  *\r
2118  * Input:\r
2119  *      dat_event_num   DAT event we need an equivelent CM event for\r
2120  *\r
2121  * Output:\r
2122  *      none\r
2123  *\r
2124  * Returns:\r
2125  *      ib_cm_event of translated DAPL value\r
2126  */\r
2127 ib_cm_events_t\r
2128 dapls_ib_get_cm_event (\r
2129         IN    DAT_EVENT_NUMBER          dat_event_num)\r
2130 {\r
2131     ib_cm_events_t      ib_cm_event = 0;\r
2132 \r
2133     switch (dat_event_num)\r
2134     {\r
2135         case DAT_CONNECTION_EVENT_ESTABLISHED:\r
2136              ib_cm_event = IB_CME_CONNECTED;\r
2137              break;\r
2138         case DAT_CONNECTION_EVENT_DISCONNECTED:\r
2139              ib_cm_event = IB_CME_DISCONNECTED;\r
2140              break;\r
2141         case DAT_CONNECTION_REQUEST_EVENT:\r
2142              ib_cm_event =  IB_CME_CONNECTION_REQUEST_PENDING;\r
2143              break;\r
2144         case DAT_CONNECTION_EVENT_NON_PEER_REJECTED:\r
2145              ib_cm_event = IB_CME_DESTINATION_REJECT;\r
2146              break;\r
2147         case DAT_CONNECTION_EVENT_PEER_REJECTED:\r
2148              ib_cm_event = IB_CME_DESTINATION_REJECT_PRIVATE_DATA;\r
2149              break;\r
2150         case DAT_CONNECTION_EVENT_UNREACHABLE:\r
2151              ib_cm_event = IB_CME_DESTINATION_UNREACHABLE;\r
2152              break;\r
2153         case DAT_CONNECTION_EVENT_BROKEN:\r
2154              ib_cm_event = IB_CME_LOCAL_FAILURE;\r
2155              break;\r
2156         default:\r
2157              break;\r
2158     }\r
2159 \r
2160     return ib_cm_event;\r
2161 }\r
2162 \r
2163 \r
2164 \r
2165 /*\r
2166  * dapls_set_provider_specific_attr\r
2167  *\r
2168  * Input:\r
2169  *      attr_ptr        Pointer provider specific attributes\r
2170  *\r
2171  * Output:\r
2172  *      none\r
2173  *\r
2174  * Returns:\r
2175  *      void\r
2176  */\r
2177 \r
2178 #ifdef DAT_EXTENSIONS\r
2179 static DAT_NAMED_ATTR   ib_attrs[] = {\r
2180     {\r
2181         "DAT_EXTENSION_INTERFACE", "TRUE"\r
2182     },\r
2183     {\r
2184         DAT_IB_ATTR_FETCH_AND_ADD, "TRUE"\r
2185     },\r
2186     {\r
2187         DAT_IB_ATTR_CMP_AND_SWAP, "TRUE"\r
2188     },\r
2189     {\r
2190         DAT_IB_ATTR_IMMED_DATA, "TRUE"\r
2191     },\r
2192 };\r
2193 #define SPEC_ATTR_SIZE( x )     (sizeof( x ) / sizeof( DAT_NAMED_ATTR))\r
2194 #else\r
2195 static DAT_NAMED_ATTR   *ib_attrs = NULL;\r
2196 #define SPEC_ATTR_SIZE( x )     0\r
2197 #endif\r
2198 \r
2199 void dapls_query_provider_specific_attr(\r
2200         IN      DAPL_IA                         *ia_ptr,\r
2201         IN      DAT_PROVIDER_ATTR       *attr_ptr )\r
2202 {\r
2203     attr_ptr->num_provider_specific_attr = SPEC_ATTR_SIZE(ib_attrs);\r
2204     attr_ptr->provider_specific_attr     = ib_attrs;\r
2205 }\r
2206 \r
2207 \r
2208 DAT_RETURN dapls_ns_map_gid (\r
2209         IN  DAPL_HCA            *hca_ptr,\r
2210         IN  DAT_IA_ADDRESS_PTR  remote_ia_address,\r
2211         OUT GID                 *gid)\r
2212 {\r
2213     return (dapls_ib_ns_map_gid (hca_ptr, remote_ia_address, gid));\r
2214 }\r
2215 \r
2216 DAT_RETURN dapls_ns_map_ipaddr (\r
2217         IN  DAPL_HCA            *hca_ptr,\r
2218         IN  GID                 gid,\r
2219         OUT DAT_IA_ADDRESS_PTR  remote_ia_address)\r
2220 {\r
2221     return (dapls_ib_ns_map_ipaddr (hca_ptr, gid, remote_ia_address));\r
2222 }\r
2223 \r
2224 \r
2225 #ifdef NOT_USED\r
2226 /*\r
2227  * dapls_ib_post_recv - defered.until QP ! in init state.\r
2228  *\r
2229  * Provider specific Post RECV function\r
2230  */\r
2231 \r
2232 DAT_RETURN \r
2233 dapls_ib_post_recv_defered (\r
2234         IN  DAPL_EP                     *ep_ptr,\r
2235         IN  DAPL_COOKIE                 *cookie,\r
2236         IN  DAT_COUNT                   num_segments,\r
2237         IN  DAT_LMR_TRIPLET             *local_iov)\r
2238 {\r
2239     ib_api_status_t     ib_status;\r
2240     ib_recv_wr_t        *recv_wr, *rwr;\r
2241     ib_local_ds_t       *ds_array_p;\r
2242     DAT_COUNT           i, total_len;\r
2243 \r
2244     if (ep_ptr->qp_state != IB_QPS_INIT)\r
2245     {\r
2246         dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsPR: BAD QP state(%s), not init? "\r
2247                       "EP %p QP %p cookie %p, num_seg %d\n", \r
2248                       ib_get_port_state_str(ep_ptr->qp_state), ep_ptr,\r
2249                       ep_ptr->qp_handle, cookie, num_segments);\r
2250         return (DAT_INSUFFICIENT_RESOURCES);\r
2251     }\r
2252 \r
2253     recv_wr = dapl_os_alloc (sizeof(ib_recv_wr_t)\r
2254                              + (num_segments*sizeof(ib_local_ds_t)));\r
2255     if (NULL == recv_wr)\r
2256     {\r
2257         return (DAT_INSUFFICIENT_RESOURCES);\r
2258     }\r
2259 \r
2260     dapl_os_memzero(recv_wr, sizeof(ib_recv_wr_t));\r
2261     recv_wr->wr_id        = (DAT_UINT64) cookie;\r
2262     recv_wr->num_ds       = num_segments;\r
2263 \r
2264     ds_array_p = (ib_local_ds_t*)(recv_wr+1);\r
2265 \r
2266     recv_wr->ds_array     = ds_array_p;\r
2267 \r
2268     //total_len = 0;\r
2269 \r
2270     for (total_len = i = 0; i < num_segments; i++, ds_array_p++)\r
2271     {\r
2272         ds_array_p->length = (uint32_t)local_iov[i].segment_length;\r
2273         ds_array_p->lkey  = cl_hton32(local_iov[i].lmr_context);\r
2274         ds_array_p->vaddr = local_iov[i].virtual_address;\r
2275         total_len        += ds_array_p->length;\r
2276     }\r
2277 \r
2278     if (cookie != NULL)\r
2279     {\r
2280         cookie->val.dto.size = total_len;\r
2281 \r
2282         dapl_dbg_log (DAPL_DBG_TYPE_EP,\r
2283                       "--> DsPR: EP = %p QP = %p cookie= %p, num_seg= %d\n", \r
2284                       ep_ptr, ep_ptr->qp_handle, cookie, num_segments);\r
2285     }\r
2286 \r
2287     recv_wr->p_next = NULL;\r
2288 \r
2289     /* find last defered recv work request, link new on the end */\r
2290     rwr=ep_ptr->cm_post;\r
2291     if (rwr == NULL)\r
2292     {\r
2293         ep_ptr->cm_post = (void*)recv_wr;\r
2294         i = 1;\r
2295     }\r
2296     else\r
2297     {\r
2298         for(i=2; rwr->p_next; rwr=rwr->p_next) i++;\r
2299         rwr->p_next = recv_wr;\r
2300     }\r
2301 \r
2302     dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsPR: %s() EP %p QP %p cookie %p "\r
2303                   "num_seg %d Tdefered %d\n", \r
2304                   __FUNCTION__, ep_ptr, ep_ptr->qp_handle, cookie, num_segments,\r
2305                   i);\r
2306 \r
2307     return DAT_SUCCESS;\r
2308 }\r
2309 #endif\r
2310 \r
2311 /*\r
2312  * Local variables:\r
2313  *  c-indent-level: 4\r
2314  *  c-basic-offset: 4\r
2315  *  tab-width: 8\r
2316  * End:\r
2317  */\r
2318 \r