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