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 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 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 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 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 /* //////////////////////////////////////////////////////////////////////// */ 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 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 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 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 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 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 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 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 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