1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/ib/mgt/ibcm/ibcm_impl.h> 27 #include <sys/ib/mgt/ibcm/ibcm_arp.h> 28 29 /* 30 * ibcm_path.c 31 * 32 * ibt_get_paths() implement the Path Informations related functionality. 33 */ 34 35 /* ibcm_saa_service_rec() fills in ServiceID and DGID. */ 36 typedef struct ibcm_dest_s { 37 ib_gid_t d_gid; 38 ib_svc_id_t d_sid; 39 ibt_srv_data_t d_sdata; 40 ib_pkey_t d_pkey; 41 uint_t d_tag; /* 0 = Unicast, 1 = Multicast, 2 = LoopBack */ 42 } ibcm_dest_t; 43 44 /* Holds Destination information needed to fill in ibt_path_info_t. */ 45 typedef struct ibcm_dinfo_s { 46 uint8_t num_dest; 47 ib_pkey_t p_key; 48 ibcm_dest_t dest[1]; 49 } ibcm_dinfo_t; 50 51 _NOTE(SCHEME_PROTECTS_DATA("Temporary path storage", ibcm_dinfo_s)) 52 _NOTE(READ_ONLY_DATA(ibt_path_attr_s)) 53 54 typedef struct ibcm_path_tqargs_s { 55 ibt_path_attr_t attr; 56 ibt_path_info_t *paths; 57 uint8_t *num_paths_p; 58 ibt_path_handler_t func; 59 void *arg; 60 ibt_path_flags_t flags; 61 uint8_t max_paths; 62 } ibcm_path_tqargs_t; 63 64 65 /* Prototype Declarations. */ 66 static ibt_status_t ibcm_get_path_rec(ibcm_path_tqargs_t *, ibcm_dinfo_t *, 67 uint8_t *, ibt_path_info_t *); 68 69 static ibt_status_t ibcm_saa_path_rec(ibcm_path_tqargs_t *, 70 ibtl_cm_port_list_t *, ibcm_dinfo_t *, uint8_t *); 71 72 static ibt_status_t ibcm_update_cep_info(sa_path_record_t *, 73 ibtl_cm_port_list_t *, ibtl_cm_hca_port_t *, ibt_cep_path_t *); 74 75 static ibt_status_t ibcm_fillin_loopbackinfo(ibtl_cm_port_list_t *, 76 uint8_t index, ibcm_dinfo_t *, ibt_path_info_t *); 77 78 static ibt_status_t ibcm_saa_service_rec(ibcm_path_tqargs_t *, 79 ibtl_cm_port_list_t *, ibcm_dinfo_t *); 80 81 static ibt_status_t ibcm_get_single_pathrec(ibcm_path_tqargs_t *, 82 ibtl_cm_port_list_t *, ibcm_dinfo_t *, uint8_t, 83 uint8_t *, ibt_path_info_t *); 84 85 static ibt_status_t ibcm_get_multi_pathrec(ibcm_path_tqargs_t *, 86 ibtl_cm_port_list_t *, ibcm_dinfo_t *dinfo, 87 uint8_t *, ibt_path_info_t *); 88 89 static ibt_status_t ibcm_validate_path_attributes(ibt_path_attr_t *attrp, 90 ibt_path_flags_t flags, uint8_t max_paths); 91 92 static ibt_status_t ibcm_handle_get_path(ibt_path_attr_t *attrp, 93 ibt_path_flags_t flags, uint8_t max_paths, ibt_path_info_t *paths, 94 uint8_t *num_path_p, ibt_path_handler_t func, void *arg); 95 96 static void ibcm_process_async_get_paths(void *tq_arg); 97 98 static ibt_status_t ibcm_process_get_paths(void *tq_arg); 99 100 static ibt_status_t ibcm_get_comp_pgids(ib_gid_t, ib_gid_t, ib_guid_t, 101 ib_gid_t **, uint_t *); 102 103 int ibcm_printip = 0; 104 105 /* 106 * Function: 107 * ibcm_printip 108 * Input: 109 * label Arbitrary qualifying string 110 * ipa Pointer to IP Address to print 111 */ 112 void 113 ibcm_ip_print(char *label, ibt_ip_addr_t *ipaddr) 114 { 115 uint8_t *ipa = (uint8_t *)&ipaddr->un.ip4addr; 116 117 IBTF_DPRINTF_L2(cmlog, "ip_print: %s: %d.%d.%d.%d", label, 118 ipa[0], ipa[1], ipa[2], ipa[3]); 119 } 120 121 /* 122 * Function: 123 * ibt_aget_paths 124 * Input: 125 * ibt_hdl The handle returned to the client by the IBTF from an 126 * ibt_attach() call. Can be used by the IBTF Policy module 127 * and CM in the determination of the "best" path to the 128 * specified destination for this class of driver. 129 * flags Path flags. 130 * attrp Points to an ibt_path_attr_t struct that contains 131 * required and optional attributes. 132 * func A pointer to an ibt_path_handler_t function to call 133 * when ibt_aget_paths() completes. 134 * arg The argument to 'func'. 135 * Returns: 136 * IBT_SUCCESS on early validation of attributes else appropriate error. 137 * Description: 138 * Finds the best path to a specified destination or service 139 * asynchronously (as determined by the IBTL) that satisfies the 140 * requirements specified in an ibt_path_attr_t struct. 141 * ibt_aget_paths() is a Non-Blocking version of ibt_get_paths(). 142 */ 143 ibt_status_t 144 ibt_aget_paths(ibt_clnt_hdl_t ibt_hdl, ibt_path_flags_t flags, 145 ibt_path_attr_t *attrp, uint8_t max_paths, ibt_path_handler_t func, 146 void *arg) 147 { 148 IBTF_DPRINTF_L3(cmlog, "ibt_aget_paths(%p, 0x%X, %p, %d, %p)", 149 ibt_hdl, flags, attrp, max_paths, func); 150 151 if (func == NULL) { 152 IBTF_DPRINTF_L2(cmlog, "ibt_aget_paths: Function Pointer is " 153 "NULL - ERROR "); 154 return (IBT_INVALID_PARAM); 155 } 156 157 /* Memory for path info will be allocated in ibcm_process_get_paths() */ 158 return (ibcm_handle_get_path(attrp, flags, max_paths, NULL, NULL, 159 func, arg)); 160 } 161 162 163 /* 164 * ibt_get_paths() cache consists of one or more of: 165 * 166 * ib_gid_t dgid (attrp->pa_dgids[0]) 167 * ibt_path_attr_t attr 168 * ibt_path_flags_t flags 169 * ibt_path_info_t path 170 * 171 * If the first 3 match, max_paths is 1, sname is NULL, and sid is 0, 172 * then the path is returned immediately. 173 * 174 * Note that a compare of "attr" is non-trivial. Only accept ones 175 * that memcmp() succeeds, i.e., basically assume a bzero was done. 176 * 177 * Cache must be invalidated if PORT_DOWN event or GID_UNAVAIL occurs. 178 * Cache must be freed as part of _fini. 179 */ 180 181 #define IBCM_PATH_CACHE_SIZE 16 /* keep small for linear search */ 182 #define IBCM_PATH_CACHE_TIMEOUT 60 /* purge cache after 60 seconds */ 183 184 typedef struct ibcm_path_cache_s { 185 ib_gid_t dgid; 186 ibt_path_attr_t attr; 187 ibt_path_flags_t flags; 188 ibt_path_info_t path; 189 } ibcm_path_cache_t; 190 191 kmutex_t ibcm_path_cache_mutex; 192 int ibcm_path_cache_invalidate; /* invalidate cache on next ibt_get_paths */ 193 clock_t ibcm_path_cache_timeout = IBCM_PATH_CACHE_TIMEOUT; /* tunable */ 194 timeout_id_t ibcm_path_cache_timeout_id; 195 int ibcm_path_cache_size_init = IBCM_PATH_CACHE_SIZE; /* tunable */ 196 int ibcm_path_cache_size; 197 ibcm_path_cache_t *ibcm_path_cachep; 198 199 struct ibcm_path_cache_stat_s { 200 int hits; 201 int misses; 202 int adds; 203 int already_in_cache; 204 int bad_path_for_cache; 205 int purges; 206 int timeouts; 207 } ibcm_path_cache_stats; 208 209 /*ARGSUSED*/ 210 static void 211 ibcm_path_cache_timeout_cb(void *arg) 212 { 213 clock_t timeout_in_hz; 214 215 timeout_in_hz = drv_usectohz(ibcm_path_cache_timeout * 1000000); 216 mutex_enter(&ibcm_path_cache_mutex); 217 ibcm_path_cache_invalidate = 1; /* invalidate cache on next check */ 218 if (ibcm_path_cache_timeout_id) 219 ibcm_path_cache_timeout_id = timeout(ibcm_path_cache_timeout_cb, 220 NULL, timeout_in_hz); 221 /* else we're in _fini */ 222 mutex_exit(&ibcm_path_cache_mutex); 223 } 224 225 void 226 ibcm_path_cache_init(void) 227 { 228 clock_t timeout_in_hz; 229 int cache_size = ibcm_path_cache_size_init; 230 ibcm_path_cache_t *path_cachep; 231 232 timeout_in_hz = drv_usectohz(ibcm_path_cache_timeout * 1000000); 233 path_cachep = kmem_zalloc(cache_size * sizeof (*path_cachep), KM_SLEEP); 234 mutex_init(&ibcm_path_cache_mutex, NULL, MUTEX_DEFAULT, NULL); 235 mutex_enter(&ibcm_path_cache_mutex); 236 ibcm_path_cache_size = cache_size; 237 ibcm_path_cachep = path_cachep; 238 ibcm_path_cache_timeout_id = timeout(ibcm_path_cache_timeout_cb, 239 NULL, timeout_in_hz); 240 mutex_exit(&ibcm_path_cache_mutex); 241 } 242 243 void 244 ibcm_path_cache_fini(void) 245 { 246 timeout_id_t tmp_timeout_id; 247 int cache_size; 248 ibcm_path_cache_t *path_cachep; 249 250 mutex_enter(&ibcm_path_cache_mutex); 251 if (ibcm_path_cache_timeout_id) { 252 tmp_timeout_id = ibcm_path_cache_timeout_id; 253 ibcm_path_cache_timeout_id = 0; /* no more timeouts */ 254 } 255 cache_size = ibcm_path_cache_size; 256 path_cachep = ibcm_path_cachep; 257 mutex_exit(&ibcm_path_cache_mutex); 258 if (tmp_timeout_id) 259 (void) untimeout(tmp_timeout_id); 260 mutex_destroy(&ibcm_path_cache_mutex); 261 kmem_free(path_cachep, cache_size * sizeof (*path_cachep)); 262 } 263 264 static ibcm_status_t 265 ibcm_path_cache_check(ibt_path_flags_t flags, ibt_path_attr_t *attrp, 266 uint8_t max_paths, ibt_path_info_t *path, uint8_t *num_paths_p) 267 { 268 int i; 269 ib_gid_t dgid; 270 ibcm_path_cache_t *path_cachep; 271 272 if (max_paths != 1 || attrp->pa_num_dgids != 1 || 273 attrp->pa_sname != NULL || attrp->pa_sid != 0) { 274 mutex_enter(&ibcm_path_cache_mutex); 275 ibcm_path_cache_stats.bad_path_for_cache++; 276 mutex_exit(&ibcm_path_cache_mutex); 277 return (IBCM_FAILURE); 278 } 279 280 dgid = attrp->pa_dgids[0]; 281 if ((dgid.gid_guid | dgid.gid_prefix) == 0ULL) 282 return (IBCM_FAILURE); 283 284 mutex_enter(&ibcm_path_cache_mutex); 285 if (ibcm_path_cache_invalidate) { /* invalidate all entries */ 286 ibcm_path_cache_stats.timeouts++; 287 ibcm_path_cache_invalidate = 0; 288 path_cachep = ibcm_path_cachep; 289 for (i = 0; i < ibcm_path_cache_size; i++, path_cachep++) { 290 path_cachep->dgid.gid_guid = 0ULL; 291 path_cachep->dgid.gid_prefix = 0ULL; 292 } 293 mutex_exit(&ibcm_path_cache_mutex); 294 return (IBCM_FAILURE); 295 } 296 297 path_cachep = ibcm_path_cachep; 298 for (i = 0; i < ibcm_path_cache_size; i++, path_cachep++) { 299 if (path_cachep->dgid.gid_guid == 0ULL) 300 break; /* end of search, no more valid cache entries */ 301 302 /* make pa_dgids pointers match, so we can use memcmp */ 303 path_cachep->attr.pa_dgids = attrp->pa_dgids; 304 if (path_cachep->flags != flags || 305 path_cachep->dgid.gid_guid != dgid.gid_guid || 306 path_cachep->dgid.gid_prefix != dgid.gid_prefix || 307 memcmp(&(path_cachep->attr), attrp, sizeof (*attrp)) != 0) { 308 /* make pa_dgids NULL again */ 309 path_cachep->attr.pa_dgids = NULL; 310 continue; 311 } 312 /* else we have a match */ 313 /* make pa_dgids NULL again */ 314 path_cachep->attr.pa_dgids = NULL; 315 *path = path_cachep->path; /* retval */ 316 if (num_paths_p) 317 *num_paths_p = 1; /* retval */ 318 ibcm_path_cache_stats.hits++; 319 mutex_exit(&ibcm_path_cache_mutex); 320 return (IBCM_SUCCESS); 321 } 322 ibcm_path_cache_stats.misses++; 323 mutex_exit(&ibcm_path_cache_mutex); 324 return (IBCM_FAILURE); 325 } 326 327 static void 328 ibcm_path_cache_add(ibt_path_flags_t flags, 329 ibt_path_attr_t *attrp, uint8_t max_paths, ibt_path_info_t *path) 330 { 331 int i; 332 ib_gid_t dgid; 333 ibcm_path_cache_t *path_cachep; 334 335 if (max_paths != 1 || attrp->pa_num_dgids != 1 || 336 attrp->pa_sname != NULL || attrp->pa_sid != 0) 337 return; 338 339 dgid = attrp->pa_dgids[0]; 340 if ((dgid.gid_guid | dgid.gid_prefix) == 0ULL) 341 return; 342 343 mutex_enter(&ibcm_path_cache_mutex); 344 path_cachep = ibcm_path_cachep; 345 for (i = 0; i < ibcm_path_cache_size; i++, path_cachep++) { 346 path_cachep->attr.pa_dgids = attrp->pa_dgids; 347 if (path_cachep->flags == flags && 348 path_cachep->dgid.gid_guid == dgid.gid_guid && 349 path_cachep->dgid.gid_prefix == dgid.gid_prefix && 350 memcmp(&(path_cachep->attr), attrp, sizeof (*attrp)) == 0) { 351 /* already in cache */ 352 ibcm_path_cache_stats.already_in_cache++; 353 path_cachep->attr.pa_dgids = NULL; 354 mutex_exit(&ibcm_path_cache_mutex); 355 return; 356 } 357 if (path_cachep->dgid.gid_guid != 0ULL) { 358 path_cachep->attr.pa_dgids = NULL; 359 continue; 360 } 361 /* else the rest of the entries are free, so use this one */ 362 ibcm_path_cache_stats.adds++; 363 path_cachep->flags = flags; 364 path_cachep->attr = *attrp; 365 path_cachep->attr.pa_dgids = NULL; 366 path_cachep->dgid = attrp->pa_dgids[0]; 367 path_cachep->path = *path; 368 mutex_exit(&ibcm_path_cache_mutex); 369 return; 370 } 371 mutex_exit(&ibcm_path_cache_mutex); 372 } 373 374 void 375 ibcm_path_cache_purge(void) 376 { 377 mutex_enter(&ibcm_path_cache_mutex); 378 ibcm_path_cache_invalidate = 1; /* invalidate cache on next check */ 379 ibcm_path_cache_stats.purges++; 380 mutex_exit(&ibcm_path_cache_mutex); 381 } 382 383 /* 384 * Function: 385 * ibt_get_paths 386 * Input: 387 * ibt_hdl The handle returned to the client by the IBTF from an 388 * ibt_attach() call. Can be used by the IBTF Policy module 389 * and CM in the determination of the "best" path to the 390 * specified destination for this class of driver. 391 * flags Path flags. 392 * attrp Points to an ibt_path_attr_t struct that contains 393 * required and optional attributes. 394 * max_paths The size of the "paths" array argument. Also, this 395 * is the limit on the number of paths returned. 396 * max_paths indicates the number of requested paths to 397 * the specified destination(s). 398 * Output: 399 * paths An array of ibt_path_info_t structs filled in by 400 * ibt_get_paths() as output parameters. Upon return, 401 * array elements with non-NULL HCA GUIDs are valid. 402 * num_paths_p If non-NULL, return the actual number of paths found. 403 * Returns: 404 * IBT_SUCCESS on Success else appropriate error. 405 * Description: 406 * Finds the best path to a specified destination (as determined by the 407 * IBTL) that satisfies the requirements specified in an ibt_path_attr_t 408 * struct. 409 * 410 * This routine can not be called from interrupt context. 411 */ 412 ibt_status_t 413 ibt_get_paths(ibt_clnt_hdl_t ibt_hdl, ibt_path_flags_t flags, 414 ibt_path_attr_t *attrp, uint8_t max_paths, ibt_path_info_t *paths, 415 uint8_t *num_paths_p) 416 { 417 ibt_status_t retval; 418 419 ASSERT(paths != NULL); 420 421 IBTF_DPRINTF_L3(cmlog, "ibt_get_paths(%p, 0x%X, %p, %d)", 422 ibt_hdl, flags, attrp, max_paths); 423 424 if (paths == NULL) { 425 IBTF_DPRINTF_L2(cmlog, "ibt_get_paths: Path Info Pointer is " 426 "NULL - ERROR "); 427 return (IBT_INVALID_PARAM); 428 } 429 430 if (num_paths_p != NULL) 431 *num_paths_p = 0; 432 433 if (ibcm_path_cache_check(flags, attrp, max_paths, paths, 434 num_paths_p) == IBCM_SUCCESS) 435 return (IBT_SUCCESS); 436 437 retval = ibcm_handle_get_path(attrp, flags, max_paths, paths, 438 num_paths_p, NULL, NULL); 439 440 if (retval == IBT_SUCCESS) 441 ibcm_path_cache_add(flags, attrp, max_paths, paths); 442 return (retval); 443 } 444 445 446 static ibt_status_t 447 ibcm_handle_get_path(ibt_path_attr_t *attrp, ibt_path_flags_t flags, 448 uint8_t max_paths, ibt_path_info_t *paths, uint8_t *num_path_p, 449 ibt_path_handler_t func, void *arg) 450 { 451 ibcm_path_tqargs_t *path_tq; 452 int sleep_flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP); 453 int len; 454 ibt_status_t retval; 455 456 retval = ibcm_validate_path_attributes(attrp, flags, max_paths); 457 if (retval != IBT_SUCCESS) 458 return (retval); 459 460 len = (attrp->pa_num_dgids * sizeof (ib_gid_t)) + 461 sizeof (ibcm_path_tqargs_t); 462 463 path_tq = kmem_alloc(len, sleep_flag); 464 if (path_tq == NULL) { 465 IBTF_DPRINTF_L2(cmlog, "ibcm_handle_get_path: " 466 "Unable to allocate memory for local usage."); 467 return (IBT_INSUFF_KERNEL_RESOURCE); 468 } 469 470 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*path_tq)) 471 472 bcopy(attrp, &path_tq->attr, sizeof (ibt_path_attr_t)); 473 474 if (attrp->pa_num_dgids) { 475 path_tq->attr.pa_dgids = (ib_gid_t *)(((uchar_t *)path_tq) + 476 sizeof (ibcm_path_tqargs_t)); 477 478 bcopy(attrp->pa_dgids, path_tq->attr.pa_dgids, 479 sizeof (ib_gid_t) * attrp->pa_num_dgids); 480 } else { 481 path_tq->attr.pa_dgids = NULL; 482 } 483 484 /* Ignore IBT_PATH_AVAIL flag, if only one path is requested. */ 485 if ((flags & IBT_PATH_AVAIL) && (max_paths == 1)) { 486 flags &= ~IBT_PATH_AVAIL; 487 488 IBTF_DPRINTF_L4(cmlog, "ibcm_handle_get_path: " 489 "Ignoring IBT_PATH_AVAIL flag, as only ONE path " 490 "information is requested."); 491 } 492 493 path_tq->flags = flags; 494 path_tq->max_paths = max_paths; 495 path_tq->paths = paths; 496 path_tq->num_paths_p = num_path_p; 497 path_tq->func = func; 498 path_tq->arg = arg; 499 500 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*path_tq)) 501 502 if (func != NULL) { /* Non-Blocking */ 503 IBTF_DPRINTF_L3(cmlog, "ibcm_handle_get_path: Non Blocking"); 504 if (taskq_dispatch(ibcm_taskq, ibcm_process_async_get_paths, 505 path_tq, TQ_NOSLEEP) == 0) { 506 IBTF_DPRINTF_L2(cmlog, "ibcm_handle_get_path: " 507 "Failed to dispatch the TaskQ"); 508 kmem_free(path_tq, len); 509 return (IBT_INSUFF_KERNEL_RESOURCE); 510 } else 511 return (IBT_SUCCESS); 512 } else { /* Blocking */ 513 IBTF_DPRINTF_L3(cmlog, "ibcm_handle_get_path: Blocking"); 514 return (ibcm_process_get_paths(path_tq)); 515 } 516 } 517 518 519 static void 520 ibcm_process_async_get_paths(void *tq_arg) 521 { 522 (void) ibcm_process_get_paths(tq_arg); 523 } 524 525 526 static ibt_status_t 527 ibcm_validate_path_attributes(ibt_path_attr_t *attrp, ibt_path_flags_t flags, 528 uint8_t max_paths) 529 { 530 uint_t i; 531 532 IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: Inputs are: " 533 "HCA (%llX, %d),\n\tSGID(%llX:%llX), SName=\"%s\",\n\tSID= %llX, " 534 "Maxpath= %d, Flags= 0x%X, #Dgid= %d, SDFlag= 0x%llX", 535 attrp->pa_hca_guid, attrp->pa_hca_port_num, 536 attrp->pa_sgid.gid_prefix, attrp->pa_sgid.gid_guid, 537 ((attrp->pa_sname != NULL) ? attrp->pa_sname : ""), attrp->pa_sid, 538 max_paths, flags, attrp->pa_num_dgids, attrp->pa_sd_flags); 539 540 /* 541 * Validate Path Flags. 542 * IBT_PATH_AVAIL & IBT_PATH_PERF are mutually exclusive. 543 */ 544 if ((flags & IBT_PATH_AVAIL) && (flags & IBT_PATH_PERF)) { 545 IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: " 546 "Invalid Flags: 0x%X,\n\t AVAIL and PERF flags cannot " 547 "specified together.", flags); 548 return (IBT_INVALID_PARAM); 549 } 550 551 /* Validate number of records requested. */ 552 if ((flags & (IBT_PATH_AVAIL | IBT_PATH_PERF)) && 553 (max_paths > IBT_MAX_SPECIAL_PATHS)) { 554 IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: " 555 "Max records that can be requested is <%d> \n" 556 "when IBT_PATH_AVAIL or IBT_PATH_PERF flag is specified.", 557 IBT_MAX_SPECIAL_PATHS); 558 return (IBT_INVALID_PARAM); 559 } 560 561 /* Only 2 destinations can be specified w/ APM flag. */ 562 if ((flags & IBT_PATH_APM) && (attrp->pa_num_dgids > 2)) { 563 IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes:\n\t Max " 564 "number of DGIDs that can be specified w/APM flag is 2"); 565 return (IBT_INVALID_PARAM); 566 } 567 568 /* 569 * Max_paths of "0" is invalid. 570 * w/ IBT_PATH_MULTI_SVC_DEST flag, max_paths must be greater than "1". 571 */ 572 if ((max_paths == 0) || 573 ((flags & IBT_PATH_MULTI_SVC_DEST) && (max_paths < 2))) { 574 IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: " 575 "Invalid number of records requested:\n flags 0x%X, " 576 "max_paths %d", flags, max_paths); 577 return (IBT_INVALID_PARAM); 578 } 579 580 /* 581 * If IBT_PATH_MULTI_SVC_DEST is set, then ServiceName and/or Service ID 582 * must be specified and DGIDs SHOULD NOT be specified. 583 */ 584 if ((flags & IBT_PATH_MULTI_SVC_DEST) && ((attrp->pa_num_dgids > 0) || 585 ((attrp->pa_sid == 0) && ((attrp->pa_sname == NULL) || 586 ((attrp->pa_sname != NULL) && (strlen(attrp->pa_sname) == 0)))))) { 587 IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: " 588 "Invalid Flags: 0x%X, IBT_PATH_MULTI_SVC_DEST flag set " 589 "but Service Name \n or Service ID NOT specified or DGIDs " 590 "are specified.", flags); 591 return (IBT_INVALID_PARAM); 592 } 593 594 /* 595 * User need to specify the destination information, which can be 596 * provided as one or more of the following. 597 * o ServiceName 598 * o ServiceID 599 * o Array of DGIDs w/Num of DGIDs, (max of 2) 600 */ 601 if ((attrp->pa_sid == 0) && (attrp->pa_num_dgids == 0) && 602 ((attrp->pa_sname == NULL) || ((attrp->pa_sname != NULL) && 603 (strlen(attrp->pa_sname) == 0)))) { 604 /* Destination information not provided, bail out. */ 605 IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: " 606 "Client's MUST supply DestInfo."); 607 return (IBT_INVALID_PARAM); 608 } 609 610 /* If DGIDs are provided, validate them. */ 611 if (attrp->pa_num_dgids > 0) { 612 if (attrp->pa_dgids == NULL) { 613 IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: " 614 "pa_dgids NULL, but pa_num_dgids : %d", 615 attrp->pa_num_dgids); 616 return (IBT_INVALID_PARAM); 617 } 618 619 /* Validate DGIDs */ 620 for (i = 0; i < attrp->pa_num_dgids; i++) { 621 ib_gid_t gid = attrp->pa_dgids[i]; 622 623 IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: " 624 "DGID[%d] = %llX:%llX", i, gid.gid_prefix, 625 gid.gid_guid); 626 627 /* APM request for MultiCast destination is invalid. */ 628 if ((gid.gid_prefix >> 56ULL & 0xFF) == 0xFF) { 629 if (flags & IBT_PATH_APM) { 630 IBTF_DPRINTF_L2(cmlog, 631 "ibcm_validate_path_attributes: " 632 "APM for MGIDs not supported."); 633 return (IBT_INVALID_PARAM); 634 } 635 } else if ((gid.gid_prefix == 0) || 636 (gid.gid_guid == 0)) { 637 IBTF_DPRINTF_L2(cmlog, 638 "ibcm_validate_path_attributes: ERROR: " 639 "Invalid DGIDs specified"); 640 return (IBT_INVALID_PARAM); 641 } 642 } 643 } 644 645 /* Check for valid Service Name length. */ 646 if ((attrp->pa_sname != NULL) && 647 (strlen(attrp->pa_sname) >= IB_SVC_NAME_LEN)) { 648 IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: " 649 "ServiceName too long"); 650 return (IBT_INVALID_PARAM); 651 } 652 653 /* If P_Key is specified, check for invalid p_key's */ 654 if (flags & IBT_PATH_PKEY) { 655 /* Limited P_Key is NOT supported as of now!. */ 656 if ((attrp->pa_pkey == IB_PKEY_INVALID_FULL) || 657 (attrp->pa_pkey & 0x8000) == 0) { 658 IBTF_DPRINTF_L2(cmlog, "ibcm_validate_path_attributes: " 659 "Specified P_Key is invalid: 0x%X", attrp->pa_pkey); 660 return (IBT_INVALID_PARAM); 661 } 662 IBTF_DPRINTF_L3(cmlog, "ibcm_validate_path_attributes: " 663 "P_Key= 0x%X", attrp->pa_pkey); 664 } 665 666 return (IBT_SUCCESS); 667 } 668 669 670 static ibt_status_t 671 ibcm_process_get_paths(void *tq_arg) 672 { 673 ibcm_path_tqargs_t *p_arg = (ibcm_path_tqargs_t *)tq_arg; 674 ibcm_dinfo_t *dinfo; 675 int len; 676 uint8_t max_paths, num_path; 677 ibt_status_t retval; 678 ib_gid_t *d_gids_p = NULL; 679 ibtl_cm_port_list_t *slistp = NULL; 680 uint_t dnum = 0, num_dest; 681 uint_t i, j; 682 ibcm_hca_info_t *hcap; 683 ibmf_saa_handle_t saa_handle; 684 685 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths(%p, 0x%X, %d) ", 686 p_arg, p_arg->flags, p_arg->max_paths); 687 688 max_paths = num_path = p_arg->max_paths; 689 690 /* 691 * Prepare the Destination list based on the input DGIDs and 692 * other attributes. 693 * 694 * APM is requested and pa_dgids are specified. If multiple DGIDs are 695 * specified, check out whether they are companion to each other or if 696 * only one DGID is specified, then get the companion port GID for that. 697 */ 698 if (p_arg->attr.pa_num_dgids) { 699 if (p_arg->flags & IBT_PATH_APM) { 700 ib_gid_t c_gid, n_gid; 701 702 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: " 703 "DGIDs specified w/ APM Flag"); 704 705 c_gid = p_arg->attr.pa_dgids[0]; 706 if (p_arg->attr.pa_num_dgids > 1) 707 n_gid = p_arg->attr.pa_dgids[1]; 708 else 709 n_gid.gid_prefix = n_gid.gid_guid = 0; 710 711 retval = ibcm_get_comp_pgids(c_gid, n_gid, 0, &d_gids_p, 712 &dnum); 713 if ((retval != IBT_SUCCESS) && 714 (retval != IBT_GIDS_NOT_FOUND)) { 715 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths:" 716 " Invalid DGIDs specified w/ APM Flag"); 717 goto path_error2; 718 } 719 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: " 720 "Found %d Comp DGID", dnum); 721 } 722 723 if (dnum) { 724 len = 1; 725 } else { 726 len = p_arg->attr.pa_num_dgids - 1; 727 } 728 num_dest = len + 1; 729 730 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: #dgid %d, dnum " 731 "%d, #dest %d", p_arg->attr.pa_num_dgids, dnum, num_dest); 732 } else { 733 if (p_arg->flags & IBT_PATH_MULTI_SVC_DEST) { 734 IBTF_DPRINTF_L4(cmlog, "ibcm_process_get_paths: " 735 "IBT_PATH_MULTI_SVC_DEST flags set"); 736 len = max_paths - 1; 737 } else if (p_arg->flags & IBT_PATH_APM) { 738 len = 1; 739 } else { 740 len = 0; 741 } 742 num_dest = 0; 743 } 744 745 /* Allocate memory and accumulate all destination information */ 746 len = (len * sizeof (ibcm_dest_t)) + sizeof (ibcm_dinfo_t); 747 748 dinfo = kmem_zalloc(len, KM_SLEEP); 749 dinfo->num_dest = num_dest; 750 if (p_arg->flags & IBT_PATH_PKEY) 751 dinfo->p_key = p_arg->attr.pa_pkey; 752 753 for (i = 0, j = 0; i < num_dest; i++) { 754 if (i < p_arg->attr.pa_num_dgids) 755 dinfo->dest[i].d_gid = p_arg->attr.pa_dgids[i]; 756 else 757 dinfo->dest[i].d_gid = d_gids_p[j++]; 758 } 759 760 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*p_arg)) 761 762 /* IBTF allocates memory for path_info in case of Async Get Paths */ 763 if (p_arg->paths == NULL) 764 p_arg->paths = kmem_zalloc(sizeof (ibt_path_info_t) * max_paths, 765 KM_SLEEP); 766 767 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*p_arg)) 768 769 /* 770 * Get list of active HCA<->Port list, that matches input specified attr 771 */ 772 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: Get Paths from \n HCA " 773 "(%llX:%d), SGID %llX:%llX", p_arg->attr.pa_hca_guid, 774 p_arg->attr.pa_hca_port_num, p_arg->attr.pa_sgid.gid_prefix, 775 p_arg->attr.pa_sgid.gid_guid); 776 777 retval = ibtl_cm_get_active_plist(&p_arg->attr, p_arg->flags, &slistp); 778 if (retval != IBT_SUCCESS) { 779 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: HCA capable of " 780 "requested source attributes NOT available."); 781 goto path_error; 782 } 783 784 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: HCA (%llX, %d)", 785 slistp->p_hca_guid, slistp->p_port_num); 786 787 hcap = ibcm_find_hca_entry(slistp->p_hca_guid); 788 if (hcap == NULL) { 789 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: " 790 "NO HCA found"); 791 retval = IBT_HCA_BUSY_DETACHING; 792 goto path_error; 793 } 794 795 /* Get SA Access Handle. */ 796 for (i = 0; i < slistp->p_count; i++) { 797 if (i == 0) { 798 /* Validate whether this HCA supports APM */ 799 if ((p_arg->flags & IBT_PATH_APM) && 800 (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG))) { 801 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths:" 802 " HCA (%llX): APM NOT SUPPORTED ", 803 slistp[i].p_hca_guid); 804 retval = IBT_APM_NOT_SUPPORTED; 805 goto path_error1; 806 } 807 } 808 809 saa_handle = ibcm_get_saa_handle(hcap, slistp[i].p_port_num); 810 if (saa_handle == NULL) { 811 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: " 812 "SAA HDL NULL, HCA (%llX:%d) NOT ACTIVE", 813 slistp[i].p_hca_guid, slistp[i].p_port_num); 814 retval = IBT_HCA_PORT_NOT_ACTIVE; 815 goto path_error1; 816 } 817 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*slistp)) 818 slistp[i].p_saa_hdl = saa_handle; 819 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*slistp)) 820 } 821 822 /* 823 * If Service Name or Service ID are specified, first retrieve 824 * Service Records. 825 */ 826 if ((p_arg->attr.pa_sid != 0) || ((p_arg->attr.pa_sname != NULL) && 827 (strlen(p_arg->attr.pa_sname) != 0))) { 828 829 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_paths: Get Service " 830 "Record for \n\t(%llX, \"%s\")", p_arg->attr.pa_sid, 831 ((p_arg->attr.pa_sname != NULL) ? 832 p_arg->attr.pa_sname : "")); 833 834 /* Get Service Records. */ 835 retval = ibcm_saa_service_rec(p_arg, slistp, dinfo); 836 if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA)) { 837 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: Status=" 838 "%d, Failed to get Service Record for \n\t" 839 "(%llX, \"%s\")", retval, p_arg->attr.pa_sid, 840 ((p_arg->attr.pa_sname != NULL) ? 841 p_arg->attr.pa_sname : "")); 842 goto path_error1; 843 } 844 } 845 846 /* Get Path Records. */ 847 retval = ibcm_saa_path_rec(p_arg, slistp, dinfo, &num_path); 848 849 path_error1: 850 ibcm_dec_hca_acc_cnt(hcap); 851 852 path_error: 853 if (slistp) 854 ibtl_cm_free_active_plist(slistp); 855 856 if (dinfo) 857 kmem_free(dinfo, len); 858 859 path_error2: 860 if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA)) 861 num_path = 0; 862 863 if (p_arg->num_paths_p != NULL) 864 *p_arg->num_paths_p = num_path; 865 866 if ((dnum) && (d_gids_p)) 867 kmem_free(d_gids_p, dnum * sizeof (ib_gid_t)); 868 869 if (p_arg->func) { /* Do these only for Async Get Paths */ 870 ibt_path_info_t *tmp_path_p; 871 872 if (retval == IBT_INSUFF_DATA) { 873 /* 874 * We allocated earlier memory based on "max_paths", 875 * but we got lesser path-records, so re-adjust that 876 * buffer so that caller can free the correct memory. 877 */ 878 tmp_path_p = kmem_alloc( 879 sizeof (ibt_path_info_t) * num_path, KM_SLEEP); 880 881 bcopy(p_arg->paths, tmp_path_p, 882 num_path * sizeof (ibt_path_info_t)); 883 884 kmem_free(p_arg->paths, 885 sizeof (ibt_path_info_t) * max_paths); 886 } else if (retval != IBT_SUCCESS) { 887 if (p_arg->paths) 888 kmem_free(p_arg->paths, 889 sizeof (ibt_path_info_t) * max_paths); 890 tmp_path_p = NULL; 891 } else { 892 tmp_path_p = p_arg->paths; 893 } 894 (*(p_arg->func))(p_arg->arg, retval, tmp_path_p, num_path); 895 } 896 897 len = (sizeof (ib_gid_t) * p_arg->attr.pa_num_dgids) + 898 sizeof (ibcm_path_tqargs_t); 899 900 if (p_arg && len) 901 kmem_free(p_arg, len); 902 903 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_paths: done: status %d, " 904 "Found %d/%d Path Records", retval, num_path, max_paths); 905 906 return (retval); 907 } 908 909 910 /* 911 * Perform SA Access to retrieve Path Records. 912 */ 913 static ibt_status_t 914 ibcm_saa_path_rec(ibcm_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl, 915 ibcm_dinfo_t *dinfo, uint8_t *max_count) 916 { 917 uint8_t num_path = *max_count; 918 uint8_t num_path_plus; 919 uint_t extra, idx, rec_found = 0; 920 ibt_status_t retval = IBT_SUCCESS; 921 int unicast_dgid_present = 0; 922 uint8_t i; 923 924 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec(%p, %p, %p, 0x%X, %d)", 925 p_arg, sl, dinfo, p_arg->flags, *max_count); 926 927 if ((dinfo->num_dest == 0) || (num_path == 0) || (sl == NULL)) { 928 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: Invalid Counters"); 929 return (IBT_INVALID_PARAM); 930 } 931 932 /* 933 * Of the total needed "X" number of paths to "Y" number of destination 934 * we need to get X/Y plus X%Y extra paths to each destination, 935 * We do this so that we can choose the required number of path records 936 * for the specific destination. 937 */ 938 num_path /= dinfo->num_dest; 939 extra = (*max_count % dinfo->num_dest); 940 941 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: numpath %d extra %d dest %d", 942 num_path, extra, dinfo->num_dest); 943 944 /* 945 * Find out whether we need to get PathRecord for a MGID as DGID or 946 * qualifies for a LoopBack. 947 */ 948 for (idx = 0; idx < dinfo->num_dest; idx++) { 949 ib_gid_t dgid = dinfo->dest[idx].d_gid; 950 951 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: DGID[%d]: %llX:%llX", 952 idx, dgid.gid_prefix, dgid.gid_guid); 953 954 if ((dgid.gid_prefix >> 56ULL & 0xFF) == 0xFF) { 955 if (extra) 956 num_path_plus = num_path + 1; 957 else 958 num_path_plus = num_path; 959 960 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: Get %d Paths" 961 "- MGID(%016llX%016llX)", num_path_plus, 962 dgid.gid_prefix, dgid.gid_guid); 963 964 dinfo->dest[idx].d_tag = 1; /* MultiCast */ 965 966 /* Yes, it's Single PathRec query for MGID as DGID. */ 967 retval = ibcm_get_single_pathrec(p_arg, sl, dinfo, idx, 968 &num_path_plus, &p_arg->paths[rec_found]); 969 if ((retval != IBT_SUCCESS) && 970 (retval != IBT_INSUFF_DATA)) { 971 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: " 972 "Failed to get PathRec for MGID %d", 973 retval); 974 continue; 975 } 976 if (extra) 977 extra--; 978 979 rec_found += num_path_plus; 980 } else { 981 /* 982 * Check out whether we are looking for loop-back path 983 * info. In this case, we should not contact SA Access 984 * for Path Records, but instead we need to "synthesize" 985 * a loop back path record. 986 */ 987 for (i = 0; i < sl->p_count; i++) { 988 if ((sl[i].p_sgid.gid_prefix == 989 dgid.gid_prefix) && 990 (sl[i].p_sgid.gid_guid == dgid.gid_guid)) { 991 992 dinfo->dest[idx].d_tag = 2; 993 994 /* Yes, it's loop back case. */ 995 retval = ibcm_fillin_loopbackinfo( 996 &sl[i], idx, dinfo, 997 &p_arg->paths[rec_found]); 998 if (retval != IBT_SUCCESS) 999 break; 1000 1001 /* 1002 * We update only one record for 1003 * loop-back case. 1004 */ 1005 rec_found++; 1006 if (rec_found == *max_count) 1007 break; 1008 } 1009 } 1010 } 1011 if (rec_found == *max_count) 1012 break; 1013 } 1014 1015 for (i = 0; i < dinfo->num_dest; i++) { 1016 if (dinfo->dest[i].d_tag == 0) { 1017 unicast_dgid_present++; 1018 } 1019 } 1020 1021 num_path_plus = *max_count - rec_found; 1022 1023 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: Recfound: %d, need to find " 1024 "%d, UniCastGID present %d", rec_found, num_path_plus, 1025 unicast_dgid_present); 1026 1027 if ((unicast_dgid_present != 0) && (num_path_plus > 0)) { 1028 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: MultiSM=%X, #SRC=%d," 1029 "Dest%d", sl->p_multi, sl->p_count, unicast_dgid_present); 1030 1031 if ((sl->p_multi != IBTL_CM_SIMPLE_SETUP) || 1032 ((unicast_dgid_present == 1) && (sl->p_count == 1))) { 1033 /* 1034 * Use SinglePathRec if we are dealing w/ MultiSM or 1035 * request is for one SGID to one DGID. 1036 */ 1037 retval = ibcm_get_single_pathrec(p_arg, sl, dinfo, 0xFF, 1038 &num_path_plus, &p_arg->paths[rec_found]); 1039 } else { 1040 uint8_t old_num_path_plus = num_path_plus; 1041 1042 /* MultiPathRec will be used for other queries. */ 1043 retval = ibcm_get_multi_pathrec(p_arg, sl, dinfo, 1044 &num_path_plus, &p_arg->paths[rec_found]); 1045 if ((retval != IBT_SUCCESS) && 1046 (retval != IBT_INSUFF_DATA) && 1047 (sl->p_count > 0) && 1048 (dinfo->num_dest > 0)) { 1049 ibtl_cm_port_list_t sl_tmp = *sl; 1050 ibcm_dinfo_t dinfo_tmp = *dinfo; 1051 1052 sl_tmp.p_count = 1; 1053 dinfo_tmp.num_dest = 1; 1054 num_path_plus = old_num_path_plus; 1055 retval = ibcm_get_single_pathrec(p_arg, &sl_tmp, 1056 &dinfo_tmp, 0xFF, &num_path_plus, 1057 &p_arg->paths[rec_found]); 1058 } 1059 } 1060 if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA)) { 1061 IBTF_DPRINTF_L2(cmlog, "ibcm_saa_path_rec: " 1062 "Failed to get PathRec: Status %d", retval); 1063 } else { 1064 rec_found += num_path_plus; 1065 } 1066 } 1067 1068 if (rec_found == 0) { 1069 if (retval == IBT_SUCCESS) 1070 retval = IBT_PATH_RECORDS_NOT_FOUND; 1071 } else if (rec_found != *max_count) 1072 retval = IBT_INSUFF_DATA; 1073 else if (rec_found != 0) 1074 retval = IBT_SUCCESS; 1075 1076 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_path_rec: done. Status = %d, " 1077 "Found %d/%d Paths", retval, rec_found, *max_count); 1078 1079 *max_count = rec_found; /* Update the return count. */ 1080 1081 return (retval); 1082 } 1083 1084 ibt_status_t 1085 ibcm_contact_sa_access(ibmf_saa_handle_t saa_handle, 1086 ibmf_saa_access_args_t *access_args, size_t *length, void **results_p) 1087 { 1088 int retry; 1089 int sa_retval; 1090 1091 IBTF_DPRINTF_L3(cmlog, "ibcm_contact_sa_access(%p, %p)", 1092 saa_handle, access_args); 1093 1094 ibcm_sa_access_enter(); 1095 1096 for (retry = 0; retry < ibcm_max_sa_retries; retry++) { 1097 sa_retval = ibmf_sa_access(saa_handle, access_args, 0, 1098 length, results_p); 1099 if (sa_retval != IBMF_TRANS_TIMEOUT) 1100 break; 1101 1102 IBTF_DPRINTF_L2(cmlog, "ibcm_contact_sa_access: " 1103 "ibmf_sa_access() - Timed Out (%d)", sa_retval); 1104 delay(ibcm_sa_timeout_delay); 1105 } 1106 1107 ibcm_sa_access_exit(); 1108 1109 if ((sa_retval == IBMF_SUCCESS) || (sa_retval == IBMF_NO_RECORDS) || 1110 (sa_retval == IBMF_REQ_INVALID)) { 1111 IBTF_DPRINTF_L3(cmlog, "ibcm_contact_sa_access: " 1112 "ibmf_sa_access() returned (%d)", sa_retval); 1113 return (IBT_SUCCESS); 1114 } else { 1115 IBTF_DPRINTF_L2(cmlog, "ibcm_contact_sa_access: " 1116 "ibmf_sa_access(): Failed (%d)", sa_retval); 1117 return (ibcm_ibmf_analyze_error(sa_retval)); 1118 } 1119 } 1120 1121 1122 static ibt_status_t 1123 ibcm_update_pri(sa_path_record_t *pr_resp, ibtl_cm_port_list_t *sl, 1124 ibcm_dinfo_t *dinfo, ibt_path_info_t *paths) 1125 { 1126 ibt_status_t retval = IBT_SUCCESS; 1127 int d, s; 1128 1129 retval = ibcm_update_cep_info(pr_resp, sl, NULL, 1130 &paths->pi_prim_cep_path); 1131 if (retval != IBT_SUCCESS) 1132 return (retval); 1133 1134 /* Update some leftovers */ 1135 paths->pi_prim_pkt_lt = pr_resp->PacketLifeTime; 1136 paths->pi_path_mtu = pr_resp->Mtu; 1137 1138 for (d = 0; d < dinfo->num_dest; d++) { 1139 if (pr_resp->DGID.gid_guid == dinfo->dest[d].d_gid.gid_guid) { 1140 paths->pi_sid = dinfo->dest[d].d_sid; 1141 if (paths->pi_sid != 0) { 1142 bcopy(&dinfo->dest[d].d_sdata, 1143 &paths->pi_sdata, sizeof (ibt_srv_data_t)); 1144 } 1145 break; 1146 } 1147 } 1148 1149 for (s = 0; s < sl->p_count; s++) { 1150 if (pr_resp->SGID.gid_guid == sl[s].p_sgid.gid_guid) { 1151 paths->pi_hca_guid = sl[s].p_hca_guid; 1152 } 1153 } 1154 1155 /* Set Alternate Path to invalid state. */ 1156 paths->pi_alt_cep_path.cep_hca_port_num = 0; 1157 paths->pi_alt_cep_path.cep_adds_vect.av_dlid = 0; 1158 1159 IBTF_DPRINTF_L5(cmlog, "Path: HCA GUID = 0x%llX", paths->pi_hca_guid); 1160 IBTF_DPRINTF_L5(cmlog, "Path: ServiceID = 0x%llX", paths->pi_sid); 1161 1162 return (retval); 1163 } 1164 1165 1166 static ibt_status_t 1167 ibcm_get_single_pathrec(ibcm_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl, 1168 ibcm_dinfo_t *dinfo, uint8_t idx, uint8_t *num_path, ibt_path_info_t *paths) 1169 { 1170 sa_path_record_t pathrec_req; 1171 sa_path_record_t *pr_resp; 1172 ibmf_saa_access_args_t access_args; 1173 uint64_t c_mask = 0; 1174 void *results_p; 1175 uint8_t num_rec; 1176 size_t length; 1177 ibt_status_t retval; 1178 int i, j, k; 1179 int found, p_fnd; 1180 ibt_path_attr_t *attrp = &p_arg->attr; 1181 ibmf_saa_handle_t saa_handle; 1182 1183 IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec(%p, %p, %p, %d)", 1184 p_arg, sl, dinfo, *num_path); 1185 1186 bzero(&pathrec_req, sizeof (sa_path_record_t)); 1187 1188 /* Is Flow Label Specified. */ 1189 if (attrp->pa_flow) { 1190 pathrec_req.FlowLabel = attrp->pa_flow; 1191 c_mask |= SA_PR_COMPMASK_FLOWLABEL; 1192 } 1193 1194 /* Is HopLimit Specified. */ 1195 if (p_arg->flags & IBT_PATH_HOP) { 1196 pathrec_req.HopLimit = attrp->pa_hop; 1197 c_mask |= SA_PR_COMPMASK_HOPLIMIT; 1198 } 1199 1200 /* Is P_Key Specified. */ 1201 if (dinfo->p_key) { 1202 IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec: " 1203 "Specified or Global PKEY 0x%X", dinfo->p_key); 1204 pathrec_req.P_Key = dinfo->p_key; 1205 c_mask |= SA_PR_COMPMASK_PKEY; 1206 } 1207 1208 /* Is TClass Specified. */ 1209 if (attrp->pa_tclass) { 1210 pathrec_req.TClass = attrp->pa_tclass; 1211 c_mask |= SA_PR_COMPMASK_TCLASS; 1212 } 1213 1214 /* Is SL specified. */ 1215 if (attrp->pa_sl) { 1216 pathrec_req.SL = attrp->pa_sl; 1217 c_mask |= SA_PR_COMPMASK_SL; 1218 } 1219 1220 /* If IBT_PATH_PERF is set, then mark all selectors to BEST. */ 1221 if (p_arg->flags & IBT_PATH_PERF) { 1222 pathrec_req.PacketLifeTimeSelector = IBT_BEST; 1223 pathrec_req.MtuSelector = IBT_BEST; 1224 pathrec_req.RateSelector = IBT_BEST; 1225 1226 c_mask |= SA_PR_COMPMASK_PKTLTSELECTOR | 1227 SA_PR_COMPMASK_RATESELECTOR | SA_PR_COMPMASK_MTUSELECTOR; 1228 } else { 1229 if (attrp->pa_pkt_lt.p_selector == IBT_BEST) { 1230 pathrec_req.PacketLifeTimeSelector = IBT_BEST; 1231 c_mask |= SA_PR_COMPMASK_PKTLTSELECTOR; 1232 } 1233 1234 if (attrp->pa_srate.r_selector == IBT_BEST) { 1235 pathrec_req.RateSelector = IBT_BEST; 1236 c_mask |= SA_PR_COMPMASK_RATESELECTOR; 1237 } 1238 1239 if (attrp->pa_mtu.r_selector == IBT_BEST) { 1240 pathrec_req.MtuSelector = IBT_BEST; 1241 c_mask |= SA_PR_COMPMASK_MTUSELECTOR; 1242 } 1243 } 1244 1245 /* 1246 * Honor individual selection of these attributes, 1247 * even if IBT_PATH_PERF is set. 1248 */ 1249 /* Check out whether Packet Life Time is specified. */ 1250 if (attrp->pa_pkt_lt.p_pkt_lt) { 1251 pathrec_req.PacketLifeTime = 1252 ibt_usec2ib(attrp->pa_pkt_lt.p_pkt_lt); 1253 pathrec_req.PacketLifeTimeSelector = 1254 attrp->pa_pkt_lt.p_selector; 1255 1256 c_mask |= SA_PR_COMPMASK_PKTLT | SA_PR_COMPMASK_PKTLTSELECTOR; 1257 } 1258 1259 /* Is SRATE specified. */ 1260 if (attrp->pa_srate.r_srate) { 1261 pathrec_req.Rate = attrp->pa_srate.r_srate; 1262 pathrec_req.RateSelector = attrp->pa_srate.r_selector; 1263 1264 c_mask |= SA_PR_COMPMASK_RATE | SA_PR_COMPMASK_RATESELECTOR; 1265 } 1266 1267 /* Is MTU specified. */ 1268 if (attrp->pa_mtu.r_mtu) { 1269 pathrec_req.Mtu = attrp->pa_mtu.r_mtu; 1270 pathrec_req.MtuSelector = attrp->pa_mtu.r_selector; 1271 1272 c_mask |= SA_PR_COMPMASK_MTU | SA_PR_COMPMASK_MTUSELECTOR; 1273 } 1274 1275 /* We always get REVERSIBLE paths. */ 1276 pathrec_req.Reversible = 1; 1277 c_mask |= SA_PR_COMPMASK_REVERSIBLE; 1278 1279 pathrec_req.NumbPath = *num_path; 1280 c_mask |= SA_PR_COMPMASK_NUMBPATH; 1281 1282 if (idx != 0xFF) { 1283 /* MGID */ 1284 pathrec_req.DGID = dinfo->dest[idx].d_gid; 1285 c_mask |= SA_PR_COMPMASK_DGID; 1286 } 1287 1288 p_fnd = found = 0; 1289 1290 for (i = 0; i < sl->p_count; i++) { 1291 /* SGID */ 1292 pathrec_req.SGID = sl[i].p_sgid; 1293 c_mask |= SA_PR_COMPMASK_SGID; 1294 saa_handle = sl[i].p_saa_hdl; 1295 1296 for (k = 0; k < dinfo->num_dest; k++) { 1297 if (idx == 0xFF) { /* DGID */ 1298 if (dinfo->dest[k].d_tag != 0) 1299 continue; 1300 1301 if (pathrec_req.SGID.gid_prefix != 1302 dinfo->dest[k].d_gid.gid_prefix) { 1303 IBTF_DPRINTF_L3(cmlog, 1304 "ibcm_get_single_pathrec: SGID_pfx=" 1305 "%llX, DGID_pfx=%llX doesn't match", 1306 pathrec_req.SGID.gid_prefix, 1307 dinfo->dest[k].d_gid.gid_prefix); 1308 continue; 1309 } else if (pathrec_req.SGID.gid_guid == 1310 pathrec_req.DGID.gid_guid) { 1311 IBTF_DPRINTF_L3(cmlog, 1312 "ibcm_get_single_pathrec: Why " 1313 "LoopBack request came here!!!! " 1314 "GID(%llX:%llX)", 1315 pathrec_req.SGID.gid_prefix, 1316 pathrec_req.SGID.gid_guid); 1317 continue; 1318 } 1319 1320 pathrec_req.DGID = dinfo->dest[k].d_gid; 1321 c_mask |= SA_PR_COMPMASK_DGID; 1322 1323 /* 1324 * If we had performed Service Look-up, then we 1325 * got P_Key from ServiceRecord, so get path 1326 * records that satisfy this particular P_Key. 1327 */ 1328 if ((dinfo->p_key == 0) && 1329 (dinfo->dest[k].d_pkey != 0)) { 1330 pathrec_req.P_Key = 1331 dinfo->dest[k].d_pkey; 1332 c_mask |= SA_PR_COMPMASK_PKEY; 1333 } 1334 } 1335 1336 IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec: " 1337 "Get %d Path(s) between\nSGID %llX:%llX " 1338 "DGID %llX:%llX", pathrec_req.NumbPath, 1339 pathrec_req.SGID.gid_prefix, 1340 pathrec_req.SGID.gid_guid, 1341 pathrec_req.DGID.gid_prefix, 1342 pathrec_req.DGID.gid_guid); 1343 1344 IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec: CMask" 1345 "=0x%llX, PKey=0x%X", c_mask, pathrec_req.P_Key); 1346 1347 /* Contact SA Access to retrieve Path Records. */ 1348 access_args.sq_attr_id = SA_PATHRECORD_ATTRID; 1349 access_args.sq_template = &pathrec_req; 1350 access_args.sq_access_type = IBMF_SAA_RETRIEVE; 1351 access_args.sq_template_length = 1352 sizeof (sa_path_record_t); 1353 access_args.sq_component_mask = c_mask; 1354 access_args.sq_callback = NULL; 1355 access_args.sq_callback_arg = NULL; 1356 1357 retval = ibcm_contact_sa_access(saa_handle, 1358 &access_args, &length, &results_p); 1359 if (retval != IBT_SUCCESS) { 1360 *num_path = 0; 1361 return (retval); 1362 } 1363 1364 num_rec = length / sizeof (sa_path_record_t); 1365 1366 IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec: " 1367 "FOUND %d/%d path requested", num_rec, *num_path); 1368 1369 if ((results_p == NULL) || (num_rec == 0)) { 1370 if (idx != 0xFF) 1371 break; 1372 else 1373 continue; 1374 } 1375 1376 /* Update the PathInfo from the response. */ 1377 pr_resp = (sa_path_record_t *)results_p; 1378 for (j = 0; j < num_rec; j++, pr_resp++) { 1379 if ((p_fnd != 0) && 1380 (p_arg->flags & IBT_PATH_APM)) { 1381 IBTF_DPRINTF_L3(cmlog, 1382 "ibcm_get_single_pathrec: " 1383 "Fill Alternate Path"); 1384 retval = ibcm_update_cep_info(pr_resp, 1385 sl, NULL, 1386 &paths[found - 1].pi_alt_cep_path); 1387 if (retval != IBT_SUCCESS) 1388 continue; 1389 1390 /* Update some leftovers */ 1391 paths[found - 1].pi_alt_pkt_lt = 1392 pr_resp->PacketLifeTime; 1393 p_fnd = 0; 1394 } else { 1395 IBTF_DPRINTF_L3(cmlog, 1396 "ibcm_get_single_pathrec: " 1397 "Fill Primary Path"); 1398 1399 if (found == *num_path) 1400 break; 1401 1402 retval = ibcm_update_pri(pr_resp, sl, 1403 dinfo, &paths[found]); 1404 if (retval != IBT_SUCCESS) 1405 continue; 1406 p_fnd = 1; 1407 found++; 1408 } 1409 1410 } 1411 /* Deallocate the memory for results_p. */ 1412 kmem_free(results_p, length); 1413 1414 if (idx != 0xFF) 1415 break; /* We r here for MGID */ 1416 } 1417 if ((idx != 0xFF) && (found == *num_path)) 1418 break; /* We r here for MGID */ 1419 } 1420 1421 if (found == 0) 1422 retval = IBT_PATH_RECORDS_NOT_FOUND; 1423 else if (found != *num_path) 1424 retval = IBT_INSUFF_DATA; 1425 else 1426 retval = IBT_SUCCESS; 1427 1428 IBTF_DPRINTF_L3(cmlog, "ibcm_get_single_pathrec: done. Status %d, " 1429 "Found %d/%d Paths", retval, found, *num_path); 1430 1431 *num_path = found; 1432 1433 return (retval); 1434 } 1435 1436 1437 static ibt_status_t 1438 ibcm_get_multi_pathrec(ibcm_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl, 1439 ibcm_dinfo_t *dinfo, uint8_t *num_path, ibt_path_info_t *paths) 1440 { 1441 sa_multipath_record_t *mpr_req; 1442 sa_path_record_t *pr_resp; 1443 ibmf_saa_access_args_t access_args; 1444 void *results_p; 1445 uint64_t c_mask = 0; 1446 ib_gid_t *gid_ptr, *gid_s_ptr; 1447 size_t length; 1448 int template_len, found, num_rec; 1449 int i, k; 1450 ibt_status_t retval; 1451 uint8_t sgid_cnt, dgid_cnt; 1452 ibt_path_attr_t *attrp = &p_arg->attr; 1453 1454 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec(%p, %p, %p, %d)", 1455 attrp, sl, dinfo, *num_path); 1456 1457 for (i = 0, dgid_cnt = 0; i < dinfo->num_dest; i++) { 1458 if (dinfo->dest[i].d_tag == 0) 1459 dgid_cnt++; 1460 } 1461 1462 sgid_cnt = sl->p_count; 1463 1464 if ((sgid_cnt == 0) || (dgid_cnt == 0)) { 1465 IBTF_DPRINTF_L2(cmlog, "ibcm_get_multi_pathrec: sgid_cnt(%d) or" 1466 " dgid_cnt(%d) is zero", sgid_cnt, dgid_cnt); 1467 return (IBT_INVALID_PARAM); 1468 } 1469 1470 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: Get %d records between " 1471 "%d Src(s) <=> %d Dest(s)", *num_path, sgid_cnt, dgid_cnt); 1472 1473 /* 1474 * Calculate the size for multi-path records template, which includes 1475 * constant portion of the multipath record, plus variable size for 1476 * SGID (sgid_cnt) and DGID (dgid_cnt). 1477 */ 1478 template_len = ((dgid_cnt + sgid_cnt) * sizeof (ib_gid_t)) + 1479 sizeof (sa_multipath_record_t); 1480 1481 mpr_req = kmem_zalloc(template_len, KM_SLEEP); 1482 1483 ASSERT(mpr_req != NULL); 1484 1485 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) + 1486 sizeof (sa_multipath_record_t)); 1487 1488 /* Get the starting pointer where GIDs are stored. */ 1489 gid_s_ptr = gid_ptr; 1490 1491 /* SGID */ 1492 for (i = 0; i < sl->p_count; i++) { 1493 *gid_ptr = sl[i].p_sgid; 1494 1495 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: SGID[%d] = " 1496 "(%llX:%llX)", i, gid_ptr->gid_prefix, gid_ptr->gid_guid); 1497 1498 gid_ptr++; 1499 } 1500 1501 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req)) 1502 1503 mpr_req->SGIDCount = sgid_cnt; 1504 c_mask = SA_MPR_COMPMASK_SGIDCOUNT; 1505 1506 /* DGIDs */ 1507 for (i = 0; i < dinfo->num_dest; i++) { 1508 if (dinfo->dest[i].d_tag == 0) { 1509 *gid_ptr = dinfo->dest[i].d_gid; 1510 1511 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: " 1512 "DGID[%d] = (%llX:%llX)", i, gid_ptr->gid_prefix, 1513 gid_ptr->gid_guid); 1514 gid_ptr++; 1515 } 1516 } 1517 1518 mpr_req->DGIDCount = dgid_cnt; 1519 c_mask |= SA_MPR_COMPMASK_DGIDCOUNT; 1520 1521 /* Is Flow Label Specified. */ 1522 if (attrp->pa_flow) { 1523 mpr_req->FlowLabel = attrp->pa_flow; 1524 c_mask |= SA_MPR_COMPMASK_FLOWLABEL; 1525 } 1526 1527 /* Is HopLimit Specified. */ 1528 if (p_arg->flags & IBT_PATH_HOP) { 1529 mpr_req->HopLimit = attrp->pa_hop; 1530 c_mask |= SA_MPR_COMPMASK_HOPLIMIT; 1531 } 1532 1533 /* Is TClass Specified. */ 1534 if (attrp->pa_tclass) { 1535 mpr_req->TClass = attrp->pa_tclass; 1536 c_mask |= SA_MPR_COMPMASK_TCLASS; 1537 } 1538 1539 /* Is SL specified. */ 1540 if (attrp->pa_sl) { 1541 mpr_req->SL = attrp->pa_sl; 1542 c_mask |= SA_MPR_COMPMASK_SL; 1543 } 1544 1545 if (p_arg->flags & IBT_PATH_PERF) { 1546 mpr_req->PacketLifeTimeSelector = IBT_BEST; 1547 mpr_req->RateSelector = IBT_BEST; 1548 mpr_req->MtuSelector = IBT_BEST; 1549 1550 c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR | 1551 SA_MPR_COMPMASK_RATESELECTOR | SA_MPR_COMPMASK_MTUSELECTOR; 1552 } else { 1553 if (attrp->pa_pkt_lt.p_selector == IBT_BEST) { 1554 mpr_req->PacketLifeTimeSelector = IBT_BEST; 1555 c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR; 1556 } 1557 1558 if (attrp->pa_srate.r_selector == IBT_BEST) { 1559 mpr_req->RateSelector = IBT_BEST; 1560 c_mask |= SA_MPR_COMPMASK_RATESELECTOR; 1561 } 1562 1563 if (attrp->pa_mtu.r_selector == IBT_BEST) { 1564 mpr_req->MtuSelector = IBT_BEST; 1565 c_mask |= SA_MPR_COMPMASK_MTUSELECTOR; 1566 } 1567 } 1568 1569 /* 1570 * Honor individual selection of these attributes, 1571 * even if IBT_PATH_PERF is set. 1572 */ 1573 /* Check out whether Packet Life Time is specified. */ 1574 if (attrp->pa_pkt_lt.p_pkt_lt) { 1575 mpr_req->PacketLifeTime = 1576 ibt_usec2ib(attrp->pa_pkt_lt.p_pkt_lt); 1577 mpr_req->PacketLifeTimeSelector = 1578 attrp->pa_pkt_lt.p_selector; 1579 1580 c_mask |= SA_MPR_COMPMASK_PKTLT | 1581 SA_MPR_COMPMASK_PKTLTSELECTOR; 1582 } 1583 1584 /* Is SRATE specified. */ 1585 if (attrp->pa_srate.r_srate) { 1586 mpr_req->Rate = attrp->pa_srate.r_srate; 1587 mpr_req->RateSelector = attrp->pa_srate.r_selector; 1588 1589 c_mask |= SA_MPR_COMPMASK_RATE | 1590 SA_MPR_COMPMASK_RATESELECTOR; 1591 } 1592 1593 /* Is MTU specified. */ 1594 if (attrp->pa_mtu.r_mtu) { 1595 mpr_req->Mtu = attrp->pa_mtu.r_mtu; 1596 mpr_req->MtuSelector = attrp->pa_mtu.r_selector; 1597 1598 c_mask |= SA_MPR_COMPMASK_MTU | 1599 SA_MPR_COMPMASK_MTUSELECTOR; 1600 } 1601 1602 /* Is P_Key Specified or obtained during Service Look-up. */ 1603 if (dinfo->p_key) { 1604 mpr_req->P_Key = dinfo->p_key; 1605 c_mask |= SA_MPR_COMPMASK_PKEY; 1606 } 1607 1608 /* We always get REVERSIBLE paths. */ 1609 mpr_req->Reversible = 1; 1610 c_mask |= SA_MPR_COMPMASK_REVERSIBLE; 1611 1612 if (p_arg->flags & IBT_PATH_AVAIL) { 1613 mpr_req->IndependenceSelector = 1; 1614 c_mask |= SA_MPR_COMPMASK_INDEPSEL; 1615 } 1616 1617 /* we will not specify how many records we want. */ 1618 1619 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req)) 1620 1621 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: CMask: %llX Pkey: %X", 1622 c_mask, mpr_req->P_Key); 1623 1624 /* Contact SA Access to retrieve Path Records. */ 1625 access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID; 1626 access_args.sq_access_type = IBMF_SAA_RETRIEVE; 1627 access_args.sq_component_mask = c_mask; 1628 access_args.sq_template = mpr_req; 1629 access_args.sq_template_length = sizeof (sa_multipath_record_t); 1630 access_args.sq_callback = NULL; 1631 access_args.sq_callback_arg = NULL; 1632 1633 retval = ibcm_contact_sa_access(sl->p_saa_hdl, &access_args, &length, 1634 &results_p); 1635 if (retval != IBT_SUCCESS) { 1636 *num_path = 0; /* Update the return count. */ 1637 kmem_free(mpr_req, template_len); 1638 return (retval); 1639 } 1640 1641 num_rec = length / sizeof (sa_path_record_t); 1642 1643 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: Found %d Paths", 1644 num_rec); 1645 1646 found = 0; 1647 if ((results_p != NULL) && (num_rec > 0)) { 1648 /* Update the PathInfo with the response Path Records */ 1649 pr_resp = (sa_path_record_t *)results_p; 1650 1651 for (i = 0; i < num_rec; i++) { 1652 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: " 1653 "P[%d]: SG %llX, DG %llX", i, 1654 pr_resp[i].SGID.gid_guid, pr_resp[i].DGID.gid_guid); 1655 } 1656 1657 if (p_arg->flags & (IBT_PATH_APM | IBT_PATH_AVAIL)) { 1658 sa_path_record_t *p_resp = NULL, *a_resp = NULL; 1659 sa_path_record_t *p_tmp = NULL, *a_tmp = NULL; 1660 int p_found = 0, a_found = 0; 1661 ib_gid_t p_sg, a_sg, p_dg, a_dg; 1662 int p_tmp_found = 0, a_tmp_found = 0; 1663 1664 p_sg = gid_s_ptr[0]; 1665 if (sgid_cnt > 1) 1666 a_sg = gid_s_ptr[1]; 1667 else 1668 a_sg = p_sg; 1669 1670 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: " 1671 "REQ: P_SG: %llX, A_SG: %llX", 1672 p_sg.gid_guid, a_sg.gid_guid); 1673 1674 p_dg = gid_s_ptr[sgid_cnt]; 1675 if (dgid_cnt > 1) 1676 a_dg = gid_s_ptr[sgid_cnt + 1]; 1677 else 1678 a_dg = p_dg; 1679 1680 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: " 1681 "REQ: P_DG: %llX, A_DG: %llX", 1682 p_dg.gid_guid, a_dg.gid_guid); 1683 1684 /* 1685 * If SGID and/or DGID is specified by user, make sure 1686 * he gets his primary-path on those node points. 1687 */ 1688 for (i = 0; i < num_rec; i++, pr_resp++) { 1689 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec:" 1690 " PF %d, AF %d,\n\t\t P[%d] = SG: %llX, " 1691 "DG: %llX", p_found, a_found, i, 1692 pr_resp->SGID.gid_guid, 1693 pr_resp->DGID.gid_guid); 1694 1695 if ((!p_found) && 1696 (p_dg.gid_guid == pr_resp->DGID.gid_guid)) { 1697 IBTF_DPRINTF_L3(cmlog, 1698 "ibcm_get_multi_pathrec: " 1699 "Pri DGID Match.. "); 1700 if (p_sg.gid_guid == 1701 pr_resp->SGID.gid_guid) { 1702 p_found = 1; 1703 p_resp = pr_resp; 1704 IBTF_DPRINTF_L3(cmlog, 1705 "ibcm_get_multi_pathrec: " 1706 "Primary Path Found"); 1707 1708 if (a_found) 1709 break; 1710 else 1711 continue; 1712 } else if ((!p_tmp_found) && 1713 (a_sg.gid_guid == 1714 pr_resp->SGID.gid_guid)) { 1715 p_tmp_found = 1; 1716 p_tmp = pr_resp; 1717 IBTF_DPRINTF_L3(cmlog, 1718 "ibcm_get_multi_pathrec: " 1719 "Tmp Pri Path Found"); 1720 } 1721 IBTF_DPRINTF_L3(cmlog, 1722 "ibcm_get_multi_pathrec:" 1723 "Pri SGID Don't Match.. "); 1724 } 1725 1726 if ((!a_found) && 1727 (a_dg.gid_guid == pr_resp->DGID.gid_guid)) { 1728 IBTF_DPRINTF_L3(cmlog, 1729 "ibcm_get_multi_pathrec:" 1730 "Alt DGID Match.. "); 1731 if (a_sg.gid_guid == 1732 pr_resp->SGID.gid_guid) { 1733 a_found = 1; 1734 a_resp = pr_resp; 1735 1736 IBTF_DPRINTF_L3(cmlog, 1737 "ibcm_get_multi_pathrec:" 1738 "Alternate Path Found "); 1739 1740 if (p_found) 1741 break; 1742 else 1743 continue; 1744 } else if ((!a_tmp_found) && 1745 (p_sg.gid_guid == 1746 pr_resp->SGID.gid_guid)) { 1747 a_tmp_found = 1; 1748 a_tmp = pr_resp; 1749 1750 IBTF_DPRINTF_L3(cmlog, 1751 "ibcm_get_multi_pathrec:" 1752 "Tmp Alt Path Found "); 1753 } 1754 IBTF_DPRINTF_L3(cmlog, 1755 "ibcm_get_multi_pathrec:" 1756 "Alt SGID Don't Match.. "); 1757 } 1758 } 1759 1760 if ((p_found == 0) && (a_found == 0) && 1761 (p_tmp_found == 0) && (a_tmp_found == 0)) { 1762 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec:" 1763 " Path to desired node points NOT " 1764 "Available."); 1765 retval = IBT_PATH_RECORDS_NOT_FOUND; 1766 goto get_mpr_end; 1767 } 1768 1769 if (p_resp == NULL) { 1770 if (a_resp != NULL) { 1771 p_resp = a_resp; 1772 a_resp = NULL; 1773 } else if (p_tmp != NULL) { 1774 p_resp = p_tmp; 1775 p_tmp = NULL; 1776 } else if (a_tmp != NULL) { 1777 p_resp = a_tmp; 1778 a_tmp = NULL; 1779 } 1780 } 1781 if (a_resp == NULL) { 1782 if (a_tmp != NULL) { 1783 a_resp = a_tmp; 1784 a_tmp = NULL; 1785 } else if (p_tmp != NULL) { 1786 a_resp = p_tmp; 1787 p_tmp = NULL; 1788 } 1789 } 1790 1791 /* Fill in Primary Path */ 1792 retval = ibcm_update_pri(p_resp, sl, dinfo, 1793 &paths[found]); 1794 if (retval != IBT_SUCCESS) 1795 goto get_mpr_end; 1796 1797 if (p_arg->flags & IBT_PATH_APM) { 1798 /* Fill in Alternate Path */ 1799 if (a_resp != NULL) { 1800 /* 1801 * a_resp will point to AltPathInfo 1802 * buffer. 1803 */ 1804 retval = ibcm_update_cep_info(a_resp, 1805 sl, NULL, 1806 &paths[found].pi_alt_cep_path); 1807 if (retval != IBT_SUCCESS) 1808 goto get_mpr_end; 1809 1810 /* Update some leftovers */ 1811 paths[found].pi_alt_pkt_lt = 1812 a_resp->PacketLifeTime; 1813 } else { 1814 IBTF_DPRINTF_L3(cmlog, 1815 "ibcm_get_multi_pathrec:" 1816 " Alternate Path NOT Available."); 1817 retval = IBT_INSUFF_DATA; 1818 } 1819 found++; 1820 } else if (p_arg->flags & IBT_PATH_AVAIL) { 1821 found++; 1822 1823 if (found < *num_path) { 1824 1825 /* Fill in second Path */ 1826 if (a_resp != NULL) { 1827 retval = ibcm_update_pri(a_resp, 1828 sl, dinfo, &paths[found]); 1829 if (retval != IBT_SUCCESS) 1830 goto get_mpr_end; 1831 else 1832 found++; 1833 } else { 1834 IBTF_DPRINTF_L3(cmlog, 1835 "ibcm_get_multi_pathrec: " 1836 "SecondPath NOT Available"); 1837 retval = IBT_INSUFF_DATA; 1838 } 1839 } 1840 } 1841 } else { /* If NOT APM */ 1842 boolean_t check_pkey = B_FALSE; 1843 1844 /* mark flag whether to validate PKey or not. */ 1845 if ((dinfo->p_key == 0) && (dinfo->dest[0].d_pkey != 0)) 1846 check_pkey = B_TRUE; 1847 1848 for (i = 0; i < num_rec; i++, pr_resp++) { 1849 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec:" 1850 " PKeyCheck - %s, PKey=0x%X, DGID(%llX)", 1851 ((check_pkey == B_TRUE)?"REQD":"NOT_REQD"), 1852 pr_resp->P_Key, pr_resp->DGID.gid_guid); 1853 1854 if (check_pkey == B_TRUE) { 1855 boolean_t match_found = B_FALSE; 1856 1857 /* For all DGIDs */ 1858 for (k = 0; k < dinfo->num_dest; k++) { 1859 if (dinfo->dest[k].d_tag != 0) 1860 continue; 1861 1862 if ((dinfo->dest[k].d_gid. 1863 gid_guid == 1864 pr_resp->DGID.gid_guid) && 1865 (dinfo->dest[k].d_pkey == 1866 pr_resp->P_Key)) { 1867 match_found = B_TRUE; 1868 break; 1869 } 1870 } 1871 if (match_found == B_FALSE) 1872 continue; 1873 } 1874 /* Fill in Primary Path */ 1875 retval = ibcm_update_pri(pr_resp, sl, dinfo, 1876 &paths[found]); 1877 if (retval != IBT_SUCCESS) 1878 continue; 1879 1880 if (++found == *num_path) 1881 break; 1882 } 1883 } 1884 get_mpr_end: 1885 kmem_free(results_p, length); 1886 } 1887 kmem_free(mpr_req, template_len); 1888 1889 if (found == 0) 1890 retval = IBT_PATH_RECORDS_NOT_FOUND; 1891 else if (found != *num_path) 1892 retval = IBT_INSUFF_DATA; 1893 else 1894 retval = IBT_SUCCESS; 1895 1896 IBTF_DPRINTF_L3(cmlog, "ibcm_get_multi_pathrec: Done (status %d). " 1897 "Found %d/%d Paths", retval, found, *num_path); 1898 1899 *num_path = found; /* Update the return count. */ 1900 1901 return (retval); 1902 } 1903 1904 1905 /* 1906 * Here we "synthesize" loop back path record information. 1907 * 1908 * Currently the synthesize values are assumed as follows: 1909 * SLID, DLID = Base LID from Query HCA Port. 1910 * FlowLabel, HopLimit, TClass = 0, as GRH is False. 1911 * RawTraffic = 0. 1912 * P_Key = first valid one in P_Key table as obtained from Query HCA Port. 1913 * SL = as from Query HCA Port. 1914 * MTU = from Query HCA Port. 1915 * Rate = 2 (arbitrary). 1916 * PacketLifeTime = 0 (4.096 usec). 1917 */ 1918 static ibt_status_t 1919 ibcm_fillin_loopbackinfo(ibtl_cm_port_list_t *sl, uint8_t index, 1920 ibcm_dinfo_t *dinfo, ibt_path_info_t *paths) 1921 { 1922 ibt_status_t retval; 1923 ib_pkey_t pkey = 0; 1924 1925 IBTF_DPRINTF_L3(cmlog, "ibcm_fillin_loopbackinfo(%p, %p)", sl, dinfo); 1926 1927 /* Synthesize path record with appropriate loop back information. */ 1928 if (dinfo->p_key) 1929 pkey = dinfo->p_key; 1930 else 1931 pkey = dinfo->dest[index].d_pkey; 1932 if (pkey) { 1933 /* Convert P_Key to P_Key_Index */ 1934 retval = ibt_pkey2index_byguid(sl->p_hca_guid, sl->p_port_num, 1935 pkey, &paths->pi_prim_cep_path.cep_pkey_ix); 1936 if (retval != IBT_SUCCESS) { 1937 /* Failed to get pkey_index from pkey */ 1938 IBTF_DPRINTF_L2(cmlog, "ibcm_fillin_loopbackinfo: " 1939 "Pkey2Index (P_Key = %X) conversion failed: %d", 1940 pkey, retval); 1941 return (retval); 1942 } 1943 } else { 1944 paths->pi_prim_cep_path.cep_pkey_ix = 1945 ibtl_cm_get_1st_full_pkey_ix(sl->p_hca_guid, 1946 sl->p_port_num); 1947 IBTF_DPRINTF_L3(cmlog, "ibcm_fillin_loopbackinfo: " 1948 "1st Full Member P_Key_ix = %d", 1949 paths->pi_prim_cep_path.cep_pkey_ix); 1950 } 1951 1952 paths->pi_hca_guid = sl->p_hca_guid; 1953 paths->pi_prim_cep_path.cep_adds_vect.av_dgid = 1954 dinfo->dest[index].d_gid; 1955 paths->pi_prim_cep_path.cep_adds_vect.av_sgid = sl->p_sgid; 1956 paths->pi_prim_cep_path.cep_adds_vect.av_srate = IBT_SRATE_1X; 1957 paths->pi_prim_cep_path.cep_adds_vect.av_srvl = 0; /* SL */ 1958 1959 paths->pi_prim_cep_path.cep_adds_vect.av_send_grh = B_FALSE; 1960 paths->pi_prim_cep_path.cep_adds_vect.av_flow = 0; 1961 paths->pi_prim_cep_path.cep_adds_vect.av_tclass = 0; 1962 paths->pi_prim_cep_path.cep_adds_vect.av_hop = 0; 1963 1964 /* SLID and DLID will be equal to BLID. */ 1965 paths->pi_prim_cep_path.cep_adds_vect.av_dlid = sl->p_base_lid; 1966 paths->pi_prim_cep_path.cep_adds_vect.av_src_path = 0; 1967 paths->pi_prim_cep_path.cep_adds_vect.av_sgid_ix = sl->p_sgid_ix; 1968 paths->pi_prim_cep_path.cep_adds_vect.av_port_num = sl->p_port_num; 1969 paths->pi_prim_cep_path.cep_hca_port_num = sl->p_port_num; 1970 paths->pi_prim_cep_path.cep_timeout = 0; /* To be filled in by CM. */ 1971 paths->pi_path_mtu = sl->p_mtu; /* MTU */ 1972 paths->pi_prim_pkt_lt = 0; /* Packet Life Time. */ 1973 paths->pi_alt_pkt_lt = 0; /* Packet Life Time. */ 1974 1975 paths->pi_sid = dinfo->dest[index].d_sid; 1976 1977 if (paths->pi_sid != 0) 1978 bcopy(&dinfo->dest[index].d_sdata, &paths->pi_sdata, 1979 sizeof (ibt_srv_data_t)); 1980 1981 IBTF_DPRINTF_L3(cmlog, "ibcm_fillin_loopbackinfo: HCA %llX:%d SID %llX" 1982 "\n\t SGID %llX:%llX DGID %llX:%llX", paths->pi_hca_guid, 1983 paths->pi_prim_cep_path.cep_hca_port_num, paths->pi_sid, 1984 sl->p_sgid.gid_prefix, sl->p_sgid.gid_guid, 1985 dinfo->dest[index].d_gid.gid_prefix, 1986 dinfo->dest[index].d_gid.gid_guid); 1987 1988 /* Set Alternate Path to invalid state. */ 1989 paths->pi_alt_cep_path.cep_hca_port_num = 0; 1990 paths->pi_alt_cep_path.cep_adds_vect.av_dlid = 0; 1991 1992 return (IBT_SUCCESS); 1993 } 1994 1995 1996 /* 1997 * Update the output path records buffer with the values as obtained from 1998 * SA Access retrieve call results for Path Records. 1999 */ 2000 static ibt_status_t 2001 ibcm_update_cep_info(sa_path_record_t *prec_resp, ibtl_cm_port_list_t *sl, 2002 ibtl_cm_hca_port_t *hport, ibt_cep_path_t *cep_p) 2003 { 2004 ibt_status_t retval; 2005 int i; 2006 2007 IBCM_DUMP_PATH_REC(prec_resp); 2008 2009 /* 2010 * If path's packet life time is more than 4 seconds, IBCM cannot 2011 * handle this path connection, so discard this path record. 2012 */ 2013 if (prec_resp->PacketLifeTime > ibcm_max_ib_pkt_lt) { 2014 IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: Path's Packet " 2015 "LifeTime too high %d, Maximum allowed %d IB Time (4 sec)", 2016 prec_resp->PacketLifeTime, ibcm_max_ib_pkt_lt); 2017 return (ibt_get_module_failure(IBT_FAILURE_IBSM, 0)); 2018 } 2019 2020 if ((prec_resp->Mtu > IB_MTU_4K) || (prec_resp->Mtu < IB_MTU_256)) { 2021 IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: MTU (%d) from " 2022 "pathrecord is invalid, reject it.", prec_resp->Mtu); 2023 return (ibt_get_module_failure(IBT_FAILURE_IBSM, 0)); 2024 } 2025 2026 /* Source Node Information. */ 2027 cep_p->cep_adds_vect.av_sgid = prec_resp->SGID; 2028 if (hport != NULL) { 2029 /* Convert P_Key to P_Key_Index */ 2030 retval = ibt_pkey2index_byguid(hport->hp_hca_guid, 2031 hport->hp_port, prec_resp->P_Key, &cep_p->cep_pkey_ix); 2032 if (retval != IBT_SUCCESS) { 2033 /* Failed to get pkey_index from pkey */ 2034 IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: " 2035 "Pkey2Index (PKey = %X) conversion failed: %d", 2036 prec_resp->P_Key, retval); 2037 return (ibt_get_module_failure(IBT_FAILURE_IBSM, 0)); 2038 } 2039 cep_p->cep_adds_vect.av_sgid_ix = hport->hp_sgid_ix; 2040 cep_p->cep_adds_vect.av_src_path = 2041 prec_resp->SLID - hport->hp_base_lid; 2042 cep_p->cep_adds_vect.av_port_num = cep_p->cep_hca_port_num = 2043 hport->hp_port; 2044 } else if (sl != NULL) { 2045 for (i = 0; i < sl->p_count; i++) { 2046 if (prec_resp->SGID.gid_guid == sl[i].p_sgid.gid_guid) { 2047 /* Convert P_Key to P_Key_Index */ 2048 retval = ibt_pkey2index_byguid(sl[i].p_hca_guid, 2049 sl[i].p_port_num, prec_resp->P_Key, 2050 &cep_p->cep_pkey_ix); 2051 if (retval != IBT_SUCCESS) { 2052 /* Failed to get pkey_index from pkey */ 2053 IBTF_DPRINTF_L2(cmlog, 2054 "ibcm_update_cep_info: Pkey2Index " 2055 "(PKey = %X) conversion failed: %d", 2056 prec_resp->P_Key, retval); 2057 return (ibt_get_module_failure( 2058 IBT_FAILURE_IBSM, 0)); 2059 } 2060 2061 cep_p->cep_adds_vect.av_sgid_ix = 2062 sl[i].p_sgid_ix; 2063 cep_p->cep_adds_vect.av_src_path = 2064 prec_resp->SLID - sl[i].p_base_lid; 2065 cep_p->cep_adds_vect.av_port_num = 2066 sl[i].p_port_num; 2067 cep_p->cep_hca_port_num = sl[i].p_port_num; 2068 2069 break; 2070 } 2071 } 2072 } else { 2073 IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: Sl or Hport " 2074 "must be non-null"); 2075 return (IBT_INVALID_PARAM); 2076 } 2077 2078 if (prec_resp->Rate) { 2079 cep_p->cep_adds_vect.av_srate = prec_resp->Rate; 2080 } else { 2081 IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: SRate (%d) from " 2082 "pathrecord is invalid, reject it.", prec_resp->Rate); 2083 return (ibt_get_module_failure(IBT_FAILURE_IBSM, 0)); 2084 } 2085 /* 2086 * If both Source and Destination GID prefix are same, then GRH is not 2087 * valid, so make it as false, else set this field as true. 2088 */ 2089 if (prec_resp->SGID.gid_prefix == prec_resp->DGID.gid_prefix) 2090 cep_p->cep_adds_vect.av_send_grh = B_FALSE; 2091 else 2092 cep_p->cep_adds_vect.av_send_grh = B_TRUE; 2093 2094 /* SGID and SGID Index. */ 2095 cep_p->cep_adds_vect.av_sgid = prec_resp->SGID; 2096 cep_p->cep_adds_vect.av_flow = prec_resp->FlowLabel; 2097 cep_p->cep_adds_vect.av_tclass = prec_resp->TClass; 2098 cep_p->cep_adds_vect.av_hop = prec_resp->HopLimit; 2099 2100 /* Address Vector Definition. */ 2101 cep_p->cep_adds_vect.av_dlid = prec_resp->DLID; 2102 cep_p->cep_adds_vect.av_srvl = prec_resp->SL; 2103 2104 /* DGID */ 2105 cep_p->cep_adds_vect.av_dgid = prec_resp->DGID; 2106 2107 /* CEP Timeout is NOT filled in by PATH routines. */ 2108 cep_p->cep_timeout = 0; 2109 2110 IBTF_DPRINTF_L2(cmlog, "ibcm_update_cep_info: Done. Port=%d, PKey=%X\n" 2111 "SGID=%llX:%llX DGID=%llX:%llX", cep_p->cep_adds_vect.av_port_num, 2112 prec_resp->P_Key, 2113 prec_resp->SGID.gid_prefix, prec_resp->SGID.gid_guid, 2114 prec_resp->DGID.gid_prefix, prec_resp->DGID.gid_guid); 2115 2116 return (IBT_SUCCESS); 2117 } 2118 2119 2120 static void 2121 ibcm_fill_svcinfo(sa_service_record_t *sr_resp, ibcm_dest_t *dest) 2122 { 2123 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dest)) 2124 2125 dest->d_gid = sr_resp->ServiceGID; 2126 dest->d_sid = sr_resp->ServiceID; 2127 ibcm_swizzle_to_srv(sr_resp->ServiceData, &dest->d_sdata); 2128 dest->d_pkey = sr_resp->ServiceP_Key; 2129 2130 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*dest)) 2131 2132 IBTF_DPRINTF_L3(cmlog, "ibcm_fill_svcinfo: SID(%llX), GID(%llX:%llX)" 2133 "\n\tSvcPKey 0x%X", dest->d_sid, dest->d_gid.gid_prefix, 2134 dest->d_gid.gid_guid, dest->d_pkey); 2135 } 2136 2137 2138 static ib_gid_t 2139 ibcm_saa_get_agid(ibtl_cm_port_list_t *sl, ib_gid_t *gidp, uint_t ngid) 2140 { 2141 int k, l; 2142 ib_gid_t a_gid; 2143 2144 a_gid.gid_prefix = a_gid.gid_guid = 0; 2145 2146 for (k = 0; k < sl->p_count; k++) { 2147 for (l = 0; l < ngid; l++) { 2148 2149 if (gidp->gid_prefix == sl->p_sgid.gid_prefix) { 2150 a_gid = *gidp; 2151 break; 2152 } 2153 if (a_gid.gid_guid && a_gid.gid_prefix) 2154 break; 2155 gidp++; 2156 } 2157 if (a_gid.gid_guid && a_gid.gid_prefix) 2158 break; 2159 sl++; 2160 } 2161 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_get_agid: AltGID = %llX:%llX", 2162 a_gid.gid_prefix, a_gid.gid_guid); 2163 2164 return (a_gid); 2165 } 2166 2167 /* 2168 * Perform SA Access to retrieve Service Records. 2169 * On Success, returns ServiceID and ServiceGID info in '*dinfo'. 2170 */ 2171 static ibt_status_t 2172 ibcm_saa_service_rec(ibcm_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl, 2173 ibcm_dinfo_t *dinfo) 2174 { 2175 sa_service_record_t svcrec_req; 2176 sa_service_record_t *svcrec_resp; 2177 void *results_p; 2178 uint64_t component_mask = 0; 2179 size_t length; 2180 uint8_t i, j, k, rec_found, s; 2181 ibmf_saa_access_args_t access_args; 2182 ibt_status_t retval; 2183 ibt_path_attr_t *attrp = &p_arg->attr; 2184 uint64_t tmp_sd_flag = attrp->pa_sd_flags; 2185 uint8_t num_req; 2186 2187 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec(%p, %p)", p_arg, sl); 2188 2189 bzero(&svcrec_req, sizeof (svcrec_req)); 2190 2191 /* Service Name */ 2192 if ((attrp->pa_sname != NULL) && (strlen(attrp->pa_sname) != 0)) { 2193 (void) strncpy((char *)(svcrec_req.ServiceName), 2194 attrp->pa_sname, IB_SVC_NAME_LEN); 2195 2196 component_mask |= SA_SR_COMPMASK_NAME; 2197 } 2198 2199 /* Service ID */ 2200 if (attrp->pa_sid) { 2201 svcrec_req.ServiceID = attrp->pa_sid; 2202 component_mask |= SA_SR_COMPMASK_ID; 2203 } 2204 2205 /* Is P_Key Specified. */ 2206 if (p_arg->flags & IBT_PATH_PKEY) { 2207 svcrec_req.ServiceP_Key = attrp->pa_pkey; 2208 component_mask |= SA_SR_COMPMASK_PKEY; 2209 } 2210 2211 /* Is ServiceData Specified. */ 2212 if (attrp->pa_sd_flags != IBT_NO_SDATA) { 2213 /* Handle endianess for service data. */ 2214 ibcm_swizzle_from_srv(&attrp->pa_sdata, svcrec_req.ServiceData); 2215 2216 /* 2217 * Lets not interpret each and every ServiceData flags, 2218 * just pass it on to SAA. Shift the flag, to suit 2219 * SA_SR_COMPMASK_ALL_DATA definition. 2220 */ 2221 component_mask |= (tmp_sd_flag << 7); 2222 } 2223 2224 if (dinfo->num_dest == 1) { 2225 2226 /* If a single DGID is specified, provide it */ 2227 svcrec_req.ServiceGID = dinfo->dest->d_gid; 2228 component_mask |= SA_SR_COMPMASK_GID; 2229 2230 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec:%llX:%llX", 2231 svcrec_req.ServiceGID.gid_prefix, 2232 svcrec_req.ServiceGID.gid_guid); 2233 } 2234 2235 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: " 2236 "Perform SA Access: Mask: 0x%X", component_mask); 2237 2238 /* 2239 * Call in SA Access retrieve routine to get Service Records. 2240 * 2241 * SA Access framework allocated memory for the "results_p". 2242 * Make sure to deallocate once we are done with the results_p. 2243 * The size of the buffer allocated will be as returned in 2244 * "length" field. 2245 */ 2246 access_args.sq_attr_id = SA_SERVICERECORD_ATTRID; 2247 access_args.sq_access_type = IBMF_SAA_RETRIEVE; 2248 access_args.sq_component_mask = component_mask; 2249 access_args.sq_template = &svcrec_req; 2250 access_args.sq_template_length = sizeof (sa_service_record_t); 2251 access_args.sq_callback = NULL; 2252 access_args.sq_callback_arg = NULL; 2253 2254 for (s = 0; s < sl->p_count; s++) { 2255 retval = ibcm_contact_sa_access(sl[s].p_saa_hdl, &access_args, 2256 &length, &results_p); 2257 if (retval != IBT_SUCCESS) 2258 if (sl[s].p_multi & IBTL_CM_MULTI_SM) 2259 continue; 2260 else 2261 return (retval); 2262 2263 if ((results_p == NULL) || (length == 0)) { 2264 IBTF_DPRINTF_L2(cmlog, "ibcm_saa_service_rec: SvcRec " 2265 "Not Found: res_p %p, len %d", results_p, length); 2266 if (sl[s].p_multi & IBTL_CM_MULTI_SM) { 2267 retval = IBT_SERVICE_RECORDS_NOT_FOUND; 2268 continue; 2269 } else 2270 return (IBT_SERVICE_RECORDS_NOT_FOUND); 2271 } 2272 2273 /* if we are here, we got some records. so break. */ 2274 break; 2275 } 2276 2277 if (retval != IBT_SUCCESS) 2278 return (retval); 2279 2280 num_req = length / sizeof (sa_service_record_t); 2281 2282 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: Got %d Service Records.", 2283 num_req); 2284 2285 svcrec_resp = (sa_service_record_t *)results_p; 2286 rec_found = 0; 2287 2288 /* Update the return values. */ 2289 if (dinfo->num_dest) { 2290 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: Get ServiceRec " 2291 "for Specified DGID: %d", dinfo->num_dest); 2292 2293 for (i = 0; i < num_req; i++, svcrec_resp++) { 2294 /* Limited P_Key is NOT supported as of now!. */ 2295 if ((svcrec_resp->ServiceP_Key & 0x8000) == 0) { 2296 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: " 2297 "SvcPkey 0x%X limited, reject the record.", 2298 svcrec_resp->ServiceP_Key); 2299 continue; 2300 } 2301 2302 for (j = 0; j < dinfo->num_dest; j++) { 2303 if (dinfo->dest[j].d_gid.gid_guid == 2304 svcrec_resp->ServiceGID.gid_guid) { 2305 ibcm_fill_svcinfo(svcrec_resp, 2306 &dinfo->dest[j]); 2307 rec_found++; 2308 } 2309 if (rec_found == dinfo->num_dest) 2310 break; 2311 } 2312 if (rec_found == dinfo->num_dest) 2313 break; 2314 } 2315 if (rec_found != dinfo->num_dest) { 2316 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: Did NOT " 2317 "find ServiceRec for all DGIDs: (%d/%d)", rec_found, 2318 dinfo->num_dest); 2319 retval = IBT_INSUFF_DATA; 2320 } 2321 } else if (p_arg->flags & IBT_PATH_APM) { 2322 ib_gid_t p_gid, a_gid, last_p_gid; 2323 ib_gid_t *gidp = NULL; 2324 uint_t n_gids; 2325 sa_service_record_t *stmp; 2326 boolean_t pri_fill_done = B_FALSE; 2327 boolean_t alt_fill_done = B_FALSE; 2328 ib_pkey_t p_pkey = 0, a_pkey = 0; 2329 2330 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: Need to " 2331 "find ServiceRec that can satisfy APM"); 2332 2333 p_gid.gid_prefix = p_gid.gid_guid = 0; 2334 a_gid.gid_prefix = a_gid.gid_guid = 0; 2335 last_p_gid.gid_prefix = last_p_gid.gid_guid = 0; 2336 2337 for (i = 0; i < num_req; i++, svcrec_resp++) { 2338 ibt_status_t ret; 2339 boolean_t is_this_on_local_node = B_FALSE; 2340 2341 /* Limited P_Key is NOT supported as of now!. */ 2342 if ((svcrec_resp->ServiceP_Key & 0x8000) == 0) { 2343 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: " 2344 "SvcPkey 0x%X limited, reject the record.", 2345 svcrec_resp->ServiceP_Key); 2346 continue; 2347 } 2348 2349 p_gid = svcrec_resp->ServiceGID; 2350 2351 /* Let's avoid LoopBack Nodes. */ 2352 for (j = 0; j < sl->p_count; j++) { 2353 if (p_gid.gid_guid == sl[j].p_sgid.gid_guid) { 2354 is_this_on_local_node = B_TRUE; 2355 2356 IBTF_DPRINTF_L3(cmlog, 2357 "ibcm_saa_service_rec: ServiceGID " 2358 "%llX:%llX is on Local Node, " 2359 "search for remote.", 2360 p_gid.gid_prefix, p_gid.gid_guid); 2361 } 2362 } 2363 2364 if (is_this_on_local_node == B_TRUE) { 2365 if ((i + 1) < num_req) { 2366 p_gid.gid_prefix = 0; 2367 p_gid.gid_guid = 0; 2368 continue; 2369 } else if (last_p_gid.gid_prefix != 0) { 2370 p_gid = last_p_gid; 2371 break; 2372 } 2373 } 2374 2375 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: " 2376 "Finally let Primary DGID = %llX:%llX", 2377 p_gid.gid_prefix, p_gid.gid_guid); 2378 2379 ret = ibt_get_companion_port_gids(p_gid, 0, 0, 2380 &gidp, &n_gids); 2381 if (ret == IBT_SUCCESS) { 2382 IBTF_DPRINTF_L3(cmlog, 2383 "ibcm_saa_service_rec: Found %d " 2384 "CompGID for %llX:%llX", n_gids, 2385 p_gid.gid_prefix, p_gid.gid_guid); 2386 2387 stmp = (sa_service_record_t *)results_p; 2388 a_gid.gid_prefix = a_gid.gid_guid = 0; 2389 2390 if (sl->p_multi & IBTL_CM_MULTI_SM) { 2391 /* validate sn_pfx */ 2392 a_gid = ibcm_saa_get_agid(sl, 2393 gidp, n_gids); 2394 } else { 2395 for (k = 0; k < num_req; k++) { 2396 ib_gid_t sg = stmp->ServiceGID; 2397 2398 IBTF_DPRINTF_L3(cmlog, 2399 "ibcm_saa_service_rec: " 2400 "SvcGID[%d] = %llX:%llX", k, 2401 sg.gid_prefix, sg.gid_guid); 2402 2403 for (j = 0; j < n_gids; j++) { 2404 if (gidp[j].gid_guid == 2405 sg.gid_guid) { 2406 a_gid = gidp[j]; 2407 break; 2408 } 2409 } 2410 if (a_gid.gid_guid) 2411 break; 2412 stmp++; 2413 } 2414 if (a_gid.gid_guid == 0) { 2415 /* Rec not found for Alt. */ 2416 for (j = 0; j < n_gids; j++) { 2417 if (gidp[j].gid_prefix 2418 == p_gid. 2419 gid_prefix) { 2420 a_gid = gidp[j]; 2421 break; 2422 } 2423 } 2424 } 2425 } 2426 kmem_free(gidp, 2427 n_gids * sizeof (ib_gid_t)); 2428 2429 if (a_gid.gid_guid) 2430 break; 2431 } else if (ret == IBT_GIDS_NOT_FOUND) { 2432 last_p_gid = p_gid; 2433 IBTF_DPRINTF_L3(cmlog, 2434 "ibcm_saa_service_rec: Didn't find " 2435 "CompGID for %llX:%llX, ret=%d", 2436 p_gid.gid_prefix, p_gid.gid_guid, 2437 ret); 2438 } else { 2439 IBTF_DPRINTF_L3(cmlog, 2440 "ibcm_saa_service_rec: Call to " 2441 "ibt_get_companion_port_gids(%llX:" 2442 "%llX) Failed = %d", 2443 p_gid.gid_prefix, p_gid.gid_guid, 2444 ret); 2445 } 2446 } 2447 2448 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: \n\t" 2449 "Pri DGID(%llX:%llX), Alt DGID(%llX:%llX)", 2450 p_gid.gid_prefix, p_gid.gid_guid, a_gid.gid_prefix, 2451 a_gid.gid_guid); 2452 2453 svcrec_resp = (sa_service_record_t *)results_p; 2454 2455 for (i = 0, j = 0; i < num_req; i++, svcrec_resp++) { 2456 /* Limited P_Key is NOT supported as of now!. */ 2457 if ((svcrec_resp->ServiceP_Key & 0x8000) == 0) { 2458 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: " 2459 "SvcPkey 0x%X limited, reject the record.", 2460 svcrec_resp->ServiceP_Key); 2461 continue; 2462 } 2463 2464 if ((pri_fill_done == B_FALSE) && 2465 (p_gid.gid_guid == 2466 svcrec_resp->ServiceGID.gid_guid)) { 2467 p_pkey = svcrec_resp->ServiceP_Key; 2468 if ((a_pkey != 0) && 2469 (a_pkey != p_pkey)) { 2470 IBTF_DPRINTF_L3(cmlog, 2471 "ibcm_saa_service_rec: " 2472 "Pri(0x%X) & Alt (0x%X) " 2473 "PKey must match.", 2474 p_pkey, a_pkey); 2475 p_pkey = 0; 2476 continue; 2477 } 2478 ibcm_fill_svcinfo(svcrec_resp, 2479 &dinfo->dest[j++]); 2480 rec_found++; 2481 pri_fill_done = B_TRUE; 2482 } else if ((alt_fill_done == B_FALSE) && 2483 (a_gid.gid_guid == 2484 svcrec_resp->ServiceGID.gid_guid)) { 2485 a_pkey = svcrec_resp->ServiceP_Key; 2486 if ((p_pkey != 0) && 2487 (a_pkey != p_pkey)) { 2488 IBTF_DPRINTF_L3(cmlog, 2489 "ibcm_saa_service_rec: " 2490 "Pri(0x%X) & Alt (0x%X) " 2491 "PKey must match.", 2492 p_pkey, a_pkey); 2493 a_pkey = 0; 2494 continue; 2495 } 2496 ibcm_fill_svcinfo(svcrec_resp, 2497 &dinfo->dest[j++]); 2498 rec_found++; 2499 alt_fill_done = B_TRUE; 2500 } 2501 2502 if (rec_found == 2) 2503 break; 2504 } 2505 if ((alt_fill_done == B_FALSE) && (a_gid.gid_guid)) { 2506 dinfo->dest[j].d_gid = a_gid; 2507 dinfo->dest[j].d_pkey = p_pkey; 2508 rec_found++; 2509 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: " 2510 "Let Alt Pkey=%X, DGID=%llX:%llX", p_pkey, 2511 a_gid.gid_prefix, a_gid.gid_guid); 2512 } 2513 2514 if (rec_found == 1) 2515 retval = IBT_INSUFF_DATA; 2516 } else if (p_arg->flags & IBT_PATH_MULTI_SVC_DEST) { 2517 for (i = 0; i < num_req; i++, svcrec_resp++) { 2518 ib_gid_t p_gid; 2519 boolean_t is_this_on_local_node = B_FALSE; 2520 2521 /* Limited P_Key is NOT supported as of now!. */ 2522 if ((svcrec_resp->ServiceP_Key & 0x8000) == 0) { 2523 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: " 2524 "SvcPkey 0x%X limited, reject the record.", 2525 svcrec_resp->ServiceP_Key); 2526 continue; 2527 } 2528 2529 p_gid = svcrec_resp->ServiceGID; 2530 2531 /* Let's avoid LoopBack Nodes. */ 2532 for (j = 0; j < sl->p_count; j++) { 2533 if (p_gid.gid_guid == sl[j].p_sgid.gid_guid) { 2534 is_this_on_local_node = B_TRUE; 2535 IBTF_DPRINTF_L3(cmlog, 2536 "ibcm_saa_service_rec: ServiceGID " 2537 "%llX:%llX is on Local Node, " 2538 "search for remote.", 2539 p_gid.gid_prefix, p_gid.gid_guid); 2540 } 2541 } 2542 2543 if (is_this_on_local_node == B_TRUE) 2544 if ((i + 1) < num_req) 2545 continue; 2546 2547 IBTF_DPRINTF_L4(cmlog, "ibcm_saa_service_rec: " 2548 "Found ServiceGID = %llX:%llX", 2549 p_gid.gid_prefix, p_gid.gid_guid); 2550 2551 ibcm_fill_svcinfo(svcrec_resp, 2552 &dinfo->dest[rec_found]); 2553 rec_found++; 2554 if (rec_found == p_arg->max_paths) 2555 break; 2556 } 2557 2558 if (rec_found < p_arg->max_paths) 2559 retval = IBT_INSUFF_DATA; 2560 } else { 2561 for (i = 0; i < num_req; i++) { 2562 /* Limited P_Key is NOT supported as of now!. */ 2563 if ((svcrec_resp->ServiceP_Key & 0x8000) == 0) { 2564 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: " 2565 "SvcPkey 0x%X limited, reject the record.", 2566 svcrec_resp->ServiceP_Key); 2567 svcrec_resp++; 2568 continue; 2569 } 2570 2571 ibcm_fill_svcinfo(svcrec_resp, &dinfo->dest[0]); 2572 rec_found = 1; 2573 2574 /* Avoid having loopback node */ 2575 if (svcrec_resp->ServiceGID.gid_guid != 2576 sl->p_sgid.gid_guid) { 2577 break; 2578 } else { 2579 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: " 2580 "avoid LoopBack node."); 2581 svcrec_resp++; 2582 } 2583 } 2584 } 2585 2586 /* Deallocate the memory for results_p. */ 2587 kmem_free(results_p, length); 2588 if (dinfo->num_dest == 0) 2589 dinfo->num_dest = rec_found; 2590 2591 /* 2592 * Check out whether all Service Path we looking for are on the same 2593 * P_key. If yes, then set the global p_key field with that value, 2594 * to make it easy during SA Path Query. 2595 */ 2596 if ((dinfo->num_dest) && (dinfo->p_key == 0)) { 2597 ib_pkey_t pk = dinfo->dest[0].d_pkey; 2598 2599 if (dinfo->num_dest == 1) { 2600 dinfo->p_key = pk; 2601 } else { 2602 for (i = 1; i < (dinfo->num_dest - 1); i++) { 2603 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: " 2604 "pk= 0x%X, pk[%d]= 0x%X", pk, i, 2605 dinfo->dest[i].d_pkey); 2606 if (pk != dinfo->dest[i].d_pkey) { 2607 dinfo->p_key = 0; 2608 break; 2609 } else { 2610 dinfo->p_key = pk; 2611 } 2612 } 2613 } 2614 } 2615 2616 if (rec_found == 0) { 2617 IBTF_DPRINTF_L2(cmlog, "ibcm_saa_service_rec: " 2618 "ServiceRec NOT Found"); 2619 retval = IBT_SERVICE_RECORDS_NOT_FOUND; 2620 } 2621 2622 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_service_rec: done. Status %d, " 2623 "PKey 0x%X, Found %d SvcRec", retval, dinfo->p_key, rec_found); 2624 2625 return (retval); 2626 } 2627 2628 2629 static boolean_t 2630 ibcm_compare_paths(sa_path_record_t *pr_resp, ibt_cep_path_t *rc_path, 2631 ibtl_cm_hca_port_t *c_hp) 2632 { 2633 if ((rc_path->cep_hca_port_num == c_hp->hp_port) && 2634 (rc_path->cep_adds_vect.av_src_path == 2635 (pr_resp->SLID - c_hp->hp_base_lid)) && 2636 (rc_path->cep_adds_vect.av_dlid == pr_resp->DLID) && 2637 (rc_path->cep_adds_vect.av_srate == pr_resp->Rate)) { 2638 return (B_TRUE); 2639 } else { 2640 return (B_FALSE); 2641 } 2642 } 2643 2644 /* 2645 * ibcm_get_comp_pgids() routine gets the companion port for 'gid'. 2646 * 2647 * On success: 2648 * If 'n_gid' is specified, then verify whether 'n_gid' is indeed a 2649 * companion portgid of 'gid'. If matches return success or else error. 2650 * 2651 * If 'n_gid' is NOT specified, then return back SUCCESS along with 2652 * obtained Companion PortGids 'gid_p', where 'num' indicated number 2653 * of companion portgids returned in 'gid_p'. 2654 */ 2655 2656 static ibt_status_t 2657 ibcm_get_comp_pgids(ib_gid_t gid, ib_gid_t n_gid, ib_guid_t hca_guid, 2658 ib_gid_t **gid_p, uint_t *num) 2659 { 2660 ibt_status_t ret; 2661 int i; 2662 2663 ret = ibt_get_companion_port_gids(gid, hca_guid, 0, gid_p, num); 2664 if ((ret != IBT_SUCCESS) && (ret != IBT_GIDS_NOT_FOUND)) { 2665 IBTF_DPRINTF_L2(cmlog, "ibcm_get_comp_pgids: " 2666 "ibt_get_companion_port_gids(%llX:%llX) Failed: %d", 2667 gid.gid_prefix, gid.gid_guid, ret); 2668 } else if ((ret == IBT_GIDS_NOT_FOUND) && (n_gid.gid_guid != 0)) { 2669 IBTF_DPRINTF_L2(cmlog, "ibcm_get_comp_pgids: Specified GID " 2670 "(%llX:%llX) is NOT a Companion \n\t to current channel's " 2671 "GID(%llX:%llX)", n_gid.gid_prefix, n_gid.gid_guid, 2672 gid.gid_prefix, gid.gid_guid); 2673 ret = IBT_INVALID_PARAM; 2674 } else if (n_gid.gid_guid != 0) { 2675 /* 2676 * We found some Comp GIDs and n_gid is specified. Validate 2677 * whether the 'n_gid' specified is indeed the companion port 2678 * GID of 'gid'. 2679 */ 2680 for (i = 0; i < *num; i++) { 2681 if ((n_gid.gid_prefix == gid_p[i]->gid_prefix) && 2682 (n_gid.gid_guid == gid_p[i]->gid_guid)) { 2683 IBTF_DPRINTF_L3(cmlog, "ibcm_get_comp_pgids: " 2684 "Matching Found!. Done."); 2685 return (IBT_SUCCESS); 2686 } 2687 } 2688 IBTF_DPRINTF_L2(cmlog, "ibcm_get_comp_pgids: GID (%llX:%llX)\n" 2689 "\t and (%llX:%llX) are NOT Companion Port GIDS", 2690 n_gid.gid_prefix, n_gid.gid_guid, gid.gid_prefix, 2691 gid.gid_guid); 2692 ret = IBT_INVALID_PARAM; 2693 } else { 2694 ret = IBT_SUCCESS; 2695 } 2696 2697 IBTF_DPRINTF_L3(cmlog, "ibcm_get_comp_pgids: done. Status = %d", ret); 2698 return (ret); 2699 } 2700 2701 /* 2702 * Function: 2703 * ibt_get_alt_path 2704 * Input: 2705 * rc_chan An RC channel handle returned in a previous call 2706 * ibt_alloc_rc_channel(9F), specifies the channel to open. 2707 * flags Path flags. 2708 * attrp A pointer to an ibt_alt_path_attr_t(9S) structure that 2709 * specifies required attributes of the selected path(s). 2710 * Output: 2711 * api_p An ibt_alt_path_info_t(9S) struct filled in as output 2712 * parameters. 2713 * Returns: 2714 * IBT_SUCCESS on Success else appropriate error. 2715 * Description: 2716 * Finds the best alternate path to a specified channel (as determined by 2717 * the IBTL) that satisfies the requirements specified in an 2718 * ibt_alt_path_attr_t struct. The specified channel must have been 2719 * previously opened successfully using ibt_open_rc_channel. 2720 * This function also ensures that the service being accessed by the 2721 * channel is available at the selected alternate port. 2722 * 2723 * Note: The apa_dgid must be on the same destination channel adapter, 2724 * if specified. 2725 * This routine can not be called from interrupt context. 2726 */ 2727 ibt_status_t 2728 ibt_get_alt_path(ibt_channel_hdl_t rc_chan, ibt_path_flags_t flags, 2729 ibt_alt_path_attr_t *attrp, ibt_alt_path_info_t *api_p) 2730 { 2731 sa_multipath_record_t *mpr_req; 2732 sa_path_record_t *pr_resp; 2733 ibmf_saa_access_args_t access_args; 2734 ibt_qp_query_attr_t qp_attr; 2735 ibtl_cm_hca_port_t c_hp, n_hp; 2736 ibcm_hca_info_t *hcap; 2737 void *results_p; 2738 uint64_t c_mask = 0; 2739 ib_gid_t *gid_ptr = NULL; 2740 ib_gid_t *sgids_p = NULL, *dgids_p = NULL; 2741 ib_gid_t cur_dgid, cur_sgid; 2742 ib_gid_t new_dgid, new_sgid; 2743 ibmf_saa_handle_t saa_handle; 2744 size_t length; 2745 int i, j, template_len, rec_found; 2746 uint_t snum = 0, dnum = 0, num_rec; 2747 ibt_status_t retval; 2748 ib_mtu_t prim_mtu; 2749 2750 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path(%p, %x, %p, %p)", 2751 rc_chan, flags, attrp, api_p); 2752 2753 /* validate channel */ 2754 if (IBCM_INVALID_CHANNEL(rc_chan)) { 2755 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: invalid channel"); 2756 return (IBT_CHAN_HDL_INVALID); 2757 } 2758 2759 if (api_p == NULL) { 2760 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: invalid attribute: " 2761 " AltPathInfo can't be NULL"); 2762 return (IBT_INVALID_PARAM); 2763 } 2764 2765 retval = ibt_query_qp(rc_chan, &qp_attr); 2766 if (retval != IBT_SUCCESS) { 2767 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: ibt_query_qp(%p) " 2768 "failed %d", rc_chan, retval); 2769 return (retval); 2770 } 2771 2772 if (qp_attr.qp_info.qp_trans != IBT_RC_SRV) { 2773 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: " 2774 "Invalid Channel type: Applicable only to RC Channel"); 2775 return (IBT_CHAN_SRV_TYPE_INVALID); 2776 } 2777 2778 cur_dgid = 2779 qp_attr.qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dgid; 2780 cur_sgid = 2781 qp_attr.qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_sgid; 2782 prim_mtu = qp_attr.qp_info.qp_transport.rc.rc_path_mtu; 2783 2784 /* If optional attributes are specified, validate them. */ 2785 if (attrp) { 2786 new_dgid = attrp->apa_dgid; 2787 new_sgid = attrp->apa_sgid; 2788 } else { 2789 new_dgid.gid_prefix = 0; 2790 new_dgid.gid_guid = 0; 2791 new_sgid.gid_prefix = 0; 2792 new_sgid.gid_guid = 0; 2793 } 2794 2795 if ((new_dgid.gid_prefix != 0) && (new_sgid.gid_prefix != 0) && 2796 (new_dgid.gid_prefix != new_sgid.gid_prefix)) { 2797 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: Specified SGID's " 2798 "SNprefix (%llX) doesn't match with \n specified DGID's " 2799 "SNprefix: %llX", new_sgid.gid_prefix, new_dgid.gid_prefix); 2800 return (IBT_INVALID_PARAM); 2801 } 2802 2803 /* For the specified SGID, get HCA information. */ 2804 retval = ibtl_cm_get_hca_port(cur_sgid, 0, &c_hp); 2805 if (retval != IBT_SUCCESS) { 2806 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: " 2807 "Get HCA Port Failed: %d", retval); 2808 return (retval); 2809 } 2810 2811 hcap = ibcm_find_hca_entry(c_hp.hp_hca_guid); 2812 if (hcap == NULL) { 2813 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: NO HCA found"); 2814 return (IBT_HCA_BUSY_DETACHING); 2815 } 2816 2817 /* Validate whether this HCA support APM */ 2818 if (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)) { 2819 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: " 2820 "HCA (%llX) - APM NOT SUPPORTED ", c_hp.hp_hca_guid); 2821 retval = IBT_APM_NOT_SUPPORTED; 2822 goto get_alt_path_done; 2823 } 2824 2825 /* Get Companion Port GID of the current Channel's SGID */ 2826 if ((new_sgid.gid_guid == 0) || ((new_sgid.gid_guid != 0) && 2827 (new_sgid.gid_guid != cur_sgid.gid_guid))) { 2828 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: SRC: " 2829 "Get Companion PortGids for - %llX:%llX", 2830 cur_sgid.gid_prefix, cur_sgid.gid_guid); 2831 2832 retval = ibcm_get_comp_pgids(cur_sgid, new_sgid, 2833 c_hp.hp_hca_guid, &sgids_p, &snum); 2834 if (retval != IBT_SUCCESS) 2835 goto get_alt_path_done; 2836 } 2837 2838 /* Get Companion Port GID of the current Channel's DGID */ 2839 if ((new_dgid.gid_guid == 0) || ((new_dgid.gid_guid != 0) && 2840 (new_dgid.gid_guid != cur_dgid.gid_guid))) { 2841 2842 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: DEST: " 2843 "Get Companion PortGids for - %llX:%llX", 2844 cur_dgid.gid_prefix, cur_dgid.gid_guid); 2845 2846 retval = ibcm_get_comp_pgids(cur_dgid, new_dgid, 0, &dgids_p, 2847 &dnum); 2848 if (retval != IBT_SUCCESS) 2849 goto get_alt_path_done; 2850 } 2851 2852 if ((new_dgid.gid_guid == 0) || (new_sgid.gid_guid == 0)) { 2853 if (new_sgid.gid_guid == 0) { 2854 for (i = 0; i < snum; i++) { 2855 if (new_dgid.gid_guid == 0) { 2856 for (j = 0; j < dnum; j++) { 2857 if (sgids_p[i].gid_prefix == 2858 dgids_p[j].gid_prefix) { 2859 new_dgid = dgids_p[j]; 2860 new_sgid = sgids_p[i]; 2861 2862 goto get_alt_proceed; 2863 } 2864 } 2865 /* Current DGID */ 2866 if (sgids_p[i].gid_prefix == 2867 cur_dgid.gid_prefix) { 2868 new_sgid = sgids_p[i]; 2869 goto get_alt_proceed; 2870 } 2871 } else { 2872 if (sgids_p[i].gid_prefix == 2873 new_dgid.gid_prefix) { 2874 new_sgid = sgids_p[i]; 2875 goto get_alt_proceed; 2876 } 2877 } 2878 } 2879 /* Current SGID */ 2880 if (new_dgid.gid_guid == 0) { 2881 for (j = 0; j < dnum; j++) { 2882 if (cur_sgid.gid_prefix == 2883 dgids_p[j].gid_prefix) { 2884 new_dgid = dgids_p[j]; 2885 2886 goto get_alt_proceed; 2887 } 2888 } 2889 } 2890 } else if (new_dgid.gid_guid == 0) { 2891 for (i = 0; i < dnum; i++) { 2892 if (dgids_p[i].gid_prefix == 2893 new_sgid.gid_prefix) { 2894 new_dgid = dgids_p[i]; 2895 goto get_alt_proceed; 2896 } 2897 } 2898 /* Current DGID */ 2899 if (cur_dgid.gid_prefix == new_sgid.gid_prefix) { 2900 goto get_alt_proceed; 2901 } 2902 } 2903 /* 2904 * hmm... No Companion Ports available. 2905 * so we will be using current or specified attributes only. 2906 */ 2907 } 2908 2909 get_alt_proceed: 2910 2911 if (new_sgid.gid_guid != 0) { 2912 retval = ibtl_cm_get_hca_port(new_sgid, 0, &n_hp); 2913 if (retval != IBT_SUCCESS) { 2914 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: " 2915 "Get HCA Port Failed: %d", retval); 2916 goto get_alt_path_done; 2917 } 2918 } 2919 2920 /* Calculate the size for multi-path records template */ 2921 template_len = (2 * sizeof (ib_gid_t)) + sizeof (sa_multipath_record_t); 2922 2923 mpr_req = kmem_zalloc(template_len, KM_SLEEP); 2924 2925 ASSERT(mpr_req != NULL); 2926 2927 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req)) 2928 2929 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) + 2930 sizeof (sa_multipath_record_t)); 2931 2932 /* SGID */ 2933 if (new_sgid.gid_guid == 0) 2934 *gid_ptr = cur_sgid; 2935 else 2936 *gid_ptr = new_sgid; 2937 2938 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Get Path Between " 2939 " SGID : %llX:%llX", gid_ptr->gid_prefix, gid_ptr->gid_guid); 2940 2941 gid_ptr++; 2942 2943 /* DGID */ 2944 if (new_dgid.gid_guid == 0) 2945 *gid_ptr = cur_dgid; 2946 else 2947 *gid_ptr = new_dgid; 2948 2949 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path:\t\t DGID : %llX:%llX", 2950 gid_ptr->gid_prefix, gid_ptr->gid_guid); 2951 2952 mpr_req->SGIDCount = 1; 2953 c_mask = SA_MPR_COMPMASK_SGIDCOUNT; 2954 2955 mpr_req->DGIDCount = 1; 2956 c_mask |= SA_MPR_COMPMASK_DGIDCOUNT; 2957 2958 /* Is Flow Label Specified. */ 2959 if (attrp) { 2960 if (attrp->apa_flow) { 2961 mpr_req->FlowLabel = attrp->apa_flow; 2962 c_mask |= SA_MPR_COMPMASK_FLOWLABEL; 2963 } 2964 2965 /* Is HopLimit Specified. */ 2966 if (flags & IBT_PATH_HOP) { 2967 mpr_req->HopLimit = attrp->apa_hop; 2968 c_mask |= SA_MPR_COMPMASK_HOPLIMIT; 2969 } 2970 2971 /* Is TClass Specified. */ 2972 if (attrp->apa_tclass) { 2973 mpr_req->TClass = attrp->apa_tclass; 2974 c_mask |= SA_MPR_COMPMASK_TCLASS; 2975 } 2976 2977 /* Is SL specified. */ 2978 if (attrp->apa_sl) { 2979 mpr_req->SL = attrp->apa_sl; 2980 c_mask |= SA_MPR_COMPMASK_SL; 2981 } 2982 2983 if (flags & IBT_PATH_PERF) { 2984 mpr_req->PacketLifeTimeSelector = IBT_BEST; 2985 mpr_req->RateSelector = IBT_BEST; 2986 2987 c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR | 2988 SA_MPR_COMPMASK_RATESELECTOR; 2989 } else { 2990 if (attrp->apa_pkt_lt.p_selector == IBT_BEST) { 2991 mpr_req->PacketLifeTimeSelector = IBT_BEST; 2992 c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR; 2993 } 2994 2995 if (attrp->apa_srate.r_selector == IBT_BEST) { 2996 mpr_req->RateSelector = IBT_BEST; 2997 c_mask |= SA_MPR_COMPMASK_RATESELECTOR; 2998 } 2999 } 3000 3001 /* 3002 * Honor individual selection of these attributes, 3003 * even if IBT_PATH_PERF is set. 3004 */ 3005 /* Check out whether Packet Life Time is specified. */ 3006 if (attrp->apa_pkt_lt.p_pkt_lt) { 3007 mpr_req->PacketLifeTime = 3008 ibt_usec2ib(attrp->apa_pkt_lt.p_pkt_lt); 3009 mpr_req->PacketLifeTimeSelector = 3010 attrp->apa_pkt_lt.p_selector; 3011 3012 c_mask |= SA_MPR_COMPMASK_PKTLT | 3013 SA_MPR_COMPMASK_PKTLTSELECTOR; 3014 } 3015 3016 /* Is SRATE specified. */ 3017 if (attrp->apa_srate.r_srate) { 3018 mpr_req->Rate = attrp->apa_srate.r_srate; 3019 mpr_req->RateSelector = attrp->apa_srate.r_selector; 3020 3021 c_mask |= SA_MPR_COMPMASK_RATE | 3022 SA_MPR_COMPMASK_RATESELECTOR; 3023 } 3024 } 3025 3026 /* Alt PathMTU can be GT or EQU to current channel's Pri PathMTU */ 3027 3028 /* P_Key must be same as that of primary path */ 3029 retval = ibt_index2pkey_byguid(c_hp.hp_hca_guid, c_hp.hp_port, 3030 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix, 3031 &mpr_req->P_Key); 3032 if (retval != IBT_SUCCESS) { 3033 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: Idx2Pkey Failed: %d", 3034 retval); 3035 goto get_alt_path_done; 3036 } 3037 c_mask |= SA_MPR_COMPMASK_PKEY; 3038 3039 mpr_req->Reversible = 1; /* We always get REVERSIBLE paths. */ 3040 mpr_req->IndependenceSelector = 1; 3041 c_mask |= SA_MPR_COMPMASK_REVERSIBLE | SA_MPR_COMPMASK_INDEPSEL; 3042 3043 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req)) 3044 3045 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: CMask: 0x%llX", c_mask); 3046 3047 /* NOTE: We will **NOT** specify how many records we want. */ 3048 3049 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Primary: MTU %d, PKey[%d]=" 3050 "0x%X\n\tSGID = %llX:%llX, DGID = %llX:%llX", prim_mtu, 3051 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix, mpr_req->P_Key, 3052 cur_sgid.gid_prefix, cur_sgid.gid_guid, cur_dgid.gid_prefix, 3053 cur_dgid.gid_guid); 3054 3055 /* Get SA Access Handle. */ 3056 if (new_sgid.gid_guid != 0) 3057 saa_handle = ibcm_get_saa_handle(hcap, n_hp.hp_port); 3058 else 3059 saa_handle = ibcm_get_saa_handle(hcap, c_hp.hp_port); 3060 if (saa_handle == NULL) { 3061 retval = IBT_HCA_PORT_NOT_ACTIVE; 3062 goto get_alt_path_done; 3063 } 3064 3065 /* Contact SA Access to retrieve Path Records. */ 3066 access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID; 3067 access_args.sq_access_type = IBMF_SAA_RETRIEVE; 3068 access_args.sq_component_mask = c_mask; 3069 access_args.sq_template = mpr_req; 3070 access_args.sq_template_length = sizeof (sa_multipath_record_t); 3071 access_args.sq_callback = NULL; 3072 access_args.sq_callback_arg = NULL; 3073 3074 retval = ibcm_contact_sa_access(saa_handle, &access_args, &length, 3075 &results_p); 3076 if (retval != IBT_SUCCESS) { 3077 goto get_alt_path_done; 3078 } 3079 3080 num_rec = length / sizeof (sa_path_record_t); 3081 3082 kmem_free(mpr_req, template_len); 3083 3084 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Found %d Paths", num_rec); 3085 3086 rec_found = 0; 3087 if ((results_p != NULL) && (num_rec > 0)) { 3088 /* Update the PathInfo with the response Path Records */ 3089 pr_resp = (sa_path_record_t *)results_p; 3090 for (i = 0; i < num_rec; i++, pr_resp++) { 3091 if (prim_mtu > pr_resp->Mtu) { 3092 IBTF_DPRINTF_L2(cmlog, "ibt_get_alt_path: " 3093 "Alt PathMTU(%d) must be GT or EQU to Pri " 3094 "PathMTU(%d). Ignore this rec", 3095 pr_resp->Mtu, prim_mtu); 3096 continue; 3097 } 3098 3099 if ((new_sgid.gid_guid == 0) && 3100 (new_dgid.gid_guid == 0)) { 3101 /* Reject PathRec if it same as Primary Path. */ 3102 if (ibcm_compare_paths(pr_resp, 3103 &qp_attr.qp_info.qp_transport.rc.rc_path, 3104 &c_hp) == B_TRUE) { 3105 IBTF_DPRINTF_L3(cmlog, 3106 "ibt_get_alt_path: PathRec obtained" 3107 " is similar to Prim Path, ignore " 3108 "this record"); 3109 continue; 3110 } 3111 } 3112 3113 if (new_sgid.gid_guid == 0) { 3114 retval = ibcm_update_cep_info(pr_resp, NULL, 3115 &c_hp, &api_p->ap_alt_cep_path); 3116 } else { 3117 retval = ibcm_update_cep_info(pr_resp, NULL, 3118 &n_hp, &api_p->ap_alt_cep_path); 3119 } 3120 if (retval != IBT_SUCCESS) 3121 continue; 3122 3123 /* Update some leftovers */ 3124 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*api_p)) 3125 3126 api_p->ap_alt_pkt_lt = pr_resp->PacketLifeTime; 3127 3128 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*api_p)) 3129 3130 rec_found = 1; 3131 break; 3132 } 3133 kmem_free(results_p, length); 3134 } 3135 3136 if (rec_found == 0) { 3137 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Alternate Path cannot" 3138 " be established"); 3139 retval = IBT_PATH_RECORDS_NOT_FOUND; 3140 } else 3141 retval = IBT_SUCCESS; 3142 3143 get_alt_path_done: 3144 if ((snum) && (sgids_p)) 3145 kmem_free(sgids_p, snum * sizeof (ib_gid_t)); 3146 3147 if ((dnum) && (dgids_p)) 3148 kmem_free(dgids_p, dnum * sizeof (ib_gid_t)); 3149 3150 ibcm_dec_hca_acc_cnt(hcap); 3151 3152 IBTF_DPRINTF_L3(cmlog, "ibt_get_alt_path: Done (status %d).", retval); 3153 3154 return (retval); 3155 } 3156 3157 3158 3159 /* 3160 * IP Path API 3161 */ 3162 3163 typedef struct ibcm_ip_path_tqargs_s { 3164 ibt_ip_path_attr_t attr; 3165 ibt_path_info_t *paths; 3166 ibt_path_ip_src_t *src_ip_p; 3167 uint8_t *num_paths_p; 3168 ibt_ip_path_handler_t func; 3169 void *arg; 3170 ibt_path_flags_t flags; 3171 ibt_clnt_hdl_t ibt_hdl; 3172 kmutex_t ip_lock; 3173 kcondvar_t ip_cv; 3174 ibt_status_t retval; 3175 uint_t len; 3176 } ibcm_ip_path_tqargs_t; 3177 3178 typedef struct ibcm_ip_dest_s { 3179 ib_gid_t d_gid; 3180 uint_t d_tag; /* 0 = Unicast, 2 = LoopBack */ 3181 ibt_ip_addr_t d_ip; 3182 } ibcm_ip_dest_t; 3183 3184 /* Holds destination information needed to fill in ibt_path_info_t. */ 3185 typedef struct ibcm_ip_dinfo_s { 3186 uint8_t num_dest; 3187 ibcm_ip_dest_t dest[1]; 3188 } ibcm_ip_dinfo_t; 3189 3190 _NOTE(SCHEME_PROTECTS_DATA("Temporary path storage", ibcm_ip_dinfo_s)) 3191 3192 /* Prototype Declarations. */ 3193 static void ibcm_process_get_ip_paths(void *tq_arg); 3194 static ibt_status_t ibcm_get_ip_spr(ibcm_ip_path_tqargs_t *, 3195 ibtl_cm_port_list_t *, ibcm_ip_dinfo_t *, uint8_t *, ibt_path_info_t *); 3196 static ibt_status_t ibcm_get_ip_mpr(ibcm_ip_path_tqargs_t *, 3197 ibtl_cm_port_list_t *, ibcm_ip_dinfo_t *dinfo, 3198 uint8_t *, ibt_path_info_t *); 3199 static ibt_status_t ibcm_fillin_ip_lbpr(ibtl_cm_port_list_t *, uint8_t index, 3200 ibcm_ip_dinfo_t *, ibt_path_info_t *); 3201 3202 /* 3203 * Perform SA Access to retrieve Path Records. 3204 */ 3205 static ibt_status_t 3206 ibcm_saa_ip_pr(ibcm_ip_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl, 3207 ibcm_ip_dinfo_t *dinfo, uint8_t *max_count) 3208 { 3209 uint8_t num_path = *max_count; 3210 uint8_t num_path_plus; 3211 uint_t extra, idx, rec_found = 0; 3212 ibt_status_t retval = IBT_SUCCESS; 3213 int dgid_present = 0; 3214 uint8_t i, j; 3215 3216 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_ip_pr(%p, %p, %p, 0x%X, %d)", 3217 p_arg, sl, dinfo, p_arg->flags, *max_count); 3218 3219 if ((dinfo->num_dest == 0) || (num_path == 0) || (sl == NULL)) { 3220 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_ip_pr: Invalid Counters"); 3221 return (IBT_INVALID_PARAM); 3222 } 3223 3224 /* 3225 * Of the total needed "X" number of paths to "Y" number of destination 3226 * we need to get X/Y plus X%Y extra paths to each destination, 3227 * We do this so that we can choose the required number of path records 3228 * for the specific destination. 3229 */ 3230 num_path /= dinfo->num_dest; 3231 extra = (*max_count % dinfo->num_dest); 3232 3233 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_ip_pr: numpath %d extra %d dest %d", 3234 num_path, extra, dinfo->num_dest); 3235 3236 /* 3237 * Find out whether we need to get PathRecord that qualifies for a 3238 * LoopBack. 3239 */ 3240 for (idx = 0; idx < dinfo->num_dest; idx++) { 3241 ib_gid_t dgid = dinfo->dest[idx].d_gid; 3242 3243 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_ip_pr: DGID[%d]: %llX:%llX", 3244 idx, dgid.gid_prefix, dgid.gid_guid); 3245 3246 /* 3247 * For loop-back path record, we should NOT contact SA Access. 3248 * But instead we need to "synthesize" a loop back path record. 3249 */ 3250 for (i = 0; i < sl->p_count; i++) { 3251 if ((sl[i].p_sgid.gid_prefix == dgid.gid_prefix) && 3252 (sl[i].p_sgid.gid_guid == dgid.gid_guid)) { 3253 3254 dinfo->dest[idx].d_tag = 2; 3255 3256 /* Yes, it's loop back case. */ 3257 retval = ibcm_fillin_ip_lbpr(&sl[i], idx, 3258 dinfo, &p_arg->paths[rec_found]); 3259 if (retval != IBT_SUCCESS) 3260 break; 3261 3262 /* 3263 * We update only one record for loop-back case. 3264 */ 3265 rec_found++; 3266 if (rec_found == *max_count) 3267 break; 3268 } 3269 } 3270 if (rec_found == *max_count) 3271 break; 3272 } 3273 3274 for (i = 0; i < dinfo->num_dest; i++) 3275 if (dinfo->dest[i].d_tag == 0) 3276 dgid_present++; 3277 3278 num_path_plus = *max_count - rec_found; 3279 3280 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_ip_pr: Recfound: %d, need to find " 3281 "%d, GID present %d", rec_found, num_path_plus, dgid_present); 3282 3283 if ((dgid_present != 0) && (num_path_plus > 0)) { 3284 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_ip_pr: MultiSM=%X, #SRC=%d, " 3285 "Dest=%d", sl->p_multi, sl->p_count, dgid_present); 3286 3287 if ((sl->p_multi != IBTL_CM_SIMPLE_SETUP) || 3288 ((dgid_present == 1) && (sl->p_count == 1))) { 3289 /* 3290 * Use SinglePathRec if we are dealing w/ MultiSM or 3291 * request is for one SGID to one DGID. 3292 */ 3293 retval = ibcm_get_ip_spr(p_arg, sl, dinfo, 3294 &num_path_plus, &p_arg->paths[rec_found]); 3295 } else { 3296 /* MultiPathRec will be used for other queries. */ 3297 retval = ibcm_get_ip_mpr(p_arg, sl, dinfo, 3298 &num_path_plus, &p_arg->paths[rec_found]); 3299 } 3300 3301 if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA)) 3302 IBTF_DPRINTF_L2(cmlog, "ibcm_saa_ip_pr: " 3303 "Failed to get PathRec: Status %d", retval); 3304 else 3305 rec_found += num_path_plus; 3306 } 3307 3308 if (rec_found == 0) { 3309 if (retval == IBT_SUCCESS) 3310 retval = IBT_PATH_RECORDS_NOT_FOUND; 3311 } else if (rec_found != *max_count) 3312 retval = IBT_INSUFF_DATA; 3313 else if (rec_found != 0) 3314 retval = IBT_SUCCESS; 3315 3316 if ((p_arg->src_ip_p != NULL) && (rec_found != 0)) { 3317 for (i = 0; i < rec_found; i++) { 3318 for (j = 0; j < sl->p_count; j++) { 3319 if (sl[j].p_sgid.gid_guid == p_arg->paths[i]. 3320 pi_prim_cep_path.cep_adds_vect. 3321 av_sgid.gid_guid) { 3322 bcopy(&sl[j].p_src_ip, 3323 &p_arg->src_ip_p[i].ip_primary, 3324 sizeof (ibt_ip_addr_t)); 3325 } 3326 /* Is Alt Path present */ 3327 if (p_arg->paths[i].pi_alt_cep_path. 3328 cep_hca_port_num) { 3329 if (sl[j].p_sgid.gid_guid == 3330 p_arg->paths[i].pi_alt_cep_path. 3331 cep_adds_vect.av_sgid.gid_guid) { 3332 bcopy(&sl[j].p_src_ip, 3333 &p_arg->src_ip_p[i]. 3334 ip_alternate, 3335 sizeof (ibt_ip_addr_t)); 3336 } 3337 } 3338 } 3339 } 3340 } 3341 IBTF_DPRINTF_L3(cmlog, "ibcm_saa_ip_pr: done. Status = %d, " 3342 "Found %d/%d Paths", retval, rec_found, *max_count); 3343 3344 *max_count = rec_found; /* Update the return count. */ 3345 3346 return (retval); 3347 } 3348 3349 static ibt_status_t 3350 ibcm_ip_update_pri(sa_path_record_t *pr_resp, ibtl_cm_port_list_t *sl, 3351 ibt_path_info_t *paths) 3352 { 3353 ibt_status_t retval = IBT_SUCCESS; 3354 int s; 3355 3356 retval = ibcm_update_cep_info(pr_resp, sl, NULL, 3357 &paths->pi_prim_cep_path); 3358 if (retval != IBT_SUCCESS) 3359 return (retval); 3360 3361 /* Update some leftovers */ 3362 paths->pi_prim_pkt_lt = pr_resp->PacketLifeTime; 3363 paths->pi_path_mtu = pr_resp->Mtu; 3364 3365 for (s = 0; s < sl->p_count; s++) { 3366 if (pr_resp->SGID.gid_guid == sl[s].p_sgid.gid_guid) 3367 paths->pi_hca_guid = sl[s].p_hca_guid; 3368 } 3369 3370 /* Set Alternate Path to invalid state. */ 3371 paths->pi_alt_cep_path.cep_hca_port_num = 0; 3372 paths->pi_alt_cep_path.cep_adds_vect.av_dlid = 0; 3373 3374 IBTF_DPRINTF_L5(cmlog, "ibcm_ip_update_pri: Path HCA GUID 0x%llX", 3375 paths->pi_hca_guid); 3376 3377 return (retval); 3378 } 3379 3380 3381 static ibt_status_t 3382 ibcm_get_ip_spr(ibcm_ip_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl, 3383 ibcm_ip_dinfo_t *dinfo, uint8_t *num_path, ibt_path_info_t *paths) 3384 { 3385 sa_path_record_t pathrec_req; 3386 sa_path_record_t *pr_resp; 3387 ibmf_saa_access_args_t access_args; 3388 uint64_t c_mask = 0; 3389 void *results_p; 3390 uint8_t num_rec; 3391 size_t length; 3392 ibt_status_t retval; 3393 int i, j, k; 3394 int found, p_fnd; 3395 ibt_ip_path_attr_t *attrp = &p_arg->attr; 3396 ibmf_saa_handle_t saa_handle; 3397 3398 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr(%p, %p, %p, %d)", 3399 p_arg, sl, dinfo, *num_path); 3400 3401 bzero(&pathrec_req, sizeof (sa_path_record_t)); 3402 3403 /* Is Flow Label Specified. */ 3404 if (attrp->ipa_flow) { 3405 pathrec_req.FlowLabel = attrp->ipa_flow; 3406 c_mask |= SA_PR_COMPMASK_FLOWLABEL; 3407 } 3408 3409 /* Is HopLimit Specified. */ 3410 if (p_arg->flags & IBT_PATH_HOP) { 3411 pathrec_req.HopLimit = attrp->ipa_hop; 3412 c_mask |= SA_PR_COMPMASK_HOPLIMIT; 3413 } 3414 3415 /* Is TClass Specified. */ 3416 if (attrp->ipa_tclass) { 3417 pathrec_req.TClass = attrp->ipa_tclass; 3418 c_mask |= SA_PR_COMPMASK_TCLASS; 3419 } 3420 3421 /* Is SL specified. */ 3422 if (attrp->ipa_sl) { 3423 pathrec_req.SL = attrp->ipa_sl; 3424 c_mask |= SA_PR_COMPMASK_SL; 3425 } 3426 3427 /* If IBT_PATH_PERF is set, then mark all selectors to BEST. */ 3428 if (p_arg->flags & IBT_PATH_PERF) { 3429 pathrec_req.PacketLifeTimeSelector = IBT_BEST; 3430 pathrec_req.MtuSelector = IBT_BEST; 3431 pathrec_req.RateSelector = IBT_BEST; 3432 3433 c_mask |= SA_PR_COMPMASK_PKTLTSELECTOR | 3434 SA_PR_COMPMASK_RATESELECTOR | SA_PR_COMPMASK_MTUSELECTOR; 3435 } else { 3436 if (attrp->ipa_pkt_lt.p_selector == IBT_BEST) { 3437 pathrec_req.PacketLifeTimeSelector = IBT_BEST; 3438 c_mask |= SA_PR_COMPMASK_PKTLTSELECTOR; 3439 } 3440 3441 if (attrp->ipa_srate.r_selector == IBT_BEST) { 3442 pathrec_req.RateSelector = IBT_BEST; 3443 c_mask |= SA_PR_COMPMASK_RATESELECTOR; 3444 } 3445 3446 if (attrp->ipa_mtu.r_selector == IBT_BEST) { 3447 pathrec_req.MtuSelector = IBT_BEST; 3448 c_mask |= SA_PR_COMPMASK_MTUSELECTOR; 3449 } 3450 } 3451 3452 /* 3453 * Honor individual selection of these attributes, 3454 * even if IBT_PATH_PERF is set. 3455 */ 3456 /* Check out whether Packet Life Time is specified. */ 3457 if (attrp->ipa_pkt_lt.p_pkt_lt) { 3458 pathrec_req.PacketLifeTime = 3459 ibt_usec2ib(attrp->ipa_pkt_lt.p_pkt_lt); 3460 pathrec_req.PacketLifeTimeSelector = 3461 attrp->ipa_pkt_lt.p_selector; 3462 3463 c_mask |= SA_PR_COMPMASK_PKTLT | SA_PR_COMPMASK_PKTLTSELECTOR; 3464 } 3465 3466 /* Is SRATE specified. */ 3467 if (attrp->ipa_srate.r_srate) { 3468 pathrec_req.Rate = attrp->ipa_srate.r_srate; 3469 pathrec_req.RateSelector = attrp->ipa_srate.r_selector; 3470 3471 c_mask |= SA_PR_COMPMASK_RATE | SA_PR_COMPMASK_RATESELECTOR; 3472 } 3473 3474 /* Is MTU specified. */ 3475 if (attrp->ipa_mtu.r_mtu) { 3476 pathrec_req.Mtu = attrp->ipa_mtu.r_mtu; 3477 pathrec_req.MtuSelector = attrp->ipa_mtu.r_selector; 3478 3479 c_mask |= SA_PR_COMPMASK_MTU | SA_PR_COMPMASK_MTUSELECTOR; 3480 } 3481 3482 /* We always get REVERSIBLE paths. */ 3483 pathrec_req.Reversible = 1; 3484 c_mask |= SA_PR_COMPMASK_REVERSIBLE; 3485 3486 pathrec_req.NumbPath = *num_path; 3487 c_mask |= SA_PR_COMPMASK_NUMBPATH; 3488 3489 p_fnd = found = 0; 3490 3491 for (i = 0; i < sl->p_count; i++) { 3492 /* SGID */ 3493 pathrec_req.SGID = sl[i].p_sgid; 3494 c_mask |= SA_PR_COMPMASK_SGID; 3495 saa_handle = sl[i].p_saa_hdl; 3496 3497 for (k = 0; k < dinfo->num_dest; k++) { 3498 if (dinfo->dest[k].d_tag != 0) 3499 continue; 3500 3501 if (pathrec_req.SGID.gid_prefix != 3502 dinfo->dest[k].d_gid.gid_prefix) { 3503 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: " 3504 "SGID_pfx=%llX DGID_pfx=%llX doesn't match", 3505 pathrec_req.SGID.gid_prefix, 3506 dinfo->dest[k].d_gid.gid_prefix); 3507 continue; 3508 } else if (pathrec_req.SGID.gid_guid == 3509 pathrec_req.DGID.gid_guid) { 3510 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: Why " 3511 "LoopBack request came here! GID %llX:%llX", 3512 pathrec_req.SGID.gid_prefix, 3513 pathrec_req.SGID.gid_guid); 3514 continue; 3515 } 3516 3517 pathrec_req.DGID = dinfo->dest[k].d_gid; 3518 c_mask |= SA_PR_COMPMASK_DGID; 3519 3520 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: " 3521 "Get %d Path(s) between\n SGID %llX:%llX " 3522 "DGID %llX:%llX", pathrec_req.NumbPath, 3523 pathrec_req.SGID.gid_prefix, 3524 pathrec_req.SGID.gid_guid, 3525 pathrec_req.DGID.gid_prefix, 3526 pathrec_req.DGID.gid_guid); 3527 3528 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: CMask=0x%llX, " 3529 "PKey=0x%X", c_mask, pathrec_req.P_Key); 3530 3531 /* Contact SA Access to retrieve Path Records. */ 3532 access_args.sq_attr_id = SA_PATHRECORD_ATTRID; 3533 access_args.sq_template = &pathrec_req; 3534 access_args.sq_access_type = IBMF_SAA_RETRIEVE; 3535 access_args.sq_template_length = 3536 sizeof (sa_path_record_t); 3537 access_args.sq_component_mask = c_mask; 3538 access_args.sq_callback = NULL; 3539 access_args.sq_callback_arg = NULL; 3540 3541 retval = ibcm_contact_sa_access(saa_handle, 3542 &access_args, &length, &results_p); 3543 if (retval != IBT_SUCCESS) { 3544 *num_path = 0; 3545 return (retval); 3546 } 3547 3548 num_rec = length / sizeof (sa_path_record_t); 3549 3550 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: " 3551 "FOUND %d/%d path requested", num_rec, *num_path); 3552 3553 if ((results_p == NULL) || (num_rec == 0)) 3554 continue; 3555 3556 /* Update the PathInfo from the response. */ 3557 pr_resp = (sa_path_record_t *)results_p; 3558 for (j = 0; j < num_rec; j++, pr_resp++) { 3559 if ((p_fnd != 0) && 3560 (p_arg->flags & IBT_PATH_APM)) { 3561 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr" 3562 ": Fill Alternate Path"); 3563 retval = ibcm_update_cep_info(pr_resp, 3564 sl, NULL, 3565 &paths[found - 1].pi_alt_cep_path); 3566 if (retval != IBT_SUCCESS) 3567 continue; 3568 3569 /* Update some leftovers */ 3570 paths[found - 1].pi_alt_pkt_lt = 3571 pr_resp->PacketLifeTime; 3572 p_fnd = 0; 3573 } else { 3574 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr" 3575 ": Fill Primary Path"); 3576 3577 if (found == *num_path) 3578 break; 3579 3580 retval = ibcm_ip_update_pri(pr_resp, sl, 3581 &paths[found]); 3582 if (retval != IBT_SUCCESS) 3583 continue; 3584 p_fnd = 1; 3585 found++; 3586 } 3587 3588 } 3589 /* Deallocate the memory for results_p. */ 3590 kmem_free(results_p, length); 3591 } 3592 } 3593 3594 if (found == 0) 3595 retval = IBT_PATH_RECORDS_NOT_FOUND; 3596 else if (found != *num_path) 3597 retval = IBT_INSUFF_DATA; 3598 else 3599 retval = IBT_SUCCESS; 3600 3601 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_spr: done. Status %d, " 3602 "Found %d/%d Paths", retval, found, *num_path); 3603 3604 *num_path = found; 3605 3606 return (retval); 3607 } 3608 3609 3610 static ibt_status_t 3611 ibcm_get_ip_mpr(ibcm_ip_path_tqargs_t *p_arg, ibtl_cm_port_list_t *sl, 3612 ibcm_ip_dinfo_t *dinfo, uint8_t *num_path, ibt_path_info_t *paths) 3613 { 3614 sa_multipath_record_t *mpr_req; 3615 sa_path_record_t *pr_resp; 3616 ibmf_saa_access_args_t access_args; 3617 void *results_p; 3618 uint64_t c_mask = 0; 3619 ib_gid_t *gid_ptr, *gid_s_ptr; 3620 size_t length; 3621 int template_len, found, num_rec; 3622 int i; 3623 ibt_status_t retval; 3624 uint8_t sgid_cnt, dgid_cnt; 3625 ibt_ip_path_attr_t *attrp = &p_arg->attr; 3626 3627 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr(%p, %p, %p, %d)", 3628 attrp, sl, dinfo, *num_path); 3629 3630 for (i = 0, dgid_cnt = 0; i < dinfo->num_dest; i++) { 3631 if (dinfo->dest[i].d_tag == 0) 3632 dgid_cnt++; 3633 } 3634 3635 sgid_cnt = sl->p_count; 3636 3637 if ((sgid_cnt == 0) || (dgid_cnt == 0)) { 3638 IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_mpr: sgid_cnt(%d) or" 3639 " dgid_cnt(%d) is zero", sgid_cnt, dgid_cnt); 3640 return (IBT_INVALID_PARAM); 3641 } 3642 3643 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: Get %d records between " 3644 "%d Src(s) <=> %d Dest(s)", *num_path, sgid_cnt, dgid_cnt); 3645 3646 /* 3647 * Calculate the size for multi-path records template, which includes 3648 * constant portion of the multipath record, plus variable size for 3649 * SGID (sgid_cnt) and DGID (dgid_cnt). 3650 */ 3651 template_len = ((dgid_cnt + sgid_cnt) * sizeof (ib_gid_t)) + 3652 sizeof (sa_multipath_record_t); 3653 3654 mpr_req = kmem_zalloc(template_len, KM_SLEEP); 3655 3656 ASSERT(mpr_req != NULL); 3657 3658 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) + 3659 sizeof (sa_multipath_record_t)); 3660 3661 /* Get the starting pointer where GIDs are stored. */ 3662 gid_s_ptr = gid_ptr; 3663 3664 /* SGID */ 3665 for (i = 0; i < sl->p_count; i++) { 3666 *gid_ptr = sl[i].p_sgid; 3667 3668 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: SGID[%d] = %llX:%llX", 3669 i, gid_ptr->gid_prefix, gid_ptr->gid_guid); 3670 3671 gid_ptr++; 3672 } 3673 3674 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req)) 3675 3676 mpr_req->SGIDCount = sgid_cnt; 3677 c_mask = SA_MPR_COMPMASK_SGIDCOUNT; 3678 3679 /* DGIDs */ 3680 for (i = 0; i < dinfo->num_dest; i++) { 3681 if (dinfo->dest[i].d_tag == 0) { 3682 *gid_ptr = dinfo->dest[i].d_gid; 3683 3684 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: DGID[%d] = " 3685 "%llX:%llX", i, gid_ptr->gid_prefix, 3686 gid_ptr->gid_guid); 3687 gid_ptr++; 3688 } 3689 } 3690 3691 mpr_req->DGIDCount = dgid_cnt; 3692 c_mask |= SA_MPR_COMPMASK_DGIDCOUNT; 3693 3694 /* Is Flow Label Specified. */ 3695 if (attrp->ipa_flow) { 3696 mpr_req->FlowLabel = attrp->ipa_flow; 3697 c_mask |= SA_MPR_COMPMASK_FLOWLABEL; 3698 } 3699 3700 /* Is HopLimit Specified. */ 3701 if (p_arg->flags & IBT_PATH_HOP) { 3702 mpr_req->HopLimit = attrp->ipa_hop; 3703 c_mask |= SA_MPR_COMPMASK_HOPLIMIT; 3704 } 3705 3706 /* Is TClass Specified. */ 3707 if (attrp->ipa_tclass) { 3708 mpr_req->TClass = attrp->ipa_tclass; 3709 c_mask |= SA_MPR_COMPMASK_TCLASS; 3710 } 3711 3712 /* Is SL specified. */ 3713 if (attrp->ipa_sl) { 3714 mpr_req->SL = attrp->ipa_sl; 3715 c_mask |= SA_MPR_COMPMASK_SL; 3716 } 3717 3718 if (p_arg->flags & IBT_PATH_PERF) { 3719 mpr_req->PacketLifeTimeSelector = IBT_BEST; 3720 mpr_req->RateSelector = IBT_BEST; 3721 mpr_req->MtuSelector = IBT_BEST; 3722 3723 c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR | 3724 SA_MPR_COMPMASK_RATESELECTOR | SA_MPR_COMPMASK_MTUSELECTOR; 3725 } else { 3726 if (attrp->ipa_pkt_lt.p_selector == IBT_BEST) { 3727 mpr_req->PacketLifeTimeSelector = IBT_BEST; 3728 c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR; 3729 } 3730 3731 if (attrp->ipa_srate.r_selector == IBT_BEST) { 3732 mpr_req->RateSelector = IBT_BEST; 3733 c_mask |= SA_MPR_COMPMASK_RATESELECTOR; 3734 } 3735 3736 if (attrp->ipa_mtu.r_selector == IBT_BEST) { 3737 mpr_req->MtuSelector = IBT_BEST; 3738 c_mask |= SA_MPR_COMPMASK_MTUSELECTOR; 3739 } 3740 } 3741 3742 /* 3743 * Honor individual selection of these attributes, 3744 * even if IBT_PATH_PERF is set. 3745 */ 3746 /* Check out whether Packet Life Time is specified. */ 3747 if (attrp->ipa_pkt_lt.p_pkt_lt) { 3748 mpr_req->PacketLifeTime = 3749 ibt_usec2ib(attrp->ipa_pkt_lt.p_pkt_lt); 3750 mpr_req->PacketLifeTimeSelector = 3751 attrp->ipa_pkt_lt.p_selector; 3752 3753 c_mask |= SA_MPR_COMPMASK_PKTLT | 3754 SA_MPR_COMPMASK_PKTLTSELECTOR; 3755 } 3756 3757 /* Is SRATE specified. */ 3758 if (attrp->ipa_srate.r_srate) { 3759 mpr_req->Rate = attrp->ipa_srate.r_srate; 3760 mpr_req->RateSelector = attrp->ipa_srate.r_selector; 3761 3762 c_mask |= SA_MPR_COMPMASK_RATE | 3763 SA_MPR_COMPMASK_RATESELECTOR; 3764 } 3765 3766 /* Is MTU specified. */ 3767 if (attrp->ipa_mtu.r_mtu) { 3768 mpr_req->Mtu = attrp->ipa_mtu.r_mtu; 3769 mpr_req->MtuSelector = attrp->ipa_mtu.r_selector; 3770 3771 c_mask |= SA_MPR_COMPMASK_MTU | 3772 SA_MPR_COMPMASK_MTUSELECTOR; 3773 } 3774 3775 /* We always get REVERSIBLE paths. */ 3776 mpr_req->Reversible = 1; 3777 c_mask |= SA_MPR_COMPMASK_REVERSIBLE; 3778 3779 if (p_arg->flags & IBT_PATH_AVAIL) { 3780 mpr_req->IndependenceSelector = 1; 3781 c_mask |= SA_MPR_COMPMASK_INDEPSEL; 3782 } 3783 3784 /* we will not specify how many records we want. */ 3785 3786 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req)) 3787 3788 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: CMask: %llX Pkey: %X", 3789 c_mask, mpr_req->P_Key); 3790 3791 /* Contact SA Access to retrieve Path Records. */ 3792 access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID; 3793 access_args.sq_access_type = IBMF_SAA_RETRIEVE; 3794 access_args.sq_component_mask = c_mask; 3795 access_args.sq_template = mpr_req; 3796 access_args.sq_template_length = sizeof (sa_multipath_record_t); 3797 access_args.sq_callback = NULL; 3798 access_args.sq_callback_arg = NULL; 3799 3800 retval = ibcm_contact_sa_access(sl->p_saa_hdl, &access_args, &length, 3801 &results_p); 3802 if (retval != IBT_SUCCESS) { 3803 *num_path = 0; /* Update the return count. */ 3804 kmem_free(mpr_req, template_len); 3805 return (retval); 3806 } 3807 3808 num_rec = length / sizeof (sa_path_record_t); 3809 3810 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: Found %d Paths", num_rec); 3811 3812 found = 0; 3813 if ((results_p != NULL) && (num_rec > 0)) { 3814 /* Update the PathInfo with the response Path Records */ 3815 pr_resp = (sa_path_record_t *)results_p; 3816 3817 for (i = 0; i < num_rec; i++) { 3818 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: " 3819 "P[%d]: SG %llX, DG %llX", i, 3820 pr_resp[i].SGID.gid_guid, pr_resp[i].DGID.gid_guid); 3821 } 3822 3823 if (p_arg->flags & IBT_PATH_APM) { 3824 sa_path_record_t *p_resp = NULL, *a_resp = NULL; 3825 int p_found = 0, a_found = 0; 3826 ib_gid_t p_sg, a_sg, p_dg, a_dg; 3827 int s_spec; 3828 3829 s_spec = 3830 p_arg->attr.ipa_src_ip.family != AF_UNSPEC ? 1 : 0; 3831 3832 p_sg = gid_s_ptr[0]; 3833 if (sgid_cnt > 1) 3834 a_sg = gid_s_ptr[1]; 3835 else 3836 a_sg = p_sg; 3837 3838 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: P_SG: %llX, " 3839 "A_SG: %llX", p_sg.gid_guid, a_sg.gid_guid); 3840 3841 p_dg = gid_s_ptr[sgid_cnt]; 3842 if (dgid_cnt > 1) 3843 a_dg = gid_s_ptr[sgid_cnt + 1]; 3844 else 3845 a_dg = p_dg; 3846 3847 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: P_DG: %llX, " 3848 "A_DG: %llX", p_dg.gid_guid, a_dg.gid_guid); 3849 3850 /* 3851 * If SGID and/or DGID is specified by user, make sure 3852 * he gets his primary-path on those node points. 3853 */ 3854 for (i = 0; i < num_rec; i++, pr_resp++) { 3855 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: " 3856 "PF %d, AF %d,\n\t\t P[%d] = SG: %llX, " 3857 "DG: %llX", p_found, a_found, i, 3858 pr_resp->SGID.gid_guid, 3859 pr_resp->DGID.gid_guid); 3860 3861 if ((!p_found) && 3862 (p_dg.gid_guid == pr_resp->DGID.gid_guid)) { 3863 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr" 3864 ": Pri DGID Match.. "); 3865 if ((s_spec == 0) || (p_sg.gid_guid == 3866 pr_resp->SGID.gid_guid)) { 3867 p_found = 1; 3868 p_resp = pr_resp; 3869 IBTF_DPRINTF_L3(cmlog, 3870 "ibcm_get_ip_mpr: " 3871 "Primary Path Found"); 3872 3873 if (a_found) 3874 break; 3875 else 3876 continue; 3877 } 3878 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr" 3879 ": Pri SGID Don't Match.. "); 3880 } 3881 3882 if ((!a_found) && 3883 (a_dg.gid_guid == pr_resp->DGID.gid_guid)) { 3884 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr" 3885 ": Alt DGID Match.. "); 3886 if ((s_spec == 0) || (a_sg.gid_guid == 3887 pr_resp->SGID.gid_guid)) { 3888 a_found = 1; 3889 a_resp = pr_resp; 3890 3891 IBTF_DPRINTF_L3(cmlog, 3892 "ibcm_get_ip_mpr:" 3893 "Alternate Path Found "); 3894 3895 if (p_found) 3896 break; 3897 else 3898 continue; 3899 } 3900 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr" 3901 ": Alt SGID Don't Match.. "); 3902 } 3903 } 3904 3905 if ((p_found == 0) && (a_found == 0)) { 3906 IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_mpr: Path " 3907 "to desired node points NOT Available."); 3908 retval = IBT_PATH_RECORDS_NOT_FOUND; 3909 goto get_ip_mpr_end; 3910 } 3911 3912 if ((p_resp == NULL) && (a_resp != NULL)) { 3913 p_resp = a_resp; 3914 a_resp = NULL; 3915 } 3916 3917 /* Fill in Primary Path */ 3918 retval = ibcm_ip_update_pri(p_resp, sl, &paths[found]); 3919 if (retval != IBT_SUCCESS) 3920 goto get_ip_mpr_end; 3921 3922 /* Fill in Alternate Path */ 3923 if (a_resp != NULL) { 3924 /* a_resp will point to AltPathInfo buffer. */ 3925 retval = ibcm_update_cep_info(a_resp, sl, 3926 NULL, &paths[found].pi_alt_cep_path); 3927 if (retval != IBT_SUCCESS) 3928 goto get_ip_mpr_end; 3929 3930 /* Update some leftovers */ 3931 paths[found].pi_alt_pkt_lt = 3932 a_resp->PacketLifeTime; 3933 } else { 3934 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: " 3935 "Alternate Path NOT Available."); 3936 retval = IBT_INSUFF_DATA; 3937 } 3938 found++; 3939 } else { /* If NOT APM */ 3940 for (i = 0; i < num_rec; i++, pr_resp++) { 3941 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: " 3942 "DGID(%llX)", pr_resp->DGID.gid_guid); 3943 3944 /* Fill in Primary Path */ 3945 retval = ibcm_ip_update_pri(pr_resp, sl, 3946 &paths[found]); 3947 if (retval != IBT_SUCCESS) 3948 continue; 3949 3950 if (++found == *num_path) 3951 break; 3952 } 3953 } 3954 get_ip_mpr_end: 3955 kmem_free(results_p, length); 3956 } 3957 kmem_free(mpr_req, template_len); 3958 3959 if (found == 0) 3960 retval = IBT_PATH_RECORDS_NOT_FOUND; 3961 else if (found != *num_path) 3962 retval = IBT_INSUFF_DATA; 3963 else 3964 retval = IBT_SUCCESS; 3965 3966 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_mpr: Done (status %d). " 3967 "Found %d/%d Paths", retval, found, *num_path); 3968 3969 *num_path = found; /* Update the return count. */ 3970 3971 return (retval); 3972 } 3973 3974 3975 /* 3976 * Here we "synthesize" loop back path record information. 3977 * 3978 * Currently the synthesize values are assumed as follows: 3979 * SLID, DLID = Base LID from Query HCA Port. 3980 * FlowLabel, HopLimit, TClass = 0, as GRH is False. 3981 * RawTraffic = 0. 3982 * P_Key = first valid one in P_Key table as obtained from Query HCA Port. 3983 * SL = as from Query HCA Port. 3984 * MTU = from Query HCA Port. 3985 * Rate = 2 (arbitrary). 3986 * PacketLifeTime = 0 (4.096 usec). 3987 */ 3988 static ibt_status_t 3989 ibcm_fillin_ip_lbpr(ibtl_cm_port_list_t *sl, uint8_t idx, 3990 ibcm_ip_dinfo_t *dinfo, ibt_path_info_t *paths) 3991 { 3992 IBTF_DPRINTF_L3(cmlog, "ibcm_fillin_ip_lbpr(%p, %p)", sl, dinfo); 3993 3994 /* Synthesize path record with appropriate loop back information. */ 3995 paths->pi_prim_cep_path.cep_pkey_ix = 3996 ibtl_cm_get_1st_full_pkey_ix(sl->p_hca_guid, sl->p_port_num); 3997 paths->pi_hca_guid = sl->p_hca_guid; 3998 paths->pi_prim_cep_path.cep_adds_vect.av_dgid = dinfo->dest[idx].d_gid; 3999 paths->pi_prim_cep_path.cep_adds_vect.av_sgid = sl->p_sgid; 4000 paths->pi_prim_cep_path.cep_adds_vect.av_srate = IBT_SRATE_1X; 4001 paths->pi_prim_cep_path.cep_adds_vect.av_srvl = 0; /* SL */ 4002 4003 paths->pi_prim_cep_path.cep_adds_vect.av_send_grh = B_FALSE; 4004 paths->pi_prim_cep_path.cep_adds_vect.av_flow = 0; 4005 paths->pi_prim_cep_path.cep_adds_vect.av_tclass = 0; 4006 paths->pi_prim_cep_path.cep_adds_vect.av_hop = 0; 4007 4008 /* SLID and DLID will be equal to BLID. */ 4009 paths->pi_prim_cep_path.cep_adds_vect.av_dlid = sl->p_base_lid; 4010 paths->pi_prim_cep_path.cep_adds_vect.av_src_path = 0; 4011 paths->pi_prim_cep_path.cep_adds_vect.av_sgid_ix = sl->p_sgid_ix; 4012 paths->pi_prim_cep_path.cep_adds_vect.av_port_num = sl->p_port_num; 4013 paths->pi_prim_cep_path.cep_hca_port_num = sl->p_port_num; 4014 paths->pi_prim_cep_path.cep_timeout = 0; /* To be filled in by CM. */ 4015 paths->pi_path_mtu = sl->p_mtu; /* MTU */ 4016 paths->pi_prim_pkt_lt = 0; /* Packet Life Time. */ 4017 paths->pi_alt_pkt_lt = 0; /* Packet Life Time. */ 4018 4019 IBTF_DPRINTF_L3(cmlog, "ibcm_fillin_ip_lbpr: HCA %llX:%d \n " 4020 "SGID %llX:%llX DGID %llX:%llX", paths->pi_hca_guid, 4021 paths->pi_prim_cep_path.cep_hca_port_num, sl->p_sgid.gid_prefix, 4022 sl->p_sgid.gid_guid, dinfo->dest[idx].d_gid.gid_prefix, 4023 dinfo->dest[idx].d_gid.gid_guid); 4024 4025 /* Set Alternate Path to invalid state. */ 4026 paths->pi_alt_cep_path.cep_hca_port_num = 0; 4027 paths->pi_alt_cep_path.cep_adds_vect.av_dlid = 0; 4028 4029 return (IBT_SUCCESS); 4030 } 4031 4032 static void 4033 ibcm_process_get_ip_paths(void *tq_arg) 4034 { 4035 ibcm_ip_path_tqargs_t *p_arg = (ibcm_ip_path_tqargs_t *)tq_arg; 4036 ibcm_ip_dinfo_t *dinfo = NULL; 4037 int len = 0; 4038 uint8_t max_paths, num_path; 4039 ib_gid_t *d_gids_p = NULL; 4040 ib_gid_t sgid, dgid1, dgid2; 4041 ibt_status_t retval = IBT_SUCCESS; 4042 ibtl_cm_port_list_t *sl = NULL; 4043 uint_t dnum = 0; 4044 uint_t i; 4045 ibcm_hca_info_t *hcap; 4046 ibmf_saa_handle_t saa_handle; 4047 4048 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths(%p, 0x%X) ", 4049 p_arg, p_arg->flags); 4050 4051 max_paths = num_path = p_arg->attr.ipa_max_paths; 4052 4053 /* 4054 * Prepare the Source and Destination GID list based on the input 4055 * attributes. We contact ARP module to perform IP to MAC 4056 * i.e. GID conversion. We use this GID for path look-up. 4057 * 4058 * If APM is requested and if multiple Dest IPs are specified, check 4059 * out whether they are companion to each other. But, if only one 4060 * Dest IP is specified, then it is beyond our scope to verify that 4061 * the companion port GID obtained has IP-Service enabled. 4062 */ 4063 dgid1.gid_prefix = dgid1.gid_guid = 0; 4064 sgid.gid_prefix = sgid.gid_guid = 0; 4065 if ((p_arg->attr.ipa_src_ip.family != AF_UNSPEC) && 4066 (!(p_arg->flags & IBT_PATH_APM))) { 4067 ibt_path_attr_t attr; 4068 4069 retval = ibcm_arp_get_ibaddr(p_arg->attr.ipa_src_ip.un.ip4addr, 4070 p_arg->attr.ipa_dst_ip[0].un.ip4addr, &sgid, &dgid1); 4071 if (retval) { 4072 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: " 4073 "ibcm_arp_get_ibaddr() failed: %d", retval); 4074 goto ippath_error; 4075 } 4076 4077 bzero(&attr, sizeof (ibt_path_attr_t)); 4078 attr.pa_hca_guid = p_arg->attr.ipa_hca_guid; 4079 attr.pa_hca_port_num = p_arg->attr.ipa_hca_port_num; 4080 attr.pa_sgid = sgid; 4081 bcopy(&p_arg->attr.ipa_mtu, &attr.pa_mtu, 4082 sizeof (ibt_mtu_req_t)); 4083 bcopy(&p_arg->attr.ipa_srate, &attr.pa_srate, 4084 sizeof (ibt_srate_req_t)); 4085 bcopy(&p_arg->attr.ipa_pkt_lt, &attr.pa_pkt_lt, 4086 sizeof (ibt_pkt_lt_req_t)); 4087 retval = ibtl_cm_get_active_plist(&attr, p_arg->flags, &sl); 4088 if (retval == IBT_SUCCESS) { 4089 bcopy(&p_arg->attr.ipa_src_ip, &sl->p_src_ip, 4090 sizeof (ibt_ip_addr_t)); 4091 } else { 4092 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: " 4093 "ibtl_cm_get_active_plist: Failed %d", retval); 4094 goto ippath_error; 4095 } 4096 } else { 4097 /* 4098 * Get list of active HCA-Port list, that matches input 4099 * specified attr. 4100 */ 4101 retval = ibcm_arp_get_srcip_plist(&p_arg->attr, p_arg->flags, 4102 &sl); 4103 if (retval != IBT_SUCCESS) { 4104 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: " 4105 "ibcm_arp_get_srcip_plist: Failed %d", retval); 4106 goto ippath_error; 4107 } 4108 4109 /* 4110 * Accumulate all destination information. 4111 * Get GID info for the specified input ip-addr. 4112 */ 4113 retval = ibcm_arp_get_ibaddr(sl->p_src_ip.un.ip4addr, 4114 p_arg->attr.ipa_dst_ip[0].un.ip4addr, NULL, &dgid1); 4115 if (retval) { 4116 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: " 4117 "ibcm_arp_get_ibaddr() failed: %d", retval); 4118 goto ippath_error1; 4119 } 4120 } 4121 IBTF_DPRINTF_L4(cmlog, "ibcm_process_get_ip_paths: SrcIP %lX DstIP %lX", 4122 sl->p_src_ip.un.ip4addr, p_arg->attr.ipa_dst_ip[0].un.ip4addr); 4123 4124 IBTF_DPRINTF_L4(cmlog, "ibcm_process_get_ip_paths: SGID %llX:%llX, " 4125 "DGID0: %llX:%llX", sl->p_sgid.gid_prefix, sl->p_sgid.gid_guid, 4126 dgid1.gid_prefix, dgid1.gid_guid); 4127 4128 len = p_arg->attr.ipa_ndst + 1; 4129 len = (len * sizeof (ibcm_ip_dest_t)) + sizeof (ibcm_ip_dinfo_t); 4130 dinfo = kmem_zalloc(len, KM_SLEEP); 4131 4132 dinfo->dest[0].d_gid = dgid1; 4133 bcopy(&p_arg->attr.ipa_dst_ip[0], &dinfo->dest[0].d_ip, 4134 sizeof (ibt_ip_addr_t)); 4135 4136 i = 1; 4137 if (p_arg->attr.ipa_ndst > 1) { 4138 /* Get DGID for all specified Dest IP Addr */ 4139 for (; i < p_arg->attr.ipa_ndst; i++) { 4140 retval = ibcm_arp_get_ibaddr(sl->p_src_ip.un.ip4addr, 4141 p_arg->attr.ipa_dst_ip[i].un.ip4addr, NULL, &dgid2); 4142 if (retval) { 4143 IBTF_DPRINTF_L2(cmlog, 4144 "ibcm_process_get_ip_paths: " 4145 "ibcm_arp_get_ibaddr failed: %d", retval); 4146 goto ippath_error2; 4147 } 4148 dinfo->dest[i].d_gid = dgid2; 4149 4150 IBTF_DPRINTF_L4(cmlog, "ibcm_process_get_ip_paths: " 4151 "DGID%d: %llX:%llX", i, dgid2.gid_prefix, 4152 dgid2.gid_guid); 4153 bcopy(&p_arg->attr.ipa_dst_ip[i], &dinfo->dest[i].d_ip, 4154 sizeof (ibt_ip_addr_t)); 4155 } 4156 4157 if (p_arg->flags & IBT_PATH_APM) { 4158 dgid2 = dinfo->dest[1].d_gid; 4159 4160 retval = ibcm_get_comp_pgids(dgid1, dgid2, 0, 4161 &d_gids_p, &dnum); 4162 if ((retval != IBT_SUCCESS) && 4163 (retval != IBT_GIDS_NOT_FOUND)) { 4164 IBTF_DPRINTF_L2(cmlog, 4165 "ibcm_process_get_ip_paths: " 4166 "Invalid DGIDs specified w/ APM Flag"); 4167 goto ippath_error2; 4168 } 4169 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths: " 4170 "Found %d Comp DGID", dnum); 4171 4172 if (dnum) { 4173 dinfo->dest[i].d_gid = d_gids_p[0]; 4174 dinfo->dest[i].d_ip.family = AF_UNSPEC; 4175 i++; 4176 } 4177 } 4178 } 4179 4180 /* "i" will get us num_dest count. */ 4181 dinfo->num_dest = i; 4182 4183 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*p_arg)) 4184 4185 /* 4186 * IBTF allocates memory for path_info & src_ip in case of 4187 * Async Get IP Paths 4188 */ 4189 if (p_arg->func) { /* Do these only for Async Get Paths */ 4190 p_arg->paths = kmem_zalloc(sizeof (ibt_path_info_t) * max_paths, 4191 KM_SLEEP); 4192 if (p_arg->src_ip_p == NULL) 4193 p_arg->src_ip_p = kmem_zalloc( 4194 sizeof (ibt_path_ip_src_t) * max_paths, KM_SLEEP); 4195 } 4196 4197 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*p_arg)) 4198 4199 IBTF_DPRINTF_L3(cmlog, "ibcm_process_get_ip_paths: HCA (%llX, %d)", 4200 sl->p_hca_guid, sl->p_port_num); 4201 4202 hcap = ibcm_find_hca_entry(sl->p_hca_guid); 4203 if (hcap == NULL) { 4204 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: " 4205 "NO HCA found"); 4206 retval = IBT_HCA_BUSY_DETACHING; 4207 goto ippath_error2; 4208 } 4209 4210 /* Get SA Access Handle. */ 4211 for (i = 0; i < sl->p_count; i++) { 4212 if (i == 0) { 4213 /* Validate whether this HCA supports APM */ 4214 if ((p_arg->flags & IBT_PATH_APM) && 4215 (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG))) { 4216 IBTF_DPRINTF_L2(cmlog, 4217 "ibcm_process_get_ip_paths: HCA (%llX): " 4218 "APM NOT SUPPORTED", sl[i].p_hca_guid); 4219 retval = IBT_APM_NOT_SUPPORTED; 4220 goto ippath_error3; 4221 } 4222 } 4223 4224 saa_handle = ibcm_get_saa_handle(hcap, sl[i].p_port_num); 4225 if (saa_handle == NULL) { 4226 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: " 4227 "SAA HDL NULL, HCA (%llX:%d) NOT ACTIVE", 4228 sl[i].p_hca_guid, sl[i].p_port_num); 4229 retval = IBT_HCA_PORT_NOT_ACTIVE; 4230 goto ippath_error3; 4231 } 4232 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sl)) 4233 sl[i].p_saa_hdl = saa_handle; 4234 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*sl)) 4235 } 4236 4237 /* Get Path Records. */ 4238 retval = ibcm_saa_ip_pr(p_arg, sl, dinfo, &num_path); 4239 4240 ippath_error3: 4241 ibcm_dec_hca_acc_cnt(hcap); 4242 4243 ippath_error2: 4244 if (dinfo && len) 4245 kmem_free(dinfo, len); 4246 4247 ippath_error1: 4248 if (sl) 4249 ibtl_cm_free_active_plist(sl); 4250 4251 ippath_error: 4252 if ((retval != IBT_SUCCESS) && (retval != IBT_INSUFF_DATA)) 4253 num_path = 0; 4254 4255 if (p_arg->num_paths_p != NULL) 4256 *p_arg->num_paths_p = num_path; 4257 4258 if (p_arg->func) { /* Do these only for Async Get Paths */ 4259 ibt_path_info_t *tmp_path_p; 4260 4261 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*p_arg)) 4262 p_arg->retval = retval; 4263 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*p_arg)) 4264 4265 if (retval == IBT_INSUFF_DATA) { 4266 /* 4267 * We allocated earlier memory based on "max_paths", 4268 * but we got lesser path-records, so re-adjust that 4269 * buffer so that caller can free the correct memory. 4270 */ 4271 tmp_path_p = kmem_alloc( 4272 sizeof (ibt_path_info_t) * num_path, KM_SLEEP); 4273 4274 bcopy(p_arg->paths, tmp_path_p, 4275 num_path * sizeof (ibt_path_info_t)); 4276 4277 kmem_free(p_arg->paths, 4278 sizeof (ibt_path_info_t) * max_paths); 4279 } else if (retval != IBT_SUCCESS) { 4280 if (p_arg->paths) 4281 kmem_free(p_arg->paths, 4282 sizeof (ibt_path_info_t) * max_paths); 4283 if (p_arg->src_ip_p) 4284 kmem_free(p_arg->src_ip_p, 4285 sizeof (ibt_path_ip_src_t) * max_paths); 4286 tmp_path_p = NULL; 4287 } else { 4288 tmp_path_p = p_arg->paths; 4289 } 4290 (*(p_arg->func))(p_arg->arg, retval, tmp_path_p, num_path, 4291 p_arg->src_ip_p); 4292 4293 cv_destroy(&p_arg->ip_cv); 4294 mutex_destroy(&p_arg->ip_lock); 4295 len = p_arg->len; 4296 if (p_arg && len) 4297 kmem_free(p_arg, len); 4298 } else { 4299 mutex_enter(&p_arg->ip_lock); 4300 p_arg->retval = retval; 4301 cv_signal(&p_arg->ip_cv); 4302 mutex_exit(&p_arg->ip_lock); 4303 } 4304 4305 IBTF_DPRINTF_L2(cmlog, "ibcm_process_get_ip_paths: done: status %d, " 4306 "Found %d/%d Path Records", retval, num_path, max_paths); 4307 } 4308 4309 4310 static ibt_status_t 4311 ibcm_val_ipattr(ibt_ip_path_attr_t *attrp, ibt_path_flags_t flags) 4312 { 4313 uint_t i; 4314 4315 if (attrp == NULL) { 4316 IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: IP Path Attr is NULL"); 4317 return (IBT_INVALID_PARAM); 4318 } 4319 4320 IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: Inputs are: HCA %llX:%d, " 4321 "Maxpath= %d, Flags= 0x%X, #Dest %d", attrp->ipa_hca_guid, 4322 attrp->ipa_hca_port_num, attrp->ipa_max_paths, flags, 4323 attrp->ipa_ndst); 4324 4325 /* 4326 * Validate Path Flags. 4327 * IBT_PATH_AVAIL & IBT_PATH_PERF are mutually exclusive. 4328 */ 4329 if ((flags & IBT_PATH_AVAIL) && (flags & IBT_PATH_PERF)) { 4330 IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: Invalid Flags: 0x%X," 4331 "\n\t AVAIL and PERF flags specified together", flags); 4332 return (IBT_INVALID_PARAM); 4333 } 4334 4335 /* 4336 * Validate number of records requested. 4337 * 4338 * Max_paths of "0" is invalid. 4339 * Max_paths <= IBT_MAX_SPECIAL_PATHS, if AVAIL or PERF is set. 4340 */ 4341 if (attrp->ipa_max_paths == 0) { 4342 IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: Invalid max_paths %d", 4343 attrp->ipa_max_paths); 4344 return (IBT_INVALID_PARAM); 4345 } 4346 4347 if ((flags & (IBT_PATH_AVAIL | IBT_PATH_PERF)) && 4348 (attrp->ipa_max_paths > IBT_MAX_SPECIAL_PATHS)) { 4349 IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: MaxPaths that can be " 4350 "requested is <%d> \n when IBT_PATH_AVAIL or IBT_PATH_PERF" 4351 " flag is specified.", IBT_MAX_SPECIAL_PATHS); 4352 return (IBT_INVALID_PARAM); 4353 } 4354 4355 /* Only 2 destinations can be specified w/ APM flag. */ 4356 if ((flags & IBT_PATH_APM) && (attrp->ipa_ndst > 2)) { 4357 IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: Max #Dest is 2, with " 4358 "APM flag"); 4359 return (IBT_INVALID_PARAM); 4360 } 4361 4362 /* Validate the destination info */ 4363 if ((attrp->ipa_ndst == 0) || (attrp->ipa_ndst == NULL)) { 4364 IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: DstIP Not provided " 4365 "dst_ip %p, ndst %d", attrp->ipa_dst_ip, attrp->ipa_ndst); 4366 return (IBT_INVALID_PARAM); 4367 } 4368 4369 /* Validate destination IP */ 4370 for (i = 0; i < attrp->ipa_ndst; i++) { 4371 ibt_ip_addr_t dst_ip = attrp->ipa_dst_ip[i]; 4372 4373 IBTF_DPRINTF_L3(cmlog, "ibcm_val_ipattr: DstIP[%d]:= family %d " 4374 "IP %lX", i, dst_ip.family, dst_ip.un.ip4addr); 4375 4376 if (dst_ip.family == AF_UNSPEC) { 4377 IBTF_DPRINTF_L2(cmlog, "ibcm_val_ipattr: ERROR: " 4378 "Invalid DstIP specified"); 4379 return (IBT_INVALID_PARAM); 4380 } 4381 } 4382 4383 IBTF_DPRINTF_L4(cmlog, "ibcm_val_ipattr: SrcIP: family %d, IP %lX", 4384 attrp->ipa_src_ip.family, attrp->ipa_src_ip.un.ip4addr); 4385 4386 return (IBT_SUCCESS); 4387 } 4388 4389 4390 static ibt_status_t 4391 ibcm_get_ip_path(ibt_clnt_hdl_t ibt_hdl, ibt_path_flags_t flags, 4392 ibt_ip_path_attr_t *attrp, ibt_path_info_t *paths, uint8_t *num_path_p, 4393 ibt_path_ip_src_t *src_ip_p, ibt_ip_path_handler_t func, void *arg) 4394 { 4395 ibcm_ip_path_tqargs_t *path_tq; 4396 int sleep_flag = ((func == NULL) ? KM_SLEEP : KM_NOSLEEP); 4397 uint_t len, ret; 4398 ibt_status_t retval; 4399 4400 IBTF_DPRINTF_L4(cmlog, "ibcm_get_ip_path(%p, %X, %p, %p, %p %p %p %p)", 4401 ibt_hdl, flags, attrp, paths, num_path_p, src_ip_p, func, arg); 4402 4403 if (src_ip_p != NULL) 4404 IBCM_PRINT_IP("ibcm_get_ip_path src_ip", &src_ip_p->ip_primary); 4405 4406 retval = ibcm_val_ipattr(attrp, flags); 4407 if (retval != IBT_SUCCESS) 4408 return (retval); 4409 4410 len = (attrp->ipa_ndst * sizeof (ibt_ip_addr_t)) + 4411 sizeof (ibcm_ip_path_tqargs_t); 4412 path_tq = kmem_zalloc(len, sleep_flag); 4413 if (path_tq == NULL) { 4414 IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_path: " 4415 "Unable to allocate memory for local usage."); 4416 return (IBT_INSUFF_KERNEL_RESOURCE); 4417 } 4418 4419 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*path_tq)) 4420 mutex_init(&path_tq->ip_lock, NULL, MUTEX_DEFAULT, NULL); 4421 cv_init(&path_tq->ip_cv, NULL, CV_DRIVER, NULL); 4422 bcopy(attrp, &path_tq->attr, sizeof (ibt_ip_path_attr_t)); 4423 4424 path_tq->attr.ipa_dst_ip = (ibt_ip_addr_t *)(((uchar_t *)path_tq) + 4425 sizeof (ibcm_ip_path_tqargs_t)); 4426 bcopy(attrp->ipa_dst_ip, path_tq->attr.ipa_dst_ip, 4427 sizeof (ibt_ip_addr_t) * attrp->ipa_ndst); 4428 IBCM_PRINT_IP("ibcm_get_ip_path dst_ip", attrp->ipa_dst_ip); 4429 4430 /* Ignore IBT_PATH_AVAIL flag, if only one path is requested. */ 4431 if ((flags & IBT_PATH_AVAIL) && (attrp->ipa_max_paths == 1)) { 4432 flags &= ~IBT_PATH_AVAIL; 4433 4434 IBTF_DPRINTF_L4(cmlog, "ibcm_get_ip_path: Ignoring " 4435 "IBT_PATH_AVAIL flag, as only ONE path info is requested."); 4436 } 4437 4438 path_tq->flags = flags; 4439 path_tq->ibt_hdl = ibt_hdl; 4440 path_tq->paths = paths; 4441 path_tq->src_ip_p = src_ip_p; 4442 path_tq->num_paths_p = num_path_p; 4443 path_tq->func = func; 4444 path_tq->arg = arg; 4445 path_tq->len = len; 4446 4447 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*path_tq)) 4448 4449 sleep_flag = ((func == NULL) ? TQ_SLEEP : TQ_NOSLEEP); 4450 mutex_enter(&path_tq->ip_lock); 4451 ret = taskq_dispatch(ibcm_taskq, ibcm_process_get_ip_paths, path_tq, 4452 sleep_flag); 4453 if (ret == 0) { 4454 IBTF_DPRINTF_L2(cmlog, "ibcm_get_ip_path: Failed to dispatch " 4455 "the TaskQ"); 4456 mutex_exit(&path_tq->ip_lock); 4457 cv_destroy(&path_tq->ip_cv); 4458 mutex_destroy(&path_tq->ip_lock); 4459 kmem_free(path_tq, len); 4460 retval = IBT_INSUFF_KERNEL_RESOURCE; 4461 } else { 4462 if (func != NULL) { /* Non-Blocking */ 4463 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_path: NonBlocking"); 4464 retval = IBT_SUCCESS; 4465 mutex_exit(&path_tq->ip_lock); 4466 } else { /* Blocking */ 4467 IBTF_DPRINTF_L3(cmlog, "ibcm_get_ip_path: Blocking"); 4468 cv_wait(&path_tq->ip_cv, &path_tq->ip_lock); 4469 retval = path_tq->retval; 4470 mutex_exit(&path_tq->ip_lock); 4471 cv_destroy(&path_tq->ip_cv); 4472 mutex_destroy(&path_tq->ip_lock); 4473 kmem_free(path_tq, len); 4474 } 4475 } 4476 4477 return (retval); 4478 } 4479 4480 4481 ibt_status_t 4482 ibt_aget_ip_paths(ibt_clnt_hdl_t ibt_hdl, ibt_path_flags_t flags, 4483 ibt_ip_path_attr_t *attrp, ibt_ip_path_handler_t func, void *arg) 4484 { 4485 IBTF_DPRINTF_L3(cmlog, "ibt_aget_ip_paths(%p, 0x%X, %p, %p, %p)", 4486 ibt_hdl, flags, attrp, func, arg); 4487 4488 if (func == NULL) { 4489 IBTF_DPRINTF_L2(cmlog, "ibt_aget_ip_paths: Function Pointer is " 4490 "NULL - ERROR "); 4491 return (IBT_INVALID_PARAM); 4492 } 4493 4494 /* path info will be allocated in ibcm_process_get_ip_paths() */ 4495 return (ibcm_get_ip_path(ibt_hdl, flags, attrp, NULL, NULL, 4496 NULL, func, arg)); 4497 } 4498 4499 4500 ibt_status_t 4501 ibt_get_ip_paths(ibt_clnt_hdl_t ibt_hdl, ibt_path_flags_t flags, 4502 ibt_ip_path_attr_t *attrp, ibt_path_info_t *paths, uint8_t *num_paths_p, 4503 ibt_path_ip_src_t *src_ip_p) 4504 { 4505 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_paths(%p, 0x%X, %p, %p, %p, %p)", 4506 ibt_hdl, flags, attrp, paths, num_paths_p, src_ip_p); 4507 4508 if (paths == NULL) { 4509 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_paths: Path Info Pointer is " 4510 "NULL - ERROR "); 4511 return (IBT_INVALID_PARAM); 4512 } 4513 4514 if (num_paths_p != NULL) 4515 *num_paths_p = 0; 4516 4517 return (ibcm_get_ip_path(ibt_hdl, flags, attrp, paths, num_paths_p, 4518 src_ip_p, NULL, NULL)); 4519 } 4520 4521 4522 ibt_status_t 4523 ibt_get_ip_alt_path(ibt_channel_hdl_t rc_chan, ibt_path_flags_t flags, 4524 ibt_alt_ip_path_attr_t *attrp, ibt_alt_path_info_t *api_p) 4525 { 4526 sa_multipath_record_t *mpr_req; 4527 sa_path_record_t *pr_resp; 4528 ibmf_saa_access_args_t access_args; 4529 ibt_qp_query_attr_t qp_attr; 4530 ibtl_cm_hca_port_t c_hp, n_hp; 4531 ibcm_hca_info_t *hcap; 4532 void *results_p; 4533 uint64_t c_mask = 0; 4534 ib_gid_t *gid_ptr = NULL; 4535 ib_gid_t *sgids_p = NULL, *dgids_p = NULL; 4536 ib_gid_t cur_dgid, cur_sgid; 4537 ib_gid_t new_dgid, new_sgid; 4538 ibmf_saa_handle_t saa_handle; 4539 size_t length; 4540 int i, j, template_len, rec_found; 4541 uint_t snum = 0, dnum = 0, num_rec; 4542 ibt_status_t retval; 4543 ib_mtu_t prim_mtu; 4544 4545 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path(%p, %x, %p, %p)", 4546 rc_chan, flags, attrp, api_p); 4547 4548 /* validate channel */ 4549 if (IBCM_INVALID_CHANNEL(rc_chan)) { 4550 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: invalid channel"); 4551 return (IBT_CHAN_HDL_INVALID); 4552 } 4553 4554 if (api_p == NULL) { 4555 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: invalid attribute:" 4556 " AltPathInfo can't be NULL"); 4557 return (IBT_INVALID_PARAM); 4558 } 4559 4560 retval = ibt_query_qp(rc_chan, &qp_attr); 4561 if (retval != IBT_SUCCESS) { 4562 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: ibt_query_qp(%p) " 4563 "failed %d", rc_chan, retval); 4564 return (retval); 4565 } 4566 4567 if (qp_attr.qp_info.qp_trans != IBT_RC_SRV) { 4568 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: " 4569 "Invalid Channel type: Applicable only to RC Channel"); 4570 return (IBT_CHAN_SRV_TYPE_INVALID); 4571 } 4572 4573 cur_dgid = 4574 qp_attr.qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dgid; 4575 cur_sgid = 4576 qp_attr.qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_sgid; 4577 prim_mtu = qp_attr.qp_info.qp_transport.rc.rc_path_mtu; 4578 4579 /* If optional attributes are specified, validate them. */ 4580 if (attrp) { 4581 /* Get SGID and DGID for the specified input ip-addr */ 4582 retval = ibcm_arp_get_ibaddr(attrp->apa_src_ip.un.ip4addr, 4583 attrp->apa_dst_ip.un.ip4addr, &new_sgid, &new_dgid); 4584 if (retval) { 4585 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: " 4586 "ibcm_arp_get_ibaddr() failed: %d", retval); 4587 return (retval); 4588 } 4589 } else { 4590 new_dgid.gid_prefix = 0; 4591 new_dgid.gid_guid = 0; 4592 new_sgid.gid_prefix = 0; 4593 new_sgid.gid_guid = 0; 4594 } 4595 4596 if ((new_dgid.gid_prefix != 0) && (new_sgid.gid_prefix != 0) && 4597 (new_dgid.gid_prefix != new_sgid.gid_prefix)) { 4598 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: Specified SGID's " 4599 "SNprefix (%llX) doesn't match with \n specified DGID's " 4600 "SNprefix: %llX", new_sgid.gid_prefix, new_dgid.gid_prefix); 4601 return (IBT_INVALID_PARAM); 4602 } 4603 4604 /* For the specified SGID, get HCA information. */ 4605 retval = ibtl_cm_get_hca_port(cur_sgid, 0, &c_hp); 4606 if (retval != IBT_SUCCESS) { 4607 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: " 4608 "Get HCA Port Failed: %d", retval); 4609 return (retval); 4610 } 4611 4612 hcap = ibcm_find_hca_entry(c_hp.hp_hca_guid); 4613 if (hcap == NULL) { 4614 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: NO HCA found"); 4615 return (IBT_HCA_BUSY_DETACHING); 4616 } 4617 4618 /* Validate whether this HCA support APM */ 4619 if (!(hcap->hca_caps & IBT_HCA_AUTO_PATH_MIG)) { 4620 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: " 4621 "HCA (%llX) - APM NOT SUPPORTED ", c_hp.hp_hca_guid); 4622 retval = IBT_APM_NOT_SUPPORTED; 4623 goto get_ip_alt_path_done; 4624 } 4625 4626 /* Get Companion Port GID of the current Channel's SGID */ 4627 if ((new_sgid.gid_guid == 0) || ((new_sgid.gid_guid != 0) && 4628 (new_sgid.gid_guid != cur_sgid.gid_guid))) { 4629 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: SRC: " 4630 "Get Companion PortGids for - %llX:%llX", 4631 cur_sgid.gid_prefix, cur_sgid.gid_guid); 4632 4633 retval = ibcm_get_comp_pgids(cur_sgid, new_sgid, 4634 c_hp.hp_hca_guid, &sgids_p, &snum); 4635 if (retval != IBT_SUCCESS) 4636 goto get_ip_alt_path_done; 4637 } 4638 4639 /* Get Companion Port GID of the current Channel's DGID */ 4640 if ((new_dgid.gid_guid == 0) || ((new_dgid.gid_guid != 0) && 4641 (new_dgid.gid_guid != cur_dgid.gid_guid))) { 4642 4643 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: DEST: " 4644 "Get Companion PortGids for - %llX:%llX", 4645 cur_dgid.gid_prefix, cur_dgid.gid_guid); 4646 4647 retval = ibcm_get_comp_pgids(cur_dgid, new_dgid, 0, &dgids_p, 4648 &dnum); 4649 if (retval != IBT_SUCCESS) 4650 goto get_ip_alt_path_done; 4651 } 4652 4653 if ((new_dgid.gid_guid == 0) || (new_sgid.gid_guid == 0)) { 4654 if (new_sgid.gid_guid == 0) { 4655 for (i = 0; i < snum; i++) { 4656 if (new_dgid.gid_guid == 0) { 4657 for (j = 0; j < dnum; j++) { 4658 if (sgids_p[i].gid_prefix == 4659 dgids_p[j].gid_prefix) { 4660 new_dgid = dgids_p[j]; 4661 new_sgid = sgids_p[i]; 4662 4663 goto get_ip_alt_proceed; 4664 } 4665 } 4666 /* Current DGID */ 4667 if (sgids_p[i].gid_prefix == 4668 cur_dgid.gid_prefix) { 4669 new_sgid = sgids_p[i]; 4670 goto get_ip_alt_proceed; 4671 } 4672 } else { 4673 if (sgids_p[i].gid_prefix == 4674 new_dgid.gid_prefix) { 4675 new_sgid = sgids_p[i]; 4676 goto get_ip_alt_proceed; 4677 } 4678 } 4679 } 4680 /* Current SGID */ 4681 if (new_dgid.gid_guid == 0) { 4682 for (j = 0; j < dnum; j++) { 4683 if (cur_sgid.gid_prefix == 4684 dgids_p[j].gid_prefix) { 4685 new_dgid = dgids_p[j]; 4686 4687 goto get_ip_alt_proceed; 4688 } 4689 } 4690 } 4691 } else if (new_dgid.gid_guid == 0) { 4692 for (i = 0; i < dnum; i++) { 4693 if (dgids_p[i].gid_prefix == 4694 new_sgid.gid_prefix) { 4695 new_dgid = dgids_p[i]; 4696 goto get_ip_alt_proceed; 4697 } 4698 } 4699 /* Current DGID */ 4700 if (cur_dgid.gid_prefix == new_sgid.gid_prefix) { 4701 goto get_ip_alt_proceed; 4702 } 4703 } 4704 /* 4705 * hmm... No Companion Ports available. 4706 * so we will be using current or specified attributes only. 4707 */ 4708 } 4709 4710 get_ip_alt_proceed: 4711 if (new_sgid.gid_guid != 0) { 4712 retval = ibtl_cm_get_hca_port(new_sgid, 0, &n_hp); 4713 if (retval != IBT_SUCCESS) { 4714 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: " 4715 "Get HCA Port Failed: %d", retval); 4716 goto get_ip_alt_path_done; 4717 } 4718 } 4719 4720 /* Calculate the size for multi-path records template */ 4721 template_len = (2 * sizeof (ib_gid_t)) + sizeof (sa_multipath_record_t); 4722 4723 mpr_req = kmem_zalloc(template_len, KM_SLEEP); 4724 4725 ASSERT(mpr_req != NULL); 4726 4727 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*mpr_req)) 4728 4729 gid_ptr = (ib_gid_t *)(((uchar_t *)mpr_req) + 4730 sizeof (sa_multipath_record_t)); 4731 4732 /* SGID */ 4733 if (new_sgid.gid_guid == 0) 4734 *gid_ptr = cur_sgid; 4735 else 4736 *gid_ptr = new_sgid; 4737 4738 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Get Path Between " 4739 " SGID : %llX:%llX", gid_ptr->gid_prefix, gid_ptr->gid_guid); 4740 4741 gid_ptr++; 4742 4743 /* DGID */ 4744 if (new_dgid.gid_guid == 0) 4745 *gid_ptr = cur_dgid; 4746 else 4747 *gid_ptr = new_dgid; 4748 4749 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path:\t\t DGID : %llX:%llX", 4750 gid_ptr->gid_prefix, gid_ptr->gid_guid); 4751 4752 mpr_req->SGIDCount = 1; 4753 c_mask = SA_MPR_COMPMASK_SGIDCOUNT; 4754 4755 mpr_req->DGIDCount = 1; 4756 c_mask |= SA_MPR_COMPMASK_DGIDCOUNT; 4757 4758 /* Is Flow Label Specified. */ 4759 if (attrp) { 4760 if (attrp->apa_flow) { 4761 mpr_req->FlowLabel = attrp->apa_flow; 4762 c_mask |= SA_MPR_COMPMASK_FLOWLABEL; 4763 } 4764 4765 /* Is HopLimit Specified. */ 4766 if (flags & IBT_PATH_HOP) { 4767 mpr_req->HopLimit = attrp->apa_hop; 4768 c_mask |= SA_MPR_COMPMASK_HOPLIMIT; 4769 } 4770 4771 /* Is TClass Specified. */ 4772 if (attrp->apa_tclass) { 4773 mpr_req->TClass = attrp->apa_tclass; 4774 c_mask |= SA_MPR_COMPMASK_TCLASS; 4775 } 4776 4777 /* Is SL specified. */ 4778 if (attrp->apa_sl) { 4779 mpr_req->SL = attrp->apa_sl; 4780 c_mask |= SA_MPR_COMPMASK_SL; 4781 } 4782 4783 if (flags & IBT_PATH_PERF) { 4784 mpr_req->PacketLifeTimeSelector = IBT_BEST; 4785 mpr_req->RateSelector = IBT_BEST; 4786 4787 c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR | 4788 SA_MPR_COMPMASK_RATESELECTOR; 4789 } else { 4790 if (attrp->apa_pkt_lt.p_selector == IBT_BEST) { 4791 mpr_req->PacketLifeTimeSelector = IBT_BEST; 4792 c_mask |= SA_MPR_COMPMASK_PKTLTSELECTOR; 4793 } 4794 4795 if (attrp->apa_srate.r_selector == IBT_BEST) { 4796 mpr_req->RateSelector = IBT_BEST; 4797 c_mask |= SA_MPR_COMPMASK_RATESELECTOR; 4798 } 4799 } 4800 4801 /* 4802 * Honor individual selection of these attributes, 4803 * even if IBT_PATH_PERF is set. 4804 */ 4805 /* Check out whether Packet Life Time is specified. */ 4806 if (attrp->apa_pkt_lt.p_pkt_lt) { 4807 mpr_req->PacketLifeTime = 4808 ibt_usec2ib(attrp->apa_pkt_lt.p_pkt_lt); 4809 mpr_req->PacketLifeTimeSelector = 4810 attrp->apa_pkt_lt.p_selector; 4811 4812 c_mask |= SA_MPR_COMPMASK_PKTLT | 4813 SA_MPR_COMPMASK_PKTLTSELECTOR; 4814 } 4815 4816 /* Is SRATE specified. */ 4817 if (attrp->apa_srate.r_srate) { 4818 mpr_req->Rate = attrp->apa_srate.r_srate; 4819 mpr_req->RateSelector = attrp->apa_srate.r_selector; 4820 4821 c_mask |= SA_MPR_COMPMASK_RATE | 4822 SA_MPR_COMPMASK_RATESELECTOR; 4823 } 4824 } 4825 4826 /* Alt PathMTU can be GT or EQU to current channel's Pri PathMTU */ 4827 4828 /* P_Key must be same as that of primary path */ 4829 retval = ibt_index2pkey_byguid(c_hp.hp_hca_guid, c_hp.hp_port, 4830 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix, 4831 &mpr_req->P_Key); 4832 if (retval != IBT_SUCCESS) { 4833 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: PKeyIdx2Pkey " 4834 "Failed: %d", retval); 4835 goto get_ip_alt_path_done; 4836 } 4837 c_mask |= SA_MPR_COMPMASK_PKEY; 4838 4839 mpr_req->Reversible = 1; /* We always get REVERSIBLE paths. */ 4840 mpr_req->IndependenceSelector = 1; 4841 c_mask |= SA_MPR_COMPMASK_REVERSIBLE | SA_MPR_COMPMASK_INDEPSEL; 4842 4843 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*mpr_req)) 4844 4845 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: CMask: 0x%llX", c_mask); 4846 4847 /* NOTE: We will **NOT** specify how many records we want. */ 4848 4849 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Primary: MTU %d, PKey[%d]=" 4850 "0x%X\n\tSGID = %llX:%llX, DGID = %llX:%llX", prim_mtu, 4851 qp_attr.qp_info.qp_transport.rc.rc_path.cep_pkey_ix, mpr_req->P_Key, 4852 cur_sgid.gid_prefix, cur_sgid.gid_guid, cur_dgid.gid_prefix, 4853 cur_dgid.gid_guid); 4854 4855 /* Get SA Access Handle. */ 4856 if (new_sgid.gid_guid != 0) 4857 saa_handle = ibcm_get_saa_handle(hcap, n_hp.hp_port); 4858 else 4859 saa_handle = ibcm_get_saa_handle(hcap, c_hp.hp_port); 4860 if (saa_handle == NULL) { 4861 retval = IBT_HCA_PORT_NOT_ACTIVE; 4862 goto get_ip_alt_path_done; 4863 } 4864 4865 /* Contact SA Access to retrieve Path Records. */ 4866 access_args.sq_attr_id = SA_MULTIPATHRECORD_ATTRID; 4867 access_args.sq_access_type = IBMF_SAA_RETRIEVE; 4868 access_args.sq_component_mask = c_mask; 4869 access_args.sq_template = mpr_req; 4870 access_args.sq_template_length = sizeof (sa_multipath_record_t); 4871 access_args.sq_callback = NULL; 4872 access_args.sq_callback_arg = NULL; 4873 4874 retval = ibcm_contact_sa_access(saa_handle, &access_args, &length, 4875 &results_p); 4876 if (retval != IBT_SUCCESS) { 4877 goto get_ip_alt_path_done; 4878 } 4879 4880 num_rec = length / sizeof (sa_path_record_t); 4881 4882 kmem_free(mpr_req, template_len); 4883 4884 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Found %d Paths", num_rec); 4885 4886 rec_found = 0; 4887 if ((results_p != NULL) && (num_rec > 0)) { 4888 /* Update the PathInfo with the response Path Records */ 4889 pr_resp = (sa_path_record_t *)results_p; 4890 for (i = 0; i < num_rec; i++, pr_resp++) { 4891 if (prim_mtu > pr_resp->Mtu) { 4892 IBTF_DPRINTF_L2(cmlog, "ibt_get_ip_alt_path: " 4893 "Alt PathMTU(%d) must be GT or EQU to Pri " 4894 "PathMTU(%d). Ignore this rec", 4895 pr_resp->Mtu, prim_mtu); 4896 continue; 4897 } 4898 4899 if ((new_sgid.gid_guid == 0) && 4900 (new_dgid.gid_guid == 0)) { 4901 /* Reject PathRec if it same as Primary Path. */ 4902 if (ibcm_compare_paths(pr_resp, 4903 &qp_attr.qp_info.qp_transport.rc.rc_path, 4904 &c_hp) == B_TRUE) { 4905 IBTF_DPRINTF_L3(cmlog, 4906 "ibt_get_ip_alt_path: PathRec " 4907 "obtained is similar to Prim Path, " 4908 "ignore this record"); 4909 continue; 4910 } 4911 } 4912 4913 if (new_sgid.gid_guid == 0) { 4914 retval = ibcm_update_cep_info(pr_resp, NULL, 4915 &c_hp, &api_p->ap_alt_cep_path); 4916 } else { 4917 retval = ibcm_update_cep_info(pr_resp, NULL, 4918 &n_hp, &api_p->ap_alt_cep_path); 4919 } 4920 if (retval != IBT_SUCCESS) 4921 continue; 4922 4923 /* Update some leftovers */ 4924 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*api_p)) 4925 4926 api_p->ap_alt_pkt_lt = pr_resp->PacketLifeTime; 4927 4928 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*api_p)) 4929 4930 rec_found = 1; 4931 break; 4932 } 4933 kmem_free(results_p, length); 4934 } 4935 4936 if (rec_found == 0) { 4937 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: AltPath cannot" 4938 " be established"); 4939 retval = IBT_PATH_RECORDS_NOT_FOUND; 4940 } else 4941 retval = IBT_SUCCESS; 4942 4943 get_ip_alt_path_done: 4944 if ((snum) && (sgids_p)) 4945 kmem_free(sgids_p, snum * sizeof (ib_gid_t)); 4946 4947 if ((dnum) && (dgids_p)) 4948 kmem_free(dgids_p, dnum * sizeof (ib_gid_t)); 4949 4950 ibcm_dec_hca_acc_cnt(hcap); 4951 4952 IBTF_DPRINTF_L3(cmlog, "ibt_get_ip_alt_path: Done (status %d)", retval); 4953 4954 return (retval); 4955 } 4956 4957 4958 /* Routines for warlock */ 4959 4960 /* ARGSUSED */ 4961 static void 4962 ibcm_dummy_path_handler(void *arg, ibt_status_t retval, ibt_path_info_t *paths, 4963 uint8_t num_path) 4964 { 4965 ibcm_path_tqargs_t dummy_path; 4966 4967 dummy_path.func = ibcm_dummy_path_handler; 4968 4969 IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_path_handler: " 4970 "dummy_path.func %p", dummy_path.func); 4971 } 4972 4973 /* ARGSUSED */ 4974 static void 4975 ibcm_dummy_ip_path_handler(void *arg, ibt_status_t retval, 4976 ibt_path_info_t *paths, uint8_t num_path, ibt_path_ip_src_t *src_ip) 4977 { 4978 ibcm_ip_path_tqargs_t dummy_path; 4979 4980 dummy_path.func = ibcm_dummy_ip_path_handler; 4981 4982 IBTF_DPRINTF_L5(cmlog, "ibcm_dummy_ip_path_handler: " 4983 "dummy_path.func %p", dummy_path.func); 4984 } 4985