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