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