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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. 25 */ 26 27 #include "cfga_ib.h" 28 29 /* 30 * cfga_ib.c: 31 * All cfgadm entry points that are defined in the config_admin(3CFGADM) 32 * needed for InfiniBand support are described here. These cfgadm 33 * interfaces issue ioctl(s) to the IB nexus driver. Attachment points 34 * supported are - IOC, VPPA, Port, HCA_SVC and Pseudo dynamic ap_ids, 35 * the HCA static ap_id, and the IB static ap_id. 36 * 37 * Given InfiniBand bus is fabric based, #of dynamic ap_ids present are 38 * unknown at any given point of time. Hence this plugin uses a 39 * packed nvlist data structure to hold ap_id related information. 40 * The IB nexus driver allocates the nvlist data in the kernel 41 * and this plugin processes the data (it is freed by IB nexus driver). 42 */ 43 44 45 /* function prototypes */ 46 static int ib_get_link(di_devlink_t, void *); 47 static icfga_ret_t ib_physpath_to_devlink(char *, char **, int *); 48 static const char *ib_get_msg(uint_t, msgcvt_t *, uint_t); 49 static void ib_set_msg(char **, ...); 50 static cfga_err_t ib_err_msg(char **, cfga_ib_ret_t, const char *, int); 51 static int ib_verify_valid_apid(const char *); 52 static cfga_ib_ret_t ib_verify_params(const char *, const char *, char **); 53 static void ib_cleanup_after_devctl_cmd(devctl_hdl_t, nvlist_t *); 54 static cfga_ib_ret_t ib_setup_for_devctl_cmd(char *, boolean_t, 55 devctl_hdl_t *, nvlist_t **); 56 static cfga_ib_ret_t ib_device_configured(devctl_hdl_t, nvlist_t *, 57 ap_rstate_t *); 58 static cfga_ib_ret_t ib_device_connected(devctl_hdl_t, nvlist_t *, 59 ap_ostate_t *); 60 static cfga_ib_ret_t ib_do_control_ioctl(char *, uint_t, uint_t, uint_t, 61 void **, size_t *); 62 cfga_err_t cfga_change_state(cfga_cmd_t, const char *, 63 const char *, struct cfga_confirm *, 64 struct cfga_msg *, char **, cfga_flags_t); 65 cfga_err_t cfga_private_func(const char *, const char *, 66 const char *, struct cfga_confirm *, 67 struct cfga_msg *, char **, cfga_flags_t); 68 cfga_err_t cfga_test(const char *, const char *, struct cfga_msg *, 69 char **, cfga_flags_t); 70 static cfga_ib_ret_t ib_fill_static_apids(char *, cfga_list_data_t *); 71 cfga_err_t cfga_list_ext(const char *, cfga_list_data_t **, int *, 72 const char *, const char *, char **, cfga_flags_t); 73 void cfga_msg(struct cfga_msg *, const char *); 74 cfga_err_t cfga_help(struct cfga_msg *, const char *, 75 cfga_flags_t); 76 static int ib_confirm(struct cfga_confirm *, char *); 77 static char *ib_get_devicepath(const char *); 78 79 80 /* External function prototypes */ 81 extern cfga_ib_ret_t ib_rcm_offline(const char *, char **, char *, 82 cfga_flags_t); 83 extern cfga_ib_ret_t ib_rcm_online(const char *, char **, char *, 84 cfga_flags_t); 85 extern cfga_ib_ret_t ib_rcm_remove(const char *, char **, char *, 86 cfga_flags_t); 87 extern int ib_add_service(char **); 88 extern int ib_delete_service(char **); 89 extern int ib_list_services(struct cfga_msg *, char **); 90 91 92 /* Globals */ 93 int cfga_version = CFGA_HSL_V2; /* Set the version number for */ 94 /* the cfgadm library's use. */ 95 96 static char *ib_help[] = { /* Help messages */ 97 NULL, 98 /* CFGA_IB_HELP_HEADER */ "IB specific commands:\n", 99 /* CFGA_IB_HELP_CONFIG */ "cfgadm -c [configure|unconfigure] " 100 "ap_id [ap_id...]\n", 101 /* CFGA_IB_HELP_LIST */ "cfgadm -x list_clients hca_ap_id " 102 "[hca_ap_id...]\n", 103 /* CFGA_IB_HELP_UPD_PKEY */ "cfgadm -x update_pkey_tbls ib\n", 104 /* CFGA_IB_HELP_CONF_FILE1 */ "cfgadm -o comm=[port|vppa|hca-svc]," 105 "service=<name> -x [add_service|delete_service] ib\n", 106 /* CFGA_IB_HELP_CONF_FILE2 */ "cfgadm -x list_services ib\n", 107 /* CFGA_IB_HELP_UPD_IOC_CONF */ "cfgadm -x update_ioc_config " 108 "[ib | ioc_apid]\n", 109 /* CFGA_IB_HELP_UNCFG_CLNTS */ "cfgadm -x unconfig_clients hca_ap_id " 110 "[hca_ap_id...]\n", 111 /* CFGA_IB_HELP_UNKNOWN */ "\tunknown command or option: ", 112 NULL 113 }; 114 115 static msgcvt_t ib_error_msgs[] = { /* Error messages */ 116 /* CFGA_IB_OK */ { CVT, CFGA_OK, "ok" }, 117 /* CFGA_IB_UNKNOWN */ { CVT, CFGA_LIB_ERROR, 118 "Unknown message; internal error " }, 119 /* CFGA_IB_INTERNAL_ERR */ { CVT, CFGA_LIB_ERROR, 120 "Internal error " }, 121 /* CFGA_IB_INVAL_ARG_ERR */ { CVT, CFGA_LIB_ERROR, 122 "Invalid input args " }, 123 /* CFGA_IB_OPTIONS_ERR */ { CVT, CFGA_ERROR, 124 "Hardware specific options not supported " }, 125 /* CFGA_IB_AP_ERR */ { CVT, CFGA_APID_NOEXIST, "" }, 126 /* CFGA_IB_DEVCTL_ERR */ { CVT, CFGA_LIB_ERROR, 127 "Cannot issue devctl to " }, 128 /* CFGA_IB_NOT_CONNECTED */ { CVT, CFGA_INSUFFICENT_CONDITION, 129 "No device connected to " }, 130 /* CFGA_IB_NOT_CONFIGURED */ { CVT, CFGA_INSUFFICENT_CONDITION, 131 "No device configured to " }, 132 /* CFGA_IB_ALREADY_CONNECTED */ { CVT, CFGA_INSUFFICENT_CONDITION, 133 "already connected; cannot connect again " }, 134 /* CFGA_IB_ALREADY_CONFIGURED */ { CVT, CFGA_INSUFFICENT_CONDITION, 135 "already configured " }, 136 /* CFGA_IB_CONFIG_OP_ERR */ { CVT, CFGA_ERROR, 137 "configure operation failed " }, 138 /* CFGA_IB_UNCONFIG_OP_ERR */ { CVT, CFGA_ERROR, 139 "unconfigure operation failed " }, 140 /* CFGA_IB_OPEN_ERR */ { CVT, CFGA_LIB_ERROR, "Cannot open " }, 141 /* CFGA_IB_IOCTL_ERR */ { CVT, CFGA_LIB_ERROR, 142 "Driver ioctl failed " }, 143 /* CFGA_IB_BUSY_ERR */ { CVT, CFGA_SYSTEM_BUSY, " " }, 144 /* CFGA_IB_ALLOC_FAIL */ { CVT, CFGA_LIB_ERROR, 145 "Memory allocation failure " }, 146 /* CFGA_IB_OPNOTSUPP */ { CVT, CFGA_OPNOTSUPP, 147 "Operation not supported " }, 148 /* CFGA_IB_INVAL_APID_ERR */ { CVT, CFGA_LIB_ERROR, 149 "Invalid ap_id supplied " }, 150 /* CFGA_IB_DEVLINK_ERR */ { CVT, CFGA_LIB_ERROR, 151 "Could not find /dev/cfg link for " }, 152 /* CFGA_IB_PRIV_ERR */ { CVT, CFGA_PRIV, " " }, 153 /* CFGA_IB_NVLIST_ERR */ { CVT, CFGA_ERROR, 154 "Internal error (nvlist) " }, 155 /* CFGA_IB_HCA_LIST_ERR */ { CVT, CFGA_ERROR, 156 "Listing HCA's clients failed " }, 157 /* CFGA_IB_HCA_UNCONFIG_ERR */ { CVT, CFGA_ERROR, 158 "Unconfiguring HCA's clients failed " }, 159 /* CFGA_IB_UPD_PKEY_TBLS_ERR */ { CVT, CFGA_ERROR, 160 "Updating P_Key tables failed " }, 161 /* CFGA_IB_RCM_HANDLE_ERR */ { CVT, CFGA_ERROR, 162 "Opening ib.conf file failed " }, 163 /* CFGA_IB_LOCK_FILE_ERR */ { CVT, CFGA_LIB_ERROR, 164 "Locking ib.conf file failed " }, 165 /* CFGA_IB_UNLOCK_FILE_ERR */ { CVT, CFGA_LIB_ERROR, 166 "Unlocking ib.conf file failed " }, 167 /* CFGA_IB_COMM_INVAL_ERR */ { CVT, CFGA_INVAL, 168 "Communication type incorrectly specified " }, 169 /* CFGA_IB_SVC_INVAL_ERR */ { CVT, CFGA_INVAL, 170 "Service name incorrectly specified " }, 171 /* CFGA_IB_SVC_LEN_ERR_ERR */ { CVT, CFGA_INVAL, 172 "Service name len should be <= to 4, " }, 173 /* CFGA_IB_SVC_EXISTS_ERR */ { CVT, CFGA_INVAL, " "}, 174 /* CFGA_IB_SVC_NO_EXIST_ERR */ { CVT, CFGA_INVAL, " " }, 175 /* CFGA_IB_UCFG_CLNTS_ERR */ { CVT, CFGA_INVAL, 176 "unconfig_clients failed for HCA " }, 177 /* CFGA_IB_INVALID_OP_ERR */ { CVT, CFGA_OPNOTSUPP, "on " }, 178 /* CFGA_IB_RCM_HANDLE */ { CVT, CFGA_ERROR, 179 "cannot get RCM handle "}, 180 /* CFGA_IB_RCM_ONLINE_ERR */ { CVT, CFGA_SYSTEM_BUSY, 181 "failed to online: "}, 182 /* CFGA_IB_RCM_OFFLINE_ERR */ { CVT, CFGA_SYSTEM_BUSY, 183 "failed to offline: "} 184 }; 185 186 /* 187 * these are the only valid sub-options for services. 188 */ 189 static char *ib_service_subopts[] = { 190 "comm", 191 "service", 192 NULL 193 }; 194 195 /* Communication Service name : "port" or "vppa" or "hca-svc" */ 196 static char *comm_name = NULL; 197 198 char *service_name = NULL; /* service name */ 199 ib_service_type_t service_type = IB_NONE; /* service type */ 200 201 202 /* ========================================================================= */ 203 /* 204 * The next two funcs are imported from cfgadm_scsi. 205 * ib_physpath_to_devlink is the only func directly used by cfgadm_ib. 206 * ib_get_link supports it. 207 */ 208 209 /* 210 * Function: 211 * ib_get_link 212 * Input: 213 * devlink - devlink for the device path 214 * arg - argument passed to this "walker" function 215 * Output: 216 * NONE 217 * Returns: 218 * Continue "walking" or not 219 * Description: 220 * Routine to search the /dev directory or a subtree of /dev. 221 */ 222 static int 223 ib_get_link(di_devlink_t devlink, void *arg) 224 { 225 walk_link_t *larg = (walk_link_t *)arg; 226 227 /* 228 * When path is specified, it's the node path without minor 229 * name. Therefore, the ../.. prefixes needs to be stripped. 230 */ 231 if (larg->path) { 232 char *content = (char *)di_devlink_content(devlink); 233 char *start = strstr(content, "/devices/"); 234 235 /* line content must have minor node */ 236 if (start == NULL || 237 strncmp(start, larg->path, larg->len) != 0 || 238 start[larg->len] != ':') { 239 return (DI_WALK_CONTINUE); 240 } 241 } 242 243 *(larg->linkpp) = strdup(di_devlink_path(devlink)); 244 return (DI_WALK_TERMINATE); 245 } 246 247 248 /* 249 * Function: 250 * ib_physpath_to_devlink 251 * Input: 252 * node_path - Physical path of the ap_id node 253 * Output: 254 * logpp - Logical path to the ap_id node 255 * l_errnop - "errno" 256 * Returns: 257 * ICFGA_OK if everything was fine; otherwise an error with 258 * l_errnop set. 259 * Description: 260 * Given a physical path to an ap_id ensure that it exists 261 */ 262 /* ARGSUSED */ 263 static icfga_ret_t 264 ib_physpath_to_devlink(char *node_path, char **logpp, int *l_errnop) 265 { 266 char *minor_path; 267 walk_link_t larg; 268 di_devlink_handle_t hdl; 269 270 if ((hdl = di_devlink_init(NULL, 0)) == NULL) { 271 *l_errnop = errno; 272 return (ICFGA_LIB_ERR); 273 } 274 275 *logpp = NULL; 276 larg.linkpp = logpp; 277 minor_path = (char *)node_path + strlen("/devices"); 278 larg.path = NULL; 279 larg.len = 0; 280 281 (void) di_devlink_walk(hdl, "^cfg/", minor_path, DI_PRIMARY_LINK, 282 (void *)&larg, ib_get_link); 283 284 di_devlink_fini(&hdl); 285 286 if (*logpp == NULL) { 287 *l_errnop = errno; 288 return (ICFGA_LIB_ERR); 289 } 290 291 return (ICFGA_OK); 292 } 293 294 295 /* ========================================================================= */ 296 /* Utilities */ 297 298 /* 299 * Function: 300 * ib_get_msg 301 * Input: 302 * msg_index - Index into the message table 303 * msg_tbl - the message table 304 * tbl_size - size of the message table 305 * Output: 306 * NONE 307 * Returns: 308 * Message string if valid, otherwise an error 309 * Description: 310 * Given the index into a table (msgcvt_t) of messages, 311 * get the message string, converting it to the proper 312 * locale if necessary. 313 * 314 * NOTE: See cfga_ib.h 315 */ 316 static const char * 317 ib_get_msg(uint_t msg_index, msgcvt_t *msg_tbl, uint_t tbl_size) 318 { 319 if (msg_index >= tbl_size) { 320 DPRINTF("get_error_msg: bad error msg index: %d\n", msg_index); 321 msg_index = CFGA_IB_UNKNOWN; 322 } 323 324 return ((msg_tbl[msg_index].intl) ? 325 dgettext(TEXT_DOMAIN, msg_tbl[msg_index].msgstr) : 326 msg_tbl[msg_index].msgstr); 327 } 328 329 330 /* 331 * Function: 332 * ib_set_msg 333 * Input: 334 * NONE 335 * Output: 336 * ret_str - Returned "message" string. 337 * Returns: 338 * NONE 339 * Description: 340 * Allocates and creates a message string (in *ret_str), 341 * by concatenating all the (char *) args together, in order. 342 * Last arg MUST be NULL. 343 */ 344 static void 345 ib_set_msg(char **ret_str, ...) 346 { 347 char *str; 348 size_t total_len, ret_str_len; 349 va_list valist; 350 351 va_start(valist, ret_str); 352 353 total_len = (*ret_str == NULL) ? 0 : strlen(*ret_str); 354 355 while ((str = va_arg(valist, char *)) != NULL) { 356 size_t len = strlen(str); 357 char *old_str = *ret_str; 358 359 ret_str_len = total_len + len + 1; 360 *ret_str = (char *)realloc(*ret_str, ret_str_len); 361 if (*ret_str == NULL) { 362 free(old_str); 363 DPRINTF("ib_set_msg: realloc failed.\n"); 364 va_end(valist); 365 return; 366 } 367 368 (void) strlcpy(*ret_str + total_len, str, ret_str_len); 369 total_len += len; 370 } 371 372 va_end(valist); 373 } 374 375 376 /* 377 * Function: 378 * ib_err_msg 379 * Input: 380 * ap_id - The attachment point of an IB fabric 381 * Output: 382 * errstring - Fill in the error msg string 383 * l_errno - The "errno" to be filled in. 384 * Returns: 385 * CFGA_IB_OK if we are able to fill in error msg; 386 * otherwise emit an error. 387 * Description: 388 * Error message handling. 389 * 390 * For the rv passed in, looks up the corresponding error message 391 * string(s), internationalized it if necessary, and concatenates 392 * it into a new memory buffer, and points *errstring to it. 393 * Note not all "rv"s will result in an error message return, as 394 * not all error conditions warrant a IB-specific error message. 395 * 396 * Some messages may display ap_id or errno, which is why they are 397 * passed in. 398 */ 399 static cfga_err_t 400 ib_err_msg(char **errstring, cfga_ib_ret_t rv, const char *ap_id, int l_errno) 401 { 402 char *errno_str; 403 404 if (errstring == NULL) { 405 return (ib_error_msgs[rv].cfga_err); 406 } 407 408 /* Generate the appropriate IB-specific error message(s) (if any). */ 409 switch (rv) { 410 case CFGA_IB_OK: /* Special case - do nothing. */ 411 break; 412 case CFGA_IB_AP_ERR: 413 case CFGA_IB_UNKNOWN: 414 case CFGA_IB_INTERNAL_ERR: 415 case CFGA_IB_OPTIONS_ERR: 416 case CFGA_IB_ALLOC_FAIL: 417 /* These messages require no additional strings passed. */ 418 ib_set_msg(errstring, ERR_STR(rv), NULL); 419 break; 420 case CFGA_IB_NOT_CONNECTED: 421 case CFGA_IB_NOT_CONFIGURED: 422 case CFGA_IB_ALREADY_CONNECTED: 423 case CFGA_IB_ALREADY_CONFIGURED: 424 case CFGA_IB_CONFIG_OP_ERR: 425 case CFGA_IB_UNCONFIG_OP_ERR: 426 case CFGA_IB_BUSY_ERR: 427 case CFGA_IB_DEVLINK_ERR: 428 case CFGA_IB_RCM_HANDLE_ERR: 429 case CFGA_IB_RCM_ONLINE_ERR: 430 case CFGA_IB_RCM_OFFLINE_ERR: 431 case CFGA_IB_DEVCTL_ERR: 432 case CFGA_IB_COMM_INVAL_ERR: 433 case CFGA_IB_SVC_INVAL_ERR: 434 case CFGA_IB_SVC_LEN_ERR: 435 case CFGA_IB_SVC_EXISTS_ERR: 436 case CFGA_IB_SVC_NO_EXIST_ERR: 437 case CFGA_IB_LOCK_FILE_ERR: 438 case CFGA_IB_CONFIG_FILE_ERR: 439 case CFGA_IB_UNLOCK_FILE_ERR: 440 case CFGA_IB_UCFG_CLNTS_ERR: 441 case CFGA_IB_INVALID_OP_ERR: 442 /* These messages also print ap_id. */ 443 ib_set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "", NULL); 444 break; 445 case CFGA_IB_IOCTL_ERR: /* These messages also print errno. */ 446 case CFGA_IB_NVLIST_ERR: 447 errno_str = l_errno ? strerror(l_errno) : ""; 448 ib_set_msg(errstring, ERR_STR(rv), errno_str, 449 l_errno ? "\n" : "", NULL); 450 break; 451 case CFGA_IB_OPEN_ERR: /* This messages also prints apid and errno. */ 452 case CFGA_IB_PRIV_ERR: 453 case CFGA_IB_HCA_LIST_ERR: 454 case CFGA_IB_OPNOTSUPP: 455 case CFGA_IB_INVAL_ARG_ERR: 456 case CFGA_IB_INVAL_APID_ERR: 457 case CFGA_IB_HCA_UNCONFIG_ERR: 458 case CFGA_IB_UPD_PKEY_TBLS_ERR: 459 errno_str = l_errno ? strerror(l_errno) : ""; 460 ib_set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "\n", 461 errno_str, l_errno ? "\n" : "", NULL); 462 break; 463 default: 464 DPRINTF("ib_err_msg: Unrecognized message index: %d\n", rv); 465 ib_set_msg(errstring, ERR_STR(CFGA_IB_INTERNAL_ERR), NULL); 466 } 467 468 /* 469 * Determine the proper error code to send back to the cfgadm library. 470 */ 471 return (ib_error_msgs[rv].cfga_err); 472 } 473 474 475 /* 476 * Function: 477 * ib_verify_valid_apid 478 * Input: 479 * ap_id - The attachment point of an IB fabric 480 * Output: 481 * NONE 482 * Returns: 483 * 0 if ap_id is valid; otherwise -1 484 * Description: 485 * Check if ap_id is valid or not. 486 * Ensure the ap_id passed is in the correct (physical ap_id) form: 487 * path/device:xx[.xx]+ 488 * where xx is a one or two-digit number. 489 * 490 * Note the library always calls the plugin with a physical ap_id. 491 * Called by ib_verify_params(). 492 */ 493 static int 494 ib_verify_valid_apid(const char *ap_id) 495 { 496 char *l_ap_id; 497 498 if (ap_id == NULL) { 499 return (-1); 500 } 501 502 l_ap_id = strchr(ap_id, *MINOR_SEP); 503 l_ap_id++; 504 505 /* fabric apids */ 506 if (strstr((char *)ap_id, IBNEX_FABRIC) != NULL) { 507 DPRINTF("ib_valid_apid: l_apid = %s\n", l_ap_id); 508 /* if the ap_id is "ib::" then report an error */ 509 if ((strlen(l_ap_id) == strlen(IBNEX_FABRIC) + 1) || 510 (strlen(l_ap_id) == strlen(IBNEX_FABRIC) + 2)) { 511 return (-1); 512 } 513 514 if (strstr(l_ap_id, "...") != NULL) { 515 return (-1); 516 } 517 518 } else { /* HCA ap_ids */ 519 /* ap_id has 1..2 or more than 2 dots */ 520 if (strstr(l_ap_id, "..") != NULL) { 521 return (-1); 522 } 523 } 524 525 return (0); 526 } 527 528 529 /* 530 * Function: 531 * ib_verify_params 532 * Input: 533 * ap_id - The attachment point of an IB fabric 534 * options - command options passed by the cfgadm(8) 535 * errstring - This contains error msg if command fails 536 * Output: 537 * NONE 538 * Returns: 539 * CFGA_IB_OK if parameters are valid; otherwise emit an error. 540 * Description: 541 * Check if "options" and "errstring" are valid and if ap_id is 542 * valid or not. 543 */ 544 static cfga_ib_ret_t 545 ib_verify_params(const char *ap_id, const char *options, char **errstring) 546 { 547 if (errstring != NULL) { 548 *errstring = NULL; 549 } 550 551 if (options != NULL) { 552 DPRINTF("ib_verify_params: h/w-specific options not " 553 "supported.\n"); 554 return (CFGA_IB_OPTIONS_ERR); 555 } 556 557 if (ib_verify_valid_apid(ap_id) != 0) { 558 DPRINTF("ib_verify_params: not an IB ap_id.\n"); 559 return (CFGA_IB_AP_ERR); 560 } 561 return (CFGA_IB_OK); 562 } 563 564 565 /* 566 * Function: 567 * ib_cleanup_after_devctl_cmd 568 * Input: 569 * devctl_hdl - Handler to devctl 570 * user_nvlistp - Name-value-pair list pointer 571 * Output: 572 * NONE 573 * Returns: 574 * NONE 575 * Description: 576 * Cleanup an initialization/setup done in the next function i.e. 577 * ib_setup_for_devctl_cmd(). 578 */ 579 static void 580 ib_cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl, nvlist_t *user_nvlist) 581 { 582 if (user_nvlist != NULL) { 583 nvlist_free(user_nvlist); 584 } 585 586 if (devctl_hdl != NULL) { 587 devctl_release(devctl_hdl); 588 } 589 } 590 591 592 /* 593 * Function: 594 * ib_setup_for_devctl_cmd 595 * Input: 596 * ap_id - Attachment point for the IB device in question 597 * use_static_ap_id - Whether to use static ap_id or not flag 598 * Output: 599 * devctl_hdl - Handler to devctl 600 * user_nvlistp - Name-value-pair list pointer 601 * Returns: 602 * CFGA_IB_OK if it succeeds or an appropriate error. 603 * Description: 604 * For any IB device that is doing a cfgadm operation this function 605 * sets up a devctl_hdl and allocates a nvlist_t. The devctl_hdl 606 * is acquired using libdevice APIs. The nvlist_t is filled up with 607 * the ap_id (as a string). This nvlist_t is looked up in the kernel 608 * to figure out which ap_id we are currently dealing with. 609 * 610 * "use_static_ap_id" flag tells if one should do a devctl_ap_acquire 611 * with IB_STATIC_APID or not. NOTE: We need an actual file-system 612 * vnode to do a devctl_ap_acquire. 613 * 614 * NOTE: always call ib_cleanup_after_devctl_cmd() after this function. 615 */ 616 static cfga_ib_ret_t 617 ib_setup_for_devctl_cmd(char *ap_id, boolean_t use_static_ap_id, 618 devctl_hdl_t *devctl_hdl, nvlist_t **user_nvlistp) 619 { 620 char *apid = (use_static_ap_id == B_TRUE) ? IB_STATIC_APID : ap_id; 621 622 /* Get a handle to the ap */ 623 if ((*devctl_hdl = devctl_ap_acquire(apid, 0)) == NULL) { 624 DPRINTF("ib_setup_for_devctl_cmd: devctl_ap_acquire " 625 "errno: %d\n", errno); 626 ib_cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp); 627 return (CFGA_IB_DEVCTL_ERR); 628 } 629 630 /* Set up to pass dynamic ap_id down to driver */ 631 if (nvlist_alloc(user_nvlistp, NV_UNIQUE_NAME_TYPE, 0) != 0) { 632 DPRINTF("ib_setup_for_devctl: nvlist_alloc errno: %d\n", errno); 633 *user_nvlistp = NULL; /* Prevent possible incorrect free in */ 634 /* ib_cleanup_after_devctl_cmd */ 635 ib_cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp); 636 return (CFGA_IB_NVLIST_ERR); 637 } 638 639 /* create a "string" entry */ 640 if (nvlist_add_string(*user_nvlistp, IB_APID, ap_id) == -1) { 641 DPRINTF("ib_setup_for_devctl_cmd: nvlist_add_string failed. " 642 "errno: %d\n", errno); 643 ib_cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp); 644 return (CFGA_IB_NVLIST_ERR); 645 } 646 647 return (CFGA_IB_OK); 648 } 649 650 651 /* 652 * Function: 653 * ib_device_configured 654 * Input: 655 * hdl - Handler to devctl 656 * nvl - Name-value-pair list pointer 657 * Output: 658 * rstate - Receptacle state for the apid 659 * Returns: 660 * CFGA_IB_OK if it succeeds or an appropriate error. 661 * Description: 662 * Checks if there is a device actually configured to the ap? If so, 663 * issues a "devctl" to get the Receptacle state for that ap_id. 664 * If the ap_id is already configured it returns CFGA_IB_OK. 665 * Otherwise it returns a failure. 666 */ 667 static cfga_ib_ret_t 668 ib_device_configured(devctl_hdl_t hdl, nvlist_t *nvl, ap_rstate_t *rstate) 669 { 670 cfga_ib_ret_t rv; 671 devctl_ap_state_t devctl_ap_state; 672 673 /* get ap_id's "devctl_ap_state" first */ 674 if (devctl_ap_getstate(hdl, nvl, &devctl_ap_state) == -1) { 675 DPRINTF("ib_device_configured failed, errno: %d\n", errno); 676 return (CFGA_IB_DEVCTL_ERR); 677 } 678 679 rv = CFGA_IB_ALREADY_CONFIGURED; 680 *rstate = devctl_ap_state.ap_rstate; 681 if (devctl_ap_state.ap_ostate != AP_OSTATE_CONFIGURED) { 682 return (CFGA_IB_NOT_CONFIGURED); 683 } 684 685 return (rv); 686 } 687 688 689 /* 690 * Function: 691 * ib_device_connected 692 * Input: 693 * hdl - Handler to devctl 694 * nvl - Name-value-pair list pointer 695 * Output: 696 * ostate - Occupant state for the apid 697 * Returns: 698 * CFGA_IB_OK if it succeeds or an appropriate error. 699 * Description: 700 * Checks if there is a device actually connected to the ap? If so, 701 * issues a "devctl" to get the Occupant state for that ap_id. 702 * If the ap_id is already connected it returns CFGA_IB_OK. 703 * Otherwise it returns a failure. 704 */ 705 static cfga_ib_ret_t 706 ib_device_connected(devctl_hdl_t hdl, nvlist_t *list, ap_ostate_t *ostate) 707 { 708 cfga_ib_ret_t rv = CFGA_IB_ALREADY_CONNECTED; 709 devctl_ap_state_t devctl_ap_state; 710 711 if (devctl_ap_getstate(hdl, list, &devctl_ap_state) == -1) { 712 DPRINTF("ib_device_connected failed, errno: %d\n", errno); 713 return (CFGA_IB_DEVCTL_ERR); 714 } 715 716 *ostate = devctl_ap_state.ap_ostate; 717 if (devctl_ap_state.ap_rstate != AP_RSTATE_CONNECTED) { 718 return (CFGA_IB_NOT_CONNECTED); 719 } 720 721 return (rv); 722 } 723 724 725 /* 726 * Function: 727 * ib_do_control_ioctl 728 * Input: 729 * ap_id - The dynamic attachment point of an IB device 730 * sub_cmd1 - Sub Command 1 to DEVCTL_AP_CONTROL devctl 731 * sub_cmd2 - Sub Command 2 to DEVCTL_AP_CONTROL devctl 732 * (Mandatory except for IBNEX_NUM_HCA_NODES, 733 * IBNEX_NUM_DEVICE_NODES, 734 * IBNEX_UPDATE_PKEY_TBLS & 735 * IBNEX_UPDATE_IOC_CONF) 736 * misc_arg - optional arguments to DEVCTL_AP_CONTROL devctl 737 * Output: 738 * descrp - Buffer containing data back from kernel 739 * sizep - Length of the buffer back from kernel 740 * Returns: 741 * CFGA_IB_OK if it succeeds or an appropriate error. 742 * Description: 743 * Issues DEVCTL_AP_CONTROL devctl with sub_cmd1 first which actually 744 * queries the IBNEX module in the kernel on the size of the data to 745 * be returned. 746 * 747 * Next issues DEVCTL_AP_CONTROL devctl with a buffer of that much 748 * size and gets the actual data back. 749 * Passes the data and the size back to caller. 750 */ 751 static cfga_ib_ret_t 752 ib_do_control_ioctl(char *ap_id, uint_t sub_cmd1, uint_t sub_cmd2, 753 uint_t misc_arg, void **descrp, size_t *sizep) 754 { 755 int fd = -1; 756 uint32_t local_size = 0; 757 cfga_ib_ret_t rv = CFGA_IB_OK; 758 struct ibnex_ioctl_data ioctl_data; 759 760 /* try to open the ONLY static ap_id */ 761 if ((fd = open(IB_STATIC_APID, O_RDONLY)) == -1) { 762 DPRINTF("ib_do_control_ioctl: open failed: " 763 "errno = %d\n", errno); 764 /* Provides a more useful error msg */ 765 rv = (errno == EBUSY) ? CFGA_IB_BUSY_ERR : CFGA_IB_OPEN_ERR; 766 return (rv); 767 } 768 769 /* 770 * Find out first how large a buffer is needed? 771 * NOTE: Ioctls only accept/return a 32-bit int for a get_size 772 * to avoid 32/64 and BE/LE issues. 773 */ 774 ioctl_data.cmd = sub_cmd1; 775 ioctl_data.misc_arg = (uint_t)misc_arg; 776 ioctl_data.buf = (caddr_t)&local_size; 777 ioctl_data.bufsiz = sizeof (local_size); 778 779 /* Pass "ap_id" up for all other commands */ 780 if (sub_cmd1 != IBNEX_NUM_DEVICE_NODES && 781 sub_cmd1 != IBNEX_NUM_HCA_NODES && 782 sub_cmd1 != IBNEX_UPDATE_PKEY_TBLS) { 783 ioctl_data.ap_id = (caddr_t)ap_id; 784 ioctl_data.ap_id_len = strlen(ap_id); 785 786 } else { 787 ioctl_data.ap_id = NULL; 788 ioctl_data.ap_id_len = 0; 789 } 790 791 if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) { 792 DPRINTF("ib_do_control_ioctl: size ioctl ERR, errno: %d\n", 793 errno); 794 (void) close(fd); 795 rv = (errno == EBUSY) ? CFGA_IB_BUSY_ERR : CFGA_IB_IOCTL_ERR; 796 return (rv); 797 } 798 *sizep = local_size; 799 800 /* 801 * Don't do the second ioctl only in these cases 802 * (NOTE: the data is returned in the first ioctl itself; if any) 803 */ 804 if (sub_cmd1 == IBNEX_NUM_DEVICE_NODES || 805 sub_cmd1 == IBNEX_NUM_HCA_NODES || 806 sub_cmd1 == IBNEX_UPDATE_PKEY_TBLS || 807 sub_cmd1 == IBNEX_UPDATE_IOC_CONF) { 808 (void) close(fd); 809 return (rv); 810 } 811 812 if (local_size == 0 || (*descrp = malloc(*sizep)) == NULL) { 813 DPRINTF("ib_do_control_ioctl: malloc failed\n"); 814 (void) close(fd); 815 return (CFGA_IB_ALLOC_FAIL); 816 } 817 818 /* Get the data */ 819 ioctl_data.cmd = sub_cmd2; 820 ioctl_data.buf = (caddr_t)*descrp; 821 ioctl_data.bufsiz = *sizep; 822 823 if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) { 824 DPRINTF("ib_do_control_ioctl: ioctl failed: errno:%d\n", errno); 825 if (*descrp != NULL) { 826 free(*descrp); 827 *descrp = NULL; 828 } 829 rv = (errno == EBUSY) ? CFGA_IB_BUSY_ERR : CFGA_IB_IOCTL_ERR; 830 } 831 832 (void) close(fd); 833 return (rv); 834 } 835 836 837 /* ========================================================================== */ 838 /* Entry points */ 839 840 /* 841 * Function: 842 * cfga_change_state 843 * Input: 844 * state_change_cmd - Argument to the cfgadm -c command 845 * ap_id - The attachment point of an IB fabric 846 * options - State Change command options passed by the cfgadm(8) 847 * confp - Whether this command requires confirmation? 848 * msgp - cfgadm error message for this plugin 849 * errstring - This contains error msg if command fails 850 * flags - cfgadm(8) flags 851 * Output: 852 * NONE 853 * Returns: 854 * If the command succeeded perform the cfgadm -c <cmd>; 855 * otherwise emit an error 856 * Description: 857 * Do cfgadm -c <cmd> 858 */ 859 /*ARGSUSED*/ 860 cfga_err_t 861 cfga_change_state(cfga_cmd_t state_change_cmd, const char *ap_id, 862 const char *options, struct cfga_confirm *confp, struct cfga_msg *msgp, 863 char **errstring, cfga_flags_t flags) 864 { 865 int ret; 866 char *devpath; 867 nvlist_t *nvl = NULL; 868 boolean_t static_ap_id = B_TRUE; 869 ap_rstate_t rstate; 870 ap_ostate_t ostate; 871 devctl_hdl_t hdl = NULL; 872 cfga_ib_ret_t rv = CFGA_IB_OK; 873 874 if ((rv = ib_verify_params(ap_id, options, errstring)) != CFGA_IB_OK) { 875 (void) cfga_help(msgp, options, flags); 876 return (ib_err_msg(errstring, CFGA_IB_INVAL_APID_ERR, 877 ap_id, errno)); 878 } 879 880 /* 881 * All subcommands which can change state of device require 882 * root privileges. 883 */ 884 if (geteuid() != 0) { 885 return (ib_err_msg(errstring, CFGA_IB_PRIV_ERR, ap_id, errno)); 886 } 887 888 if (strstr((char *)ap_id, IB_FABRIC_APID_STR) == NULL) 889 static_ap_id = B_FALSE; 890 891 if ((rv = ib_setup_for_devctl_cmd((char *)ap_id, static_ap_id, 892 &hdl, &nvl)) != CFGA_IB_OK) { 893 ib_cleanup_after_devctl_cmd(hdl, nvl); 894 return (ib_err_msg(errstring, rv, ap_id, errno)); 895 } 896 897 switch (state_change_cmd) { 898 case CFGA_CMD_CONFIGURE: 899 rv = ib_device_connected(hdl, nvl, &ostate); 900 if (rv != CFGA_IB_ALREADY_CONNECTED) { 901 ret = (rv != CFGA_IB_NOT_CONNECTED) ? 902 CFGA_IB_CONFIG_OP_ERR : rv; 903 ib_cleanup_after_devctl_cmd(hdl, nvl); 904 return (ib_err_msg(errstring, ret, ap_id, errno)); 905 } 906 907 if (rv == CFGA_IB_ALREADY_CONNECTED) { 908 /* 909 * special case handling for 910 * SLM based cfgadm disconnects 911 */ 912 if (ostate == AP_OSTATE_CONFIGURED) { 913 ib_cleanup_after_devctl_cmd(hdl, nvl); 914 return (ib_err_msg(errstring, 915 CFGA_IB_ALREADY_CONFIGURED, ap_id, 916 errno)); 917 } 918 } 919 920 921 rv = CFGA_IB_OK; /* Other status don't matter */ 922 923 if (devctl_ap_configure(hdl, nvl) != 0) { 924 DPRINTF("cfga_change_state: devctl_ap_configure " 925 "failed. errno: %d\n", errno); 926 rv = CFGA_IB_CONFIG_OP_ERR; 927 break; 928 } 929 930 devpath = ib_get_devicepath(ap_id); 931 if (devpath == NULL) { 932 int i; 933 934 /* 935 * try for some time as IB hotplug thread 936 * takes a while to create the path 937 * and then eventually give up 938 */ 939 for (i = 0; 940 i < IB_RETRY_DEVPATH && (devpath == NULL); i++) { 941 sleep(IB_MAX_DEVPATH_DELAY); 942 devpath = ib_get_devicepath(ap_id); 943 } 944 945 if (devpath == NULL) { 946 DPRINTF("cfga_change_state: get device " 947 "path failed i = %d\n", i); 948 rv = CFGA_IB_CONFIG_OP_ERR; 949 break; 950 } 951 } 952 S_FREE(devpath); 953 break; 954 955 case CFGA_CMD_UNCONFIGURE: 956 if ((rv = ib_device_connected(hdl, nvl, &ostate)) != 957 CFGA_IB_ALREADY_CONNECTED) { 958 ib_cleanup_after_devctl_cmd(hdl, nvl); 959 if (rv == CFGA_IB_DEVCTL_ERR) 960 rv = CFGA_IB_INVALID_OP_ERR; 961 return (ib_err_msg(errstring, rv, ap_id, errno)); 962 } 963 964 /* check if it is already unconfigured */ 965 if ((rv = ib_device_configured(hdl, nvl, &rstate)) == 966 CFGA_IB_NOT_CONFIGURED) { 967 ib_cleanup_after_devctl_cmd(hdl, nvl); 968 return (ib_err_msg(errstring, rv, ap_id, errno)); 969 } 970 971 rv = CFGA_IB_OK; /* Other statuses don't matter */ 972 973 if (!ib_confirm(confp, IB_CONFIRM1)) { 974 ib_cleanup_after_devctl_cmd(hdl, nvl); 975 return (CFGA_NACK); 976 } 977 978 devpath = ib_get_devicepath(ap_id); 979 if (devpath == NULL) { 980 DPRINTF("cfga_change_state: get device path failed\n"); 981 rv = CFGA_IB_UNCONFIG_OP_ERR; 982 break; 983 } 984 985 if ((rv = ib_rcm_offline(ap_id, errstring, devpath, flags)) != 986 CFGA_IB_OK) { 987 S_FREE(devpath); 988 break; 989 } 990 991 ret = devctl_ap_unconfigure(hdl, nvl); 992 if (ret != 0) { 993 DPRINTF("cfga_change_state: devctl_ap_unconfigure " 994 "failed with errno: %d\n", errno); 995 rv = CFGA_IB_UNCONFIG_OP_ERR; 996 if (errno == EBUSY) { 997 rv = CFGA_IB_BUSY_ERR; 998 } 999 (void) ib_rcm_online(ap_id, errstring, devpath, flags); 1000 1001 } else { 1002 (void) ib_rcm_remove(ap_id, errstring, devpath, flags); 1003 } 1004 1005 S_FREE(devpath); 1006 break; 1007 1008 case CFGA_CMD_LOAD: 1009 case CFGA_CMD_UNLOAD: 1010 case CFGA_CMD_CONNECT: 1011 case CFGA_CMD_DISCONNECT: 1012 (void) cfga_help(msgp, options, flags); 1013 rv = CFGA_IB_OPNOTSUPP; 1014 break; 1015 1016 case CFGA_CMD_NONE: 1017 default: 1018 (void) cfga_help(msgp, options, flags); 1019 rv = CFGA_IB_INTERNAL_ERR; 1020 } 1021 1022 ib_cleanup_after_devctl_cmd(hdl, nvl); 1023 return (ib_err_msg(errstring, rv, ap_id, errno)); 1024 } 1025 1026 1027 /* 1028 * Function: 1029 * cfga_private_func 1030 * Input: 1031 * func - The private function (passed w/ -x option) 1032 * ap_id - The attachment point of an IB fabric 1033 * options - Private function command options passed 1034 * by the cfgadm(8) 1035 * confp - Whether this command requires confirmation? 1036 * msgp - cfgadm error message for this plugin 1037 * errstring - This contains error msg if command fails 1038 * flags - cfgadm(8) flags 1039 * Output: 1040 * NONE 1041 * Returns: 1042 * If the command succeeded perform the 'cfgadm -x <func>'; otherwise 1043 * return failure. 1044 * Description: 1045 * Do cfgadm -x <func> 1046 */ 1047 /*ARGSUSED*/ 1048 cfga_err_t 1049 cfga_private_func(const char *func, const char *ap_id, const char *options, 1050 struct cfga_confirm *confp, struct cfga_msg *msgp, char **errstring, 1051 cfga_flags_t flags) 1052 { 1053 int len, ret, count = 0; 1054 char *clnt_name = NULL, *alt_hca = NULL; 1055 char *clnt_apid = NULL, *clnt_devpath = NULL; 1056 char *name, *msg = NULL; 1057 char *fab_apid = strstr((char *)ap_id, IBNEX_FABRIC); 1058 size_t info_len = 0; 1059 uchar_t *info = NULL; 1060 nvlist_t *nvl; 1061 nvpair_t *nvp = NULL; 1062 ap_rstate_t rstate; 1063 devctl_hdl_t hdl = NULL; 1064 cfga_ib_ret_t rv; 1065 1066 if ((rv = ib_verify_params(ap_id, NULL, errstring)) != CFGA_IB_OK) { 1067 DPRINTF("cfga_private_func: ib_verify_params " 1068 "failed with rv: %d\n", rv); 1069 return (ib_err_msg(errstring, rv, ap_id, errno)); 1070 } 1071 1072 if (func == NULL) { 1073 DPRINTF("cfga_private_func: func is NULL\n"); 1074 return (ib_err_msg(errstring, CFGA_IB_INVAL_ARG_ERR, ap_id, 1075 errno)); 1076 } 1077 1078 /* 1079 * check first if IB static ap_id is "configured" for use 1080 */ 1081 if (fab_apid != NULL) { 1082 if ((rv = ib_setup_for_devctl_cmd(fab_apid, B_TRUE, &hdl, 1083 &nvl)) != CFGA_IB_OK) { 1084 ib_cleanup_after_devctl_cmd(hdl, nvl); 1085 return (ib_err_msg(errstring, rv, ap_id, errno)); 1086 } 1087 if ((rv = ib_device_configured(hdl, nvl, &rstate)) == 1088 CFGA_IB_NOT_CONFIGURED) { 1089 return (ib_err_msg(errstring, rv, ap_id, errno)); 1090 } 1091 ib_cleanup_after_devctl_cmd(hdl, nvl); 1092 } 1093 1094 rv = CFGA_IB_OK; 1095 DPRINTF("cfga_private_func: func is %s\n", func); 1096 if (strcmp(func, IB_LIST_HCA_CLIENTS) == 0) { /* -x list_clients */ 1097 1098 /* only supported on HCA ap_ids */ 1099 if (fab_apid != NULL) { 1100 DPRINTF("cfga_private_func: fabric apid supplied\n"); 1101 return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR, 1102 ap_id, errno)); 1103 } 1104 1105 if ((msg = (char *)calloc(256, 1)) == NULL) { 1106 DPRINTF("cfga_private_func: malloc for msg failed. " 1107 "errno: %d\n", errno); 1108 return (ib_err_msg(errstring, CFGA_IB_ALLOC_FAIL, 1109 ap_id, errno)); 1110 } 1111 1112 if ((rv = ib_do_control_ioctl((char *)ap_id, IBNEX_HCA_LIST_SZ, 1113 IBNEX_HCA_LIST_INFO, 0, (void **)&info, &info_len)) != 0) { 1114 DPRINTF("cfga_private_func: " 1115 "ib_do_control_ioctl list failed :%d\n", rv); 1116 S_FREE(msg); 1117 return (ib_err_msg(errstring, CFGA_IB_HCA_LIST_ERR, 1118 ap_id, errno)); 1119 } 1120 1121 if (nvlist_unpack((char *)info, info_len, &nvl, 0)) { 1122 DPRINTF("cfga_private_func: " 1123 "nvlist_unpack 2 failed %p\n", info); 1124 S_FREE(info); 1125 S_FREE(msg); 1126 return (ib_err_msg(errstring, CFGA_IB_NVLIST_ERR, ap_id, 1127 errno)); 1128 } 1129 1130 (void) snprintf(msg, 256, "Ap_Id\t\t\t IB Client\t\t " 1131 "Alternate HCA\n"); 1132 cfga_msg(msgp, msg); 1133 1134 /* Walk the NVPAIR data */ 1135 while (nvp = nvlist_next_nvpair(nvl, nvp)) { 1136 name = nvpair_name(nvp); 1137 if (strcmp(name, "Client") == 0) { 1138 (void) nvpair_value_string(nvp, &clnt_name); 1139 ++count; 1140 } else if (strcmp(name, "Alt_HCA") == 0) { 1141 (void) nvpair_value_string(nvp, &alt_hca); 1142 ++count; 1143 } else if (strcmp(name, "ApID") == 0) { 1144 (void) nvpair_value_string(nvp, &clnt_apid); 1145 ++count; 1146 } 1147 1148 /* check at the end; print message per client found */ 1149 if (count == 3) { 1150 count = 0; 1151 (void) snprintf(msg, 256, "%-30s %-25s %s\n", 1152 clnt_apid, clnt_name, alt_hca); 1153 cfga_msg(msgp, msg); 1154 } 1155 } /* end of while */ 1156 1157 S_FREE(info); 1158 S_FREE(msg); 1159 nvlist_free(nvl); 1160 1161 /* -x unconfig_clients */ 1162 } else if (strcmp(func, IB_UNCONFIG_HCA_CLIENTS) == 0) { 1163 /* 1164 * -x unconfig_clients changes state by calling into RCM. 1165 * It needs root privileges. 1166 */ 1167 if (geteuid() != 0) { 1168 return (ib_err_msg(errstring, CFGA_IB_PRIV_ERR, ap_id, 1169 errno)); 1170 } 1171 1172 /* only supported on HCA ap_ids */ 1173 if (fab_apid != NULL) { 1174 DPRINTF("cfga_private_func: fabric apid supplied\n"); 1175 return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR, 1176 ap_id, errno)); 1177 } 1178 1179 /* 1180 * Check w/ user if it is ok to do this operation 1181 * If the user fails to confirm, bailout 1182 */ 1183 if (!ib_confirm(confp, IB_CONFIRM3)) 1184 return (CFGA_NACK); 1185 1186 /* Get device-paths of all the IOC/Port/Pseudo devices */ 1187 rv = ib_do_control_ioctl((char *)ap_id, IBNEX_UNCFG_CLNTS_SZ, 1188 IBNEX_UNCFG_CLNTS_INFO, 0, (void **)&info, &info_len); 1189 if (rv != 0) { 1190 DPRINTF("cfga_private_func: ib_do_control_ioctl " 1191 "failed :%d\n", rv); 1192 return (ib_err_msg(errstring, CFGA_IB_HCA_UNCONFIG_ERR, 1193 ap_id, errno)); 1194 } 1195 1196 if (nvlist_unpack((char *)info, info_len, &nvl, 0)) { 1197 DPRINTF("cfga_private_func: nvlist_unpack failed %p\n", 1198 info); 1199 S_FREE(info); 1200 return (ib_err_msg(errstring, CFGA_IB_NVLIST_ERR, ap_id, 1201 errno)); 1202 } 1203 1204 ret = 0; 1205 1206 /* Call RCM Offline on all device paths */ 1207 while (nvp = nvlist_next_nvpair(nvl, nvp)) { 1208 name = nvpair_name(nvp); 1209 if (strcmp(name, "devpath") == 0) { 1210 (void) nvpair_value_string(nvp, &clnt_devpath); 1211 ++count; 1212 } else if (strcmp(name, "ApID") == 0) { 1213 (void) nvpair_value_string(nvp, &clnt_apid); 1214 ++count; 1215 } 1216 1217 /* handle the client unconfigure now */ 1218 if (count == 2) { 1219 count = 0; /* reset count */ 1220 1221 DPRINTF("cfga_private_func: client apid = %s, " 1222 "DevPath = %s\n", clnt_apid, clnt_devpath); 1223 if ((rv = ib_setup_for_devctl_cmd(clnt_apid, 1224 B_TRUE, &hdl, &nvl)) != CFGA_IB_OK) { 1225 ib_cleanup_after_devctl_cmd(hdl, nvl); 1226 return (ib_err_msg(errstring, rv, 1227 clnt_apid, errno)); 1228 } 1229 1230 if ((rv = ib_device_configured(hdl, nvl, 1231 &rstate)) == CFGA_IB_NOT_CONFIGURED) 1232 continue; 1233 1234 if ((rv = ib_rcm_offline(clnt_apid, errstring, 1235 clnt_devpath, flags)) != CFGA_IB_OK) { 1236 DPRINTF("cfga_private_func: client rcm " 1237 "offline failed for %s, with %d\n", 1238 clnt_devpath, rv); 1239 ret = rv; 1240 continue; 1241 } 1242 1243 if (devctl_ap_unconfigure(hdl, nvl) != 0) { 1244 DPRINTF("cfga_private_func: client " 1245 "unconfigure failed: errno %d\n", 1246 errno); 1247 ret = CFGA_IB_UNCONFIG_OP_ERR; 1248 if (errno == EBUSY) 1249 ret = CFGA_IB_BUSY_ERR; 1250 (void) ib_rcm_online(clnt_apid, 1251 errstring, clnt_devpath, flags); 1252 continue; 1253 } else { 1254 (void) ib_rcm_remove(clnt_apid, 1255 errstring, clnt_devpath, flags); 1256 } 1257 ib_cleanup_after_devctl_cmd(hdl, nvl); 1258 1259 } /* end of if count == 2 */ 1260 1261 } /* end of while */ 1262 1263 S_FREE(info); 1264 nvlist_free(nvl); 1265 if (ret) { 1266 DPRINTF("cfga_private_func: unconfig_clients of %s " 1267 "failed with %d\n", ap_id, ret); 1268 return (ib_err_msg(errstring, CFGA_IB_UCFG_CLNTS_ERR, 1269 ap_id, errno)); 1270 } 1271 1272 /* -x update_pkey_tbls */ 1273 } else if (strcmp(func, IB_UPDATE_PKEY_TBLS) == 0) { 1274 /* 1275 * Check for root privileges. 1276 */ 1277 if (geteuid() != 0) { 1278 return (ib_err_msg(errstring, CFGA_IB_PRIV_ERR, ap_id, 1279 errno)); 1280 } 1281 1282 /* CHECK: Only supported on fabric ap_ids */ 1283 if (fab_apid == NULL || strcmp(fab_apid, IBNEX_FABRIC) != 0) { 1284 DPRINTF("cfga_private_func: fabric apid needed\n"); 1285 return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR, 1286 ap_id, errno)); 1287 } 1288 1289 /* Check w/ user if it is ok to do this operation */ 1290 len = strlen(IB_CONFIRM4) + 10; 1291 if ((msg = (char *)calloc(len, 1)) != NULL) { 1292 (void) snprintf(msg, len, "%s\nContinue", IB_CONFIRM4); 1293 } 1294 1295 /* If the user fails to confirm, return */ 1296 if (!ib_confirm(confp, msg)) { 1297 free(msg); 1298 return (CFGA_NACK); 1299 } 1300 free(msg); 1301 1302 /* Update P_Key tables for all ports of all HCAs */ 1303 rv = ib_do_control_ioctl((char *)ap_id, IBNEX_UPDATE_PKEY_TBLS, 1304 0, 0, 0, &info_len); 1305 1306 if (rv != 0) { 1307 DPRINTF("cfga_private_func: ib_do_control_ioctl " 1308 "failed :%d\n", rv); 1309 return (ib_err_msg(errstring, CFGA_IB_UPD_PKEY_TBLS_ERR, 1310 ap_id, errno)); 1311 } 1312 1313 /* -x [add_service|delete_service] */ 1314 } else if ((strncmp(func, IB_ADD_SERVICE, 12) == 0) || 1315 (strncmp(func, IB_DELETE_SERVICE, 15) == 0)) { 1316 char *subopts, *val; 1317 uint8_t cmd; 1318 1319 /* check: Only supported on fabric ap_ids */ 1320 if (fab_apid == NULL || strcmp(fab_apid, IBNEX_FABRIC) != 0) { 1321 DPRINTF("cfga_private_func: fabric apid needed\n"); 1322 return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR, 1323 ap_id, errno)); 1324 } 1325 1326 /* Check for root privileges. */ 1327 if (geteuid() != 0) { 1328 return (ib_err_msg(errstring, CFGA_IB_PRIV_ERR, ap_id, 1329 errno)); 1330 } 1331 1332 /* return error if no options are specified */ 1333 subopts = (char *)options; 1334 if (subopts == (char *)NULL) { 1335 DPRINTF("cfga_private_func: no sub-options\n"); 1336 (void) cfga_help(msgp, options, flags); 1337 return (ib_err_msg(errstring, CFGA_IB_INVAL_ARG_ERR, 1338 ap_id, errno)); 1339 } 1340 1341 /* parse options specified */ 1342 while (*subopts != '\0') { 1343 switch (getsubopt(&subopts, ib_service_subopts, &val)) { 1344 case 0: /* comm */ 1345 if (val == NULL) { 1346 (void) cfga_help(msgp, options, flags); 1347 S_FREE(service_name); 1348 return (ib_err_msg(errstring, 1349 CFGA_IB_INVAL_ARG_ERR, 1350 ap_id, errno)); 1351 } else { 1352 comm_name = strdup(val); 1353 if (comm_name == NULL) { 1354 DPRINTF("comm sub-opt invalid " 1355 "arg\n"); 1356 S_FREE(service_name); 1357 return (ib_err_msg(errstring, 1358 CFGA_IB_COMM_INVAL_ERR, 1359 ap_id, errno)); 1360 } 1361 } 1362 break; 1363 1364 case 1: /* service */ 1365 if (val == NULL) { 1366 (void) cfga_help(msgp, options, flags); 1367 S_FREE(comm_name); 1368 return (ib_err_msg(errstring, 1369 CFGA_IB_INVAL_ARG_ERR, 1370 ap_id, errno)); 1371 } else { 1372 /* service can be upto 4 long */ 1373 if (strlen(val) == 0 || 1374 strlen(val) > 4) { 1375 DPRINTF("comm sub-opt invalid " 1376 "service passed\n"); 1377 S_FREE(comm_name); 1378 return (ib_err_msg(errstring, 1379 CFGA_IB_SVC_LEN_ERR, 1380 ap_id, errno)); 1381 } 1382 service_name = strdup(val); 1383 if (service_name == NULL) { 1384 DPRINTF("comm sub-opt " 1385 "internal error\n"); 1386 S_FREE(comm_name); 1387 return (ib_err_msg(errstring, 1388 CFGA_IB_SVC_INVAL_ERR, 1389 ap_id, errno)); 1390 } 1391 } 1392 break; 1393 1394 default: 1395 (void) cfga_help(msgp, options, flags); 1396 S_FREE(comm_name); 1397 S_FREE(service_name); 1398 return (ib_err_msg(errstring, 1399 CFGA_IB_INVAL_ARG_ERR, ap_id, errno)); 1400 } 1401 } 1402 1403 /* figure out the "operation" */ 1404 if (strncasecmp(func, IB_ADD_SERVICE, 11) == 0) 1405 cmd = IBCONF_ADD_ENTRY; 1406 else if (strncasecmp(func, IB_DELETE_SERVICE, 14) == 0) 1407 cmd = IBCONF_DELETE_ENTRY; 1408 DPRINTF("Service = %s, Comm = %s, Operation = %s\n", 1409 service_name, comm_name, func); 1410 1411 if (strncasecmp(comm_name, IBNEX_PORT_STR, 4) == 0) 1412 service_type = IB_PORT_SERVICE; 1413 else if (strncasecmp(comm_name, IBNEX_VPPA_STR, 4) == 0) 1414 service_type = IB_VPPA_SERVICE; 1415 else if (strncasecmp(comm_name, IBNEX_HCASVC_STR, 4) == 0) 1416 service_type = IB_HCASVC_SERVICE; 1417 else { 1418 (void) cfga_help(msgp, options, flags); 1419 S_FREE(comm_name); 1420 S_FREE(service_name); 1421 return (ib_err_msg(errstring, CFGA_IB_INVAL_ARG_ERR, 1422 ap_id, errno)); 1423 } 1424 1425 /* do the add/delete entry to the service */ 1426 if (cmd == IBCONF_ADD_ENTRY) { 1427 if ((rv = ib_add_service(errstring)) != CFGA_IB_OK) 1428 DPRINTF("cfga_private_func: add failed\n"); 1429 } else if (cmd == IBCONF_DELETE_ENTRY) { 1430 if ((rv = ib_delete_service(errstring)) != CFGA_IB_OK) 1431 DPRINTF("cfga_private_func: delete failed\n"); 1432 } 1433 1434 S_FREE(comm_name); 1435 S_FREE(service_name); 1436 return (ib_err_msg(errstring, rv, ap_id, errno)); 1437 1438 } else if (strncmp(func, IB_LIST_SERVICES, 13) == 0) { 1439 1440 /* check: Only supported on fabric ap_ids */ 1441 if (fab_apid == NULL || strcmp(fab_apid, IBNEX_FABRIC) != 0) { 1442 DPRINTF("cfga_private_func: fabric apid needed\n"); 1443 return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR, 1444 ap_id, errno)); 1445 } 1446 1447 /* do the list services */ 1448 rv = ib_list_services(msgp, errstring); 1449 if (rv != CFGA_IB_OK) { 1450 DPRINTF("cfga_private_func: ib_list_services failed\n"); 1451 return (ib_err_msg(errstring, rv, ap_id, errno)); 1452 } 1453 1454 /* -x update_ioc_conf */ 1455 } else if (strncmp(func, IB_UPDATE_IOC_CONF, 17) == 0) { 1456 uint_t misc_arg; 1457 1458 /* Supported only with root privilege */ 1459 if (geteuid() != 0) { 1460 return (ib_err_msg(errstring, CFGA_IB_PRIV_ERR, ap_id, 1461 errno)); 1462 } 1463 1464 /* 1465 * check: Only supported on fabric ap_id or IOC APID 1466 * IOC APID does not have any commas in it. 1467 */ 1468 if (fab_apid == NULL || 1469 (fab_apid != NULL && strstr(fab_apid, ",") != NULL)) { 1470 DPRINTF("cfga_private_func: fabric/IOC apid needed\n"); 1471 return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR, 1472 ap_id, errno)); 1473 } 1474 1475 /* Check w/ user if it is ok to do this operation */ 1476 len = strlen(IB_CONFIRM5) + 10; 1477 if ((msg = (char *)calloc(len, 1)) != NULL) { 1478 (void) snprintf(msg, len, "%s\nContinue", IB_CONFIRM5); 1479 } 1480 1481 /* If the user fails to confirm, return */ 1482 if (!ib_confirm(confp, msg)) { 1483 free(msg); 1484 return (CFGA_NACK); 1485 } 1486 free(msg); 1487 1488 misc_arg = (strcmp(fab_apid, IBNEX_FABRIC) == 0) ? 1489 IBNEX_BASE_APID : IBNEX_DYN_APID; 1490 1491 /* Reprobe and update IOC(s) configuration */ 1492 rv = ib_do_control_ioctl((char *)ap_id, IBNEX_UPDATE_IOC_CONF, 1493 0, misc_arg, 0, &info_len); 1494 1495 if (rv != 0) { 1496 DPRINTF("cfga_private_func: ib_do_control_ioctl " 1497 "failed :%d\n", rv); 1498 return (ib_err_msg(errstring, CFGA_IB_DEVCTL_ERR, 1499 ap_id, errno)); 1500 } 1501 } else { 1502 DPRINTF("cfga_private_func: unrecognized command.\n"); 1503 (void) cfga_help(msgp, options, flags); 1504 errno = EINVAL; 1505 return (CFGA_INVAL); 1506 } 1507 1508 return (ib_err_msg(errstring, rv, ap_id, errno)); 1509 } 1510 1511 1512 /* 1513 * Function: 1514 * cfga_test 1515 * Input: 1516 * ap_id - The attachment point of an IB fabric 1517 * options - Test command options passed by the cfgadm(8) 1518 * msgp - cfgadm error message for this plugin 1519 * errstring - This contains error msg if command fails 1520 * flags - cfgadm(8) flags 1521 * Output: 1522 * NONE 1523 * Returns: 1524 * CFGA_OPNOTSUPP 1525 * Description: 1526 * Do "cfgadm -t" 1527 */ 1528 /*ARGSUSED*/ 1529 cfga_err_t 1530 cfga_test(const char *ap_id, const char *options, struct cfga_msg *msgp, 1531 char **errstring, cfga_flags_t flags) 1532 { 1533 (void) cfga_help(msgp, options, flags); 1534 return (CFGA_OPNOTSUPP); 1535 } 1536 1537 1538 /* 1539 * Function: 1540 * ib_fill_static_apids 1541 * Input: 1542 * ap_id - The static attachment point of an IB device 1543 * clp - The returned "list" information array 1544 * Output: 1545 * NONE 1546 * Returns: 1547 * Fills up the "list" information array for the static attachment point 1548 * Description: 1549 * IB fabric supports two types of static attachment points. 1550 * One is fabric and other is for the HCAs. This fills up 1551 * "cfga_list_data_t" for static attachment points. 1552 */ 1553 static cfga_ib_ret_t 1554 ib_fill_static_apids(char *ap_id, cfga_list_data_t *clp) 1555 { 1556 int rv, l_err; 1557 char *ap_id_log = NULL; 1558 1559 /* Get /dev/cfg path to corresponding to the physical ap_id */ 1560 /* Remember ap_id_log must be freed */ 1561 if (ib_physpath_to_devlink(ap_id, &ap_id_log, 1562 &l_err) != ICFGA_OK) { 1563 DPRINTF("ib_fill_static_apids: " 1564 "ib_physpath_to_devlink failed\n"); 1565 return (CFGA_IB_DEVLINK_ERR); 1566 } 1567 assert(ap_id_log != NULL); 1568 1569 /* Get logical ap-id corresponding to the physical */ 1570 if (strstr(ap_id_log, CFGA_DEV_DIR) == NULL) { 1571 DPRINTF("ib_fill_static_apids: devlink doesn't contain " 1572 "/dev/cfg\n"); 1573 free(ap_id_log); 1574 return (CFGA_IB_DEVLINK_ERR); 1575 } 1576 1577 clp->ap_cond = CFGA_COND_OK; 1578 clp->ap_r_state = CFGA_STAT_CONNECTED; 1579 clp->ap_o_state = CFGA_STAT_CONFIGURED; 1580 clp->ap_class[0] = '\0'; /* Filled by libcfgadm */ 1581 clp->ap_busy = 0; 1582 clp->ap_status_time = (time_t)-1; 1583 (void) snprintf(clp->ap_log_id, sizeof (clp->ap_log_id), "%s", 1584 /* Strip off /dev/cfg/ */ ap_id_log + strlen(CFGA_DEV_DIR) + 1); 1585 (void) strlcpy(clp->ap_phys_id, ap_id, sizeof (clp->ap_phys_id)); 1586 1587 /* Static IB apid */ 1588 if (strstr((char *)ap_id, IB_FABRIC_APID_STR) != NULL) { 1589 (void) strlcpy(clp->ap_type, IB_FABRIC_TYPE, 1590 sizeof (clp->ap_type)); /* Fill in type */ 1591 (void) strlcpy(clp->ap_info, IB_FABRIC_INFO, 1592 sizeof (clp->ap_info)); 1593 1594 } else { /* Static HCA apid */ 1595 size_t size = 0; 1596 uchar_t *data = NULL; 1597 1598 (void) strlcpy(clp->ap_type, IB_HCA_TYPE, 1599 sizeof (clp->ap_type)); /* Fill in type */ 1600 1601 rv = ib_do_control_ioctl(ap_id, IBNEX_HCA_VERBOSE_SZ, 1602 IBNEX_HCA_VERBOSE_INFO, 0, (void **)&data, &size); 1603 if (rv != 0) { 1604 DPRINTF("ib_fill_static_apids: ib_do_control_ioctl " 1605 "failed :%d\n", rv); 1606 free(ap_id_log); 1607 S_FREE(data); 1608 return (CFGA_IB_IOCTL_ERR); 1609 } 1610 1611 (void) strlcpy(clp->ap_info, (char *)data, 1612 sizeof (clp->ap_info)); 1613 S_FREE(data); 1614 } 1615 free(ap_id_log); 1616 return (CFGA_IB_OK); 1617 } 1618 1619 1620 /* 1621 * Function: 1622 * cfga_list_ext 1623 * Input: 1624 * ap_id - The attachment point of an IB fabric 1625 * ap_id_list - The returned "list" information array 1626 * nlistp - Number of elements in the "list" information array 1627 * options - List command options passed by the cfgadm(8) 1628 * listopts - "-s" specific options 1629 * errstring - This contains error msg if command fails 1630 * flags - cfgadm(8) flags 1631 * Output: 1632 * NONE 1633 * Returns: 1634 * If the command succeeded, cfgadm -l output otherwise an error 1635 * Description: 1636 * Do cfgadm -l 1637 */ 1638 /*ARGSUSED*/ 1639 cfga_err_t 1640 cfga_list_ext(const char *ap_id, cfga_list_data_t **ap_id_list, int *nlistp, 1641 const char *options, const char *listopts, char **errstring, 1642 cfga_flags_t flags) 1643 { 1644 int expand = 0; 1645 int i, index, count; 1646 int show_dynamic = 0; 1647 size_t num_devices = 0; 1648 size_t num_hcas = 0; 1649 size_t snap_size = 0; 1650 uchar_t *snap_data = NULL; 1651 nvpair_t *nvp = NULL; /* for lint purposes */ 1652 nvlist_t *nvl = NULL; 1653 boolean_t apid_matched = B_FALSE; /* for valid ap_id */ 1654 cfga_ib_ret_t rv = CFGA_IB_OK; 1655 cfga_list_data_t *clp = NULL; 1656 1657 if ((rv = ib_verify_params(ap_id, options, errstring)) != CFGA_IB_OK) { 1658 return (ib_err_msg(errstring, rv, ap_id, errno)); 1659 } 1660 1661 /* make sure we have a valid ap_id_list */ 1662 if (ap_id_list == NULL || nlistp == NULL) { 1663 DPRINTF("cfga_list_ext: list = NULL or nlistp = NULL\n"); 1664 return (ib_err_msg(errstring, CFGA_IB_INVAL_ARG_ERR, 1665 ap_id, errno)); 1666 } 1667 1668 DPRINTF("cfga_list_ext: ap_id = %s\n", ap_id); 1669 1670 if ((flags & CFGA_FLAG_LIST_ALL) == CFGA_FLAG_LIST_ALL) { 1671 expand = 1; /* -a flag passed */ 1672 } 1673 1674 if (GET_DYN(ap_id) != NULL) { 1675 show_dynamic = 1; 1676 } 1677 1678 if ((expand == 1) && /* -a option passed */ 1679 (strstr((char *)ap_id, IB_FABRIC_APID_STR) != NULL)) { 1680 /* 1681 * Figure out how many IOC/Port/Pseudo 1682 * devices exist in the system? 1683 */ 1684 if ((rv = ib_do_control_ioctl((char *)ap_id, 1685 IBNEX_NUM_DEVICE_NODES, 0, 0, 0, &num_devices)) != 1686 CFGA_IB_OK) { 1687 DPRINTF("cfga_list_ext: ib_do_control_ioctl " 1688 "IBNEX_NUM_DEVICE_NODES failed :%d\n", rv); 1689 if (errno == ENOENT) 1690 return (CFGA_APID_NOEXIST); 1691 return (ib_err_msg(errstring, rv, ap_id, errno)); 1692 } 1693 1694 DPRINTF("cfga_list_ext: num_devices = %d\n", num_devices); 1695 } 1696 1697 /* Figure out how many HCA nodes exist in the system. */ 1698 if ((rv = ib_do_control_ioctl((char *)ap_id, IBNEX_NUM_HCA_NODES, 0, 0, 1699 0, &num_hcas)) != CFGA_IB_OK) { 1700 DPRINTF("cfga_list_ext: ib_do_control_ioctl " 1701 "IBNEX_NUM_HCA_NODES failed :%d\n", rv); 1702 if (errno == ENOENT) 1703 return (CFGA_APID_NOEXIST); 1704 return (ib_err_msg(errstring, rv, ap_id, errno)); 1705 } 1706 DPRINTF("cfga_list_ext: num_hcas = %d\n", num_hcas); 1707 1708 /* 1709 * No HCAs or IOC/VPPA/Port/HCA_SVC/Pseudo devices seen (non-IB system) 1710 */ 1711 if (!(num_hcas || num_devices)) { 1712 DPRINTF("cfga_list_ext: no IB devices found\n"); 1713 return (CFGA_APID_NOEXIST); 1714 } 1715 1716 /* 1717 * *nlistp contains to how many APIDs to show w/ cfgadm -l. 1718 * If ap_id is "fabric" then 1719 * *nlistp is all Dynamic Apids + One more for "fabric" 1720 * If ap_id is "HCA" ap_id then 1721 * *nlistp is 1 1722 * Note that each HCA is a static APID, so nlistp will be 1 always 1723 * and this function will be called N times for each of the N HCAs 1724 * in the host. 1725 */ 1726 if (strstr((char *)ap_id, IB_FABRIC_APID_STR) != NULL) { 1727 *nlistp = num_devices + 1; 1728 1729 } else { 1730 /* Assume it as a HCA ap_id */ 1731 *nlistp = 1; 1732 } 1733 1734 /* Allocate storage for passing "list" info back */ 1735 if ((*ap_id_list = (cfga_list_data_t *)calloc(*nlistp, 1736 sizeof (cfga_list_data_t))) == NULL) { 1737 DPRINTF("cfga_list_ext: malloc for cfga_list_data_t failed. " 1738 "errno: %d\n", errno); 1739 return (ib_err_msg(errstring, CFGA_IB_ALLOC_FAIL, 1740 ap_id, errno)); 1741 } 1742 1743 /* 1744 * Only static ap_id is ib_fabric: 1745 * If -a options isn't specified then only show the static ap_id. 1746 */ 1747 if (!show_dynamic) { 1748 clp = &(*ap_id_list[0]); 1749 1750 if ((rv = ib_fill_static_apids((char *)ap_id, clp)) != 1751 CFGA_IB_OK) { 1752 S_FREE(*ap_id_list); 1753 return (ib_err_msg(errstring, rv, ap_id, errno)); 1754 } 1755 apid_matched = B_TRUE; 1756 } 1757 1758 /* 1759 * No -a specified 1760 * No HCAs or IOC/VPPA/HCA_SVC/Port/Pseudo devices seen (non-IB system) 1761 */ 1762 if (!expand || (!num_hcas && !num_devices)) { 1763 if (!show_dynamic) 1764 return (CFGA_OK); 1765 } 1766 1767 if (strstr((char *)ap_id, IB_FABRIC_APID_STR) != NULL) { 1768 rv = ib_do_control_ioctl((char *)ap_id, IBNEX_SNAPSHOT_SIZE, 1769 IBNEX_GET_SNAPSHOT, IBNEX_DONOT_PROBE_FLAG, 1770 (void **)&snap_data, &snap_size); 1771 if (rv != 0) { 1772 DPRINTF("cfga_list_ext: ib_do_control_ioctl " 1773 "failed :%d\n", rv); 1774 S_FREE(*ap_id_list); 1775 S_FREE(snap_data); 1776 return (ib_err_msg(errstring, rv, ap_id, errno)); 1777 } 1778 1779 if (nvlist_unpack((char *)snap_data, snap_size, &nvl, 0)) { 1780 DPRINTF("cfga_list_ext: nvlist_unpack 1 failed %p\n", 1781 snap_data); 1782 S_FREE(*ap_id_list); 1783 S_FREE(snap_data); 1784 return (ib_err_msg(errstring, CFGA_IB_NVLIST_ERR, 1785 ap_id, errno)); 1786 } 1787 1788 /* 1789 * In kernel a nvlist is build per ap_id which contains 1790 * information that is displayed using cfgadm -l. 1791 * For IB devices only these 6 items are shown: 1792 * ap_id, type, occupant, receptacle, condition and info 1793 * 1794 * In addition, one could specify a dynamic ap_id from 1795 * command-line. Then cfgadm -l should show only that 1796 * ap_id and skip rest. 1797 */ 1798 index = 1; count = 0; 1799 while (nvp = nvlist_next_nvpair(nvl, nvp)) { 1800 int32_t intval = 0; 1801 int32_t node_type; 1802 char *info; 1803 char *nv_apid; 1804 char *name = nvpair_name(nvp); 1805 1806 /* start of with next device */ 1807 if (count == IB_NUM_NVPAIRS) { 1808 count = 0; 1809 ++index; 1810 } 1811 1812 /* 1813 * Check if the index doesn't go beyond the 1814 * device number. If it goes, stop the loop 1815 * here not to cause the heap corruption. 1816 */ 1817 if (show_dynamic == 0 && index > num_devices) 1818 break; 1819 1820 /* fill up data into "clp" */ 1821 clp = (show_dynamic != 0) ? &(*ap_id_list[0]) : 1822 &(ap_id_list[0][index]); 1823 1824 /* First nvlist entry is "ap_id" always */ 1825 if (strcmp(name, IBNEX_NODE_APID_NVL) == 0) { 1826 (void) nvpair_value_string(nvp, &nv_apid); 1827 DPRINTF("cfga_list_ext: Name = %s, apid = %s\n", 1828 name, nv_apid); 1829 1830 /* 1831 * If a dynamic ap_id is specified in the 1832 * command-line, skip all entries until 1833 * the one needed matches. 1834 */ 1835 if (show_dynamic && 1836 strstr(ap_id, nv_apid) == NULL) { 1837 DPRINTF("cfga_list_ext: NO MATCH\n"); 1838 1839 /* 1840 * skip rest of the entries of this 1841 * device. 1842 */ 1843 for (i = 0; i < IB_NUM_NVPAIRS - 1; i++) 1844 nvp = nvlist_next_nvpair(nvl, 1845 nvp); 1846 count = 0; /* reset it */ 1847 continue; 1848 } 1849 1850 apid_matched = B_TRUE; 1851 1852 /* build the physical ap_id */ 1853 if (strstr(ap_id, DYN_SEP) == NULL) { 1854 (void) snprintf(clp->ap_phys_id, 1855 sizeof (clp->ap_phys_id), "%s%s%s", 1856 ap_id, DYN_SEP, nv_apid); 1857 } else { 1858 (void) snprintf(clp->ap_phys_id, 1859 sizeof (clp->ap_phys_id), "%s", 1860 ap_id); 1861 } 1862 1863 /* ensure that this is a valid apid */ 1864 if (ib_verify_valid_apid(clp->ap_phys_id) != 1865 0) { 1866 DPRINTF("cfga_list_ext: " 1867 "not a valid IB ap_id\n"); 1868 S_FREE(*ap_id_list); 1869 S_FREE(snap_data); 1870 nvlist_free(nvl); 1871 return (ib_err_msg(errstring, 1872 CFGA_IB_AP_ERR, ap_id, errno)); 1873 } 1874 1875 /* build the logical ap_id */ 1876 (void) snprintf(clp->ap_log_id, 1877 sizeof (clp->ap_log_id), "ib%s%s", 1878 DYN_SEP, nv_apid); 1879 DPRINTF("cfga_list_ext: ap_pi = %s, ap_li = %s," 1880 "\nap_info = %s\n", clp->ap_phys_id, 1881 clp->ap_log_id, clp->ap_info); 1882 ++count; 1883 1884 } else if (strcmp(name, IBNEX_NODE_INFO_NVL) == 0) { 1885 (void) nvpair_value_string(nvp, &info); 1886 DPRINTF("cfga_list_ext: Name = %s, info = %s\n", 1887 name, info); 1888 (void) snprintf(clp->ap_info, 1889 sizeof (clp->ap_info), "%s", info); 1890 ++count; 1891 1892 } else if (strcmp(name, IBNEX_NODE_TYPE_NVL) == 0) { 1893 (void) nvpair_value_int32(nvp, &node_type); 1894 if (node_type == IBNEX_PORT_NODE_TYPE) { 1895 (void) snprintf(clp->ap_type, 1896 sizeof (clp->ap_type), "%s", 1897 IB_PORT_TYPE); 1898 } else if (node_type == IBNEX_VPPA_NODE_TYPE) { 1899 (void) snprintf(clp->ap_type, 1900 sizeof (clp->ap_type), "%s", 1901 IB_VPPA_TYPE); 1902 } else if (node_type == 1903 IBNEX_HCASVC_NODE_TYPE) { 1904 (void) snprintf(clp->ap_type, 1905 sizeof (clp->ap_type), "%s", 1906 IB_HCASVC_TYPE); 1907 } else if (node_type == IBNEX_IOC_NODE_TYPE) { 1908 (void) snprintf(clp->ap_type, 1909 sizeof (clp->ap_type), "%s", 1910 IB_IOC_TYPE); 1911 } else if (node_type == 1912 IBNEX_PSEUDO_NODE_TYPE) { 1913 (void) snprintf(clp->ap_type, 1914 sizeof (clp->ap_type), "%s", 1915 IB_PSEUDO_TYPE); 1916 } 1917 DPRINTF("cfga_list_ext: Name = %s, type = %x\n", 1918 name, intval); 1919 ++count; 1920 1921 } else if (strcmp(name, IBNEX_NODE_RSTATE_NVL) == 0) { 1922 (void) nvpair_value_int32(nvp, &intval); 1923 1924 if (intval == AP_RSTATE_EMPTY) 1925 clp->ap_r_state = CFGA_STAT_EMPTY; 1926 else if (intval == AP_RSTATE_DISCONNECTED) 1927 clp->ap_r_state = 1928 CFGA_STAT_DISCONNECTED; 1929 else if (intval == AP_RSTATE_CONNECTED) 1930 clp->ap_r_state = CFGA_STAT_CONNECTED; 1931 DPRINTF("cfga_list_ext: Name = %s, " 1932 "rstate = %x\n", name, intval); 1933 ++count; 1934 1935 } else if (strcmp(name, IBNEX_NODE_OSTATE_NVL) == 0) { 1936 (void) nvpair_value_int32(nvp, &intval); 1937 1938 if (intval == AP_OSTATE_CONFIGURED) 1939 clp->ap_o_state = CFGA_STAT_CONFIGURED; 1940 else if (intval == AP_OSTATE_UNCONFIGURED) 1941 clp->ap_o_state = 1942 CFGA_STAT_UNCONFIGURED; 1943 DPRINTF("cfga_list_ext: Name = %s, " 1944 "ostate = %x\n", name, intval); 1945 ++count; 1946 1947 } else if (strcmp(name, IBNEX_NODE_COND_NVL) == 0) { 1948 (void) nvpair_value_int32(nvp, &intval); 1949 1950 if (intval == AP_COND_OK) 1951 clp->ap_cond = CFGA_COND_OK; 1952 else if (intval == AP_COND_FAILING) 1953 clp->ap_cond = CFGA_COND_FAILING; 1954 else if (intval == AP_COND_FAILED) 1955 clp->ap_cond = CFGA_COND_FAILED; 1956 else if (intval == AP_COND_UNUSABLE) 1957 clp->ap_cond = CFGA_COND_UNUSABLE; 1958 else if (intval == AP_COND_UNKNOWN) 1959 clp->ap_cond = CFGA_COND_UNKNOWN; 1960 DPRINTF("cfga_list_ext: Name = %s, " 1961 "condition = %x\n", name, intval); 1962 ++count; 1963 } 1964 1965 clp->ap_class[0] = '\0'; /* Filled by libcfgadm */ 1966 clp->ap_busy = 0; 1967 clp->ap_status_time = (time_t)-1; 1968 } /* end of while */ 1969 } 1970 1971 S_FREE(snap_data); 1972 nvlist_free(nvl); 1973 1974 /* 1975 * if a cmdline specified ap_id doesn't match the known list of ap_ids 1976 * then report an error right away 1977 */ 1978 rv = (apid_matched == B_TRUE) ? CFGA_IB_OK : CFGA_IB_AP_ERR; 1979 return (ib_err_msg(errstring, rv, ap_id, errno)); 1980 } 1981 1982 1983 /* 1984 * Function: 1985 * cfga_msg 1986 * Input: 1987 * msgp - cfgadm error message for this plugin 1988 * str - string to be passed on to the message 1989 * Output: 1990 * NONE 1991 * Returns: 1992 * NONE 1993 * Description: 1994 * This routine accepts a variable number of message IDs and 1995 * constructs a corresponding error string which is printed 1996 * via the message print routine argument. 1997 */ 1998 void 1999 cfga_msg(struct cfga_msg *msgp, const char *str) 2000 { 2001 int len; 2002 char *q; 2003 2004 if (msgp == NULL || msgp->message_routine == NULL) { 2005 DPRINTF("cfga_msg: msg\n"); 2006 return; 2007 } 2008 2009 if ((len = strlen(str)) == 0) { 2010 DPRINTF("cfga_msg: null str\n"); 2011 return; 2012 } 2013 2014 if ((q = (char *)calloc(len + 1, 1)) == NULL) { 2015 DPRINTF("cfga_msg: null q\n"); 2016 return; 2017 } 2018 2019 (void) strlcpy(q, str, len + 1); 2020 (*msgp->message_routine)(msgp->appdata_ptr, q); 2021 2022 free(q); 2023 } 2024 2025 2026 /* 2027 * Function: 2028 * cfga_help 2029 * Input: 2030 * msgp - Help message passed on to cfgadm(8) 2031 * options - Help message options passed on to cfgadm(8) 2032 * flags - cfgadm(8) flags 2033 * Output: 2034 * NONE 2035 * Returns: 2036 * Were we able to print cfgadm help or not for this plugin 2037 * Description: 2038 * Print cfgadm help for this plugin 2039 */ 2040 /* ARGSUSED */ 2041 cfga_err_t 2042 cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags) 2043 { 2044 DPRINTF("cfga_help:\n"); 2045 2046 if (options) { 2047 cfga_msg(msgp, dgettext(TEXT_DOMAIN, ib_help[ 2048 CFGA_IB_HELP_UNKNOWN])); 2049 cfga_msg(msgp, options); 2050 } 2051 2052 /* Print messages array */ 2053 cfga_msg(msgp, dgettext(TEXT_DOMAIN, ib_help[CFGA_IB_HELP_HEADER])); 2054 cfga_msg(msgp, ib_help[CFGA_IB_HELP_CONFIG]); 2055 cfga_msg(msgp, ib_help[CFGA_IB_HELP_LIST]); 2056 cfga_msg(msgp, ib_help[CFGA_IB_HELP_UPD_PKEY]); 2057 cfga_msg(msgp, ib_help[CFGA_IB_HELP_CONF_FILE1]); 2058 cfga_msg(msgp, ib_help[CFGA_IB_HELP_CONF_FILE2]); 2059 cfga_msg(msgp, ib_help[CFGA_IB_HELP_UPD_IOC_CONF]); 2060 cfga_msg(msgp, ib_help[CFGA_IB_HELP_UNCFG_CLNTS]); 2061 2062 return (CFGA_OK); 2063 } 2064 2065 2066 /* 2067 * Function: 2068 * ib_confirm 2069 * Input: 2070 * confp - The "cfga" structure that confirms a cfgadm query 2071 * msg - The message that needs confirmation 2072 * Output: 2073 * None 2074 * Returns: 2075 * If a user entered YES or NO 2076 * Description: 2077 * Queries a user if it is ok to proceed with an operation or not. 2078 * Returns user's response. 2079 */ 2080 static int 2081 ib_confirm(struct cfga_confirm *confp, char *msg) 2082 { 2083 int rval; 2084 2085 /* check that "confirm" function exists */ 2086 if (confp == NULL || confp->confirm == NULL) { 2087 return (0); 2088 } 2089 2090 /* Call cfgadm provided "confirm" function */ 2091 rval = (*confp->confirm)(confp->appdata_ptr, msg); 2092 DPRINTF("ib_confirm: %d\n", rval); 2093 2094 return (rval); 2095 } 2096 2097 2098 /* 2099 * Function: 2100 * ib_get_devicepath 2101 * Input: 2102 * ap_id - The dynamic attachment point of an IB device 2103 * Output: 2104 * None 2105 * Returns: 2106 * devpath if it exists; otherwise NULL 2107 * Description: 2108 * Returns the devicepath for a dynamic attachment point of an IB device 2109 */ 2110 static char * 2111 ib_get_devicepath(const char *ap_id) 2112 { 2113 char *devpath = NULL; 2114 size_t size; 2115 2116 /* Get device path sizes */ 2117 if (ib_do_control_ioctl((char *)ap_id, IBNEX_DEVICE_PATH_SZ, 2118 IBNEX_GET_DEVICE_PATH, 0, (void **)&devpath, &size) == CFGA_IB_OK) { 2119 DPRINTF("ib_get_devicepath: get device path ioctl ok\n"); 2120 return (devpath); 2121 2122 } else { 2123 DPRINTF("ib_get_devicepath: get device path ioctl failed\n"); 2124 return ((char *)NULL); 2125 } 2126 } 2127