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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
30 * All cfgadm entry points that are defined in the config_admin(3X)
31 * needed for InfiniBand support are described here. These cfgadm
32 * interfaces issue ioctl(s) to the IB nexus driver. Attachment points
33 * supported are - IOC, VPPA, Port, HCA_SVC and Pseudo dynamic ap_ids,
34 * the HCA static ap_id, and the IB static ap_id.
36 * Given InfiniBand bus is fabric based, #of dynamic ap_ids present are
37 * unknown at any given point of time. Hence this plugin uses a
38 * packed nvlist data structure to hold ap_id related information.
39 * The IB nexus driver allocates the nvlist data in the kernel
40 * and this plugin processes the data (it is freed by IB nexus driver).
44 /* function prototypes */
45 static int ib_get_link(di_devlink_t
, void *);
46 static icfga_ret_t
ib_physpath_to_devlink(char *, char **, int *);
47 static const char *ib_get_msg(uint_t
, msgcvt_t
*, uint_t
);
48 static void ib_set_msg(char **, ...);
49 static cfga_err_t
ib_err_msg(char **, cfga_ib_ret_t
, const char *, int);
50 static int ib_verify_valid_apid(const char *);
51 static cfga_ib_ret_t
ib_verify_params(const char *, const char *, char **);
52 static void ib_cleanup_after_devctl_cmd(devctl_hdl_t
, nvlist_t
*);
53 static cfga_ib_ret_t
ib_setup_for_devctl_cmd(char *, boolean_t
,
54 devctl_hdl_t
*, nvlist_t
**);
55 static cfga_ib_ret_t
ib_device_configured(devctl_hdl_t
, nvlist_t
*,
57 static cfga_ib_ret_t
ib_device_connected(devctl_hdl_t
, nvlist_t
*,
59 static cfga_ib_ret_t
ib_do_control_ioctl(char *, uint_t
, uint_t
, uint_t
,
61 cfga_err_t
cfga_change_state(cfga_cmd_t
, const char *,
62 const char *, struct cfga_confirm
*,
63 struct cfga_msg
*, char **, cfga_flags_t
);
64 cfga_err_t
cfga_private_func(const char *, const char *,
65 const char *, struct cfga_confirm
*,
66 struct cfga_msg
*, char **, cfga_flags_t
);
67 cfga_err_t
cfga_test(const char *, const char *, struct cfga_msg
*,
68 char **, cfga_flags_t
);
69 static cfga_ib_ret_t
ib_fill_static_apids(char *, cfga_list_data_t
*);
70 cfga_err_t
cfga_list_ext(const char *, cfga_list_data_t
**, int *,
71 const char *, const char *, char **, cfga_flags_t
);
72 void cfga_msg(struct cfga_msg
*, const char *);
73 cfga_err_t
cfga_help(struct cfga_msg
*, const char *,
75 static int ib_confirm(struct cfga_confirm
*, char *);
76 static char *ib_get_devicepath(const char *);
79 /* External function prototypes */
80 extern cfga_ib_ret_t
ib_rcm_offline(const char *, char **, char *,
82 extern cfga_ib_ret_t
ib_rcm_online(const char *, char **, char *,
84 extern cfga_ib_ret_t
ib_rcm_remove(const char *, char **, char *,
86 extern int ib_add_service(char **);
87 extern int ib_delete_service(char **);
88 extern int ib_list_services(struct cfga_msg
*, char **);
92 int cfga_version
= CFGA_HSL_V2
; /* Set the version number for */
93 /* the cfgadm library's use. */
95 static char *ib_help
[] = { /* Help messages */
97 /* CFGA_IB_HELP_HEADER */ "IB specific commands:\n",
98 /* CFGA_IB_HELP_CONFIG */ "cfgadm -c [configure|unconfigure] "
100 /* CFGA_IB_HELP_LIST */ "cfgadm -x list_clients hca_ap_id "
102 /* CFGA_IB_HELP_UPD_PKEY */ "cfgadm -x update_pkey_tbls ib\n",
103 /* CFGA_IB_HELP_CONF_FILE1 */ "cfgadm -o comm=[port|vppa|hca-svc],"
104 "service=<name> -x [add_service|delete_service] ib\n",
105 /* CFGA_IB_HELP_CONF_FILE2 */ "cfgadm -x list_services ib\n",
106 /* CFGA_IB_HELP_UPD_IOC_CONF */ "cfgadm -x update_ioc_config "
108 /* CFGA_IB_HELP_UNCFG_CLNTS */ "cfgadm -x unconfig_clients hca_ap_id "
110 /* CFGA_IB_HELP_UNKNOWN */ "\tunknown command or option: ",
114 static msgcvt_t ib_error_msgs
[] = { /* Error messages */
115 /* CFGA_IB_OK */ { CVT
, CFGA_OK
, "ok" },
116 /* CFGA_IB_UNKNOWN */ { CVT
, CFGA_LIB_ERROR
,
117 "Unknown message; internal error " },
118 /* CFGA_IB_INTERNAL_ERR */ { CVT
, CFGA_LIB_ERROR
,
120 /* CFGA_IB_INVAL_ARG_ERR */ { CVT
, CFGA_LIB_ERROR
,
121 "Invalid input args " },
122 /* CFGA_IB_OPTIONS_ERR */ { CVT
, CFGA_ERROR
,
123 "Hardware specific options not supported " },
124 /* CFGA_IB_AP_ERR */ { CVT
, CFGA_APID_NOEXIST
, "" },
125 /* CFGA_IB_DEVCTL_ERR */ { CVT
, CFGA_LIB_ERROR
,
126 "Cannot issue devctl to " },
127 /* CFGA_IB_NOT_CONNECTED */ { CVT
, CFGA_INSUFFICENT_CONDITION
,
128 "No device connected to " },
129 /* CFGA_IB_NOT_CONFIGURED */ { CVT
, CFGA_INSUFFICENT_CONDITION
,
130 "No device configured to " },
131 /* CFGA_IB_ALREADY_CONNECTED */ { CVT
, CFGA_INSUFFICENT_CONDITION
,
132 "already connected; cannot connect again " },
133 /* CFGA_IB_ALREADY_CONFIGURED */ { CVT
, CFGA_INSUFFICENT_CONDITION
,
134 "already configured " },
135 /* CFGA_IB_CONFIG_OP_ERR */ { CVT
, CFGA_ERROR
,
136 "configure operation failed " },
137 /* CFGA_IB_UNCONFIG_OP_ERR */ { CVT
, CFGA_ERROR
,
138 "unconfigure operation failed " },
139 /* CFGA_IB_OPEN_ERR */ { CVT
, CFGA_LIB_ERROR
, "Cannot open " },
140 /* CFGA_IB_IOCTL_ERR */ { CVT
, CFGA_LIB_ERROR
,
141 "Driver ioctl failed " },
142 /* CFGA_IB_BUSY_ERR */ { CVT
, CFGA_SYSTEM_BUSY
, " " },
143 /* CFGA_IB_ALLOC_FAIL */ { CVT
, CFGA_LIB_ERROR
,
144 "Memory allocation failure " },
145 /* CFGA_IB_OPNOTSUPP */ { CVT
, CFGA_OPNOTSUPP
,
146 "Operation not supported " },
147 /* CFGA_IB_INVAL_APID_ERR */ { CVT
, CFGA_LIB_ERROR
,
148 "Invalid ap_id supplied " },
149 /* CFGA_IB_DEVLINK_ERR */ { CVT
, CFGA_LIB_ERROR
,
150 "Could not find /dev/cfg link for " },
151 /* CFGA_IB_PRIV_ERR */ { CVT
, CFGA_PRIV
, " " },
152 /* CFGA_IB_NVLIST_ERR */ { CVT
, CFGA_ERROR
,
153 "Internal error (nvlist) " },
154 /* CFGA_IB_HCA_LIST_ERR */ { CVT
, CFGA_ERROR
,
155 "Listing HCA's clients failed " },
156 /* CFGA_IB_HCA_UNCONFIG_ERR */ { CVT
, CFGA_ERROR
,
157 "Unconfiguring HCA's clients failed " },
158 /* CFGA_IB_UPD_PKEY_TBLS_ERR */ { CVT
, CFGA_ERROR
,
159 "Updating P_Key tables failed " },
160 /* CFGA_IB_RCM_HANDLE_ERR */ { CVT
, CFGA_ERROR
,
161 "Opening ib.conf file failed " },
162 /* CFGA_IB_LOCK_FILE_ERR */ { CVT
, CFGA_LIB_ERROR
,
163 "Locking ib.conf file failed " },
164 /* CFGA_IB_UNLOCK_FILE_ERR */ { CVT
, CFGA_LIB_ERROR
,
165 "Unlocking ib.conf file failed " },
166 /* CFGA_IB_COMM_INVAL_ERR */ { CVT
, CFGA_INVAL
,
167 "Communication type incorrectly specified " },
168 /* CFGA_IB_SVC_INVAL_ERR */ { CVT
, CFGA_INVAL
,
169 "Service name incorrectly specified " },
170 /* CFGA_IB_SVC_LEN_ERR_ERR */ { CVT
, CFGA_INVAL
,
171 "Service name len should be <= to 4, " },
172 /* CFGA_IB_SVC_EXISTS_ERR */ { CVT
, CFGA_INVAL
, " "},
173 /* CFGA_IB_SVC_NO_EXIST_ERR */ { CVT
, CFGA_INVAL
, " " },
174 /* CFGA_IB_UCFG_CLNTS_ERR */ { CVT
, CFGA_INVAL
,
175 "unconfig_clients failed for HCA " },
176 /* CFGA_IB_INVALID_OP_ERR */ { CVT
, CFGA_OPNOTSUPP
, "on " },
177 /* CFGA_IB_RCM_HANDLE */ { CVT
, CFGA_ERROR
,
178 "cannot get RCM handle "},
179 /* CFGA_IB_RCM_ONLINE_ERR */ { CVT
, CFGA_SYSTEM_BUSY
,
180 "failed to online: "},
181 /* CFGA_IB_RCM_OFFLINE_ERR */ { CVT
, CFGA_SYSTEM_BUSY
,
182 "failed to offline: "}
186 * these are the only valid sub-options for services.
188 static char *ib_service_subopts
[] = {
194 /* Communication Service name : "port" or "vppa" or "hca-svc" */
195 static char *comm_name
= NULL
;
197 char *service_name
= NULL
; /* service name */
198 ib_service_type_t service_type
= IB_NONE
; /* service type */
201 /* ========================================================================= */
203 * The next two funcs are imported from cfgadm_scsi.
204 * ib_physpath_to_devlink is the only func directly used by cfgadm_ib.
205 * ib_get_link supports it.
212 * devlink - devlink for the device path
213 * arg - argument passed to this "walker" function
217 * Continue "walking" or not
219 * Routine to search the /dev directory or a subtree of /dev.
222 ib_get_link(di_devlink_t devlink
, void *arg
)
224 walk_link_t
*larg
= (walk_link_t
*)arg
;
227 * When path is specified, it's the node path without minor
228 * name. Therefore, the ../.. prefixes needs to be stripped.
231 char *content
= (char *)di_devlink_content(devlink
);
232 char *start
= strstr(content
, "/devices/");
234 /* line content must have minor node */
236 strncmp(start
, larg
->path
, larg
->len
) != 0 ||
237 start
[larg
->len
] != ':') {
238 return (DI_WALK_CONTINUE
);
242 *(larg
->linkpp
) = strdup(di_devlink_path(devlink
));
243 return (DI_WALK_TERMINATE
);
249 * ib_physpath_to_devlink
251 * node_path - Physical path of the ap_id node
253 * logpp - Logical path to the ap_id node
256 * ICFGA_OK if everything was fine; otherwise an error with
259 * Given a physical path to an ap_id ensure that it exists
263 ib_physpath_to_devlink(char *node_path
, char **logpp
, int *l_errnop
)
267 di_devlink_handle_t hdl
;
269 if ((hdl
= di_devlink_init(NULL
, 0)) == NULL
) {
271 return (ICFGA_LIB_ERR
);
276 minor_path
= (char *)node_path
+ strlen("/devices");
280 (void) di_devlink_walk(hdl
, "^cfg/", minor_path
, DI_PRIMARY_LINK
,
281 (void *)&larg
, ib_get_link
);
283 di_devlink_fini(&hdl
);
285 if (*logpp
== NULL
) {
287 return (ICFGA_LIB_ERR
);
294 /* ========================================================================= */
301 * msg_index - Index into the message table
302 * msg_tbl - the message table
303 * tbl_size - size of the message table
307 * Message string if valid, otherwise an error
309 * Given the index into a table (msgcvt_t) of messages,
310 * get the message string, converting it to the proper
311 * locale if necessary.
313 * NOTE: See cfga_ib.h
316 ib_get_msg(uint_t msg_index
, msgcvt_t
*msg_tbl
, uint_t tbl_size
)
318 if (msg_index
>= tbl_size
) {
319 DPRINTF("get_error_msg: bad error msg index: %d\n", msg_index
);
320 msg_index
= CFGA_IB_UNKNOWN
;
323 return ((msg_tbl
[msg_index
].intl
) ?
324 dgettext(TEXT_DOMAIN
, msg_tbl
[msg_index
].msgstr
) :
325 msg_tbl
[msg_index
].msgstr
);
335 * ret_str - Returned "message" string.
339 * Allocates and creates a message string (in *ret_str),
340 * by concatenating all the (char *) args together, in order.
341 * Last arg MUST be NULL.
344 ib_set_msg(char **ret_str
, ...)
347 size_t total_len
, ret_str_len
;
350 va_start(valist
, ret_str
);
352 total_len
= (*ret_str
== NULL
) ? 0 : strlen(*ret_str
);
354 while ((str
= va_arg(valist
, char *)) != NULL
) {
355 size_t len
= strlen(str
);
356 char *old_str
= *ret_str
;
358 ret_str_len
= total_len
+ len
+ 1;
359 *ret_str
= (char *)realloc(*ret_str
, ret_str_len
);
360 if (*ret_str
== NULL
) {
362 DPRINTF("ib_set_msg: realloc failed.\n");
367 (void) strlcpy(*ret_str
+ total_len
, str
, ret_str_len
);
379 * ap_id - The attachment point of an IB fabric
381 * errstring - Fill in the error msg string
382 * l_errno - The "errno" to be filled in.
384 * CFGA_IB_OK if we are able to fill in error msg;
385 * otherwise emit an error.
387 * Error message handling.
389 * For the rv passed in, looks up the corresponding error message
390 * string(s), internationalized it if necessary, and concatenates
391 * it into a new memory buffer, and points *errstring to it.
392 * Note not all "rv"s will result in an error message return, as
393 * not all error conditions warrant a IB-specific error message.
395 * Some messages may display ap_id or errno, which is why they are
399 ib_err_msg(char **errstring
, cfga_ib_ret_t rv
, const char *ap_id
, int l_errno
)
403 if (errstring
== NULL
) {
404 return (ib_error_msgs
[rv
].cfga_err
);
407 /* Generate the appropriate IB-specific error message(s) (if any). */
409 case CFGA_IB_OK
: /* Special case - do nothing. */
412 case CFGA_IB_UNKNOWN
:
413 case CFGA_IB_INTERNAL_ERR
:
414 case CFGA_IB_OPTIONS_ERR
:
415 case CFGA_IB_ALLOC_FAIL
:
416 /* These messages require no additional strings passed. */
417 ib_set_msg(errstring
, ERR_STR(rv
), NULL
);
419 case CFGA_IB_NOT_CONNECTED
:
420 case CFGA_IB_NOT_CONFIGURED
:
421 case CFGA_IB_ALREADY_CONNECTED
:
422 case CFGA_IB_ALREADY_CONFIGURED
:
423 case CFGA_IB_CONFIG_OP_ERR
:
424 case CFGA_IB_UNCONFIG_OP_ERR
:
425 case CFGA_IB_BUSY_ERR
:
426 case CFGA_IB_DEVLINK_ERR
:
427 case CFGA_IB_RCM_HANDLE_ERR
:
428 case CFGA_IB_RCM_ONLINE_ERR
:
429 case CFGA_IB_RCM_OFFLINE_ERR
:
430 case CFGA_IB_DEVCTL_ERR
:
431 case CFGA_IB_COMM_INVAL_ERR
:
432 case CFGA_IB_SVC_INVAL_ERR
:
433 case CFGA_IB_SVC_LEN_ERR
:
434 case CFGA_IB_SVC_EXISTS_ERR
:
435 case CFGA_IB_SVC_NO_EXIST_ERR
:
436 case CFGA_IB_LOCK_FILE_ERR
:
437 case CFGA_IB_CONFIG_FILE_ERR
:
438 case CFGA_IB_UNLOCK_FILE_ERR
:
439 case CFGA_IB_UCFG_CLNTS_ERR
:
440 case CFGA_IB_INVALID_OP_ERR
:
441 /* These messages also print ap_id. */
442 ib_set_msg(errstring
, ERR_STR(rv
), "ap_id: ", ap_id
, "", NULL
);
444 case CFGA_IB_IOCTL_ERR
: /* These messages also print errno. */
445 case CFGA_IB_NVLIST_ERR
:
446 errno_str
= l_errno
? strerror(l_errno
) : "";
447 ib_set_msg(errstring
, ERR_STR(rv
), errno_str
,
448 l_errno
? "\n" : "", NULL
);
450 case CFGA_IB_OPEN_ERR
: /* This messages also prints apid and errno. */
451 case CFGA_IB_PRIV_ERR
:
452 case CFGA_IB_HCA_LIST_ERR
:
453 case CFGA_IB_OPNOTSUPP
:
454 case CFGA_IB_INVAL_ARG_ERR
:
455 case CFGA_IB_INVAL_APID_ERR
:
456 case CFGA_IB_HCA_UNCONFIG_ERR
:
457 case CFGA_IB_UPD_PKEY_TBLS_ERR
:
458 errno_str
= l_errno
? strerror(l_errno
) : "";
459 ib_set_msg(errstring
, ERR_STR(rv
), "ap_id: ", ap_id
, "\n",
460 errno_str
, l_errno
? "\n" : "", NULL
);
463 DPRINTF("ib_err_msg: Unrecognized message index: %d\n", rv
);
464 ib_set_msg(errstring
, ERR_STR(CFGA_IB_INTERNAL_ERR
), NULL
);
468 * Determine the proper error code to send back to the cfgadm library.
470 return (ib_error_msgs
[rv
].cfga_err
);
476 * ib_verify_valid_apid
478 * ap_id - The attachment point of an IB fabric
482 * 0 if ap_id is valid; otherwise -1
484 * Check if ap_id is valid or not.
485 * Ensure the ap_id passed is in the correct (physical ap_id) form:
486 * path/device:xx[.xx]+
487 * where xx is a one or two-digit number.
489 * Note the library always calls the plugin with a physical ap_id.
490 * Called by ib_verify_params().
493 ib_verify_valid_apid(const char *ap_id
)
501 l_ap_id
= strchr(ap_id
, *MINOR_SEP
);
505 if (strstr((char *)ap_id
, IBNEX_FABRIC
) != NULL
) {
506 DPRINTF("ib_valid_apid: l_apid = %s\n", l_ap_id
);
507 /* if the ap_id is "ib::" then report an error */
508 if ((strlen(l_ap_id
) == strlen(IBNEX_FABRIC
) + 1) ||
509 (strlen(l_ap_id
) == strlen(IBNEX_FABRIC
) + 2)) {
513 if (strstr(l_ap_id
, "...") != NULL
) {
517 } else { /* HCA ap_ids */
518 /* ap_id has 1..2 or more than 2 dots */
519 if (strstr(l_ap_id
, "..") != NULL
) {
532 * ap_id - The attachment point of an IB fabric
533 * options - command options passed by the cfgadm(1M)
534 * errstring - This contains error msg if command fails
538 * CFGA_IB_OK if parameters are valid; otherwise emit an error.
540 * Check if "options" and "errstring" are valid and if ap_id is
544 ib_verify_params(const char *ap_id
, const char *options
, char **errstring
)
546 if (errstring
!= NULL
) {
550 if (options
!= NULL
) {
551 DPRINTF("ib_verify_params: h/w-specific options not "
553 return (CFGA_IB_OPTIONS_ERR
);
556 if (ib_verify_valid_apid(ap_id
) != 0) {
557 DPRINTF("ib_verify_params: not an IB ap_id.\n");
558 return (CFGA_IB_AP_ERR
);
566 * ib_cleanup_after_devctl_cmd
568 * devctl_hdl - Handler to devctl
569 * user_nvlistp - Name-value-pair list pointer
575 * Cleanup an initialization/setup done in the next function i.e.
576 * ib_setup_for_devctl_cmd().
579 ib_cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl
, nvlist_t
*user_nvlist
)
581 if (user_nvlist
!= NULL
) {
582 nvlist_free(user_nvlist
);
585 if (devctl_hdl
!= NULL
) {
586 devctl_release(devctl_hdl
);
593 * ib_setup_for_devctl_cmd
595 * ap_id - Attachment point for the IB device in question
596 * use_static_ap_id - Whether to use static ap_id or not flag
598 * devctl_hdl - Handler to devctl
599 * user_nvlistp - Name-value-pair list pointer
601 * CFGA_IB_OK if it succeeds or an appropriate error.
603 * For any IB device that is doing a cfgadm operation this function
604 * sets up a devctl_hdl and allocates a nvlist_t. The devctl_hdl
605 * is acquired using libdevice APIs. The nvlist_t is filled up with
606 * the ap_id (as a string). This nvlist_t is looked up in the kernel
607 * to figure out which ap_id we are currently dealing with.
609 * "use_static_ap_id" flag tells if one should do a devctl_ap_acquire
610 * with IB_STATIC_APID or not. NOTE: We need an actual file-system
611 * vnode to do a devctl_ap_acquire.
613 * NOTE: always call ib_cleanup_after_devctl_cmd() after this function.
616 ib_setup_for_devctl_cmd(char *ap_id
, boolean_t use_static_ap_id
,
617 devctl_hdl_t
*devctl_hdl
, nvlist_t
**user_nvlistp
)
619 char *apid
= (use_static_ap_id
== B_TRUE
) ? IB_STATIC_APID
: ap_id
;
621 /* Get a handle to the ap */
622 if ((*devctl_hdl
= devctl_ap_acquire(apid
, NULL
)) == NULL
) {
623 DPRINTF("ib_setup_for_devctl_cmd: devctl_ap_acquire "
624 "errno: %d\n", errno
);
625 ib_cleanup_after_devctl_cmd(*devctl_hdl
, *user_nvlistp
);
626 return (CFGA_IB_DEVCTL_ERR
);
629 /* Set up to pass dynamic ap_id down to driver */
630 if (nvlist_alloc(user_nvlistp
, NV_UNIQUE_NAME_TYPE
, NULL
) != 0) {
631 DPRINTF("ib_setup_for_devctl: nvlist_alloc errno: %d\n", errno
);
632 *user_nvlistp
= NULL
; /* Prevent possible incorrect free in */
633 /* ib_cleanup_after_devctl_cmd */
634 ib_cleanup_after_devctl_cmd(*devctl_hdl
, *user_nvlistp
);
635 return (CFGA_IB_NVLIST_ERR
);
638 /* create a "string" entry */
639 if (nvlist_add_string(*user_nvlistp
, IB_APID
, ap_id
) == -1) {
640 DPRINTF("ib_setup_for_devctl_cmd: nvlist_add_string failed. "
641 "errno: %d\n", errno
);
642 ib_cleanup_after_devctl_cmd(*devctl_hdl
, *user_nvlistp
);
643 return (CFGA_IB_NVLIST_ERR
);
652 * ib_device_configured
654 * hdl - Handler to devctl
655 * nvl - Name-value-pair list pointer
657 * rstate - Receptacle state for the apid
659 * CFGA_IB_OK if it succeeds or an appropriate error.
661 * Checks if there is a device actually configured to the ap? If so,
662 * issues a "devctl" to get the Receptacle state for that ap_id.
663 * If the ap_id is already configured it returns CFGA_IB_OK.
664 * Otherwise it returns a failure.
667 ib_device_configured(devctl_hdl_t hdl
, nvlist_t
*nvl
, ap_rstate_t
*rstate
)
670 devctl_ap_state_t devctl_ap_state
;
672 /* get ap_id's "devctl_ap_state" first */
673 if (devctl_ap_getstate(hdl
, nvl
, &devctl_ap_state
) == -1) {
674 DPRINTF("ib_device_configured failed, errno: %d\n", errno
);
675 return (CFGA_IB_DEVCTL_ERR
);
678 rv
= CFGA_IB_ALREADY_CONFIGURED
;
679 *rstate
= devctl_ap_state
.ap_rstate
;
680 if (devctl_ap_state
.ap_ostate
!= AP_OSTATE_CONFIGURED
) {
681 return (CFGA_IB_NOT_CONFIGURED
);
690 * ib_device_connected
692 * hdl - Handler to devctl
693 * nvl - Name-value-pair list pointer
695 * ostate - Occupant state for the apid
697 * CFGA_IB_OK if it succeeds or an appropriate error.
699 * Checks if there is a device actually connected to the ap? If so,
700 * issues a "devctl" to get the Occupant state for that ap_id.
701 * If the ap_id is already connected it returns CFGA_IB_OK.
702 * Otherwise it returns a failure.
705 ib_device_connected(devctl_hdl_t hdl
, nvlist_t
*list
, ap_ostate_t
*ostate
)
707 cfga_ib_ret_t rv
= CFGA_IB_ALREADY_CONNECTED
;
708 devctl_ap_state_t devctl_ap_state
;
710 if (devctl_ap_getstate(hdl
, list
, &devctl_ap_state
) == -1) {
711 DPRINTF("ib_device_connected failed, errno: %d\n", errno
);
712 return (CFGA_IB_DEVCTL_ERR
);
715 *ostate
= devctl_ap_state
.ap_ostate
;
716 if (devctl_ap_state
.ap_rstate
!= AP_RSTATE_CONNECTED
) {
717 return (CFGA_IB_NOT_CONNECTED
);
726 * ib_do_control_ioctl
728 * ap_id - The dynamic attachment point of an IB device
729 * sub_cmd1 - Sub Command 1 to DEVCTL_AP_CONTROL devctl
730 * sub_cmd2 - Sub Command 2 to DEVCTL_AP_CONTROL devctl
731 * (Mandatory except for IBNEX_NUM_HCA_NODES,
732 * IBNEX_NUM_DEVICE_NODES,
733 * IBNEX_UPDATE_PKEY_TBLS &
734 * IBNEX_UPDATE_IOC_CONF)
735 * misc_arg - optional arguments to DEVCTL_AP_CONTROL devctl
737 * descrp - Buffer containing data back from kernel
738 * sizep - Length of the buffer back from kernel
740 * CFGA_IB_OK if it succeeds or an appropriate error.
742 * Issues DEVCTL_AP_CONTROL devctl with sub_cmd1 first which actually
743 * queries the IBNEX module in the kernel on the size of the data to
746 * Next issues DEVCTL_AP_CONTROL devctl with a buffer of that much
747 * size and gets the actual data back.
748 * Passes the data and the size back to caller.
751 ib_do_control_ioctl(char *ap_id
, uint_t sub_cmd1
, uint_t sub_cmd2
,
752 uint_t misc_arg
, void **descrp
, size_t *sizep
)
755 uint32_t local_size
= 0;
756 cfga_ib_ret_t rv
= CFGA_IB_OK
;
757 struct ibnex_ioctl_data ioctl_data
;
759 /* try to open the ONLY static ap_id */
760 if ((fd
= open(IB_STATIC_APID
, O_RDONLY
)) == -1) {
761 DPRINTF("ib_do_control_ioctl: open failed: "
762 "errno = %d\n", errno
);
763 /* Provides a more useful error msg */
764 rv
= (errno
== EBUSY
) ? CFGA_IB_BUSY_ERR
: CFGA_IB_OPEN_ERR
;
769 * Find out first how large a buffer is needed?
770 * NOTE: Ioctls only accept/return a 32-bit int for a get_size
771 * to avoid 32/64 and BE/LE issues.
773 ioctl_data
.cmd
= sub_cmd1
;
774 ioctl_data
.misc_arg
= (uint_t
)misc_arg
;
775 ioctl_data
.buf
= (caddr_t
)&local_size
;
776 ioctl_data
.bufsiz
= sizeof (local_size
);
778 /* Pass "ap_id" up for all other commands */
779 if (sub_cmd1
!= IBNEX_NUM_DEVICE_NODES
&&
780 sub_cmd1
!= IBNEX_NUM_HCA_NODES
&&
781 sub_cmd1
!= IBNEX_UPDATE_PKEY_TBLS
) {
782 ioctl_data
.ap_id
= (caddr_t
)ap_id
;
783 ioctl_data
.ap_id_len
= strlen(ap_id
);
786 ioctl_data
.ap_id
= NULL
;
787 ioctl_data
.ap_id_len
= 0;
790 if (ioctl(fd
, DEVCTL_AP_CONTROL
, &ioctl_data
) != 0) {
791 DPRINTF("ib_do_control_ioctl: size ioctl ERR, errno: %d\n",
794 rv
= (errno
== EBUSY
) ? CFGA_IB_BUSY_ERR
: CFGA_IB_IOCTL_ERR
;
800 * Don't do the second ioctl only in these cases
801 * (NOTE: the data is returned in the first ioctl itself; if any)
803 if (sub_cmd1
== IBNEX_NUM_DEVICE_NODES
||
804 sub_cmd1
== IBNEX_NUM_HCA_NODES
||
805 sub_cmd1
== IBNEX_UPDATE_PKEY_TBLS
||
806 sub_cmd1
== IBNEX_UPDATE_IOC_CONF
) {
811 if (local_size
== 0 || (*descrp
= malloc(*sizep
)) == NULL
) {
812 DPRINTF("ib_do_control_ioctl: malloc failed\n");
814 return (CFGA_IB_ALLOC_FAIL
);
818 ioctl_data
.cmd
= sub_cmd2
;
819 ioctl_data
.buf
= (caddr_t
)*descrp
;
820 ioctl_data
.bufsiz
= *sizep
;
822 if (ioctl(fd
, DEVCTL_AP_CONTROL
, &ioctl_data
) != 0) {
823 DPRINTF("ib_do_control_ioctl: ioctl failed: errno:%d\n", errno
);
824 if (*descrp
!= NULL
) {
828 rv
= (errno
== EBUSY
) ? CFGA_IB_BUSY_ERR
: CFGA_IB_IOCTL_ERR
;
836 /* ========================================================================== */
843 * state_change_cmd - Argument to the cfgadm -c command
844 * ap_id - The attachment point of an IB fabric
845 * options - State Change command options passed by the cfgadm(1M)
846 * confp - Whether this command requires confirmation?
847 * msgp - cfgadm error message for this plugin
848 * errstring - This contains error msg if command fails
849 * flags - Cfgadm(1m) flags
853 * If the command succeeded perform the cfgadm -c <cmd>;
854 * otherwise emit an error
860 cfga_change_state(cfga_cmd_t state_change_cmd
, const char *ap_id
,
861 const char *options
, struct cfga_confirm
*confp
, struct cfga_msg
*msgp
,
862 char **errstring
, cfga_flags_t flags
)
866 nvlist_t
*nvl
= NULL
;
867 boolean_t static_ap_id
= B_TRUE
;
870 devctl_hdl_t hdl
= NULL
;
871 cfga_ib_ret_t rv
= CFGA_IB_OK
;
873 if ((rv
= ib_verify_params(ap_id
, options
, errstring
)) != CFGA_IB_OK
) {
874 (void) cfga_help(msgp
, options
, flags
);
875 return (ib_err_msg(errstring
, CFGA_IB_INVAL_APID_ERR
,
880 * All subcommands which can change state of device require
883 if (geteuid() != 0) {
884 return (ib_err_msg(errstring
, CFGA_IB_PRIV_ERR
, ap_id
, errno
));
887 if (strstr((char *)ap_id
, IB_FABRIC_APID_STR
) == NULL
)
888 static_ap_id
= B_FALSE
;
890 if ((rv
= ib_setup_for_devctl_cmd((char *)ap_id
, static_ap_id
,
891 &hdl
, &nvl
)) != CFGA_IB_OK
) {
892 ib_cleanup_after_devctl_cmd(hdl
, nvl
);
893 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
896 switch (state_change_cmd
) {
897 case CFGA_CMD_CONFIGURE
:
898 rv
= ib_device_connected(hdl
, nvl
, &ostate
);
899 if (rv
!= CFGA_IB_ALREADY_CONNECTED
) {
900 ret
= (rv
!= CFGA_IB_NOT_CONNECTED
) ?
901 CFGA_IB_CONFIG_OP_ERR
: rv
;
902 ib_cleanup_after_devctl_cmd(hdl
, nvl
);
903 return (ib_err_msg(errstring
, ret
, ap_id
, errno
));
906 if (rv
== CFGA_IB_ALREADY_CONNECTED
) {
908 * special case handling for
909 * SLM based cfgadm disconnects
911 if (ostate
== AP_OSTATE_CONFIGURED
) {
912 ib_cleanup_after_devctl_cmd(hdl
, nvl
);
913 return (ib_err_msg(errstring
,
914 CFGA_IB_ALREADY_CONFIGURED
, ap_id
,
920 rv
= CFGA_IB_OK
; /* Other status don't matter */
922 if (devctl_ap_configure(hdl
, nvl
) != 0) {
923 DPRINTF("cfga_change_state: devctl_ap_configure "
924 "failed. errno: %d\n", errno
);
925 rv
= CFGA_IB_CONFIG_OP_ERR
;
929 devpath
= ib_get_devicepath(ap_id
);
930 if (devpath
== NULL
) {
934 * try for some time as IB hotplug thread
935 * takes a while to create the path
936 * and then eventually give up
939 i
< IB_RETRY_DEVPATH
&& (devpath
== NULL
); i
++) {
940 sleep(IB_MAX_DEVPATH_DELAY
);
941 devpath
= ib_get_devicepath(ap_id
);
944 if (devpath
== NULL
) {
945 DPRINTF("cfga_change_state: get device "
946 "path failed i = %d\n", i
);
947 rv
= CFGA_IB_CONFIG_OP_ERR
;
954 case CFGA_CMD_UNCONFIGURE
:
955 if ((rv
= ib_device_connected(hdl
, nvl
, &ostate
)) !=
956 CFGA_IB_ALREADY_CONNECTED
) {
957 ib_cleanup_after_devctl_cmd(hdl
, nvl
);
958 if (rv
== CFGA_IB_DEVCTL_ERR
)
959 rv
= CFGA_IB_INVALID_OP_ERR
;
960 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
963 /* check if it is already unconfigured */
964 if ((rv
= ib_device_configured(hdl
, nvl
, &rstate
)) ==
965 CFGA_IB_NOT_CONFIGURED
) {
966 ib_cleanup_after_devctl_cmd(hdl
, nvl
);
967 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
970 rv
= CFGA_IB_OK
; /* Other statuses don't matter */
972 if (!ib_confirm(confp
, IB_CONFIRM1
)) {
973 ib_cleanup_after_devctl_cmd(hdl
, nvl
);
977 devpath
= ib_get_devicepath(ap_id
);
978 if (devpath
== NULL
) {
979 DPRINTF("cfga_change_state: get device path failed\n");
980 rv
= CFGA_IB_UNCONFIG_OP_ERR
;
984 if ((rv
= ib_rcm_offline(ap_id
, errstring
, devpath
, flags
)) !=
990 ret
= devctl_ap_unconfigure(hdl
, nvl
);
992 DPRINTF("cfga_change_state: devctl_ap_unconfigure "
993 "failed with errno: %d\n", errno
);
994 rv
= CFGA_IB_UNCONFIG_OP_ERR
;
995 if (errno
== EBUSY
) {
996 rv
= CFGA_IB_BUSY_ERR
;
998 (void) ib_rcm_online(ap_id
, errstring
, devpath
, flags
);
1001 (void) ib_rcm_remove(ap_id
, errstring
, devpath
, flags
);
1008 case CFGA_CMD_UNLOAD
:
1009 case CFGA_CMD_CONNECT
:
1010 case CFGA_CMD_DISCONNECT
:
1011 (void) cfga_help(msgp
, options
, flags
);
1012 rv
= CFGA_IB_OPNOTSUPP
;
1017 (void) cfga_help(msgp
, options
, flags
);
1018 rv
= CFGA_IB_INTERNAL_ERR
;
1021 ib_cleanup_after_devctl_cmd(hdl
, nvl
);
1022 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1030 * func - The private function (passed w/ -x option)
1031 * ap_id - The attachment point of an IB fabric
1032 * options - Private function command options passed
1034 * confp - Whether this command requires confirmation?
1035 * msgp - cfgadm error message for this plugin
1036 * errstring - This contains error msg if command fails
1037 * flags - Cfgadm(1m) flags
1041 * If the command succeeded perform the 'cfgadm -x <func>'; otherwise
1044 * Do cfgadm -x <func>
1048 cfga_private_func(const char *func
, const char *ap_id
, const char *options
,
1049 struct cfga_confirm
*confp
, struct cfga_msg
*msgp
, char **errstring
,
1052 int len
, ret
, count
= 0;
1053 char *clnt_name
= NULL
, *alt_hca
= NULL
;
1054 char *clnt_apid
= NULL
, *clnt_devpath
= NULL
;
1055 char *name
, *msg
= NULL
;
1056 char *fab_apid
= strstr((char *)ap_id
, IBNEX_FABRIC
);
1057 size_t info_len
= 0;
1058 uchar_t
*info
= NULL
;
1060 nvpair_t
*nvp
= NULL
;
1062 devctl_hdl_t hdl
= NULL
;
1065 if ((rv
= ib_verify_params(ap_id
, NULL
, errstring
)) != CFGA_IB_OK
) {
1066 DPRINTF("cfga_private_func: ib_verify_params "
1067 "failed with rv: %d\n", rv
);
1068 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1072 DPRINTF("cfga_private_func: func is NULL\n");
1073 return (ib_err_msg(errstring
, CFGA_IB_INVAL_ARG_ERR
, ap_id
,
1078 * check first if IB static ap_id is "configured" for use
1080 if (fab_apid
!= NULL
) {
1081 if ((rv
= ib_setup_for_devctl_cmd(fab_apid
, B_TRUE
, &hdl
,
1082 &nvl
)) != CFGA_IB_OK
) {
1083 ib_cleanup_after_devctl_cmd(hdl
, nvl
);
1084 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1086 if ((rv
= ib_device_configured(hdl
, nvl
, &rstate
)) ==
1087 CFGA_IB_NOT_CONFIGURED
) {
1088 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1090 ib_cleanup_after_devctl_cmd(hdl
, nvl
);
1094 DPRINTF("cfga_private_func: func is %s\n", func
);
1095 if (strcmp(func
, IB_LIST_HCA_CLIENTS
) == 0) { /* -x list_clients */
1097 /* only supported on HCA ap_ids */
1098 if (fab_apid
!= NULL
) {
1099 DPRINTF("cfga_private_func: fabric apid supplied\n");
1100 return (ib_err_msg(errstring
, CFGA_IB_INVALID_OP_ERR
,
1104 if ((msg
= (char *)calloc(256, 1)) == NULL
) {
1105 DPRINTF("cfga_private_func: malloc for msg failed. "
1106 "errno: %d\n", errno
);
1107 return (ib_err_msg(errstring
, CFGA_IB_ALLOC_FAIL
,
1111 if ((rv
= ib_do_control_ioctl((char *)ap_id
, IBNEX_HCA_LIST_SZ
,
1112 IBNEX_HCA_LIST_INFO
, 0, (void **)&info
, &info_len
)) != 0) {
1113 DPRINTF("cfga_private_func: "
1114 "ib_do_control_ioctl list failed :%d\n", rv
);
1116 return (ib_err_msg(errstring
, CFGA_IB_HCA_LIST_ERR
,
1120 if (nvlist_unpack((char *)info
, info_len
, &nvl
, 0)) {
1121 DPRINTF("cfga_private_func: "
1122 "nvlist_unpack 2 failed %p\n", info
);
1125 return (ib_err_msg(errstring
, CFGA_IB_NVLIST_ERR
, ap_id
,
1129 (void) snprintf(msg
, 256, "Ap_Id\t\t\t IB Client\t\t "
1131 cfga_msg(msgp
, msg
);
1133 /* Walk the NVPAIR data */
1134 while (nvp
= nvlist_next_nvpair(nvl
, nvp
)) {
1135 name
= nvpair_name(nvp
);
1136 if (strcmp(name
, "Client") == 0) {
1137 (void) nvpair_value_string(nvp
, &clnt_name
);
1139 } else if (strcmp(name
, "Alt_HCA") == 0) {
1140 (void) nvpair_value_string(nvp
, &alt_hca
);
1142 } else if (strcmp(name
, "ApID") == 0) {
1143 (void) nvpair_value_string(nvp
, &clnt_apid
);
1147 /* check at the end; print message per client found */
1150 (void) snprintf(msg
, 256, "%-30s %-25s %s\n",
1151 clnt_apid
, clnt_name
, alt_hca
);
1152 cfga_msg(msgp
, msg
);
1154 } /* end of while */
1160 /* -x unconfig_clients */
1161 } else if (strcmp(func
, IB_UNCONFIG_HCA_CLIENTS
) == 0) {
1163 * -x unconfig_clients changes state by calling into RCM.
1164 * It needs root privileges.
1166 if (geteuid() != 0) {
1167 return (ib_err_msg(errstring
, CFGA_IB_PRIV_ERR
, ap_id
,
1171 /* only supported on HCA ap_ids */
1172 if (fab_apid
!= NULL
) {
1173 DPRINTF("cfga_private_func: fabric apid supplied\n");
1174 return (ib_err_msg(errstring
, CFGA_IB_INVALID_OP_ERR
,
1179 * Check w/ user if it is ok to do this operation
1180 * If the user fails to confirm, bailout
1182 if (!ib_confirm(confp
, IB_CONFIRM3
))
1185 /* Get device-paths of all the IOC/Port/Pseudo devices */
1186 rv
= ib_do_control_ioctl((char *)ap_id
, IBNEX_UNCFG_CLNTS_SZ
,
1187 IBNEX_UNCFG_CLNTS_INFO
, 0, (void **)&info
, &info_len
);
1189 DPRINTF("cfga_private_func: ib_do_control_ioctl "
1190 "failed :%d\n", rv
);
1191 return (ib_err_msg(errstring
, CFGA_IB_HCA_UNCONFIG_ERR
,
1195 if (nvlist_unpack((char *)info
, info_len
, &nvl
, 0)) {
1196 DPRINTF("cfga_private_func: nvlist_unpack failed %p\n",
1199 return (ib_err_msg(errstring
, CFGA_IB_NVLIST_ERR
, ap_id
,
1205 /* Call RCM Offline on all device paths */
1206 while (nvp
= nvlist_next_nvpair(nvl
, nvp
)) {
1207 name
= nvpair_name(nvp
);
1208 if (strcmp(name
, "devpath") == 0) {
1209 (void) nvpair_value_string(nvp
, &clnt_devpath
);
1211 } else if (strcmp(name
, "ApID") == 0) {
1212 (void) nvpair_value_string(nvp
, &clnt_apid
);
1216 /* handle the client unconfigure now */
1218 count
= 0; /* reset count */
1220 DPRINTF("cfga_private_func: client apid = %s, "
1221 "DevPath = %s\n", clnt_apid
, clnt_devpath
);
1222 if ((rv
= ib_setup_for_devctl_cmd(clnt_apid
,
1223 B_TRUE
, &hdl
, &nvl
)) != CFGA_IB_OK
) {
1224 ib_cleanup_after_devctl_cmd(hdl
, nvl
);
1225 return (ib_err_msg(errstring
, rv
,
1229 if ((rv
= ib_device_configured(hdl
, nvl
,
1230 &rstate
)) == CFGA_IB_NOT_CONFIGURED
)
1233 if ((rv
= ib_rcm_offline(clnt_apid
, errstring
,
1234 clnt_devpath
, flags
)) != CFGA_IB_OK
) {
1235 DPRINTF("cfga_private_func: client rcm "
1236 "offline failed for %s, with %d\n",
1242 if (devctl_ap_unconfigure(hdl
, nvl
) != 0) {
1243 DPRINTF("cfga_private_func: client "
1244 "unconfigure failed: errno %d\n",
1246 ret
= CFGA_IB_UNCONFIG_OP_ERR
;
1248 ret
= CFGA_IB_BUSY_ERR
;
1249 (void) ib_rcm_online(clnt_apid
,
1250 errstring
, clnt_devpath
, flags
);
1253 (void) ib_rcm_remove(clnt_apid
,
1254 errstring
, clnt_devpath
, flags
);
1256 ib_cleanup_after_devctl_cmd(hdl
, nvl
);
1258 } /* end of if count == 2 */
1260 } /* end of while */
1265 DPRINTF("cfga_private_func: unconfig_clients of %s "
1266 "failed with %d\n", ap_id
, ret
);
1267 return (ib_err_msg(errstring
, CFGA_IB_UCFG_CLNTS_ERR
,
1271 /* -x update_pkey_tbls */
1272 } else if (strcmp(func
, IB_UPDATE_PKEY_TBLS
) == 0) {
1274 * Check for root privileges.
1276 if (geteuid() != 0) {
1277 return (ib_err_msg(errstring
, CFGA_IB_PRIV_ERR
, ap_id
,
1281 /* CHECK: Only supported on fabric ap_ids */
1282 if (fab_apid
== NULL
|| strcmp(fab_apid
, IBNEX_FABRIC
) != 0) {
1283 DPRINTF("cfga_private_func: fabric apid needed\n");
1284 return (ib_err_msg(errstring
, CFGA_IB_INVALID_OP_ERR
,
1288 /* Check w/ user if it is ok to do this operation */
1289 len
= strlen(IB_CONFIRM4
) + 10;
1290 if ((msg
= (char *)calloc(len
, 1)) != NULL
) {
1291 (void) snprintf(msg
, len
, "%s\nContinue", IB_CONFIRM4
);
1294 /* If the user fails to confirm, return */
1295 if (!ib_confirm(confp
, msg
)) {
1301 /* Update P_Key tables for all ports of all HCAs */
1302 rv
= ib_do_control_ioctl((char *)ap_id
, IBNEX_UPDATE_PKEY_TBLS
,
1303 0, 0, 0, &info_len
);
1306 DPRINTF("cfga_private_func: ib_do_control_ioctl "
1307 "failed :%d\n", rv
);
1308 return (ib_err_msg(errstring
, CFGA_IB_UPD_PKEY_TBLS_ERR
,
1312 /* -x [add_service|delete_service] */
1313 } else if ((strncmp(func
, IB_ADD_SERVICE
, 12) == 0) ||
1314 (strncmp(func
, IB_DELETE_SERVICE
, 15) == 0)) {
1315 char *subopts
, *val
;
1318 /* check: Only supported on fabric ap_ids */
1319 if (fab_apid
== NULL
|| strcmp(fab_apid
, IBNEX_FABRIC
) != 0) {
1320 DPRINTF("cfga_private_func: fabric apid needed\n");
1321 return (ib_err_msg(errstring
, CFGA_IB_INVALID_OP_ERR
,
1325 /* Check for root privileges. */
1326 if (geteuid() != 0) {
1327 return (ib_err_msg(errstring
, CFGA_IB_PRIV_ERR
, ap_id
,
1331 /* return error if no options are specified */
1332 subopts
= (char *)options
;
1333 if (subopts
== (char *)NULL
) {
1334 DPRINTF("cfga_private_func: no sub-options\n");
1335 (void) cfga_help(msgp
, options
, flags
);
1336 return (ib_err_msg(errstring
, CFGA_IB_INVAL_ARG_ERR
,
1340 /* parse options specified */
1341 while (*subopts
!= '\0') {
1342 switch (getsubopt(&subopts
, ib_service_subopts
, &val
)) {
1345 (void) cfga_help(msgp
, options
, flags
);
1346 S_FREE(service_name
);
1347 return (ib_err_msg(errstring
,
1348 CFGA_IB_INVAL_ARG_ERR
,
1351 comm_name
= strdup(val
);
1352 if (comm_name
== NULL
) {
1353 DPRINTF("comm sub-opt invalid "
1355 S_FREE(service_name
);
1356 return (ib_err_msg(errstring
,
1357 CFGA_IB_COMM_INVAL_ERR
,
1363 case 1: /* service */
1365 (void) cfga_help(msgp
, options
, flags
);
1367 return (ib_err_msg(errstring
,
1368 CFGA_IB_INVAL_ARG_ERR
,
1371 /* service can be upto 4 long */
1372 if (strlen(val
) == 0 ||
1374 DPRINTF("comm sub-opt invalid "
1375 "service passed\n");
1377 return (ib_err_msg(errstring
,
1378 CFGA_IB_SVC_LEN_ERR
,
1381 service_name
= strdup(val
);
1382 if (service_name
== NULL
) {
1383 DPRINTF("comm sub-opt "
1384 "internal error\n");
1386 return (ib_err_msg(errstring
,
1387 CFGA_IB_SVC_INVAL_ERR
,
1394 (void) cfga_help(msgp
, options
, flags
);
1396 S_FREE(service_name
);
1397 return (ib_err_msg(errstring
,
1398 CFGA_IB_INVAL_ARG_ERR
, ap_id
, errno
));
1402 /* figure out the "operation" */
1403 if (strncasecmp(func
, IB_ADD_SERVICE
, 11) == 0)
1404 cmd
= IBCONF_ADD_ENTRY
;
1405 else if (strncasecmp(func
, IB_DELETE_SERVICE
, 14) == 0)
1406 cmd
= IBCONF_DELETE_ENTRY
;
1407 DPRINTF("Service = %s, Comm = %s, Operation = %s\n",
1408 service_name
, comm_name
, func
);
1410 if (strncasecmp(comm_name
, IBNEX_PORT_STR
, 4) == 0)
1411 service_type
= IB_PORT_SERVICE
;
1412 else if (strncasecmp(comm_name
, IBNEX_VPPA_STR
, 4) == 0)
1413 service_type
= IB_VPPA_SERVICE
;
1414 else if (strncasecmp(comm_name
, IBNEX_HCASVC_STR
, 4) == 0)
1415 service_type
= IB_HCASVC_SERVICE
;
1417 (void) cfga_help(msgp
, options
, flags
);
1419 S_FREE(service_name
);
1420 return (ib_err_msg(errstring
, CFGA_IB_INVAL_ARG_ERR
,
1424 /* do the add/delete entry to the service */
1425 if (cmd
== IBCONF_ADD_ENTRY
) {
1426 if ((rv
= ib_add_service(errstring
)) != CFGA_IB_OK
)
1427 DPRINTF("cfga_private_func: add failed\n");
1428 } else if (cmd
== IBCONF_DELETE_ENTRY
) {
1429 if ((rv
= ib_delete_service(errstring
)) != CFGA_IB_OK
)
1430 DPRINTF("cfga_private_func: delete failed\n");
1434 S_FREE(service_name
);
1435 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1437 } else if (strncmp(func
, IB_LIST_SERVICES
, 13) == 0) {
1439 /* check: Only supported on fabric ap_ids */
1440 if (fab_apid
== NULL
|| strcmp(fab_apid
, IBNEX_FABRIC
) != 0) {
1441 DPRINTF("cfga_private_func: fabric apid needed\n");
1442 return (ib_err_msg(errstring
, CFGA_IB_INVALID_OP_ERR
,
1446 /* do the list services */
1447 rv
= ib_list_services(msgp
, errstring
);
1448 if (rv
!= CFGA_IB_OK
) {
1449 DPRINTF("cfga_private_func: ib_list_services failed\n");
1450 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1453 /* -x update_ioc_conf */
1454 } else if (strncmp(func
, IB_UPDATE_IOC_CONF
, 17) == 0) {
1457 /* Supported only with root privilege */
1458 if (geteuid() != 0) {
1459 return (ib_err_msg(errstring
, CFGA_IB_PRIV_ERR
, ap_id
,
1464 * check: Only supported on fabric ap_id or IOC APID
1465 * IOC APID does not have any commas in it.
1467 if (fab_apid
== NULL
||
1468 (fab_apid
!= NULL
&& strstr(fab_apid
, ",") != NULL
)) {
1469 DPRINTF("cfga_private_func: fabric/IOC apid needed\n");
1470 return (ib_err_msg(errstring
, CFGA_IB_INVALID_OP_ERR
,
1474 /* Check w/ user if it is ok to do this operation */
1475 len
= strlen(IB_CONFIRM5
) + 10;
1476 if ((msg
= (char *)calloc(len
, 1)) != NULL
) {
1477 (void) snprintf(msg
, len
, "%s\nContinue", IB_CONFIRM5
);
1480 /* If the user fails to confirm, return */
1481 if (!ib_confirm(confp
, msg
)) {
1487 misc_arg
= (strcmp(fab_apid
, IBNEX_FABRIC
) == 0) ?
1488 IBNEX_BASE_APID
: IBNEX_DYN_APID
;
1490 /* Reprobe and update IOC(s) configuration */
1491 rv
= ib_do_control_ioctl((char *)ap_id
, IBNEX_UPDATE_IOC_CONF
,
1492 0, misc_arg
, 0, &info_len
);
1495 DPRINTF("cfga_private_func: ib_do_control_ioctl "
1496 "failed :%d\n", rv
);
1497 return (ib_err_msg(errstring
, CFGA_IB_DEVCTL_ERR
,
1501 DPRINTF("cfga_private_func: unrecognized command.\n");
1502 (void) cfga_help(msgp
, options
, flags
);
1504 return (CFGA_INVAL
);
1507 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1515 * ap_id - The attachment point of an IB fabric
1516 * options - Test command options passed by the cfgadm(1M)
1517 * msgp - cfgadm error message for this plugin
1518 * errstring - This contains error msg if command fails
1519 * flags - Cfgadm(1m) flags
1529 cfga_test(const char *ap_id
, const char *options
, struct cfga_msg
*msgp
,
1530 char **errstring
, cfga_flags_t flags
)
1532 (void) cfga_help(msgp
, options
, flags
);
1533 return (CFGA_OPNOTSUPP
);
1539 * ib_fill_static_apids
1541 * ap_id - The static attachment point of an IB device
1542 * clp - The returned "list" information array
1546 * Fills up the "list" information array for the static attachment point
1548 * IB fabric supports two types of static attachment points.
1549 * One is fabric and other is for the HCAs. This fills up
1550 * "cfga_list_data_t" for static attachment points.
1552 static cfga_ib_ret_t
1553 ib_fill_static_apids(char *ap_id
, cfga_list_data_t
*clp
)
1556 char *ap_id_log
= NULL
;
1558 /* Get /dev/cfg path to corresponding to the physical ap_id */
1559 /* Remember ap_id_log must be freed */
1560 if (ib_physpath_to_devlink(ap_id
, &ap_id_log
,
1561 &l_err
) != ICFGA_OK
) {
1562 DPRINTF("ib_fill_static_apids: "
1563 "ib_physpath_to_devlink failed\n");
1564 return (CFGA_IB_DEVLINK_ERR
);
1566 assert(ap_id_log
!= NULL
);
1568 /* Get logical ap-id corresponding to the physical */
1569 if (strstr(ap_id_log
, CFGA_DEV_DIR
) == NULL
) {
1570 DPRINTF("ib_fill_static_apids: devlink doesn't contain "
1573 return (CFGA_IB_DEVLINK_ERR
);
1576 clp
->ap_cond
= CFGA_COND_OK
;
1577 clp
->ap_r_state
= CFGA_STAT_CONNECTED
;
1578 clp
->ap_o_state
= CFGA_STAT_CONFIGURED
;
1579 clp
->ap_class
[0] = '\0'; /* Filled by libcfgadm */
1581 clp
->ap_status_time
= (time_t)-1;
1582 (void) snprintf(clp
->ap_log_id
, sizeof (clp
->ap_log_id
), "%s",
1583 /* Strip off /dev/cfg/ */ ap_id_log
+ strlen(CFGA_DEV_DIR
) + 1);
1584 (void) strlcpy(clp
->ap_phys_id
, ap_id
, sizeof (clp
->ap_phys_id
));
1586 /* Static IB apid */
1587 if (strstr((char *)ap_id
, IB_FABRIC_APID_STR
) != NULL
) {
1588 (void) strlcpy(clp
->ap_type
, IB_FABRIC_TYPE
,
1589 sizeof (clp
->ap_type
)); /* Fill in type */
1590 (void) strlcpy(clp
->ap_info
, IB_FABRIC_INFO
,
1591 sizeof (clp
->ap_info
));
1593 } else { /* Static HCA apid */
1595 uchar_t
*data
= NULL
;
1597 (void) strlcpy(clp
->ap_type
, IB_HCA_TYPE
,
1598 sizeof (clp
->ap_type
)); /* Fill in type */
1600 rv
= ib_do_control_ioctl(ap_id
, IBNEX_HCA_VERBOSE_SZ
,
1601 IBNEX_HCA_VERBOSE_INFO
, 0, (void **)&data
, &size
);
1603 DPRINTF("ib_fill_static_apids: ib_do_control_ioctl "
1604 "failed :%d\n", rv
);
1607 return (CFGA_IB_IOCTL_ERR
);
1610 (void) strlcpy(clp
->ap_info
, (char *)data
,
1611 sizeof (clp
->ap_info
));
1615 return (CFGA_IB_OK
);
1623 * ap_id - The attachment point of an IB fabric
1624 * ap_id_list - The returned "list" information array
1625 * nlistp - Number of elements in the "list" information array
1626 * options - List command options passed by the cfgadm(1M)
1627 * listopts - "-s" specific options
1628 * errstring - This contains error msg if command fails
1629 * flags - Cfgadm(1m) flags
1633 * If the command succeeded, cfgadm -l output otherwise an error
1639 cfga_list_ext(const char *ap_id
, cfga_list_data_t
**ap_id_list
, int *nlistp
,
1640 const char *options
, const char *listopts
, char **errstring
,
1644 int i
, index
, count
;
1645 int show_dynamic
= 0;
1646 size_t num_devices
= 0;
1647 size_t num_hcas
= 0;
1648 size_t snap_size
= 0;
1649 uchar_t
*snap_data
= NULL
;
1650 nvpair_t
*nvp
= NULL
; /* for lint purposes */
1651 nvlist_t
*nvl
= NULL
;
1652 boolean_t apid_matched
= B_FALSE
; /* for valid ap_id */
1653 cfga_ib_ret_t rv
= CFGA_IB_OK
;
1654 cfga_list_data_t
*clp
= NULL
;
1656 if ((rv
= ib_verify_params(ap_id
, options
, errstring
)) != CFGA_IB_OK
) {
1657 (void) cfga_help(NULL
, options
, flags
);
1658 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1661 /* make sure we have a valid ap_id_list */
1662 if (ap_id_list
== NULL
|| nlistp
== NULL
) {
1663 DPRINTF("cfga_list_ext: list = NULL or nlistp = NULL\n");
1664 (void) cfga_help(NULL
, options
, flags
);
1665 return (ib_err_msg(errstring
, CFGA_IB_INVAL_ARG_ERR
,
1669 DPRINTF("cfga_list_ext: ap_id = %s\n", ap_id
);
1671 if ((flags
& CFGA_FLAG_LIST_ALL
) == CFGA_FLAG_LIST_ALL
) {
1672 expand
= 1; /* -a flag passed */
1675 if (GET_DYN(ap_id
) != NULL
) {
1679 if ((expand
== 1) && /* -a option passed */
1680 (strstr((char *)ap_id
, IB_FABRIC_APID_STR
) != NULL
)) {
1682 * Figure out how many IOC/Port/Pseudo
1683 * devices exist in the system?
1685 if ((rv
= ib_do_control_ioctl((char *)ap_id
,
1686 IBNEX_NUM_DEVICE_NODES
, 0, 0, 0, &num_devices
)) !=
1688 DPRINTF("cfga_list_ext: ib_do_control_ioctl "
1689 "IBNEX_NUM_DEVICE_NODES failed :%d\n", rv
);
1690 if (errno
== ENOENT
)
1691 return (CFGA_APID_NOEXIST
);
1692 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1695 DPRINTF("cfga_list_ext: num_devices = %d\n", num_devices
);
1698 /* Figure out how many HCA nodes exist in the system. */
1699 if ((rv
= ib_do_control_ioctl((char *)ap_id
, IBNEX_NUM_HCA_NODES
, 0, 0,
1700 0, &num_hcas
)) != CFGA_IB_OK
) {
1701 DPRINTF("cfga_list_ext: ib_do_control_ioctl "
1702 "IBNEX_NUM_HCA_NODES failed :%d\n", rv
);
1703 if (errno
== ENOENT
)
1704 return (CFGA_APID_NOEXIST
);
1705 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1707 DPRINTF("cfga_list_ext: num_hcas = %d\n", num_hcas
);
1710 * No HCAs or IOC/VPPA/Port/HCA_SVC/Pseudo devices seen (non-IB system)
1712 if (!(num_hcas
|| num_devices
)) {
1713 DPRINTF("cfga_list_ext: no IB devices found\n");
1714 return (CFGA_APID_NOEXIST
);
1718 * *nlistp contains to how many APIDs to show w/ cfgadm -l.
1719 * If ap_id is "fabric" then
1720 * *nlistp is all Dynamic Apids + One more for "fabric"
1721 * If ap_id is "HCA" ap_id then
1723 * Note that each HCA is a static APID, so nlistp will be 1 always
1724 * and this function will be called N times for each of the N HCAs
1727 if (strstr((char *)ap_id
, IB_FABRIC_APID_STR
) != NULL
) {
1728 *nlistp
= num_devices
+ 1;
1731 /* Assume it as a HCA ap_id */
1735 /* Allocate storage for passing "list" info back */
1736 if ((*ap_id_list
= (cfga_list_data_t
*)calloc(*nlistp
,
1737 sizeof (cfga_list_data_t
))) == NULL
) {
1738 DPRINTF("cfga_list_ext: malloc for cfga_list_data_t failed. "
1739 "errno: %d\n", errno
);
1740 return (ib_err_msg(errstring
, CFGA_IB_ALLOC_FAIL
,
1745 * Only static ap_id is ib_fabric:
1746 * If -a options isn't specified then only show the static ap_id.
1748 if (!show_dynamic
) {
1749 clp
= &(*ap_id_list
[0]);
1751 if ((rv
= ib_fill_static_apids((char *)ap_id
, clp
)) !=
1753 S_FREE(*ap_id_list
);
1754 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1756 apid_matched
= B_TRUE
;
1761 * No HCAs or IOC/VPPA/HCA_SVC/Port/Pseudo devices seen (non-IB system)
1763 if (!expand
|| (!num_hcas
&& !num_devices
)) {
1768 if (strstr((char *)ap_id
, IB_FABRIC_APID_STR
) != NULL
) {
1769 rv
= ib_do_control_ioctl((char *)ap_id
, IBNEX_SNAPSHOT_SIZE
,
1770 IBNEX_GET_SNAPSHOT
, IBNEX_DONOT_PROBE_FLAG
,
1771 (void **)&snap_data
, &snap_size
);
1773 DPRINTF("cfga_list_ext: ib_do_control_ioctl "
1774 "failed :%d\n", rv
);
1775 S_FREE(*ap_id_list
);
1777 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1780 if (nvlist_unpack((char *)snap_data
, snap_size
, &nvl
, 0)) {
1781 DPRINTF("cfga_list_ext: nvlist_unpack 1 failed %p\n",
1783 S_FREE(*ap_id_list
);
1785 return (ib_err_msg(errstring
, CFGA_IB_NVLIST_ERR
,
1790 * In kernel a nvlist is build per ap_id which contains
1791 * information that is displayed using cfgadm -l.
1792 * For IB devices only these 6 items are shown:
1793 * ap_id, type, occupant, receptacle, condition and info
1795 * In addition, one could specify a dynamic ap_id from
1796 * command-line. Then cfgadm -l should show only that
1797 * ap_id and skip rest.
1799 index
= 1; count
= 0;
1800 while (nvp
= nvlist_next_nvpair(nvl
, nvp
)) {
1805 char *name
= nvpair_name(nvp
);
1807 /* start of with next device */
1808 if (count
== IB_NUM_NVPAIRS
) {
1814 * Check if the index doesn't go beyond the
1815 * device number. If it goes, stop the loop
1816 * here not to cause the heap corruption.
1818 if (show_dynamic
== 0 && index
> num_devices
)
1821 /* fill up data into "clp" */
1822 clp
= (show_dynamic
!= 0) ? &(*ap_id_list
[0]) :
1823 &(ap_id_list
[0][index
]);
1825 /* First nvlist entry is "ap_id" always */
1826 if (strcmp(name
, IBNEX_NODE_APID_NVL
) == 0) {
1827 (void) nvpair_value_string(nvp
, &nv_apid
);
1828 DPRINTF("cfga_list_ext: Name = %s, apid = %s\n",
1832 * If a dynamic ap_id is specified in the
1833 * command-line, skip all entries until
1834 * the one needed matches.
1837 strstr(ap_id
, nv_apid
) == NULL
) {
1838 DPRINTF("cfga_list_ext: NO MATCH\n");
1841 * skip rest of the entries of this
1844 for (i
= 0; i
< IB_NUM_NVPAIRS
- 1; i
++)
1845 nvp
= nvlist_next_nvpair(nvl
,
1847 count
= 0; /* reset it */
1851 apid_matched
= B_TRUE
;
1853 /* build the physical ap_id */
1854 if (strstr(ap_id
, DYN_SEP
) == NULL
) {
1855 (void) snprintf(clp
->ap_phys_id
,
1856 sizeof (clp
->ap_phys_id
), "%s%s%s",
1857 ap_id
, DYN_SEP
, nv_apid
);
1859 (void) snprintf(clp
->ap_phys_id
,
1860 sizeof (clp
->ap_phys_id
), "%s",
1864 /* ensure that this is a valid apid */
1865 if (ib_verify_valid_apid(clp
->ap_phys_id
) !=
1867 DPRINTF("cfga_list_ext: "
1868 "not a valid IB ap_id\n");
1869 S_FREE(*ap_id_list
);
1872 return (ib_err_msg(errstring
,
1873 CFGA_IB_AP_ERR
, ap_id
, errno
));
1876 /* build the logical ap_id */
1877 (void) snprintf(clp
->ap_log_id
,
1878 sizeof (clp
->ap_log_id
), "ib%s%s",
1880 DPRINTF("cfga_list_ext: ap_pi = %s, ap_li = %s,"
1881 "\nap_info = %s\n", clp
->ap_phys_id
,
1882 clp
->ap_log_id
, clp
->ap_info
);
1885 } else if (strcmp(name
, IBNEX_NODE_INFO_NVL
) == 0) {
1886 (void) nvpair_value_string(nvp
, &info
);
1887 DPRINTF("cfga_list_ext: Name = %s, info = %s\n",
1889 (void) snprintf(clp
->ap_info
,
1890 sizeof (clp
->ap_info
), "%s", info
);
1893 } else if (strcmp(name
, IBNEX_NODE_TYPE_NVL
) == 0) {
1894 (void) nvpair_value_int32(nvp
, &node_type
);
1895 if (node_type
== IBNEX_PORT_NODE_TYPE
) {
1896 (void) snprintf(clp
->ap_type
,
1897 sizeof (clp
->ap_type
), "%s",
1899 } else if (node_type
== IBNEX_VPPA_NODE_TYPE
) {
1900 (void) snprintf(clp
->ap_type
,
1901 sizeof (clp
->ap_type
), "%s",
1903 } else if (node_type
==
1904 IBNEX_HCASVC_NODE_TYPE
) {
1905 (void) snprintf(clp
->ap_type
,
1906 sizeof (clp
->ap_type
), "%s",
1908 } else if (node_type
== IBNEX_IOC_NODE_TYPE
) {
1909 (void) snprintf(clp
->ap_type
,
1910 sizeof (clp
->ap_type
), "%s",
1912 } else if (node_type
==
1913 IBNEX_PSEUDO_NODE_TYPE
) {
1914 (void) snprintf(clp
->ap_type
,
1915 sizeof (clp
->ap_type
), "%s",
1918 DPRINTF("cfga_list_ext: Name = %s, type = %x\n",
1922 } else if (strcmp(name
, IBNEX_NODE_RSTATE_NVL
) == 0) {
1923 (void) nvpair_value_int32(nvp
, &intval
);
1925 if (intval
== AP_RSTATE_EMPTY
)
1926 clp
->ap_r_state
= CFGA_STAT_EMPTY
;
1927 else if (intval
== AP_RSTATE_DISCONNECTED
)
1929 CFGA_STAT_DISCONNECTED
;
1930 else if (intval
== AP_RSTATE_CONNECTED
)
1931 clp
->ap_r_state
= CFGA_STAT_CONNECTED
;
1932 DPRINTF("cfga_list_ext: Name = %s, "
1933 "rstate = %x\n", name
, intval
);
1936 } else if (strcmp(name
, IBNEX_NODE_OSTATE_NVL
) == 0) {
1937 (void) nvpair_value_int32(nvp
, &intval
);
1939 if (intval
== AP_OSTATE_CONFIGURED
)
1940 clp
->ap_o_state
= CFGA_STAT_CONFIGURED
;
1941 else if (intval
== AP_OSTATE_UNCONFIGURED
)
1943 CFGA_STAT_UNCONFIGURED
;
1944 DPRINTF("cfga_list_ext: Name = %s, "
1945 "ostate = %x\n", name
, intval
);
1948 } else if (strcmp(name
, IBNEX_NODE_COND_NVL
) == 0) {
1949 (void) nvpair_value_int32(nvp
, &intval
);
1951 if (intval
== AP_COND_OK
)
1952 clp
->ap_cond
= CFGA_COND_OK
;
1953 else if (intval
== AP_COND_FAILING
)
1954 clp
->ap_cond
= CFGA_COND_FAILING
;
1955 else if (intval
== AP_COND_FAILED
)
1956 clp
->ap_cond
= CFGA_COND_FAILED
;
1957 else if (intval
== AP_COND_UNUSABLE
)
1958 clp
->ap_cond
= CFGA_COND_UNUSABLE
;
1959 else if (intval
== AP_COND_UNKNOWN
)
1960 clp
->ap_cond
= CFGA_COND_UNKNOWN
;
1961 DPRINTF("cfga_list_ext: Name = %s, "
1962 "condition = %x\n", name
, intval
);
1966 clp
->ap_class
[0] = '\0'; /* Filled by libcfgadm */
1968 clp
->ap_status_time
= (time_t)-1;
1969 } /* end of while */
1976 * if a cmdline specified ap_id doesn't match the known list of ap_ids
1977 * then report an error right away
1979 rv
= (apid_matched
== B_TRUE
) ? CFGA_IB_OK
: CFGA_IB_AP_ERR
;
1980 return (ib_err_msg(errstring
, rv
, ap_id
, errno
));
1988 * msgp - cfgadm error message for this plugin
1989 * str - string to be passed on to the message
1995 * This routine accepts a variable number of message IDs and
1996 * constructs a corresponding error string which is printed
1997 * via the message print routine argument.
2000 cfga_msg(struct cfga_msg
*msgp
, const char *str
)
2005 if (msgp
== NULL
|| msgp
->message_routine
== NULL
) {
2006 DPRINTF("cfga_msg: msg\n");
2010 if ((len
= strlen(str
)) == 0) {
2011 DPRINTF("cfga_msg: null str\n");
2015 if ((q
= (char *)calloc(len
+ 1, 1)) == NULL
) {
2016 DPRINTF("cfga_msg: null q\n");
2020 (void) strlcpy(q
, str
, len
+ 1);
2021 (*msgp
->message_routine
)(msgp
->appdata_ptr
, q
);
2031 * msgp - Help message passed on to cfgadm(1M)
2032 * options - Help message options passed on to cfgadm(1M)
2033 * flags - Cfgadm(1m) flags
2037 * Were we able to print cfgadm help or not for this plugin
2039 * Print cfgadm help for this plugin
2043 cfga_help(struct cfga_msg
*msgp
, const char *options
, cfga_flags_t flags
)
2045 DPRINTF("cfga_help:\n");
2048 cfga_msg(msgp
, dgettext(TEXT_DOMAIN
, ib_help
[
2049 CFGA_IB_HELP_UNKNOWN
]));
2050 cfga_msg(msgp
, options
);
2053 /* Print messages array */
2054 cfga_msg(msgp
, dgettext(TEXT_DOMAIN
, ib_help
[CFGA_IB_HELP_HEADER
]));
2055 cfga_msg(msgp
, ib_help
[CFGA_IB_HELP_CONFIG
]);
2056 cfga_msg(msgp
, ib_help
[CFGA_IB_HELP_LIST
]);
2057 cfga_msg(msgp
, ib_help
[CFGA_IB_HELP_UPD_PKEY
]);
2058 cfga_msg(msgp
, ib_help
[CFGA_IB_HELP_CONF_FILE1
]);
2059 cfga_msg(msgp
, ib_help
[CFGA_IB_HELP_CONF_FILE2
]);
2060 cfga_msg(msgp
, ib_help
[CFGA_IB_HELP_UPD_IOC_CONF
]);
2061 cfga_msg(msgp
, ib_help
[CFGA_IB_HELP_UNCFG_CLNTS
]);
2071 * confp - The "cfga" structure that confirms a cfgadm query
2072 * msg - The message that needs confirmation
2076 * If a user entered YES or NO
2078 * Queries a user if it is ok to proceed with an operation or not.
2079 * Returns user's response.
2082 ib_confirm(struct cfga_confirm
*confp
, char *msg
)
2086 /* check that "confirm" function exists */
2087 if (confp
== NULL
|| confp
->confirm
== NULL
) {
2091 /* Call cfgadm provided "confirm" function */
2092 rval
= (*confp
->confirm
)(confp
->appdata_ptr
, msg
);
2093 DPRINTF("ib_confirm: %d\n", rval
);
2103 * ap_id - The dynamic attachment point of an IB device
2107 * devpath if it exists; otherwise NULL
2109 * Returns the devicepath for a dynamic attachment point of an IB device
2112 ib_get_devicepath(const char *ap_id
)
2114 char *devpath
= NULL
;
2117 /* Get device path sizes */
2118 if (ib_do_control_ioctl((char *)ap_id
, IBNEX_DEVICE_PATH_SZ
,
2119 IBNEX_GET_DEVICE_PATH
, 0, (void **)&devpath
, &size
) == CFGA_IB_OK
) {
2120 DPRINTF("ib_get_devicepath: get device path ioctl ok\n");
2124 DPRINTF("ib_get_devicepath: get device path ioctl failed\n");
2125 return ((char *)NULL
);