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