1 /*
2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 *
34 */
35
36 /*
37 * Abstract:
38 * Implementation of osm_req_t.
39 * This object represents the generic attribute requester.
40 * This object is part of the opensm family of objects.
41 *
42 */
43
44 /*
45 Next available error code: 0x300
46 */
47
48 #if HAVE_CONFIG_H
49 # include <config.h>
50 #endif /* HAVE_CONFIG_H */
51
52 #ifdef OSM_VENDOR_INTF_UMADT
53
54 #include <stdlib.h>
55 #include <stdio.h>
56 #include <dlfcn.h>
57 #include <string.h>
58
59 #include <complib/cl_qlist.h>
60 #include <complib/cl_thread.h>
61 #include <complib/cl_timer.h>
62 #include <iba/ib_types.h>
63 #include <opensm/osm_madw.h>
64 #include <opensm/osm_log.h>
65 #include <opensm/osm_mad_pool.h>
66
67 #include <vendor/osm_vendor_umadt.h>
68 #include <vendor/osm_umadt.h>
69
70 /* GEN1 includes */
71 #include "umadt_so.h"
72 #include "ibt.h"
73 #include "statustext.h"
74
75 /* //////////////////////////////////////////////////////////////////////// */
76 /* //////////////////////////////////////////////////////////////////////// */
77 /* //////////////////////////////////////////////////////////////////////// */
78 /* //////////////////////////////////////////////////////////////////////// */
79 /* //////////////////////////////////////////////////////////////////////// */
80 /* */
81 /* VENDOR_MAD_INTF */
82 /* */
83 /* //////////////////////////////////////////////////////////////////////// */
84 /* //////////////////////////////////////////////////////////////////////// */
85 /* //////////////////////////////////////////////////////////////////////// */
86 /* //////////////////////////////////////////////////////////////////////// */
87 /* //////////////////////////////////////////////////////////////////////// */
88
89 /* //////////////////// */
90 /* Globals // */
91 /* //////////////////// */
92 typedef struct _ib_sa_mad_vM3 {
93 uint8_t base_ver;
94 uint8_t mgmt_class;
95 uint8_t class_ver;
96 uint8_t method;
97 ib_net16_t status;
98 ib_net16_t resv;
99 ib_net64_t trans_id;
100 ib_net16_t attr_id;
101 ib_net16_t resv1;
102 ib_net32_t attr_mod;
103 ib_net64_t resv2;
104 ib_net64_t sm_key;
105
106 ib_net32_t seg_num;
107 ib_net32_t payload_len;
108 uint8_t frag_flag;
109 uint8_t edit_mod;
110 ib_net16_t window;
111 ib_net16_t attr_offset;
112 ib_net16_t resv3;
113
114 ib_net64_t comp_mask;
115
116 uint8_t data[IB_SA_DATA_SIZE];
117 } ib_sa_mad_t_vM3;
118 #define DEFAULT_TIMER_INTERVAL_MSEC 500 /* 500msec timer interval */
119
120 void __mad_recv_processor(void *context);
121
122 boolean_t __valid_mad_handle(IN mad_bind_info_t * p_mad_bind_info);
123
124 cl_status_t
125 __match_tid_context(const cl_list_item_t * const p_list_item, void *context);
126 void __osm_vendor_timer_callback(IN void *context);
127
osm_vendor_new(IN osm_log_t * const p_log,IN const uint32_t timeout)128 osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log,
129 IN const uint32_t timeout)
130 {
131 ib_api_status_t status;
132 umadt_obj_t *p_umadt_obj;
133
134 OSM_LOG_ENTER(p_log);
135
136 p_umadt_obj = malloc(sizeof(umadt_obj_t));
137 if (p_umadt_obj) {
138 memset(p_umadt_obj, 0, sizeof(umadt_obj_t));
139
140 status = osm_vendor_init((osm_vendor_t *) p_umadt_obj, p_log,
141 timeout);
142 if (status != IB_SUCCESS) {
143 osm_vendor_delete((osm_vendor_t **) & p_umadt_obj);
144 }
145 } else {
146 printf
147 ("osm_vendor_construct: ERROR! Unable to create Umadt object!\n");
148 }
149
150 OSM_LOG_EXIT(p_log);
151
152 return ((osm_vendor_t *) p_umadt_obj);
153 }
154
osm_vendor_delete(IN osm_vendor_t ** const pp_vend)155 void osm_vendor_delete(IN osm_vendor_t ** const pp_vend)
156 {
157 umadt_obj_t *p_umadt_obj = (umadt_obj_t *) * pp_vend;
158 cl_list_item_t *p_list_item;
159 uint32_t count, i;
160 mad_bind_info_t *p_mad_bind_info;
161
162 OSM_LOG_ENTER(p_umadt_obj->p_log);
163
164 cl_spinlock_acquire(&p_umadt_obj->register_lock);
165 p_mad_bind_info =
166 (mad_bind_info_t *) cl_qlist_head(&p_umadt_obj->register_list);
167 count = cl_qlist_count(&p_umadt_obj->register_list);
168 cl_spinlock_release(&p_umadt_obj->register_lock);
169 for (i = 0; i < count; i++) {
170 cl_spinlock_acquire(&p_umadt_obj->register_lock);
171 p_list_item = cl_qlist_next(&p_mad_bind_info->list_item);
172 cl_spinlock_release(&p_umadt_obj->register_lock);
173 /* Unbind this handle */
174 /* osm_vendor_ubind also removesd the item from the list */
175 /* osm_vendor_unbind takes the list lock so release it here */
176 osm_vendor_unbind((osm_bind_handle_t) p_mad_bind_info);
177 p_mad_bind_info = (mad_bind_info_t *) p_list_item;
178 }
179 dlclose(p_umadt_obj->umadt_handle);
180 free(p_umadt_obj);
181 *pp_vend = NULL;
182
183 OSM_LOG_EXIT(p_umadt_obj->p_log);
184 }
185
186 /* //////////////////////////////////////////////////////////////////////// */
187 /* See VendorAbstractMadIntf.h for info */
188 /* //////////////////////////////////////////////////////////////////////// */
189 /* */
190 ib_api_status_t
osm_vendor_init(IN osm_vendor_t * const p_vend,IN osm_log_t * const p_log,IN const uint32_t timeout)191 osm_vendor_init(IN osm_vendor_t * const p_vend,
192 IN osm_log_t * const p_log, IN const uint32_t timeout)
193 {
194 FSTATUS Status;
195 PUMADT_GET_INTERFACE uMadtGetInterface;
196 char *error;
197 umadt_obj_t *p_umadt_obj = (umadt_obj_t *) p_vend;
198
199 OSM_LOG_ENTER(p_log);
200
201 p_umadt_obj->p_log = p_log;
202 p_umadt_obj->timeout = timeout;
203
204 p_umadt_obj->umadt_handle = dlopen("libibt.so", RTLD_NOW);
205
206 if (!p_umadt_obj->umadt_handle) {
207 printf("Could not load libibt.so <%s>\n", dlerror());
208 return IB_ERROR;
209 }
210 uMadtGetInterface =
211 dlsym(p_umadt_obj->umadt_handle, "uMadtGetInterface");
212 if ((error = dlerror()) != NULL) {
213 printf("Could not resolve symbol uMadtGetInterface ERROR<%s>\n",
214 error);
215 return IB_ERROR;
216 }
217
218 Status = (*uMadtGetInterface) (&p_umadt_obj->uMadtInterface);
219 if (Status != FSUCCESS) {
220 printf(" Error in getting uMADT interface ERROR<%d>\n", Status);
221 return IB_ERROR;
222 }
223
224 /* Initialize the register list and register list lock */
225 cl_qlist_init(&p_umadt_obj->register_list);
226
227 cl_spinlock_construct(&p_umadt_obj->register_lock);
228 CL_ASSERT(cl_spinlock_init(&p_umadt_obj->register_lock) == CL_SUCCESS);
229 p_umadt_obj->init_done = TRUE;
230 printf("*****SUCCESS*****\n");
231
232 OSM_LOG_EXIT(p_log);
233 return IB_SUCCESS;
234
235 }
236
237 /* //////////////////////////////////////////////////////////////////////// */
238 /* See VendorAbstractMadIntf.h for info */
239 /* //////////////////////////////////////////////////////////////////////// */
240 ib_api_status_t
osm_vendor_get_ports(IN osm_vendor_t * const p_vend,IN ib_net64_t * const p_guids,IN uint32_t * const p_num_guids)241 osm_vendor_get_ports(IN osm_vendor_t * const p_vend,
242 IN ib_net64_t * const p_guids,
243 IN uint32_t * const p_num_guids)
244 {
245 char *error = NULL;
246 PIBT_GET_INTERFACE pfnIbtGetInterface;
247 PIBT_INIT pfnIbtInitFunc;
248
249 FSTATUS Status;
250 uint32_t caCount, caGuidCount;
251 IB_CA_ATTRIBUTES caAttributes;
252 IB_HANDLE caHandle;
253 uint32_t i;
254 IB_PORT_ATTRIBUTES *pPortAttributesList;
255 EUI64 CaGuidArray[8];
256 void *context;
257 uint64_t *p_port_guid;
258 uint32_t free_guids;
259
260 umadt_obj_t *p_umadt_obj = (umadt_obj_t *) p_vend;
261
262 OSM_LOG_ENTER(p_umadt_obj->p_log);
263
264 CL_ASSERT(p_guids);
265 CL_ASSERT(p_num_guids);
266
267 pfnIbtInitFunc =
268 (PIBT_INIT) dlsym(p_umadt_obj->umadt_handle, "IbtInit");
269
270 if (!pfnIbtInitFunc) {
271 printf("Error getting IbtInit function address.\n");
272 return IB_ERROR;
273 }
274
275 (*pfnIbtInitFunc) ();
276
277 pfnIbtGetInterface =
278 (PIBT_GET_INTERFACE) dlsym(p_umadt_obj->umadt_handle,
279 "IbtGetInterface");
280
281 if (!pfnIbtGetInterface || (error = dlerror()) != NULL) {
282 printf("Error getting IbtGetInterface function address.<%s>\n",
283 error);
284 return FALSE;
285 }
286 (*pfnIbtGetInterface) (&p_umadt_obj->IbtInterface);
287
288 caGuidCount = 8;
289 Status =
290 p_umadt_obj->IbtInterface.GetCaGuidArray(&caGuidCount,
291 &CaGuidArray[0]);
292
293 if ((Status != FSUCCESS) || (caGuidCount == 0)) {
294 return FALSE;
295 }
296
297 free_guids = *p_num_guids;
298 p_port_guid = p_guids;
299
300 /* query each ca & copy its info into callers buffer */
301 for (caCount = 0; caCount < caGuidCount; caCount++) {
302 memset(&caAttributes, 0, sizeof(IB_CA_ATTRIBUTES));
303
304 /* Open the CA */
305 Status = p_umadt_obj->IbtInterface.Vpi.OpenCA(CaGuidArray[caCount], NULL, /* CACompletionCallback */
306 NULL, /* AsyncEventCallback */
307 NULL, &caHandle);
308 if (Status != FSUCCESS) {
309 return IB_ERROR;
310 }
311
312 Status = p_umadt_obj->IbtInterface.Vpi.QueryCA(caHandle,
313 &caAttributes,
314 &context);
315
316 if (Status != FSUCCESS) {
317 p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);
318 return IB_ERROR;
319 }
320
321 if (caAttributes.Ports > free_guids) {
322 *p_num_guids = 0;
323 memset(p_guids, 0, (*p_num_guids) * sizeof(uint64_t));
324 return IB_INSUFFICIENT_MEMORY;
325 }
326
327 pPortAttributesList =
328 (IB_PORT_ATTRIBUTES *) malloc(caAttributes.
329 PortAttributesListSize);
330
331 if (pPortAttributesList == NULL) {
332 p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);
333 *p_num_guids = 0;
334 memset(p_guids, 0, (*p_num_guids) * sizeof(uint64_t));
335 return IB_INSUFFICIENT_MEMORY;
336 }
337
338 memset(pPortAttributesList, 0,
339 caAttributes.PortAttributesListSize);
340
341 caAttributes.PortAttributesList = pPortAttributesList;
342
343 Status = p_umadt_obj->IbtInterface.Vpi.QueryCA(caHandle,
344 &caAttributes,
345 &context);
346
347 if (Status != FSUCCESS) {
348 p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);
349 *p_num_guids = 0;
350 memset(p_guids, 0, (*p_num_guids) * sizeof(uint64_t));
351 return IB_ERROR;
352 }
353
354 pPortAttributesList = caAttributes.PortAttributesList;
355
356 for (i = 0; i < caAttributes.Ports; i++) {
357 *(p_port_guid) =
358 cl_hton64((uint64_t) pPortAttributesList->GUID);
359 pPortAttributesList = pPortAttributesList->Next;
360 p_port_guid++;
361 }
362 free(caAttributes.PortAttributesList);
363 p_umadt_obj->IbtInterface.Vpi.CloseCA(caHandle);
364
365 free_guids = free_guids - caAttributes.Ports;
366
367 }
368 *p_num_guids = *p_num_guids - free_guids;
369 return IB_SUCCESS;
370 }
371
372 /* //////////////////////////////////////////////////////////////////////// */
373 /* See VendorAbstractMadIntf.h for info */
374 /* //////////////////////////////////////////////////////////////////////// */
osm_vendor_get(IN osm_bind_handle_t h_bind,IN const uint32_t mad_size,IN osm_vend_wrap_t * p_vend_wrap)375 ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind,
376 IN const uint32_t mad_size,
377 IN osm_vend_wrap_t * p_vend_wrap)
378 {
379 /* FSTATUS Status; */
380 /* uint32_t mad_count = 0; */
381 /* MadtStruct *p_madt_struct; */
382 mad_bind_info_t *p_mad_bind_info = (mad_bind_info_t *) h_bind;
383 umadt_obj_t *p_umadt_obj = p_mad_bind_info->p_umadt_obj;
384 ib_mad_t *p_mad;
385 OSM_LOG_ENTER(p_umadt_obj->p_log);
386
387 CL_ASSERT(h_bind);
388
389 p_umadt_obj = p_mad_bind_info->p_umadt_obj;
390
391 /* Sanity check */
392 CL_ASSERT(p_umadt_obj->init_done);
393 CL_ASSERT(p_vend_wrap);
394 CL_ASSERT(__valid_mad_handle(p_mad_bind_info));
395
396 #if 0
397 mad_count = 1;
398 Status =
399 p_umadt_obj->uMadtInterface.uMadtGetSendMad(p_mad_bind_info->
400 umadt_handle,
401 &mad_count,
402 &p_madt_struct);
403
404 if (Status != FSUCCESS || p_madt_struct == NULL) {
405 p_vend_wrap->p_madt_struct = NULL;
406 return NULL;
407 }
408 p_vend_wrap->p_madt_struct = p_madt_struct;
409 p_vend_wrap->direction = SEND;
410 return ((ib_mad_t *) & p_madt_struct->IBMad);
411 #endif /* 0 */
412 p_mad = (ib_mad_t *) malloc(mad_size);
413 if (!p_mad) {
414 p_vend_wrap->p_madt_struct = NULL;
415 return NULL;
416 }
417
418 memset(p_mad, 0, mad_size);
419
420 p_vend_wrap->p_madt_struct = NULL;
421 p_vend_wrap->direction = SEND;
422 p_vend_wrap->size = mad_size;
423 return (p_mad);
424
425 }
426
427 /* //////////////////////////////////////////////////////////////////////// */
428 /* See VendorAbstractMadIntf.h for info */
429 /* //////////////////////////////////////////////////////////////////////// */
430 void
osm_vendor_put(IN osm_bind_handle_t h_bind,IN osm_vend_wrap_t * const p_vend_wrap,IN ib_mad_t * const p_mad)431 osm_vendor_put(IN osm_bind_handle_t h_bind,
432 IN osm_vend_wrap_t * const p_vend_wrap,
433 IN ib_mad_t * const p_mad)
434 {
435
436 FSTATUS Status;
437
438 mad_bind_info_t *p_mad_bind_info;
439 umadt_obj_t *p_umadt_obj;
440
441 /* */
442 /* Validate the vendor mad transport handle */
443 /* */
444 CL_ASSERT(h_bind);
445 p_mad_bind_info = (mad_bind_info_t *) h_bind;
446 p_umadt_obj = p_mad_bind_info->p_umadt_obj;
447
448 /* sanity check */
449 CL_ASSERT(p_umadt_obj->init_done);
450 CL_ASSERT(h_bind);
451 CL_ASSERT(__valid_mad_handle(p_mad_bind_info));
452 CL_ASSERT(p_vend_wrap);
453 /* CL_ASSERT( (ib_mad_t*)&p_vend_wrap->p_madt_struct->IBMad == p_mad ); */
454
455 /* Release the MAD based on the direction of the MAD */
456 if (p_vend_wrap->direction == SEND) {
457 /* */
458 /* For a send the PostSend released the MAD with Umadt. Simply dealloacte the */
459 /* local memory that was allocated on the osm_vendor_get() call. */
460 /* */
461 free(p_mad);
462 #if 0
463 Status =
464 p_umadt_obj->uMadtInterface.
465 uMadtReleaseSendMad(p_mad_bind_info->umadt_handle,
466 p_vend_wrap->p_madt_struct);
467 if (Status != FSUCCESS) {
468 /* printf("uMadtReleaseSendMad: Status = <%d>\n", Status); */
469 return;
470 }
471 #endif
472 } else if (p_vend_wrap->direction == RECEIVE) {
473 CL_ASSERT((ib_mad_t *) & p_vend_wrap->p_madt_struct->IBMad ==
474 p_mad);
475 Status =
476 p_umadt_obj->uMadtInterface.
477 uMadtReleaseRecvMad(p_mad_bind_info->umadt_handle,
478 p_vend_wrap->p_madt_struct);
479 if (Status != FSUCCESS) {
480 /* printf("uMadtReleaseRecvMad Status=<%d>\n", Status); */
481 return;
482 }
483 } else {
484 return;
485 }
486 return;
487 }
488
489 /* //////////////////////////////////////////////////////////////////////// */
490 /* See VendorAbstractMadIntf.h for info */
491 /* //////////////////////////////////////////////////////////////////////// */
492 ib_api_status_t
osm_vendor_send(IN osm_bind_handle_t h_bind,IN osm_vend_wrap_t * const p_vend_wrap,IN osm_mad_addr_t * const p_mad_addr,IN ib_mad_t * const p_mad,IN void * transaction_context,IN boolean_t const resp_expected)493 osm_vendor_send(IN osm_bind_handle_t h_bind,
494 IN osm_vend_wrap_t * const p_vend_wrap,
495 IN osm_mad_addr_t * const p_mad_addr,
496 IN ib_mad_t * const p_mad,
497 IN void *transaction_context, IN boolean_t const resp_expected)
498 {
499 FSTATUS Status;
500
501 MadAddrStruct destAddr = { 0 };
502
503 mad_bind_info_t *p_mad_bind_info;
504 trans_context_t *p_trans_context;
505
506 umadt_obj_t *p_umadt_obj = NULL;
507
508 uint32_t mad_count = 0;
509 MadtStruct *p_madt_struct = NULL;
510 uint32_t i;
511 uint32_t num_mads = 0;
512 uint32_t seg_num = 0;
513 uint8_t *p_frag_data = NULL;
514 ib_sa_mad_t_vM3 *p_sa_mad = NULL;
515
516 CL_ASSERT(h_bind);
517 p_mad_bind_info = (mad_bind_info_t *) h_bind;
518 p_umadt_obj = p_mad_bind_info->p_umadt_obj;
519
520 /* sanity check */
521 CL_ASSERT(p_umadt_obj);
522 CL_ASSERT(p_umadt_obj->init_done);
523 CL_ASSERT(__valid_mad_handle(p_mad_bind_info));
524 CL_ASSERT(p_vend_wrap);
525 CL_ASSERT(p_mad_addr);
526 CL_ASSERT(p_mad);
527 /* CL_ASSERT( (ib_mad_t*)&p_vend_wrap->p_madt_struct->IBMad == p_mad ); */
528
529 /* */
530 /* based on the class, fill out the address info */
531 /* */
532 destAddr.DestLid = p_mad_addr->dest_lid;
533 destAddr.PathBits = p_mad_addr->path_bits;
534 destAddr.StaticRate = p_mad_addr->static_rate;
535
536 if (p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_LID ||
537 p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_DIR) {
538 CL_ASSERT(p_mad_addr->addr_type.smi.source_lid);
539 destAddr.AddrType.Smi.SourceLid =
540 p_mad_addr->addr_type.smi.source_lid;
541 } else {
542 destAddr.AddrType.Gsi.RemoteQpNumber =
543 p_mad_addr->addr_type.gsi.remote_qp;
544 destAddr.AddrType.Gsi.RemoteQkey =
545 p_mad_addr->addr_type.gsi.remote_qkey;
546 destAddr.AddrType.Gsi.PKey = OSM_DEFAULT_PKEY;
547 destAddr.AddrType.Gsi.ServiceLevel =
548 p_mad_addr->addr_type.gsi.service_level;
549 destAddr.AddrType.Gsi.GlobalRoute =
550 p_mad_addr->addr_type.gsi.global_route;
551 /* destAddr.AddrType.Gsi.GRHInfo = p_mad_addr->addr_type.gsi.grh_info; */
552 }
553 p_mad->trans_id = cl_ntoh64(p_mad->trans_id) << 24;
554
555 /* */
556 /* Create a transaction context for this send and save the TID and client context. */
557 /* */
558
559 if (resp_expected) {
560 p_trans_context = malloc(sizeof(trans_context_t));
561 CL_ASSERT(p_trans_context);
562
563 memset(p_trans_context, 0, sizeof(trans_context_t));
564 p_trans_context->trans_id = p_mad->trans_id;
565 p_trans_context->context = transaction_context;
566 p_trans_context->sent_time = cl_get_time_stamp();
567
568 cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock);
569 cl_qlist_insert_tail(&p_mad_bind_info->trans_ctxt_list,
570 &p_trans_context->list_item);
571 cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock);
572 }
573
574 if (p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_LID ||
575 p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_DIR) {
576 /* Get one mad from uMadt */
577 mad_count = 1;
578 Status =
579 p_umadt_obj->uMadtInterface.
580 uMadtGetSendMad(p_mad_bind_info->umadt_handle, &mad_count,
581 &p_madt_struct);
582
583 if (Status != FSUCCESS || p_madt_struct == NULL) {
584 return IB_ERROR;
585 }
586
587 /* No Segmentation required */
588 memcpy(&p_madt_struct->IBMad, p_mad, MAD_BLOCK_SIZE);
589
590 /* Post the MAD */
591
592 Status =
593 p_umadt_obj->uMadtInterface.uMadtPostSend(p_mad_bind_info->
594 umadt_handle,
595 p_madt_struct,
596 &destAddr);
597 if (Status != FSUCCESS) {
598 printf("uMadtPostSendMad: Status = <%d>\n", Status);
599 return IB_ERROR;
600 }
601
602 /* Release send MAD */
603 Status =
604 p_umadt_obj->uMadtInterface.
605 uMadtReleaseSendMad(p_mad_bind_info->umadt_handle,
606 p_madt_struct);
607 if (Status != FSUCCESS) {
608 printf("uMadtReleaseSendMad: Status = <%d>\n", Status);
609 return IB_ERROR;
610 }
611 } else {
612
613 /* */
614 /* Segment the MAD, get the required send mads from uMadt and post the MADs. */
615 /* */
616 uint32_t payload_len;
617
618 payload_len =
619 cl_ntoh32(((ib_sa_mad_t_vM3 *) p_mad)->payload_len);
620 num_mads = payload_len / IB_SA_DATA_SIZE;
621 if (payload_len % IB_SA_DATA_SIZE != 0) {
622 num_mads++; /* Get one additional mad for the remainder */
623 }
624 for (i = 0; i < num_mads; i++) {
625 /* Get one mad from uMadt */
626 mad_count = 1;
627 Status =
628 p_umadt_obj->uMadtInterface.
629 uMadtGetSendMad(p_mad_bind_info->umadt_handle,
630 &mad_count, &p_madt_struct);
631
632 if (Status != FSUCCESS || p_madt_struct == NULL) {
633 return IB_ERROR;
634 }
635 /* Copy client MAD into uMadt's MAD. */
636 if (i == 0) { /* First Packet */
637 /* Since this is the first MAD, copy the entire MAD_SIZE */
638 memcpy(&p_madt_struct->IBMad, p_mad,
639 MAD_BLOCK_SIZE);
640
641 p_frag_data =
642 (uint8_t *) p_mad + MAD_BLOCK_SIZE;
643
644 p_sa_mad =
645 (ib_sa_mad_t_vM3 *) & p_madt_struct->IBMad;
646 if (num_mads == 1) { /* Only one Packet */
647 p_sa_mad->seg_num = 0;
648 p_sa_mad->frag_flag = 5; /* Set bit 0 for first pkt and b4 for last pkt */
649 /* the payload length gets copied with the mad header above */
650 } else { /* More than one packet in this response */
651
652 seg_num = 1;
653 p_sa_mad->seg_num =
654 cl_ntoh32(seg_num++);
655 p_sa_mad->frag_flag = 1; /* Set bit 0 for first pkt */
656 /* the payload length gets copied with the mad header above */
657 }
658
659 } else if (i < num_mads - 1) { /* Not last packet */
660 /* First copy only the header */
661 memcpy(&p_madt_struct->IBMad, p_mad,
662 IB_SA_MAD_HDR_SIZE);
663 /* Set the relevant fields in the SA_MAD_HEADER */
664 p_sa_mad =
665 (ib_sa_mad_t_vM3 *) & p_madt_struct->IBMad;
666 p_sa_mad->payload_len =
667 cl_ntoh32(IB_SA_DATA_SIZE);
668 p_sa_mad->seg_num = cl_ntoh32(seg_num++);
669 p_sa_mad->frag_flag = 0;
670 /* Now copy the fragmented data */
671 memcpy(((uint8_t *) & p_madt_struct->IBMad) +
672 IB_SA_MAD_HDR_SIZE, p_frag_data,
673 IB_SA_DATA_SIZE);
674 p_frag_data = p_frag_data + IB_SA_DATA_SIZE;
675
676 } else if (i == num_mads - 1) { /* Last packet */
677 /* First copy only the header */
678 memcpy(&p_madt_struct->IBMad, p_mad,
679 IB_SA_MAD_HDR_SIZE);
680 /* Set the relevant fields in the SA_MAD_HEADER */
681 p_sa_mad =
682 (ib_sa_mad_t_vM3 *) & p_madt_struct->IBMad;
683 p_sa_mad->seg_num = cl_ntoh32(seg_num++);
684 p_sa_mad->frag_flag = 4; /* Set Bit 2 for last pkt */
685 p_sa_mad->payload_len =
686 cl_ntoh32(cl_ntoh32
687 (((ib_sa_mad_t_vM3 *) p_mad)->
688 payload_len) % IB_SA_DATA_SIZE);
689 /* Now copy the fragmented data */
690 memcpy((((uint8_t *) & p_madt_struct->IBMad)) +
691 IB_SA_MAD_HDR_SIZE, p_frag_data,
692 cl_ntoh32(p_sa_mad->payload_len));
693 p_frag_data = p_frag_data + IB_SA_DATA_SIZE;
694
695 }
696 /* Post the MAD */
697 Status =
698 p_umadt_obj->uMadtInterface.
699 uMadtPostSend(p_mad_bind_info->umadt_handle,
700 p_madt_struct, &destAddr);
701 if (Status != FSUCCESS) {
702 printf("uMadtPostSendMad: Status = <%d>\n",
703 Status);
704 return IB_ERROR;
705 }
706
707 /* Release send MAD */
708 Status =
709 p_umadt_obj->uMadtInterface.
710 uMadtReleaseSendMad(p_mad_bind_info->umadt_handle,
711 p_madt_struct);
712 if (Status != FSUCCESS) {
713 printf("uMadtReleaseSendMad: Status = <%d>\n",
714 Status);
715 return IB_ERROR;
716 }
717 }
718 }
719 return (IB_SUCCESS);
720 }
721
722 /* //////////////////////////////////////////////////////////////////////// */
723 /* See VendorAbstractMadIntf.h for info */
724 /* //////////////////////////////////////////////////////////////////////// */
725
726 osm_bind_handle_t
osm_vendor_bind(IN osm_vendor_t * const p_vend,IN osm_bind_info_t * const p_osm_bind_info,IN osm_mad_pool_t * const p_mad_pool,IN osm_vend_mad_recv_callback_t mad_recv_callback,IN void * context)727 osm_vendor_bind(IN osm_vendor_t * const p_vend,
728 IN osm_bind_info_t * const p_osm_bind_info,
729 IN osm_mad_pool_t * const p_mad_pool,
730 IN osm_vend_mad_recv_callback_t mad_recv_callback,
731 IN void *context)
732 {
733 cl_status_t cl_status;
734 FSTATUS Status; /* GEN1 Status for Umadt */
735
736 mad_bind_info_t *p_mad_bind_info;
737 RegisterClassStruct *p_umadt_reg_class;
738
739 umadt_obj_t *p_umadt_obj;
740 OSM_LOG_ENTER(((umadt_obj_t *) p_vend)->p_log);
741
742 CL_ASSERT(p_vend);
743
744 p_umadt_obj = (umadt_obj_t *) p_vend;
745
746 /* Sanity check */
747 CL_ASSERT(p_umadt_obj->init_done);
748 CL_ASSERT(p_osm_bind_info);
749 CL_ASSERT(p_mad_pool);
750 CL_ASSERT(mad_recv_callback);
751
752 /* Allocate memory for registering the handle. */
753 p_mad_bind_info = (mad_bind_info_t *) malloc(sizeof(*p_mad_bind_info));
754 if (p_mad_bind_info) {
755 memset(p_mad_bind_info, 0, sizeof(*p_mad_bind_info));
756 p_umadt_reg_class = &p_mad_bind_info->umadt_reg_class;
757 }
758 p_umadt_reg_class->PortGuid = cl_ntoh64(p_osm_bind_info->port_guid);
759 p_umadt_reg_class->ClassId = p_osm_bind_info->mad_class;
760 p_umadt_reg_class->ClassVersion = p_osm_bind_info->class_version;
761 p_umadt_reg_class->isResponder = p_osm_bind_info->is_responder;
762 p_umadt_reg_class->isTrapProcessor = p_osm_bind_info->is_trap_processor;
763 p_umadt_reg_class->isReportProcessor =
764 p_osm_bind_info->is_report_processor;
765 p_umadt_reg_class->SendQueueSize = p_osm_bind_info->send_q_size;
766 p_umadt_reg_class->RecvQueueSize = p_osm_bind_info->recv_q_size;
767 p_umadt_reg_class->NotifySendCompletion = TRUE;
768
769 p_mad_bind_info->p_umadt_obj = p_umadt_obj;
770 p_mad_bind_info->p_mad_pool = p_mad_pool;
771 p_mad_bind_info->mad_recv_callback = mad_recv_callback;
772 p_mad_bind_info->client_context = context;
773
774 /* register with Umadt for MAD interface */
775 Status = p_umadt_obj->uMadtInterface.uMadtRegister(p_umadt_reg_class,
776 &p_mad_bind_info->
777 umadt_handle);
778 if (Status != FSUCCESS) {
779 free(p_mad_bind_info);
780 OSM_LOG_EXIT(p_umadt_obj->p_log);
781 return (OSM_BIND_INVALID_HANDLE);
782 }
783 CL_ASSERT(p_mad_bind_info->umadt_handle);
784 /* */
785 /* Start a worker thread to process receives. */
786 /* */
787 cl_thread_construct(&p_mad_bind_info->recv_processor_thread);
788 cl_status = cl_thread_init(&p_mad_bind_info->recv_processor_thread,
789 __mad_recv_processor,
790 (void *)p_mad_bind_info, "mad_recv_worker");
791 CL_ASSERT(cl_status == CL_SUCCESS);
792
793 cl_qlist_init(&p_mad_bind_info->trans_ctxt_list);
794 cl_spinlock_construct(&p_mad_bind_info->trans_ctxt_lock);
795 cl_spinlock_init(&p_mad_bind_info->trans_ctxt_lock);
796 cl_spinlock_construct(&p_mad_bind_info->timeout_list_lock);
797 cl_spinlock_init(&p_mad_bind_info->timeout_list_lock);
798
799 cl_status = cl_timer_init(&p_mad_bind_info->timeout_timer,
800 __osm_vendor_timer_callback,
801 (void *)p_mad_bind_info);
802 CL_ASSERT(cl_status == CL_SUCCESS);
803 cl_qlist_init(&p_mad_bind_info->timeout_list);
804 /* */
805 /* Insert the mad_reg_struct in list and return pointer to it as the handle */
806 /* */
807 cl_spinlock_acquire(&p_umadt_obj->register_lock);
808
809 cl_qlist_insert_head(&p_umadt_obj->register_list,
810 &p_mad_bind_info->list_item);
811
812 cl_spinlock_release(&p_umadt_obj->register_lock);
813
814 /*
815 A timeout value of 0 means disable timeouts.
816 */
817 if (p_umadt_obj->timeout) {
818 cl_timer_start(&p_mad_bind_info->timeout_timer,
819 DEFAULT_TIMER_INTERVAL_MSEC);
820 }
821
822 OSM_LOG_EXIT(p_umadt_obj->p_log);
823 return ((osm_bind_handle_t) p_mad_bind_info);
824 }
825
osm_vendor_unbind(IN osm_bind_handle_t h_bind)826 void osm_vendor_unbind(IN osm_bind_handle_t h_bind)
827 {
828 mad_bind_info_t *p_mad_bind_info;
829 umadt_obj_t *p_umadt_obj;
830 cl_list_item_t *p_list_item, *p_next_list_item;
831
832 CL_ASSERT(h_bind);
833 p_mad_bind_info = (mad_bind_info_t *) h_bind;
834 p_umadt_obj = p_mad_bind_info->p_umadt_obj;
835
836 /* sanity check */
837 CL_ASSERT(p_umadt_obj);
838 CL_ASSERT(p_umadt_obj->init_done);
839 CL_ASSERT(__valid_mad_handle(p_mad_bind_info));
840
841 p_umadt_obj->uMadtInterface.uMadtDestroy(&p_mad_bind_info->
842 umadt_handle);
843 cl_timer_destroy(&p_mad_bind_info->timeout_timer);
844 cl_thread_destroy(&p_mad_bind_info->recv_processor_thread);
845
846 cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock);
847 p_list_item = cl_qlist_head(&p_mad_bind_info->trans_ctxt_list);
848 while (p_list_item != cl_qlist_end(&p_mad_bind_info->trans_ctxt_list)) {
849 p_next_list_item = cl_qlist_next(p_list_item);
850 cl_qlist_remove_item(&p_mad_bind_info->trans_ctxt_list,
851 p_list_item);
852 free(p_list_item);
853 p_list_item = p_next_list_item;
854 }
855 cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock);
856
857 cl_spinlock_acquire(&p_mad_bind_info->timeout_list_lock);
858 p_list_item = cl_qlist_head(&p_mad_bind_info->timeout_list);
859 while (p_list_item != cl_qlist_end(&p_mad_bind_info->timeout_list)) {
860 p_next_list_item = cl_qlist_next(p_list_item);
861 cl_qlist_remove_item(&p_mad_bind_info->timeout_list,
862 p_list_item);
863 free(p_list_item);
864 p_list_item = p_next_list_item;
865 }
866 cl_spinlock_release(&p_mad_bind_info->timeout_list_lock);
867
868 free(p_mad_bind_info);
869 }
870
__mad_recv_processor(IN void * context)871 void __mad_recv_processor(IN void *context)
872 {
873 mad_bind_info_t *p_mad_bind_info = (mad_bind_info_t *) context;
874 umadt_obj_t *p_umadt_obj;
875 osm_madw_t *p_osm_madw = NULL;
876 osm_vend_wrap_t *p_vend_wrap = NULL;
877 osm_mad_addr_t osm_mad_addr = { 0 };
878 cl_list_item_t *p_list_item;
879 void *transaction_context;
880
881 FSTATUS Status;
882 MadtStruct *pRecvMad = NULL;
883 MadWorkCompletion *pRecvCmp = NULL;
884
885 CL_ASSERT(context);
886
887 p_mad_bind_info = (mad_bind_info_t *) context;
888 p_umadt_obj = p_mad_bind_info->p_umadt_obj;
889 /* PollFor a completion */
890 /* if FNOTFOND, then wait for a completion then again poll and return the MAD */
891 while (1) {
892 Status =
893 p_umadt_obj->uMadtInterface.
894 uMadtPollForRecvCompletion(p_mad_bind_info->umadt_handle,
895 &pRecvMad, &pRecvCmp);
896 if (Status != FSUCCESS) {
897 if (Status == FNOT_FOUND) {
898 /* Wait for a completion */
899 Status = p_umadt_obj->uMadtInterface.uMadtWaitForAnyCompletion(p_mad_bind_info->umadt_handle, RECV_COMPLETION, 0x5000); /* 5 sec timeout */
900
901 if (Status == FTIMEOUT) {
902 continue;
903 }
904 CL_ASSERT(Status == FSUCCESS);
905
906 Status =
907 p_umadt_obj->uMadtInterface.
908 uMadtPollForRecvCompletion(p_mad_bind_info->
909 umadt_handle,
910 &pRecvMad,
911 &pRecvCmp);
912 if (Status != FSUCCESS) {
913 printf
914 (" mad_recv_worker: Error in PollForRecv returning <%x>\n",
915 Status);
916 CL_ASSERT(0);
917 }
918 } else {
919 printf
920 ("uMadtPollForRecvCompletion Status=<%x>\n",
921 Status);
922 CL_ASSERT(0);
923 }
924 }
925 CL_ASSERT(pRecvMad);
926 CL_ASSERT(pRecvCmp);
927
928 if (((ib_sa_mad_t_vM3 *) (&pRecvMad->IBMad))->frag_flag & 0x20) {
929 /* Ignore the ACK packet */
930 Status =
931 p_umadt_obj->uMadtInterface.
932 uMadtReleaseRecvMad(p_mad_bind_info->umadt_handle,
933 pRecvMad);
934 continue;
935 }
936 /* */
937 /* Extract the return address to pass it on to the client */
938 /* */
939 osm_mad_addr.dest_lid = pRecvCmp->AddressInfo.DestLid;
940 osm_mad_addr.path_bits = pRecvCmp->AddressInfo.PathBits;
941 osm_mad_addr.static_rate = pRecvCmp->AddressInfo.StaticRate;
942
943 if (p_mad_bind_info->umadt_reg_class.ClassId ==
944 IB_MCLASS_SUBN_LID
945 || p_mad_bind_info->umadt_reg_class.ClassId ==
946 IB_MCLASS_SUBN_DIR) {
947 osm_mad_addr.addr_type.smi.source_lid =
948 pRecvCmp->AddressInfo.AddrType.Smi.SourceLid;
949 /* osm_mad_addr.addr_type.smi.port_num = pRecvCmp->AddressInfo.AddrType.Smi.PortNumber; */
950 } else {
951 osm_mad_addr.addr_type.gsi.remote_qp =
952 pRecvCmp->AddressInfo.AddrType.Gsi.RemoteQpNumber;
953 osm_mad_addr.addr_type.gsi.remote_qkey =
954 pRecvCmp->AddressInfo.AddrType.Gsi.RemoteQkey;
955 osm_mad_addr.addr_type.gsi.pkey_ix = 0;
956 osm_mad_addr.addr_type.gsi.service_level =
957 pRecvCmp->AddressInfo.AddrType.Gsi.ServiceLevel;
958 osm_mad_addr.addr_type.gsi.global_route =
959 pRecvCmp->AddressInfo.AddrType.Gsi.GlobalRoute;
960 /* osm_mad_addr.addr_type.gsi.grh_info = pRecvCmp->AddressInfo.AddrType.Gsi.GRHInfo; */
961 }
962 p_osm_madw =
963 osm_mad_pool_get_wrapper(p_mad_bind_info->p_mad_pool,
964 p_mad_bind_info, MAD_BLOCK_SIZE,
965 (ib_mad_t *) & pRecvMad->IBMad,
966 &osm_mad_addr);
967 CL_ASSERT(p_osm_madw);
968 p_vend_wrap = osm_madw_get_vend_ptr(p_osm_madw);
969 CL_ASSERT(p_vend_wrap);
970 p_vend_wrap->p_madt_struct = pRecvMad;
971 p_vend_wrap->direction = RECEIVE;
972
973 osm_log(p_mad_bind_info->p_umadt_obj->p_log, OSM_LOG_DEBUG,
974 "__mad_recv_processor: "
975 "Received data p_osm_madw[0x%p].\n", p_osm_madw);
976
977 /* */
978 /* Do TID Processing. */
979 /* */
980 /* If R bit is set swap the TID */
981
982 cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock);
983 p_list_item =
984 cl_qlist_find_from_head(&p_mad_bind_info->trans_ctxt_list,
985 __match_tid_context,
986 &p_osm_madw->p_mad->trans_id);
987
988 if (p_list_item ==
989 cl_qlist_end(&p_mad_bind_info->trans_ctxt_list)) {
990 transaction_context = NULL;
991 } else {
992 transaction_context =
993 ((trans_context_t *) p_list_item)->context;
994 cl_qlist_remove_item(&p_mad_bind_info->trans_ctxt_list,
995 p_list_item);
996 free(p_list_item);
997 }
998 cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock);
999 ((ib_mad_t *) p_osm_madw->p_mad)->trans_id =
1000 cl_ntoh64(p_osm_madw->p_mad->trans_id >> 24);
1001 osm_log(p_mad_bind_info->p_umadt_obj->p_log, OSM_LOG_DEBUG,
1002 "__mad_recv_processor: "
1003 "Received data p_osm_madw [0x%p]" "\n\t\t\t\tTID[0x%"
1004 PRIx64 ", context[%p]. \n", p_osm_madw,
1005 ((ib_mad_t *) p_osm_madw->p_mad)->trans_id,
1006 transaction_context);
1007
1008 (*(p_mad_bind_info->mad_recv_callback)) (p_osm_madw,
1009 p_mad_bind_info->
1010 client_context,
1011 transaction_context);
1012
1013 }
1014 }
1015
1016 cl_status_t
__match_tid_context(const cl_list_item_t * const p_list_item,void * context)1017 __match_tid_context(const cl_list_item_t * const p_list_item, void *context)
1018 {
1019 if (((trans_context_t *) p_list_item)->trans_id ==
1020 *((uint64_t *) context))
1021 return CL_SUCCESS;
1022 return CL_NOT_FOUND;
1023 }
1024
__valid_mad_handle(IN mad_bind_info_t * p_mad_bind_info)1025 boolean_t __valid_mad_handle(IN mad_bind_info_t * p_mad_bind_info)
1026 {
1027
1028 umadt_obj_t *p_umadt_obj;
1029
1030 p_umadt_obj = p_mad_bind_info->p_umadt_obj;
1031
1032 cl_spinlock_acquire(&p_umadt_obj->register_lock);
1033 if (!cl_is_item_in_qlist(&p_umadt_obj->register_list,
1034 &p_mad_bind_info->list_item)) {
1035 cl_spinlock_release(&p_umadt_obj->register_lock);
1036 return FALSE;
1037 }
1038 cl_spinlock_release(&p_umadt_obj->register_lock);
1039 return TRUE;
1040 }
1041
__osm_vendor_timer_callback(IN void * context)1042 void __osm_vendor_timer_callback(IN void *context)
1043 {
1044 uint64_t current_time;
1045 mad_bind_info_t *p_mad_bind_info;
1046 umadt_obj_t *p_umadt_obj;
1047 uint32_t timeout;
1048
1049 cl_list_item_t *p_list_item, *p_next_list_item;
1050
1051 CL_ASSERT(context);
1052
1053 p_mad_bind_info = (mad_bind_info_t *) context;
1054 p_umadt_obj = p_mad_bind_info->p_umadt_obj;
1055 timeout = p_umadt_obj->timeout * 1000;
1056
1057 current_time = cl_get_time_stamp();
1058
1059 cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock);
1060
1061 p_list_item = cl_qlist_head(&p_mad_bind_info->trans_ctxt_list);
1062 while (p_list_item != cl_qlist_end(&p_mad_bind_info->trans_ctxt_list)) {
1063
1064 p_next_list_item = cl_qlist_next(p_list_item);
1065
1066 /* DEFAULT_PKT_TIMEOUT is in milli seconds */
1067 if (current_time - ((trans_context_t *) p_list_item)->sent_time
1068 > timeout) {
1069 /* Add this transaction to the timeout_list */
1070 cl_qlist_remove_item(&p_mad_bind_info->trans_ctxt_list,
1071 p_list_item);
1072 cl_qlist_insert_tail(&p_mad_bind_info->timeout_list,
1073 p_list_item);
1074 }
1075
1076 p_list_item = p_next_list_item;
1077 }
1078
1079 cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock);
1080
1081 p_list_item = cl_qlist_head(&p_mad_bind_info->timeout_list);
1082 while (p_list_item != cl_qlist_end(&p_mad_bind_info->timeout_list)) {
1083 osm_log(p_mad_bind_info->p_umadt_obj->p_log, OSM_LOG_DEBUG,
1084 "__osm_vendor_timer_callback: "
1085 "Timing out transaction context [0x%p].\n",
1086 ((trans_context_t *) p_list_item)->context);
1087
1088 (*(p_mad_bind_info->mad_recv_callback)) (NULL,
1089 p_mad_bind_info->
1090 client_context,
1091 ((trans_context_t *)
1092 p_list_item)->
1093 context);
1094
1095 p_next_list_item = cl_qlist_next(p_list_item);
1096 cl_qlist_remove_item(&p_mad_bind_info->timeout_list,
1097 p_list_item);
1098 free(p_list_item);
1099 p_list_item = p_next_list_item;
1100 }
1101
1102 cl_timer_start(&p_mad_bind_info->timeout_timer,
1103 DEFAULT_TIMER_INTERVAL_MSEC);
1104
1105 }
1106
1107 #endif /* OSM_VENDOR_INTF_UMADT */
1108