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