10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
56601Seota * Common Development and Distribution License (the "License").
66601Seota * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*8695SRajkumar.Sivaprakasam@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include "cfga_ib.h"
270Sstevel@tonic-gate
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate * cfga_ib.c:
300Sstevel@tonic-gate * All cfgadm entry points that are defined in the config_admin(3X)
310Sstevel@tonic-gate * needed for InfiniBand support are described here. These cfgadm
320Sstevel@tonic-gate * interfaces issue ioctl(s) to the IB nexus driver. Attachment points
330Sstevel@tonic-gate * supported are - IOC, VPPA, Port, HCA_SVC and Pseudo dynamic ap_ids,
340Sstevel@tonic-gate * the HCA static ap_id, and the IB static ap_id.
350Sstevel@tonic-gate *
360Sstevel@tonic-gate * Given InfiniBand bus is fabric based, #of dynamic ap_ids present are
370Sstevel@tonic-gate * unknown at any given point of time. Hence this plugin uses a
380Sstevel@tonic-gate * packed nvlist data structure to hold ap_id related information.
390Sstevel@tonic-gate * The IB nexus driver allocates the nvlist data in the kernel
400Sstevel@tonic-gate * and this plugin processes the data (it is freed by IB nexus driver).
410Sstevel@tonic-gate */
420Sstevel@tonic-gate
430Sstevel@tonic-gate
440Sstevel@tonic-gate /* function prototypes */
450Sstevel@tonic-gate static int ib_get_link(di_devlink_t, void *);
460Sstevel@tonic-gate static icfga_ret_t ib_physpath_to_devlink(char *, char **, int *);
470Sstevel@tonic-gate static const char *ib_get_msg(uint_t, msgcvt_t *, uint_t);
480Sstevel@tonic-gate static void ib_set_msg(char **, ...);
490Sstevel@tonic-gate static cfga_err_t ib_err_msg(char **, cfga_ib_ret_t, const char *, int);
500Sstevel@tonic-gate static int ib_verify_valid_apid(const char *);
510Sstevel@tonic-gate static cfga_ib_ret_t ib_verify_params(const char *, const char *, char **);
520Sstevel@tonic-gate static void ib_cleanup_after_devctl_cmd(devctl_hdl_t, nvlist_t *);
530Sstevel@tonic-gate static cfga_ib_ret_t ib_setup_for_devctl_cmd(char *, boolean_t,
540Sstevel@tonic-gate devctl_hdl_t *, nvlist_t **);
550Sstevel@tonic-gate static cfga_ib_ret_t ib_device_configured(devctl_hdl_t, nvlist_t *,
560Sstevel@tonic-gate ap_rstate_t *);
570Sstevel@tonic-gate static cfga_ib_ret_t ib_device_connected(devctl_hdl_t, nvlist_t *,
580Sstevel@tonic-gate ap_ostate_t *);
590Sstevel@tonic-gate static cfga_ib_ret_t ib_do_control_ioctl(char *, uint_t, uint_t, uint_t,
600Sstevel@tonic-gate void **, size_t *);
610Sstevel@tonic-gate cfga_err_t cfga_change_state(cfga_cmd_t, const char *,
620Sstevel@tonic-gate const char *, struct cfga_confirm *,
630Sstevel@tonic-gate struct cfga_msg *, char **, cfga_flags_t);
640Sstevel@tonic-gate cfga_err_t cfga_private_func(const char *, const char *,
650Sstevel@tonic-gate const char *, struct cfga_confirm *,
660Sstevel@tonic-gate struct cfga_msg *, char **, cfga_flags_t);
670Sstevel@tonic-gate cfga_err_t cfga_test(const char *, const char *, struct cfga_msg *,
680Sstevel@tonic-gate char **, cfga_flags_t);
690Sstevel@tonic-gate static cfga_ib_ret_t ib_fill_static_apids(char *, cfga_list_data_t *);
700Sstevel@tonic-gate cfga_err_t cfga_list_ext(const char *, cfga_list_data_t **, int *,
710Sstevel@tonic-gate const char *, const char *, char **, cfga_flags_t);
720Sstevel@tonic-gate void cfga_msg(struct cfga_msg *, const char *);
730Sstevel@tonic-gate cfga_err_t cfga_help(struct cfga_msg *, const char *,
740Sstevel@tonic-gate cfga_flags_t);
750Sstevel@tonic-gate static int ib_confirm(struct cfga_confirm *, char *);
760Sstevel@tonic-gate static char *ib_get_devicepath(const char *);
770Sstevel@tonic-gate
780Sstevel@tonic-gate
790Sstevel@tonic-gate /* External function prototypes */
800Sstevel@tonic-gate extern cfga_ib_ret_t ib_rcm_offline(const char *, char **, char *,
810Sstevel@tonic-gate cfga_flags_t);
820Sstevel@tonic-gate extern cfga_ib_ret_t ib_rcm_online(const char *, char **, char *,
830Sstevel@tonic-gate cfga_flags_t);
840Sstevel@tonic-gate extern cfga_ib_ret_t ib_rcm_remove(const char *, char **, char *,
850Sstevel@tonic-gate cfga_flags_t);
860Sstevel@tonic-gate extern int ib_add_service(char **);
870Sstevel@tonic-gate extern int ib_delete_service(char **);
880Sstevel@tonic-gate extern int ib_list_services(struct cfga_msg *, char **);
890Sstevel@tonic-gate
900Sstevel@tonic-gate
910Sstevel@tonic-gate /* Globals */
920Sstevel@tonic-gate int cfga_version = CFGA_HSL_V2; /* Set the version number for */
930Sstevel@tonic-gate /* the cfgadm library's use. */
940Sstevel@tonic-gate
950Sstevel@tonic-gate static char *ib_help[] = { /* Help messages */
960Sstevel@tonic-gate NULL,
970Sstevel@tonic-gate /* CFGA_IB_HELP_HEADER */ "IB specific commands:\n",
980Sstevel@tonic-gate /* CFGA_IB_HELP_CONFIG */ "cfgadm -c [configure|unconfigure] "
990Sstevel@tonic-gate "ap_id [ap_id...]\n",
1000Sstevel@tonic-gate /* CFGA_IB_HELP_LIST */ "cfgadm -x list_clients hca_ap_id "
1010Sstevel@tonic-gate "[hca_ap_id...]\n",
1020Sstevel@tonic-gate /* CFGA_IB_HELP_UPD_PKEY */ "cfgadm -x update_pkey_tbls ib\n",
1030Sstevel@tonic-gate /* CFGA_IB_HELP_CONF_FILE1 */ "cfgadm -o comm=[port|vppa|hca-svc],"
1040Sstevel@tonic-gate "service=<name> -x [add_service|delete_service] ib\n",
1050Sstevel@tonic-gate /* CFGA_IB_HELP_CONF_FILE2 */ "cfgadm -x list_services ib\n",
1060Sstevel@tonic-gate /* CFGA_IB_HELP_UPD_IOC_CONF */ "cfgadm -x update_ioc_config "
1070Sstevel@tonic-gate "[ib | ioc_apid]\n",
1080Sstevel@tonic-gate /* CFGA_IB_HELP_UNCFG_CLNTS */ "cfgadm -x unconfig_clients hca_ap_id "
1090Sstevel@tonic-gate "[hca_ap_id...]\n",
1100Sstevel@tonic-gate /* CFGA_IB_HELP_UNKNOWN */ "\tunknown command or option: ",
1110Sstevel@tonic-gate NULL
1120Sstevel@tonic-gate };
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate static msgcvt_t ib_error_msgs[] = { /* Error messages */
1150Sstevel@tonic-gate /* CFGA_IB_OK */ { CVT, CFGA_OK, "ok" },
1160Sstevel@tonic-gate /* CFGA_IB_UNKNOWN */ { CVT, CFGA_LIB_ERROR,
1170Sstevel@tonic-gate "Unknown message; internal error " },
1180Sstevel@tonic-gate /* CFGA_IB_INTERNAL_ERR */ { CVT, CFGA_LIB_ERROR,
1190Sstevel@tonic-gate "Internal error " },
1200Sstevel@tonic-gate /* CFGA_IB_INVAL_ARG_ERR */ { CVT, CFGA_LIB_ERROR,
1210Sstevel@tonic-gate "Invalid input args " },
1220Sstevel@tonic-gate /* CFGA_IB_OPTIONS_ERR */ { CVT, CFGA_ERROR,
1230Sstevel@tonic-gate "Hardware specific options not supported " },
1240Sstevel@tonic-gate /* CFGA_IB_AP_ERR */ { CVT, CFGA_APID_NOEXIST, "" },
1250Sstevel@tonic-gate /* CFGA_IB_DEVCTL_ERR */ { CVT, CFGA_LIB_ERROR,
1260Sstevel@tonic-gate "Cannot issue devctl to " },
1270Sstevel@tonic-gate /* CFGA_IB_NOT_CONNECTED */ { CVT, CFGA_INSUFFICENT_CONDITION,
1280Sstevel@tonic-gate "No device connected to " },
1290Sstevel@tonic-gate /* CFGA_IB_NOT_CONFIGURED */ { CVT, CFGA_INSUFFICENT_CONDITION,
1300Sstevel@tonic-gate "No device configured to " },
1310Sstevel@tonic-gate /* CFGA_IB_ALREADY_CONNECTED */ { CVT, CFGA_INSUFFICENT_CONDITION,
1320Sstevel@tonic-gate "already connected; cannot connect again " },
1330Sstevel@tonic-gate /* CFGA_IB_ALREADY_CONFIGURED */ { CVT, CFGA_INSUFFICENT_CONDITION,
1340Sstevel@tonic-gate "already configured " },
1350Sstevel@tonic-gate /* CFGA_IB_CONFIG_OP_ERR */ { CVT, CFGA_ERROR,
1360Sstevel@tonic-gate "configure operation failed " },
1370Sstevel@tonic-gate /* CFGA_IB_UNCONFIG_OP_ERR */ { CVT, CFGA_ERROR,
1380Sstevel@tonic-gate "unconfigure operation failed " },
1390Sstevel@tonic-gate /* CFGA_IB_OPEN_ERR */ { CVT, CFGA_LIB_ERROR, "Cannot open " },
1400Sstevel@tonic-gate /* CFGA_IB_IOCTL_ERR */ { CVT, CFGA_LIB_ERROR,
1410Sstevel@tonic-gate "Driver ioctl failed " },
1420Sstevel@tonic-gate /* CFGA_IB_BUSY_ERR */ { CVT, CFGA_SYSTEM_BUSY, " " },
1430Sstevel@tonic-gate /* CFGA_IB_ALLOC_FAIL */ { CVT, CFGA_LIB_ERROR,
1440Sstevel@tonic-gate "Memory allocation failure " },
1450Sstevel@tonic-gate /* CFGA_IB_OPNOTSUPP */ { CVT, CFGA_OPNOTSUPP,
1460Sstevel@tonic-gate "Operation not supported " },
1470Sstevel@tonic-gate /* CFGA_IB_INVAL_APID_ERR */ { CVT, CFGA_LIB_ERROR,
1480Sstevel@tonic-gate "Invalid ap_id supplied " },
1490Sstevel@tonic-gate /* CFGA_IB_DEVLINK_ERR */ { CVT, CFGA_LIB_ERROR,
1500Sstevel@tonic-gate "Could not find /dev/cfg link for " },
1510Sstevel@tonic-gate /* CFGA_IB_PRIV_ERR */ { CVT, CFGA_PRIV, " " },
1520Sstevel@tonic-gate /* CFGA_IB_NVLIST_ERR */ { CVT, CFGA_ERROR,
1530Sstevel@tonic-gate "Internal error (nvlist) " },
1540Sstevel@tonic-gate /* CFGA_IB_HCA_LIST_ERR */ { CVT, CFGA_ERROR,
1550Sstevel@tonic-gate "Listing HCA's clients failed " },
1560Sstevel@tonic-gate /* CFGA_IB_HCA_UNCONFIG_ERR */ { CVT, CFGA_ERROR,
1570Sstevel@tonic-gate "Unconfiguring HCA's clients failed " },
1580Sstevel@tonic-gate /* CFGA_IB_UPD_PKEY_TBLS_ERR */ { CVT, CFGA_ERROR,
1590Sstevel@tonic-gate "Updating P_Key tables failed " },
1600Sstevel@tonic-gate /* CFGA_IB_RCM_HANDLE_ERR */ { CVT, CFGA_ERROR,
1610Sstevel@tonic-gate "Opening ib.conf file failed " },
1620Sstevel@tonic-gate /* CFGA_IB_LOCK_FILE_ERR */ { CVT, CFGA_LIB_ERROR,
1630Sstevel@tonic-gate "Locking ib.conf file failed " },
1640Sstevel@tonic-gate /* CFGA_IB_UNLOCK_FILE_ERR */ { CVT, CFGA_LIB_ERROR,
1650Sstevel@tonic-gate "Unlocking ib.conf file failed " },
1660Sstevel@tonic-gate /* CFGA_IB_COMM_INVAL_ERR */ { CVT, CFGA_INVAL,
1670Sstevel@tonic-gate "Communication type incorrectly specified " },
1680Sstevel@tonic-gate /* CFGA_IB_SVC_INVAL_ERR */ { CVT, CFGA_INVAL,
1690Sstevel@tonic-gate "Service name incorrectly specified " },
1700Sstevel@tonic-gate /* CFGA_IB_SVC_LEN_ERR_ERR */ { CVT, CFGA_INVAL,
1710Sstevel@tonic-gate "Service name len should be <= to 4, " },
1720Sstevel@tonic-gate /* CFGA_IB_SVC_EXISTS_ERR */ { CVT, CFGA_INVAL, " "},
1730Sstevel@tonic-gate /* CFGA_IB_SVC_NO_EXIST_ERR */ { CVT, CFGA_INVAL, " " },
1740Sstevel@tonic-gate /* CFGA_IB_UCFG_CLNTS_ERR */ { CVT, CFGA_INVAL,
1750Sstevel@tonic-gate "unconfig_clients failed for HCA " },
1760Sstevel@tonic-gate /* CFGA_IB_INVALID_OP_ERR */ { CVT, CFGA_OPNOTSUPP, "on " },
1770Sstevel@tonic-gate /* CFGA_IB_RCM_HANDLE */ { CVT, CFGA_ERROR,
1780Sstevel@tonic-gate "cannot get RCM handle "},
1790Sstevel@tonic-gate /* CFGA_IB_RCM_ONLINE_ERR */ { CVT, CFGA_SYSTEM_BUSY,
1800Sstevel@tonic-gate "failed to online: "},
1810Sstevel@tonic-gate /* CFGA_IB_RCM_OFFLINE_ERR */ { CVT, CFGA_SYSTEM_BUSY,
1820Sstevel@tonic-gate "failed to offline: "}
1830Sstevel@tonic-gate };
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate /*
1860Sstevel@tonic-gate * these are the only valid sub-options for services.
1870Sstevel@tonic-gate */
1880Sstevel@tonic-gate static char *ib_service_subopts[] = {
1890Sstevel@tonic-gate "comm",
1900Sstevel@tonic-gate "service",
1910Sstevel@tonic-gate NULL
1920Sstevel@tonic-gate };
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate /* Communication Service name : "port" or "vppa" or "hca-svc" */
1950Sstevel@tonic-gate static char *comm_name = NULL;
1960Sstevel@tonic-gate
1970Sstevel@tonic-gate char *service_name = NULL; /* service name */
1980Sstevel@tonic-gate ib_service_type_t service_type = IB_NONE; /* service type */
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate /* ========================================================================= */
2020Sstevel@tonic-gate /*
2030Sstevel@tonic-gate * The next two funcs are imported from cfgadm_scsi.
2040Sstevel@tonic-gate * ib_physpath_to_devlink is the only func directly used by cfgadm_ib.
2050Sstevel@tonic-gate * ib_get_link supports it.
2060Sstevel@tonic-gate */
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate /*
2090Sstevel@tonic-gate * Function:
2100Sstevel@tonic-gate * ib_get_link
2110Sstevel@tonic-gate * Input:
2120Sstevel@tonic-gate * devlink - devlink for the device path
2130Sstevel@tonic-gate * arg - argument passed to this "walker" function
2140Sstevel@tonic-gate * Output:
2150Sstevel@tonic-gate * NONE
2160Sstevel@tonic-gate * Returns:
2170Sstevel@tonic-gate * Continue "walking" or not
2180Sstevel@tonic-gate * Description:
2190Sstevel@tonic-gate * Routine to search the /dev directory or a subtree of /dev.
2200Sstevel@tonic-gate */
2210Sstevel@tonic-gate static int
ib_get_link(di_devlink_t devlink,void * arg)2220Sstevel@tonic-gate ib_get_link(di_devlink_t devlink, void *arg)
2230Sstevel@tonic-gate {
2240Sstevel@tonic-gate walk_link_t *larg = (walk_link_t *)arg;
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate /*
2270Sstevel@tonic-gate * When path is specified, it's the node path without minor
2280Sstevel@tonic-gate * name. Therefore, the ../.. prefixes needs to be stripped.
2290Sstevel@tonic-gate */
2300Sstevel@tonic-gate if (larg->path) {
2310Sstevel@tonic-gate char *content = (char *)di_devlink_content(devlink);
2320Sstevel@tonic-gate char *start = strstr(content, "/devices/");
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate /* line content must have minor node */
2350Sstevel@tonic-gate if (start == NULL ||
2360Sstevel@tonic-gate strncmp(start, larg->path, larg->len) != 0 ||
2370Sstevel@tonic-gate start[larg->len] != ':') {
2380Sstevel@tonic-gate return (DI_WALK_CONTINUE);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate *(larg->linkpp) = strdup(di_devlink_path(devlink));
2430Sstevel@tonic-gate return (DI_WALK_TERMINATE);
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate /*
2480Sstevel@tonic-gate * Function:
2490Sstevel@tonic-gate * ib_physpath_to_devlink
2500Sstevel@tonic-gate * Input:
2510Sstevel@tonic-gate * node_path - Physical path of the ap_id node
2520Sstevel@tonic-gate * Output:
2530Sstevel@tonic-gate * logpp - Logical path to the ap_id node
2540Sstevel@tonic-gate * l_errnop - "errno"
2550Sstevel@tonic-gate * Returns:
2560Sstevel@tonic-gate * ICFGA_OK if everything was fine; otherwise an error with
2570Sstevel@tonic-gate * l_errnop set.
2580Sstevel@tonic-gate * Description:
2590Sstevel@tonic-gate * Given a physical path to an ap_id ensure that it exists
2600Sstevel@tonic-gate */
2610Sstevel@tonic-gate /* ARGSUSED */
2620Sstevel@tonic-gate static icfga_ret_t
ib_physpath_to_devlink(char * node_path,char ** logpp,int * l_errnop)2630Sstevel@tonic-gate ib_physpath_to_devlink(char *node_path, char **logpp, int *l_errnop)
2640Sstevel@tonic-gate {
2650Sstevel@tonic-gate char *minor_path;
2660Sstevel@tonic-gate walk_link_t larg;
2670Sstevel@tonic-gate di_devlink_handle_t hdl;
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate if ((hdl = di_devlink_init(NULL, 0)) == NULL) {
2700Sstevel@tonic-gate *l_errnop = errno;
2710Sstevel@tonic-gate return (ICFGA_LIB_ERR);
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate *logpp = NULL;
2750Sstevel@tonic-gate larg.linkpp = logpp;
2760Sstevel@tonic-gate minor_path = (char *)node_path + strlen("/devices");
2770Sstevel@tonic-gate larg.path = NULL;
2780Sstevel@tonic-gate larg.len = 0;
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate (void) di_devlink_walk(hdl, "^cfg/", minor_path, DI_PRIMARY_LINK,
2810Sstevel@tonic-gate (void *)&larg, ib_get_link);
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate di_devlink_fini(&hdl);
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate if (*logpp == NULL) {
2860Sstevel@tonic-gate *l_errnop = errno;
2870Sstevel@tonic-gate return (ICFGA_LIB_ERR);
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate return (ICFGA_OK);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate /* ========================================================================= */
2950Sstevel@tonic-gate /* Utilities */
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate /*
2980Sstevel@tonic-gate * Function:
2990Sstevel@tonic-gate * ib_get_msg
3000Sstevel@tonic-gate * Input:
3010Sstevel@tonic-gate * msg_index - Index into the message table
3020Sstevel@tonic-gate * msg_tbl - the message table
3030Sstevel@tonic-gate * tbl_size - size of the message table
3040Sstevel@tonic-gate * Output:
3050Sstevel@tonic-gate * NONE
3060Sstevel@tonic-gate * Returns:
3070Sstevel@tonic-gate * Message string if valid, otherwise an error
3080Sstevel@tonic-gate * Description:
3090Sstevel@tonic-gate * Given the index into a table (msgcvt_t) of messages,
3100Sstevel@tonic-gate * get the message string, converting it to the proper
3110Sstevel@tonic-gate * locale if necessary.
3120Sstevel@tonic-gate *
3130Sstevel@tonic-gate * NOTE: See cfga_ib.h
3140Sstevel@tonic-gate */
3150Sstevel@tonic-gate static const char *
ib_get_msg(uint_t msg_index,msgcvt_t * msg_tbl,uint_t tbl_size)3160Sstevel@tonic-gate ib_get_msg(uint_t msg_index, msgcvt_t *msg_tbl, uint_t tbl_size)
3170Sstevel@tonic-gate {
3180Sstevel@tonic-gate if (msg_index >= tbl_size) {
3190Sstevel@tonic-gate DPRINTF("get_error_msg: bad error msg index: %d\n", msg_index);
3200Sstevel@tonic-gate msg_index = CFGA_IB_UNKNOWN;
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate return ((msg_tbl[msg_index].intl) ?
3240Sstevel@tonic-gate dgettext(TEXT_DOMAIN, msg_tbl[msg_index].msgstr) :
3250Sstevel@tonic-gate msg_tbl[msg_index].msgstr);
3260Sstevel@tonic-gate }
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate /*
3300Sstevel@tonic-gate * Function:
3310Sstevel@tonic-gate * ib_set_msg
3320Sstevel@tonic-gate * Input:
3330Sstevel@tonic-gate * NONE
3340Sstevel@tonic-gate * Output:
3350Sstevel@tonic-gate * ret_str - Returned "message" string.
3360Sstevel@tonic-gate * Returns:
3370Sstevel@tonic-gate * NONE
3380Sstevel@tonic-gate * Description:
3390Sstevel@tonic-gate * Allocates and creates a message string (in *ret_str),
3400Sstevel@tonic-gate * by concatenating all the (char *) args together, in order.
3410Sstevel@tonic-gate * Last arg MUST be NULL.
3420Sstevel@tonic-gate */
3430Sstevel@tonic-gate static void
ib_set_msg(char ** ret_str,...)3440Sstevel@tonic-gate ib_set_msg(char **ret_str, ...)
3450Sstevel@tonic-gate {
3460Sstevel@tonic-gate char *str;
3470Sstevel@tonic-gate size_t total_len, ret_str_len;
3480Sstevel@tonic-gate va_list valist;
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate va_start(valist, ret_str);
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate total_len = (*ret_str == NULL) ? 0 : strlen(*ret_str);
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate while ((str = va_arg(valist, char *)) != NULL) {
3550Sstevel@tonic-gate size_t len = strlen(str);
3560Sstevel@tonic-gate char *old_str = *ret_str;
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate ret_str_len = total_len + len + 1;
3590Sstevel@tonic-gate *ret_str = (char *)realloc(*ret_str, ret_str_len);
3600Sstevel@tonic-gate if (*ret_str == NULL) {
3610Sstevel@tonic-gate free(old_str);
3620Sstevel@tonic-gate DPRINTF("ib_set_msg: realloc failed.\n");
3630Sstevel@tonic-gate va_end(valist);
3640Sstevel@tonic-gate return;
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate (void) strlcpy(*ret_str + total_len, str, ret_str_len);
3680Sstevel@tonic-gate total_len += len;
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate va_end(valist);
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate
3750Sstevel@tonic-gate /*
3760Sstevel@tonic-gate * Function:
3770Sstevel@tonic-gate * ib_err_msg
3780Sstevel@tonic-gate * Input:
3790Sstevel@tonic-gate * ap_id - The attachment point of an IB fabric
3800Sstevel@tonic-gate * Output:
3810Sstevel@tonic-gate * errstring - Fill in the error msg string
3820Sstevel@tonic-gate * l_errno - The "errno" to be filled in.
3830Sstevel@tonic-gate * Returns:
3840Sstevel@tonic-gate * CFGA_IB_OK if we are able to fill in error msg;
3850Sstevel@tonic-gate * otherwise emit an error.
3860Sstevel@tonic-gate * Description:
3870Sstevel@tonic-gate * Error message handling.
3880Sstevel@tonic-gate *
3890Sstevel@tonic-gate * For the rv passed in, looks up the corresponding error message
3900Sstevel@tonic-gate * string(s), internationalized it if necessary, and concatenates
3910Sstevel@tonic-gate * it into a new memory buffer, and points *errstring to it.
3920Sstevel@tonic-gate * Note not all "rv"s will result in an error message return, as
3930Sstevel@tonic-gate * not all error conditions warrant a IB-specific error message.
3940Sstevel@tonic-gate *
3950Sstevel@tonic-gate * Some messages may display ap_id or errno, which is why they are
3960Sstevel@tonic-gate * passed in.
3970Sstevel@tonic-gate */
3980Sstevel@tonic-gate static cfga_err_t
ib_err_msg(char ** errstring,cfga_ib_ret_t rv,const char * ap_id,int l_errno)3990Sstevel@tonic-gate ib_err_msg(char **errstring, cfga_ib_ret_t rv, const char *ap_id, int l_errno)
4000Sstevel@tonic-gate {
4010Sstevel@tonic-gate char *errno_str;
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate if (errstring == NULL) {
4040Sstevel@tonic-gate return (ib_error_msgs[rv].cfga_err);
4050Sstevel@tonic-gate }
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate /* Generate the appropriate IB-specific error message(s) (if any). */
4080Sstevel@tonic-gate switch (rv) {
4090Sstevel@tonic-gate case CFGA_IB_OK: /* Special case - do nothing. */
4100Sstevel@tonic-gate break;
4110Sstevel@tonic-gate case CFGA_IB_AP_ERR:
4120Sstevel@tonic-gate case CFGA_IB_UNKNOWN:
4130Sstevel@tonic-gate case CFGA_IB_INTERNAL_ERR:
4140Sstevel@tonic-gate case CFGA_IB_OPTIONS_ERR:
4150Sstevel@tonic-gate case CFGA_IB_ALLOC_FAIL:
4160Sstevel@tonic-gate /* These messages require no additional strings passed. */
4170Sstevel@tonic-gate ib_set_msg(errstring, ERR_STR(rv), NULL);
4180Sstevel@tonic-gate break;
4190Sstevel@tonic-gate case CFGA_IB_NOT_CONNECTED:
4200Sstevel@tonic-gate case CFGA_IB_NOT_CONFIGURED:
4210Sstevel@tonic-gate case CFGA_IB_ALREADY_CONNECTED:
4220Sstevel@tonic-gate case CFGA_IB_ALREADY_CONFIGURED:
4230Sstevel@tonic-gate case CFGA_IB_CONFIG_OP_ERR:
4240Sstevel@tonic-gate case CFGA_IB_UNCONFIG_OP_ERR:
4250Sstevel@tonic-gate case CFGA_IB_BUSY_ERR:
4260Sstevel@tonic-gate case CFGA_IB_DEVLINK_ERR:
4270Sstevel@tonic-gate case CFGA_IB_RCM_HANDLE_ERR:
4280Sstevel@tonic-gate case CFGA_IB_RCM_ONLINE_ERR:
4290Sstevel@tonic-gate case CFGA_IB_RCM_OFFLINE_ERR:
4300Sstevel@tonic-gate case CFGA_IB_DEVCTL_ERR:
4310Sstevel@tonic-gate case CFGA_IB_COMM_INVAL_ERR:
4320Sstevel@tonic-gate case CFGA_IB_SVC_INVAL_ERR:
4330Sstevel@tonic-gate case CFGA_IB_SVC_LEN_ERR:
4340Sstevel@tonic-gate case CFGA_IB_SVC_EXISTS_ERR:
4350Sstevel@tonic-gate case CFGA_IB_SVC_NO_EXIST_ERR:
4360Sstevel@tonic-gate case CFGA_IB_LOCK_FILE_ERR:
4370Sstevel@tonic-gate case CFGA_IB_CONFIG_FILE_ERR:
4380Sstevel@tonic-gate case CFGA_IB_UNLOCK_FILE_ERR:
4390Sstevel@tonic-gate case CFGA_IB_UCFG_CLNTS_ERR:
4400Sstevel@tonic-gate case CFGA_IB_INVALID_OP_ERR:
4410Sstevel@tonic-gate /* These messages also print ap_id. */
4420Sstevel@tonic-gate ib_set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "", NULL);
4430Sstevel@tonic-gate break;
4440Sstevel@tonic-gate case CFGA_IB_IOCTL_ERR: /* These messages also print errno. */
4450Sstevel@tonic-gate case CFGA_IB_NVLIST_ERR:
4460Sstevel@tonic-gate errno_str = l_errno ? strerror(l_errno) : "";
4470Sstevel@tonic-gate ib_set_msg(errstring, ERR_STR(rv), errno_str,
4480Sstevel@tonic-gate l_errno ? "\n" : "", NULL);
4490Sstevel@tonic-gate break;
4500Sstevel@tonic-gate case CFGA_IB_OPEN_ERR: /* This messages also prints apid and errno. */
4510Sstevel@tonic-gate case CFGA_IB_PRIV_ERR:
4520Sstevel@tonic-gate case CFGA_IB_HCA_LIST_ERR:
4530Sstevel@tonic-gate case CFGA_IB_OPNOTSUPP:
4540Sstevel@tonic-gate case CFGA_IB_INVAL_ARG_ERR:
4550Sstevel@tonic-gate case CFGA_IB_INVAL_APID_ERR:
4560Sstevel@tonic-gate case CFGA_IB_HCA_UNCONFIG_ERR:
4570Sstevel@tonic-gate case CFGA_IB_UPD_PKEY_TBLS_ERR:
4580Sstevel@tonic-gate errno_str = l_errno ? strerror(l_errno) : "";
4590Sstevel@tonic-gate ib_set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "\n",
4600Sstevel@tonic-gate errno_str, l_errno ? "\n" : "", NULL);
4610Sstevel@tonic-gate break;
4620Sstevel@tonic-gate default:
4630Sstevel@tonic-gate DPRINTF("ib_err_msg: Unrecognized message index: %d\n", rv);
4640Sstevel@tonic-gate ib_set_msg(errstring, ERR_STR(CFGA_IB_INTERNAL_ERR), NULL);
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate /*
4680Sstevel@tonic-gate * Determine the proper error code to send back to the cfgadm library.
4690Sstevel@tonic-gate */
4700Sstevel@tonic-gate return (ib_error_msgs[rv].cfga_err);
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate /*
4750Sstevel@tonic-gate * Function:
4760Sstevel@tonic-gate * ib_verify_valid_apid
4770Sstevel@tonic-gate * Input:
4780Sstevel@tonic-gate * ap_id - The attachment point of an IB fabric
4790Sstevel@tonic-gate * Output:
4800Sstevel@tonic-gate * NONE
4810Sstevel@tonic-gate * Returns:
4820Sstevel@tonic-gate * 0 if ap_id is valid; otherwise -1
4830Sstevel@tonic-gate * Description:
4840Sstevel@tonic-gate * Check if ap_id is valid or not.
4850Sstevel@tonic-gate * Ensure the ap_id passed is in the correct (physical ap_id) form:
4860Sstevel@tonic-gate * path/device:xx[.xx]+
4870Sstevel@tonic-gate * where xx is a one or two-digit number.
4880Sstevel@tonic-gate *
4890Sstevel@tonic-gate * Note the library always calls the plugin with a physical ap_id.
4900Sstevel@tonic-gate * Called by ib_verify_params().
4910Sstevel@tonic-gate */
4920Sstevel@tonic-gate static int
ib_verify_valid_apid(const char * ap_id)4930Sstevel@tonic-gate ib_verify_valid_apid(const char *ap_id)
4940Sstevel@tonic-gate {
4950Sstevel@tonic-gate char *l_ap_id;
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate if (ap_id == NULL) {
4980Sstevel@tonic-gate return (-1);
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate l_ap_id = strchr(ap_id, *MINOR_SEP);
5020Sstevel@tonic-gate l_ap_id++;
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate /* fabric apids */
5050Sstevel@tonic-gate if (strstr((char *)ap_id, IBNEX_FABRIC) != NULL) {
5060Sstevel@tonic-gate DPRINTF("ib_valid_apid: l_apid = %s\n", l_ap_id);
5070Sstevel@tonic-gate /* if the ap_id is "ib::" then report an error */
5080Sstevel@tonic-gate if ((strlen(l_ap_id) == strlen(IBNEX_FABRIC) + 1) ||
5090Sstevel@tonic-gate (strlen(l_ap_id) == strlen(IBNEX_FABRIC) + 2)) {
5100Sstevel@tonic-gate return (-1);
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate if (strstr(l_ap_id, "...") != NULL) {
5140Sstevel@tonic-gate return (-1);
5150Sstevel@tonic-gate }
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate } else { /* HCA ap_ids */
5180Sstevel@tonic-gate /* ap_id has 1..2 or more than 2 dots */
5190Sstevel@tonic-gate if (strstr(l_ap_id, "..") != NULL) {
5200Sstevel@tonic-gate return (-1);
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate
5240Sstevel@tonic-gate return (0);
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate /*
5290Sstevel@tonic-gate * Function:
5300Sstevel@tonic-gate * ib_verify_params
5310Sstevel@tonic-gate * Input:
5320Sstevel@tonic-gate * ap_id - The attachment point of an IB fabric
5330Sstevel@tonic-gate * options - command options passed by the cfgadm(1M)
5340Sstevel@tonic-gate * errstring - This contains error msg if command fails
5350Sstevel@tonic-gate * Output:
5360Sstevel@tonic-gate * NONE
5370Sstevel@tonic-gate * Returns:
5380Sstevel@tonic-gate * CFGA_IB_OK if parameters are valid; otherwise emit an error.
5390Sstevel@tonic-gate * Description:
5400Sstevel@tonic-gate * Check if "options" and "errstring" are valid and if ap_id is
5410Sstevel@tonic-gate * valid or not.
5420Sstevel@tonic-gate */
5430Sstevel@tonic-gate static cfga_ib_ret_t
ib_verify_params(const char * ap_id,const char * options,char ** errstring)5440Sstevel@tonic-gate ib_verify_params(const char *ap_id, const char *options, char **errstring)
5450Sstevel@tonic-gate {
5460Sstevel@tonic-gate if (errstring != NULL) {
5470Sstevel@tonic-gate *errstring = NULL;
5480Sstevel@tonic-gate }
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate if (options != NULL) {
5510Sstevel@tonic-gate DPRINTF("ib_verify_params: h/w-specific options not "
5520Sstevel@tonic-gate "supported.\n");
5530Sstevel@tonic-gate return (CFGA_IB_OPTIONS_ERR);
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate if (ib_verify_valid_apid(ap_id) != 0) {
5570Sstevel@tonic-gate DPRINTF("ib_verify_params: not an IB ap_id.\n");
5580Sstevel@tonic-gate return (CFGA_IB_AP_ERR);
5590Sstevel@tonic-gate }
5600Sstevel@tonic-gate return (CFGA_IB_OK);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate /*
5650Sstevel@tonic-gate * Function:
5660Sstevel@tonic-gate * ib_cleanup_after_devctl_cmd
5670Sstevel@tonic-gate * Input:
5680Sstevel@tonic-gate * devctl_hdl - Handler to devctl
5690Sstevel@tonic-gate * user_nvlistp - Name-value-pair list pointer
5700Sstevel@tonic-gate * Output:
5710Sstevel@tonic-gate * NONE
5720Sstevel@tonic-gate * Returns:
5730Sstevel@tonic-gate * NONE
5740Sstevel@tonic-gate * Description:
5750Sstevel@tonic-gate * Cleanup an initialization/setup done in the next function i.e.
5760Sstevel@tonic-gate * ib_setup_for_devctl_cmd().
5770Sstevel@tonic-gate */
5780Sstevel@tonic-gate static void
ib_cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl,nvlist_t * user_nvlist)5790Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl, nvlist_t *user_nvlist)
5800Sstevel@tonic-gate {
5810Sstevel@tonic-gate if (user_nvlist != NULL) {
5820Sstevel@tonic-gate nvlist_free(user_nvlist);
5830Sstevel@tonic-gate }
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate if (devctl_hdl != NULL) {
5860Sstevel@tonic-gate devctl_release(devctl_hdl);
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate }
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate /*
5920Sstevel@tonic-gate * Function:
5930Sstevel@tonic-gate * ib_setup_for_devctl_cmd
5940Sstevel@tonic-gate * Input:
5950Sstevel@tonic-gate * ap_id - Attachment point for the IB device in question
5960Sstevel@tonic-gate * use_static_ap_id - Whether to use static ap_id or not flag
5970Sstevel@tonic-gate * Output:
5980Sstevel@tonic-gate * devctl_hdl - Handler to devctl
5990Sstevel@tonic-gate * user_nvlistp - Name-value-pair list pointer
6000Sstevel@tonic-gate * Returns:
6010Sstevel@tonic-gate * CFGA_IB_OK if it succeeds or an appropriate error.
6020Sstevel@tonic-gate * Description:
6030Sstevel@tonic-gate * For any IB device that is doing a cfgadm operation this function
6040Sstevel@tonic-gate * sets up a devctl_hdl and allocates a nvlist_t. The devctl_hdl
6050Sstevel@tonic-gate * is acquired using libdevice APIs. The nvlist_t is filled up with
6060Sstevel@tonic-gate * the ap_id (as a string). This nvlist_t is looked up in the kernel
6070Sstevel@tonic-gate * to figure out which ap_id we are currently dealing with.
6080Sstevel@tonic-gate *
6090Sstevel@tonic-gate * "use_static_ap_id" flag tells if one should do a devctl_ap_acquire
6100Sstevel@tonic-gate * with IB_STATIC_APID or not. NOTE: We need an actual file-system
6110Sstevel@tonic-gate * vnode to do a devctl_ap_acquire.
6120Sstevel@tonic-gate *
6130Sstevel@tonic-gate * NOTE: always call ib_cleanup_after_devctl_cmd() after this function.
6140Sstevel@tonic-gate */
6150Sstevel@tonic-gate static cfga_ib_ret_t
ib_setup_for_devctl_cmd(char * ap_id,boolean_t use_static_ap_id,devctl_hdl_t * devctl_hdl,nvlist_t ** user_nvlistp)6160Sstevel@tonic-gate ib_setup_for_devctl_cmd(char *ap_id, boolean_t use_static_ap_id,
6170Sstevel@tonic-gate devctl_hdl_t *devctl_hdl, nvlist_t **user_nvlistp)
6180Sstevel@tonic-gate {
6190Sstevel@tonic-gate char *apid = (use_static_ap_id == B_TRUE) ? IB_STATIC_APID : ap_id;
6200Sstevel@tonic-gate
6210Sstevel@tonic-gate /* Get a handle to the ap */
6220Sstevel@tonic-gate if ((*devctl_hdl = devctl_ap_acquire(apid, NULL)) == NULL) {
6230Sstevel@tonic-gate DPRINTF("ib_setup_for_devctl_cmd: devctl_ap_acquire "
6240Sstevel@tonic-gate "errno: %d\n", errno);
6250Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp);
6260Sstevel@tonic-gate return (CFGA_IB_DEVCTL_ERR);
6270Sstevel@tonic-gate }
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate /* Set up to pass dynamic ap_id down to driver */
6300Sstevel@tonic-gate if (nvlist_alloc(user_nvlistp, NV_UNIQUE_NAME_TYPE, NULL) != 0) {
6310Sstevel@tonic-gate DPRINTF("ib_setup_for_devctl: nvlist_alloc errno: %d\n", errno);
6320Sstevel@tonic-gate *user_nvlistp = NULL; /* Prevent possible incorrect free in */
6330Sstevel@tonic-gate /* ib_cleanup_after_devctl_cmd */
6340Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp);
6350Sstevel@tonic-gate return (CFGA_IB_NVLIST_ERR);
6360Sstevel@tonic-gate }
6370Sstevel@tonic-gate
6380Sstevel@tonic-gate /* create a "string" entry */
6390Sstevel@tonic-gate if (nvlist_add_string(*user_nvlistp, IB_APID, ap_id) == -1) {
6400Sstevel@tonic-gate DPRINTF("ib_setup_for_devctl_cmd: nvlist_add_string failed. "
6410Sstevel@tonic-gate "errno: %d\n", errno);
6420Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp);
6430Sstevel@tonic-gate return (CFGA_IB_NVLIST_ERR);
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate return (CFGA_IB_OK);
6470Sstevel@tonic-gate }
6480Sstevel@tonic-gate
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate /*
6510Sstevel@tonic-gate * Function:
6520Sstevel@tonic-gate * ib_device_configured
6530Sstevel@tonic-gate * Input:
6540Sstevel@tonic-gate * hdl - Handler to devctl
6550Sstevel@tonic-gate * nvl - Name-value-pair list pointer
6560Sstevel@tonic-gate * Output:
6570Sstevel@tonic-gate * rstate - Receptacle state for the apid
6580Sstevel@tonic-gate * Returns:
6590Sstevel@tonic-gate * CFGA_IB_OK if it succeeds or an appropriate error.
6600Sstevel@tonic-gate * Description:
6610Sstevel@tonic-gate * Checks if there is a device actually configured to the ap? If so,
6620Sstevel@tonic-gate * issues a "devctl" to get the Receptacle state for that ap_id.
6630Sstevel@tonic-gate * If the ap_id is already configured it returns CFGA_IB_OK.
6640Sstevel@tonic-gate * Otherwise it returns a failure.
6650Sstevel@tonic-gate */
6660Sstevel@tonic-gate static cfga_ib_ret_t
ib_device_configured(devctl_hdl_t hdl,nvlist_t * nvl,ap_rstate_t * rstate)6670Sstevel@tonic-gate ib_device_configured(devctl_hdl_t hdl, nvlist_t *nvl, ap_rstate_t *rstate)
6680Sstevel@tonic-gate {
6690Sstevel@tonic-gate cfga_ib_ret_t rv;
6700Sstevel@tonic-gate devctl_ap_state_t devctl_ap_state;
6710Sstevel@tonic-gate
6720Sstevel@tonic-gate /* get ap_id's "devctl_ap_state" first */
6730Sstevel@tonic-gate if (devctl_ap_getstate(hdl, nvl, &devctl_ap_state) == -1) {
6740Sstevel@tonic-gate DPRINTF("ib_device_configured failed, errno: %d\n", errno);
6750Sstevel@tonic-gate return (CFGA_IB_DEVCTL_ERR);
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate
6780Sstevel@tonic-gate rv = CFGA_IB_ALREADY_CONFIGURED;
6790Sstevel@tonic-gate *rstate = devctl_ap_state.ap_rstate;
6800Sstevel@tonic-gate if (devctl_ap_state.ap_ostate != AP_OSTATE_CONFIGURED) {
6810Sstevel@tonic-gate return (CFGA_IB_NOT_CONFIGURED);
6820Sstevel@tonic-gate }
6830Sstevel@tonic-gate
6840Sstevel@tonic-gate return (rv);
6850Sstevel@tonic-gate }
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate /*
6890Sstevel@tonic-gate * Function:
6900Sstevel@tonic-gate * ib_device_connected
6910Sstevel@tonic-gate * Input:
6920Sstevel@tonic-gate * hdl - Handler to devctl
6930Sstevel@tonic-gate * nvl - Name-value-pair list pointer
6940Sstevel@tonic-gate * Output:
6950Sstevel@tonic-gate * ostate - Occupant state for the apid
6960Sstevel@tonic-gate * Returns:
6970Sstevel@tonic-gate * CFGA_IB_OK if it succeeds or an appropriate error.
6980Sstevel@tonic-gate * Description:
6990Sstevel@tonic-gate * Checks if there is a device actually connected to the ap? If so,
7000Sstevel@tonic-gate * issues a "devctl" to get the Occupant state for that ap_id.
7010Sstevel@tonic-gate * If the ap_id is already connected it returns CFGA_IB_OK.
7020Sstevel@tonic-gate * Otherwise it returns a failure.
7030Sstevel@tonic-gate */
7040Sstevel@tonic-gate static cfga_ib_ret_t
ib_device_connected(devctl_hdl_t hdl,nvlist_t * list,ap_ostate_t * ostate)7050Sstevel@tonic-gate ib_device_connected(devctl_hdl_t hdl, nvlist_t *list, ap_ostate_t *ostate)
7060Sstevel@tonic-gate {
7070Sstevel@tonic-gate cfga_ib_ret_t rv = CFGA_IB_ALREADY_CONNECTED;
7080Sstevel@tonic-gate devctl_ap_state_t devctl_ap_state;
7090Sstevel@tonic-gate
7100Sstevel@tonic-gate if (devctl_ap_getstate(hdl, list, &devctl_ap_state) == -1) {
7110Sstevel@tonic-gate DPRINTF("ib_device_connected failed, errno: %d\n", errno);
7120Sstevel@tonic-gate return (CFGA_IB_DEVCTL_ERR);
7130Sstevel@tonic-gate }
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate *ostate = devctl_ap_state.ap_ostate;
7160Sstevel@tonic-gate if (devctl_ap_state.ap_rstate != AP_RSTATE_CONNECTED) {
7170Sstevel@tonic-gate return (CFGA_IB_NOT_CONNECTED);
7180Sstevel@tonic-gate }
7190Sstevel@tonic-gate
7200Sstevel@tonic-gate return (rv);
7210Sstevel@tonic-gate }
7220Sstevel@tonic-gate
7230Sstevel@tonic-gate
7240Sstevel@tonic-gate /*
7250Sstevel@tonic-gate * Function:
7260Sstevel@tonic-gate * ib_do_control_ioctl
7270Sstevel@tonic-gate * Input:
7280Sstevel@tonic-gate * ap_id - The dynamic attachment point of an IB device
7290Sstevel@tonic-gate * sub_cmd1 - Sub Command 1 to DEVCTL_AP_CONTROL devctl
7300Sstevel@tonic-gate * sub_cmd2 - Sub Command 2 to DEVCTL_AP_CONTROL devctl
7310Sstevel@tonic-gate * (Mandatory except for IBNEX_NUM_HCA_NODES,
7320Sstevel@tonic-gate * IBNEX_NUM_DEVICE_NODES,
7330Sstevel@tonic-gate * IBNEX_UPDATE_PKEY_TBLS &
7340Sstevel@tonic-gate * IBNEX_UPDATE_IOC_CONF)
7350Sstevel@tonic-gate * misc_arg - optional arguments to DEVCTL_AP_CONTROL devctl
7360Sstevel@tonic-gate * Output:
7370Sstevel@tonic-gate * descrp - Buffer containing data back from kernel
7380Sstevel@tonic-gate * sizep - Length of the buffer back from kernel
7390Sstevel@tonic-gate * Returns:
7400Sstevel@tonic-gate * CFGA_IB_OK if it succeeds or an appropriate error.
7410Sstevel@tonic-gate * Description:
7420Sstevel@tonic-gate * Issues DEVCTL_AP_CONTROL devctl with sub_cmd1 first which actually
7430Sstevel@tonic-gate * queries the IBNEX module in the kernel on the size of the data to
7440Sstevel@tonic-gate * be returned.
7450Sstevel@tonic-gate *
7460Sstevel@tonic-gate * Next issues DEVCTL_AP_CONTROL devctl with a buffer of that much
7470Sstevel@tonic-gate * size and gets the actual data back.
7480Sstevel@tonic-gate * Passes the data and the size back to caller.
7490Sstevel@tonic-gate */
7500Sstevel@tonic-gate static cfga_ib_ret_t
ib_do_control_ioctl(char * ap_id,uint_t sub_cmd1,uint_t sub_cmd2,uint_t misc_arg,void ** descrp,size_t * sizep)7510Sstevel@tonic-gate ib_do_control_ioctl(char *ap_id, uint_t sub_cmd1, uint_t sub_cmd2,
7520Sstevel@tonic-gate uint_t misc_arg, void **descrp, size_t *sizep)
7530Sstevel@tonic-gate {
7540Sstevel@tonic-gate int fd = -1;
7550Sstevel@tonic-gate uint32_t local_size = 0;
7560Sstevel@tonic-gate cfga_ib_ret_t rv = CFGA_IB_OK;
7570Sstevel@tonic-gate struct ibnex_ioctl_data ioctl_data;
7580Sstevel@tonic-gate
7590Sstevel@tonic-gate /* try to open the ONLY static ap_id */
7600Sstevel@tonic-gate if ((fd = open(IB_STATIC_APID, O_RDONLY)) == -1) {
7610Sstevel@tonic-gate DPRINTF("ib_do_control_ioctl: open failed: "
7620Sstevel@tonic-gate "errno = %d\n", errno);
7630Sstevel@tonic-gate /* Provides a more useful error msg */
7640Sstevel@tonic-gate rv = (errno == EBUSY) ? CFGA_IB_BUSY_ERR : CFGA_IB_OPEN_ERR;
7650Sstevel@tonic-gate return (rv);
7660Sstevel@tonic-gate }
7670Sstevel@tonic-gate
7680Sstevel@tonic-gate /*
7690Sstevel@tonic-gate * Find out first how large a buffer is needed?
7700Sstevel@tonic-gate * NOTE: Ioctls only accept/return a 32-bit int for a get_size
7710Sstevel@tonic-gate * to avoid 32/64 and BE/LE issues.
7720Sstevel@tonic-gate */
7730Sstevel@tonic-gate ioctl_data.cmd = sub_cmd1;
7740Sstevel@tonic-gate ioctl_data.misc_arg = (uint_t)misc_arg;
7750Sstevel@tonic-gate ioctl_data.buf = (caddr_t)&local_size;
7760Sstevel@tonic-gate ioctl_data.bufsiz = sizeof (local_size);
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate /* Pass "ap_id" up for all other commands */
7790Sstevel@tonic-gate if (sub_cmd1 != IBNEX_NUM_DEVICE_NODES &&
7800Sstevel@tonic-gate sub_cmd1 != IBNEX_NUM_HCA_NODES &&
7810Sstevel@tonic-gate sub_cmd1 != IBNEX_UPDATE_PKEY_TBLS) {
7820Sstevel@tonic-gate ioctl_data.ap_id = (caddr_t)ap_id;
7830Sstevel@tonic-gate ioctl_data.ap_id_len = strlen(ap_id);
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate } else {
7860Sstevel@tonic-gate ioctl_data.ap_id = NULL;
7870Sstevel@tonic-gate ioctl_data.ap_id_len = 0;
7880Sstevel@tonic-gate }
7890Sstevel@tonic-gate
7900Sstevel@tonic-gate if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
7910Sstevel@tonic-gate DPRINTF("ib_do_control_ioctl: size ioctl ERR, errno: %d\n",
7920Sstevel@tonic-gate errno);
7930Sstevel@tonic-gate (void) close(fd);
7940Sstevel@tonic-gate rv = (errno == EBUSY) ? CFGA_IB_BUSY_ERR : CFGA_IB_IOCTL_ERR;
7950Sstevel@tonic-gate return (rv);
7960Sstevel@tonic-gate }
7970Sstevel@tonic-gate *sizep = local_size;
7980Sstevel@tonic-gate
7990Sstevel@tonic-gate /*
8000Sstevel@tonic-gate * Don't do the second ioctl only in these cases
8010Sstevel@tonic-gate * (NOTE: the data is returned in the first ioctl itself; if any)
8020Sstevel@tonic-gate */
8030Sstevel@tonic-gate if (sub_cmd1 == IBNEX_NUM_DEVICE_NODES ||
8040Sstevel@tonic-gate sub_cmd1 == IBNEX_NUM_HCA_NODES ||
8050Sstevel@tonic-gate sub_cmd1 == IBNEX_UPDATE_PKEY_TBLS ||
8060Sstevel@tonic-gate sub_cmd1 == IBNEX_UPDATE_IOC_CONF) {
8070Sstevel@tonic-gate (void) close(fd);
8080Sstevel@tonic-gate return (rv);
8090Sstevel@tonic-gate }
8100Sstevel@tonic-gate
8110Sstevel@tonic-gate if (local_size == 0 || (*descrp = malloc(*sizep)) == NULL) {
8120Sstevel@tonic-gate DPRINTF("ib_do_control_ioctl: malloc failed\n");
8130Sstevel@tonic-gate (void) close(fd);
8140Sstevel@tonic-gate return (CFGA_IB_ALLOC_FAIL);
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate /* Get the data */
8180Sstevel@tonic-gate ioctl_data.cmd = sub_cmd2;
8190Sstevel@tonic-gate ioctl_data.buf = (caddr_t)*descrp;
8200Sstevel@tonic-gate ioctl_data.bufsiz = *sizep;
8210Sstevel@tonic-gate
8220Sstevel@tonic-gate if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
8230Sstevel@tonic-gate DPRINTF("ib_do_control_ioctl: ioctl failed: errno:%d\n", errno);
8240Sstevel@tonic-gate if (*descrp != NULL) {
8250Sstevel@tonic-gate free(*descrp);
8260Sstevel@tonic-gate *descrp = NULL;
8270Sstevel@tonic-gate }
8280Sstevel@tonic-gate rv = (errno == EBUSY) ? CFGA_IB_BUSY_ERR : CFGA_IB_IOCTL_ERR;
8290Sstevel@tonic-gate }
8300Sstevel@tonic-gate
8310Sstevel@tonic-gate (void) close(fd);
8320Sstevel@tonic-gate return (rv);
8330Sstevel@tonic-gate }
8340Sstevel@tonic-gate
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate /* ========================================================================== */
8370Sstevel@tonic-gate /* Entry points */
8380Sstevel@tonic-gate
8390Sstevel@tonic-gate /*
8400Sstevel@tonic-gate * Function:
8410Sstevel@tonic-gate * cfga_change_state
8420Sstevel@tonic-gate * Input:
8430Sstevel@tonic-gate * state_change_cmd - Argument to the cfgadm -c command
8440Sstevel@tonic-gate * ap_id - The attachment point of an IB fabric
8450Sstevel@tonic-gate * options - State Change command options passed by the cfgadm(1M)
8460Sstevel@tonic-gate * confp - Whether this command requires confirmation?
8470Sstevel@tonic-gate * msgp - cfgadm error message for this plugin
8480Sstevel@tonic-gate * errstring - This contains error msg if command fails
8490Sstevel@tonic-gate * flags - Cfgadm(1m) flags
8500Sstevel@tonic-gate * Output:
8510Sstevel@tonic-gate * NONE
8520Sstevel@tonic-gate * Returns:
8530Sstevel@tonic-gate * If the command succeeded perform the cfgadm -c <cmd>;
8540Sstevel@tonic-gate * otherwise emit an error
8550Sstevel@tonic-gate * Description:
8560Sstevel@tonic-gate * Do cfgadm -c <cmd>
8570Sstevel@tonic-gate */
8580Sstevel@tonic-gate /*ARGSUSED*/
8590Sstevel@tonic-gate cfga_err_t
cfga_change_state(cfga_cmd_t state_change_cmd,const char * ap_id,const char * options,struct cfga_confirm * confp,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)8600Sstevel@tonic-gate cfga_change_state(cfga_cmd_t state_change_cmd, const char *ap_id,
8610Sstevel@tonic-gate const char *options, struct cfga_confirm *confp, struct cfga_msg *msgp,
8620Sstevel@tonic-gate char **errstring, cfga_flags_t flags)
8630Sstevel@tonic-gate {
8640Sstevel@tonic-gate int ret;
8650Sstevel@tonic-gate char *devpath;
8660Sstevel@tonic-gate nvlist_t *nvl = NULL;
8670Sstevel@tonic-gate boolean_t static_ap_id = B_TRUE;
8680Sstevel@tonic-gate ap_rstate_t rstate;
8690Sstevel@tonic-gate ap_ostate_t ostate;
8700Sstevel@tonic-gate devctl_hdl_t hdl = NULL;
8710Sstevel@tonic-gate cfga_ib_ret_t rv = CFGA_IB_OK;
8720Sstevel@tonic-gate
8730Sstevel@tonic-gate if ((rv = ib_verify_params(ap_id, options, errstring)) != CFGA_IB_OK) {
8740Sstevel@tonic-gate (void) cfga_help(msgp, options, flags);
8750Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_INVAL_APID_ERR,
8760Sstevel@tonic-gate ap_id, errno));
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate /*
8800Sstevel@tonic-gate * All subcommands which can change state of device require
8810Sstevel@tonic-gate * root privileges.
8820Sstevel@tonic-gate */
8830Sstevel@tonic-gate if (geteuid() != 0) {
8840Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_PRIV_ERR, ap_id, errno));
8850Sstevel@tonic-gate }
8860Sstevel@tonic-gate
8870Sstevel@tonic-gate if (strstr((char *)ap_id, IB_FABRIC_APID_STR) == NULL)
8880Sstevel@tonic-gate static_ap_id = B_FALSE;
8890Sstevel@tonic-gate
8900Sstevel@tonic-gate if ((rv = ib_setup_for_devctl_cmd((char *)ap_id, static_ap_id,
8910Sstevel@tonic-gate &hdl, &nvl)) != CFGA_IB_OK) {
8920Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(hdl, nvl);
8930Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate
8960Sstevel@tonic-gate switch (state_change_cmd) {
8970Sstevel@tonic-gate case CFGA_CMD_CONFIGURE:
8980Sstevel@tonic-gate rv = ib_device_connected(hdl, nvl, &ostate);
8990Sstevel@tonic-gate if (rv != CFGA_IB_ALREADY_CONNECTED) {
9000Sstevel@tonic-gate ret = (rv != CFGA_IB_NOT_CONNECTED) ?
9010Sstevel@tonic-gate CFGA_IB_CONFIG_OP_ERR : rv;
9020Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(hdl, nvl);
9030Sstevel@tonic-gate return (ib_err_msg(errstring, ret, ap_id, errno));
9040Sstevel@tonic-gate }
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate if (rv == CFGA_IB_ALREADY_CONNECTED) {
9070Sstevel@tonic-gate /*
9080Sstevel@tonic-gate * special case handling for
9090Sstevel@tonic-gate * SLM based cfgadm disconnects
9100Sstevel@tonic-gate */
9110Sstevel@tonic-gate if (ostate == AP_OSTATE_CONFIGURED) {
9120Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(hdl, nvl);
9130Sstevel@tonic-gate return (ib_err_msg(errstring,
9140Sstevel@tonic-gate CFGA_IB_ALREADY_CONFIGURED, ap_id,
9150Sstevel@tonic-gate errno));
9160Sstevel@tonic-gate }
9170Sstevel@tonic-gate }
9180Sstevel@tonic-gate
9190Sstevel@tonic-gate
9200Sstevel@tonic-gate rv = CFGA_IB_OK; /* Other status don't matter */
9210Sstevel@tonic-gate
9220Sstevel@tonic-gate if (devctl_ap_configure(hdl, nvl) != 0) {
9230Sstevel@tonic-gate DPRINTF("cfga_change_state: devctl_ap_configure "
9240Sstevel@tonic-gate "failed. errno: %d\n", errno);
9250Sstevel@tonic-gate rv = CFGA_IB_CONFIG_OP_ERR;
9260Sstevel@tonic-gate break;
9270Sstevel@tonic-gate }
9280Sstevel@tonic-gate
9290Sstevel@tonic-gate devpath = ib_get_devicepath(ap_id);
9300Sstevel@tonic-gate if (devpath == NULL) {
9310Sstevel@tonic-gate int i;
9320Sstevel@tonic-gate
9330Sstevel@tonic-gate /*
9340Sstevel@tonic-gate * try for some time as IB hotplug thread
9350Sstevel@tonic-gate * takes a while to create the path
9360Sstevel@tonic-gate * and then eventually give up
9370Sstevel@tonic-gate */
9380Sstevel@tonic-gate for (i = 0;
9390Sstevel@tonic-gate i < IB_RETRY_DEVPATH && (devpath == NULL); i++) {
9400Sstevel@tonic-gate sleep(IB_MAX_DEVPATH_DELAY);
9410Sstevel@tonic-gate devpath = ib_get_devicepath(ap_id);
9420Sstevel@tonic-gate }
9430Sstevel@tonic-gate
9440Sstevel@tonic-gate if (devpath == NULL) {
9450Sstevel@tonic-gate DPRINTF("cfga_change_state: get device "
9460Sstevel@tonic-gate "path failed i = %d\n", i);
9470Sstevel@tonic-gate rv = CFGA_IB_CONFIG_OP_ERR;
9480Sstevel@tonic-gate break;
9490Sstevel@tonic-gate }
9500Sstevel@tonic-gate }
9510Sstevel@tonic-gate S_FREE(devpath);
9520Sstevel@tonic-gate break;
9530Sstevel@tonic-gate
9540Sstevel@tonic-gate case CFGA_CMD_UNCONFIGURE:
9550Sstevel@tonic-gate if ((rv = ib_device_connected(hdl, nvl, &ostate)) !=
9560Sstevel@tonic-gate CFGA_IB_ALREADY_CONNECTED) {
9570Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(hdl, nvl);
9580Sstevel@tonic-gate if (rv == CFGA_IB_DEVCTL_ERR)
9590Sstevel@tonic-gate rv = CFGA_IB_INVALID_OP_ERR;
9600Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
9610Sstevel@tonic-gate }
9620Sstevel@tonic-gate
9630Sstevel@tonic-gate /* check if it is already unconfigured */
9640Sstevel@tonic-gate if ((rv = ib_device_configured(hdl, nvl, &rstate)) ==
9650Sstevel@tonic-gate CFGA_IB_NOT_CONFIGURED) {
9660Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(hdl, nvl);
9670Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
9680Sstevel@tonic-gate }
9690Sstevel@tonic-gate
9700Sstevel@tonic-gate rv = CFGA_IB_OK; /* Other statuses don't matter */
9710Sstevel@tonic-gate
9728082SRamaswamy.Tummala@Sun.COM if (!ib_confirm(confp, IB_CONFIRM1)) {
9730Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(hdl, nvl);
9740Sstevel@tonic-gate return (CFGA_NACK);
9750Sstevel@tonic-gate }
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate devpath = ib_get_devicepath(ap_id);
9780Sstevel@tonic-gate if (devpath == NULL) {
9790Sstevel@tonic-gate DPRINTF("cfga_change_state: get device path failed\n");
9800Sstevel@tonic-gate rv = CFGA_IB_UNCONFIG_OP_ERR;
9810Sstevel@tonic-gate break;
9820Sstevel@tonic-gate }
9830Sstevel@tonic-gate
9840Sstevel@tonic-gate if ((rv = ib_rcm_offline(ap_id, errstring, devpath, flags)) !=
9850Sstevel@tonic-gate CFGA_IB_OK) {
9860Sstevel@tonic-gate S_FREE(devpath);
9870Sstevel@tonic-gate break;
9880Sstevel@tonic-gate }
9890Sstevel@tonic-gate
9900Sstevel@tonic-gate ret = devctl_ap_unconfigure(hdl, nvl);
9910Sstevel@tonic-gate if (ret != 0) {
9920Sstevel@tonic-gate DPRINTF("cfga_change_state: devctl_ap_unconfigure "
9930Sstevel@tonic-gate "failed with errno: %d\n", errno);
9940Sstevel@tonic-gate rv = CFGA_IB_UNCONFIG_OP_ERR;
9950Sstevel@tonic-gate if (errno == EBUSY) {
9960Sstevel@tonic-gate rv = CFGA_IB_BUSY_ERR;
9970Sstevel@tonic-gate }
9980Sstevel@tonic-gate (void) ib_rcm_online(ap_id, errstring, devpath, flags);
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate } else {
10010Sstevel@tonic-gate (void) ib_rcm_remove(ap_id, errstring, devpath, flags);
10020Sstevel@tonic-gate }
10030Sstevel@tonic-gate
10040Sstevel@tonic-gate S_FREE(devpath);
10050Sstevel@tonic-gate break;
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate case CFGA_CMD_LOAD:
10080Sstevel@tonic-gate case CFGA_CMD_UNLOAD:
10090Sstevel@tonic-gate case CFGA_CMD_CONNECT:
10100Sstevel@tonic-gate case CFGA_CMD_DISCONNECT:
10110Sstevel@tonic-gate (void) cfga_help(msgp, options, flags);
10120Sstevel@tonic-gate rv = CFGA_IB_OPNOTSUPP;
10130Sstevel@tonic-gate break;
10140Sstevel@tonic-gate
10150Sstevel@tonic-gate case CFGA_CMD_NONE:
10160Sstevel@tonic-gate default:
10170Sstevel@tonic-gate (void) cfga_help(msgp, options, flags);
10180Sstevel@tonic-gate rv = CFGA_IB_INTERNAL_ERR;
10190Sstevel@tonic-gate }
10200Sstevel@tonic-gate
10210Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(hdl, nvl);
10220Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
10230Sstevel@tonic-gate }
10240Sstevel@tonic-gate
10250Sstevel@tonic-gate
10260Sstevel@tonic-gate /*
10270Sstevel@tonic-gate * Function:
10280Sstevel@tonic-gate * cfga_private_func
10290Sstevel@tonic-gate * Input:
10300Sstevel@tonic-gate * func - The private function (passed w/ -x option)
10310Sstevel@tonic-gate * ap_id - The attachment point of an IB fabric
10320Sstevel@tonic-gate * options - Private function command options passed
10330Sstevel@tonic-gate * by the cfgadm(1M)
10340Sstevel@tonic-gate * confp - Whether this command requires confirmation?
10350Sstevel@tonic-gate * msgp - cfgadm error message for this plugin
10360Sstevel@tonic-gate * errstring - This contains error msg if command fails
10370Sstevel@tonic-gate * flags - Cfgadm(1m) flags
10380Sstevel@tonic-gate * Output:
10390Sstevel@tonic-gate * NONE
10400Sstevel@tonic-gate * Returns:
10410Sstevel@tonic-gate * If the command succeeded perform the 'cfgadm -x <func>'; otherwise
10420Sstevel@tonic-gate * return failure.
10430Sstevel@tonic-gate * Description:
10440Sstevel@tonic-gate * Do cfgadm -x <func>
10450Sstevel@tonic-gate */
10460Sstevel@tonic-gate /*ARGSUSED*/
10470Sstevel@tonic-gate cfga_err_t
cfga_private_func(const char * func,const char * ap_id,const char * options,struct cfga_confirm * confp,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)10480Sstevel@tonic-gate cfga_private_func(const char *func, const char *ap_id, const char *options,
10490Sstevel@tonic-gate struct cfga_confirm *confp, struct cfga_msg *msgp, char **errstring,
10500Sstevel@tonic-gate cfga_flags_t flags)
10510Sstevel@tonic-gate {
10520Sstevel@tonic-gate int len, ret, count = 0;
10530Sstevel@tonic-gate char *clnt_name = NULL, *alt_hca = NULL;
10540Sstevel@tonic-gate char *clnt_apid = NULL, *clnt_devpath = NULL;
10550Sstevel@tonic-gate char *name, *msg = NULL;
10560Sstevel@tonic-gate char *fab_apid = strstr((char *)ap_id, IBNEX_FABRIC);
10570Sstevel@tonic-gate size_t info_len = 0;
10580Sstevel@tonic-gate uchar_t *info = NULL;
10590Sstevel@tonic-gate nvlist_t *nvl;
10600Sstevel@tonic-gate nvpair_t *nvp = NULL;
10610Sstevel@tonic-gate ap_rstate_t rstate;
10620Sstevel@tonic-gate devctl_hdl_t hdl = NULL;
10630Sstevel@tonic-gate cfga_ib_ret_t rv;
10640Sstevel@tonic-gate
10650Sstevel@tonic-gate if ((rv = ib_verify_params(ap_id, NULL, errstring)) != CFGA_IB_OK) {
10660Sstevel@tonic-gate DPRINTF("cfga_private_func: ib_verify_params "
10670Sstevel@tonic-gate "failed with rv: %d\n", rv);
10680Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
10690Sstevel@tonic-gate }
10700Sstevel@tonic-gate
10710Sstevel@tonic-gate if (func == NULL) {
10720Sstevel@tonic-gate DPRINTF("cfga_private_func: func is NULL\n");
10730Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_INVAL_ARG_ERR, ap_id,
10740Sstevel@tonic-gate errno));
10750Sstevel@tonic-gate }
10760Sstevel@tonic-gate
10770Sstevel@tonic-gate /*
10780Sstevel@tonic-gate * check first if IB static ap_id is "configured" for use
10790Sstevel@tonic-gate */
10800Sstevel@tonic-gate if (fab_apid != NULL) {
10810Sstevel@tonic-gate if ((rv = ib_setup_for_devctl_cmd(fab_apid, B_TRUE, &hdl,
10820Sstevel@tonic-gate &nvl)) != CFGA_IB_OK) {
10830Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(hdl, nvl);
10840Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
10850Sstevel@tonic-gate }
10860Sstevel@tonic-gate if ((rv = ib_device_configured(hdl, nvl, &rstate)) ==
10870Sstevel@tonic-gate CFGA_IB_NOT_CONFIGURED) {
10880Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
10890Sstevel@tonic-gate }
10900Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(hdl, nvl);
10910Sstevel@tonic-gate }
10920Sstevel@tonic-gate
10930Sstevel@tonic-gate rv = CFGA_IB_OK;
10940Sstevel@tonic-gate DPRINTF("cfga_private_func: func is %s\n", func);
10950Sstevel@tonic-gate if (strcmp(func, IB_LIST_HCA_CLIENTS) == 0) { /* -x list_clients */
10960Sstevel@tonic-gate
10970Sstevel@tonic-gate /* only supported on HCA ap_ids */
10980Sstevel@tonic-gate if (fab_apid != NULL) {
10990Sstevel@tonic-gate DPRINTF("cfga_private_func: fabric apid supplied\n");
11000Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR,
11010Sstevel@tonic-gate ap_id, errno));
11020Sstevel@tonic-gate }
11030Sstevel@tonic-gate
11048082SRamaswamy.Tummala@Sun.COM if ((msg = (char *)calloc(256, 1)) == NULL) {
11050Sstevel@tonic-gate DPRINTF("cfga_private_func: malloc for msg failed. "
11060Sstevel@tonic-gate "errno: %d\n", errno);
11070Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_ALLOC_FAIL,
11080Sstevel@tonic-gate ap_id, errno));
11090Sstevel@tonic-gate }
11100Sstevel@tonic-gate
11110Sstevel@tonic-gate if ((rv = ib_do_control_ioctl((char *)ap_id, IBNEX_HCA_LIST_SZ,
11120Sstevel@tonic-gate IBNEX_HCA_LIST_INFO, 0, (void **)&info, &info_len)) != 0) {
11130Sstevel@tonic-gate DPRINTF("cfga_private_func: "
11140Sstevel@tonic-gate "ib_do_control_ioctl list failed :%d\n", rv);
11150Sstevel@tonic-gate S_FREE(msg);
11160Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_HCA_LIST_ERR,
11170Sstevel@tonic-gate ap_id, errno));
11180Sstevel@tonic-gate }
11190Sstevel@tonic-gate
11200Sstevel@tonic-gate if (nvlist_unpack((char *)info, info_len, &nvl, 0)) {
11210Sstevel@tonic-gate DPRINTF("cfga_private_func: "
11220Sstevel@tonic-gate "nvlist_unpack 2 failed %p\n", info);
11230Sstevel@tonic-gate S_FREE(info);
11240Sstevel@tonic-gate S_FREE(msg);
11250Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_NVLIST_ERR, ap_id,
11260Sstevel@tonic-gate errno));
11270Sstevel@tonic-gate }
11280Sstevel@tonic-gate
11298082SRamaswamy.Tummala@Sun.COM (void) snprintf(msg, 256, "Ap_Id\t\t\t IB Client\t\t "
11300Sstevel@tonic-gate "Alternate HCA\n");
11310Sstevel@tonic-gate cfga_msg(msgp, msg);
11320Sstevel@tonic-gate
11330Sstevel@tonic-gate /* Walk the NVPAIR data */
11340Sstevel@tonic-gate while (nvp = nvlist_next_nvpair(nvl, nvp)) {
11350Sstevel@tonic-gate name = nvpair_name(nvp);
11360Sstevel@tonic-gate if (strcmp(name, "Client") == 0) {
11370Sstevel@tonic-gate (void) nvpair_value_string(nvp, &clnt_name);
11380Sstevel@tonic-gate ++count;
11390Sstevel@tonic-gate } else if (strcmp(name, "Alt_HCA") == 0) {
11400Sstevel@tonic-gate (void) nvpair_value_string(nvp, &alt_hca);
11410Sstevel@tonic-gate ++count;
11420Sstevel@tonic-gate } else if (strcmp(name, "ApID") == 0) {
11430Sstevel@tonic-gate (void) nvpair_value_string(nvp, &clnt_apid);
11440Sstevel@tonic-gate ++count;
11450Sstevel@tonic-gate }
11460Sstevel@tonic-gate
11470Sstevel@tonic-gate /* check at the end; print message per client found */
11480Sstevel@tonic-gate if (count == 3) {
11490Sstevel@tonic-gate count = 0;
11508082SRamaswamy.Tummala@Sun.COM (void) snprintf(msg, 256, "%-30s %-25s %s\n",
11510Sstevel@tonic-gate clnt_apid, clnt_name, alt_hca);
11520Sstevel@tonic-gate cfga_msg(msgp, msg);
11530Sstevel@tonic-gate }
11540Sstevel@tonic-gate } /* end of while */
11550Sstevel@tonic-gate
11560Sstevel@tonic-gate S_FREE(info);
11570Sstevel@tonic-gate S_FREE(msg);
11580Sstevel@tonic-gate nvlist_free(nvl);
11590Sstevel@tonic-gate
11600Sstevel@tonic-gate /* -x unconfig_clients */
11610Sstevel@tonic-gate } else if (strcmp(func, IB_UNCONFIG_HCA_CLIENTS) == 0) {
11620Sstevel@tonic-gate /*
11630Sstevel@tonic-gate * -x unconfig_clients changes state by calling into RCM.
11640Sstevel@tonic-gate * It needs root privileges.
11650Sstevel@tonic-gate */
11660Sstevel@tonic-gate if (geteuid() != 0) {
11670Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_PRIV_ERR, ap_id,
11680Sstevel@tonic-gate errno));
11690Sstevel@tonic-gate }
11700Sstevel@tonic-gate
11710Sstevel@tonic-gate /* only supported on HCA ap_ids */
11720Sstevel@tonic-gate if (fab_apid != NULL) {
11730Sstevel@tonic-gate DPRINTF("cfga_private_func: fabric apid supplied\n");
11740Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR,
11750Sstevel@tonic-gate ap_id, errno));
11760Sstevel@tonic-gate }
11770Sstevel@tonic-gate
11788082SRamaswamy.Tummala@Sun.COM /*
11798082SRamaswamy.Tummala@Sun.COM * Check w/ user if it is ok to do this operation
11808082SRamaswamy.Tummala@Sun.COM * If the user fails to confirm, bailout
11818082SRamaswamy.Tummala@Sun.COM */
11828082SRamaswamy.Tummala@Sun.COM if (!ib_confirm(confp, IB_CONFIRM3))
11830Sstevel@tonic-gate return (CFGA_NACK);
11840Sstevel@tonic-gate
11850Sstevel@tonic-gate /* Get device-paths of all the IOC/Port/Pseudo devices */
11860Sstevel@tonic-gate rv = ib_do_control_ioctl((char *)ap_id, IBNEX_UNCFG_CLNTS_SZ,
11870Sstevel@tonic-gate IBNEX_UNCFG_CLNTS_INFO, 0, (void **)&info, &info_len);
11880Sstevel@tonic-gate if (rv != 0) {
11890Sstevel@tonic-gate DPRINTF("cfga_private_func: ib_do_control_ioctl "
11900Sstevel@tonic-gate "failed :%d\n", rv);
11910Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_HCA_UNCONFIG_ERR,
11920Sstevel@tonic-gate ap_id, errno));
11930Sstevel@tonic-gate }
11940Sstevel@tonic-gate
11950Sstevel@tonic-gate if (nvlist_unpack((char *)info, info_len, &nvl, 0)) {
11960Sstevel@tonic-gate DPRINTF("cfga_private_func: nvlist_unpack failed %p\n",
11970Sstevel@tonic-gate info);
11980Sstevel@tonic-gate S_FREE(info);
11990Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_NVLIST_ERR, ap_id,
12000Sstevel@tonic-gate errno));
12010Sstevel@tonic-gate }
12020Sstevel@tonic-gate
12030Sstevel@tonic-gate ret = 0;
12040Sstevel@tonic-gate
12050Sstevel@tonic-gate /* Call RCM Offline on all device paths */
12060Sstevel@tonic-gate while (nvp = nvlist_next_nvpair(nvl, nvp)) {
12070Sstevel@tonic-gate name = nvpair_name(nvp);
12080Sstevel@tonic-gate if (strcmp(name, "devpath") == 0) {
12090Sstevel@tonic-gate (void) nvpair_value_string(nvp, &clnt_devpath);
12100Sstevel@tonic-gate ++count;
12110Sstevel@tonic-gate } else if (strcmp(name, "ApID") == 0) {
12120Sstevel@tonic-gate (void) nvpair_value_string(nvp, &clnt_apid);
12130Sstevel@tonic-gate ++count;
12140Sstevel@tonic-gate }
12150Sstevel@tonic-gate
12160Sstevel@tonic-gate /* handle the client unconfigure now */
12170Sstevel@tonic-gate if (count == 2) {
12180Sstevel@tonic-gate count = 0; /* reset count */
12190Sstevel@tonic-gate
12200Sstevel@tonic-gate DPRINTF("cfga_private_func: client apid = %s, "
12210Sstevel@tonic-gate "DevPath = %s\n", clnt_apid, clnt_devpath);
12220Sstevel@tonic-gate if ((rv = ib_setup_for_devctl_cmd(clnt_apid,
12230Sstevel@tonic-gate B_TRUE, &hdl, &nvl)) != CFGA_IB_OK) {
12240Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(hdl, nvl);
12250Sstevel@tonic-gate return (ib_err_msg(errstring, rv,
12260Sstevel@tonic-gate clnt_apid, errno));
12270Sstevel@tonic-gate }
12280Sstevel@tonic-gate
12290Sstevel@tonic-gate if ((rv = ib_device_configured(hdl, nvl,
12300Sstevel@tonic-gate &rstate)) == CFGA_IB_NOT_CONFIGURED)
12310Sstevel@tonic-gate continue;
12320Sstevel@tonic-gate
12330Sstevel@tonic-gate if ((rv = ib_rcm_offline(clnt_apid, errstring,
12340Sstevel@tonic-gate clnt_devpath, flags)) != CFGA_IB_OK) {
12350Sstevel@tonic-gate DPRINTF("cfga_private_func: client rcm "
12360Sstevel@tonic-gate "offline failed for %s, with %d\n",
12370Sstevel@tonic-gate clnt_devpath, rv);
12380Sstevel@tonic-gate ret = rv;
12390Sstevel@tonic-gate continue;
12400Sstevel@tonic-gate }
12410Sstevel@tonic-gate
12420Sstevel@tonic-gate if (devctl_ap_unconfigure(hdl, nvl) != 0) {
12430Sstevel@tonic-gate DPRINTF("cfga_private_func: client "
12440Sstevel@tonic-gate "unconfigure failed: errno %d\n",
12450Sstevel@tonic-gate errno);
12460Sstevel@tonic-gate ret = CFGA_IB_UNCONFIG_OP_ERR;
12470Sstevel@tonic-gate if (errno == EBUSY)
12480Sstevel@tonic-gate ret = CFGA_IB_BUSY_ERR;
12490Sstevel@tonic-gate (void) ib_rcm_online(clnt_apid,
12500Sstevel@tonic-gate errstring, clnt_devpath, flags);
12510Sstevel@tonic-gate continue;
12520Sstevel@tonic-gate } else {
12530Sstevel@tonic-gate (void) ib_rcm_remove(clnt_apid,
12540Sstevel@tonic-gate errstring, clnt_devpath, flags);
12550Sstevel@tonic-gate }
12560Sstevel@tonic-gate ib_cleanup_after_devctl_cmd(hdl, nvl);
12570Sstevel@tonic-gate
12580Sstevel@tonic-gate } /* end of if count == 2 */
12590Sstevel@tonic-gate
12600Sstevel@tonic-gate } /* end of while */
12610Sstevel@tonic-gate
12620Sstevel@tonic-gate S_FREE(info);
12630Sstevel@tonic-gate nvlist_free(nvl);
12640Sstevel@tonic-gate if (ret) {
12650Sstevel@tonic-gate DPRINTF("cfga_private_func: unconfig_clients of %s "
12660Sstevel@tonic-gate "failed with %d\n", ap_id, ret);
12670Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_UCFG_CLNTS_ERR,
12680Sstevel@tonic-gate ap_id, errno));
12690Sstevel@tonic-gate }
12700Sstevel@tonic-gate
12710Sstevel@tonic-gate /* -x update_pkey_tbls */
12720Sstevel@tonic-gate } else if (strcmp(func, IB_UPDATE_PKEY_TBLS) == 0) {
12730Sstevel@tonic-gate /*
12740Sstevel@tonic-gate * Check for root privileges.
12750Sstevel@tonic-gate */
12760Sstevel@tonic-gate if (geteuid() != 0) {
12770Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_PRIV_ERR, ap_id,
12780Sstevel@tonic-gate errno));
12790Sstevel@tonic-gate }
12800Sstevel@tonic-gate
12810Sstevel@tonic-gate /* CHECK: Only supported on fabric ap_ids */
1282*8695SRajkumar.Sivaprakasam@Sun.COM if (fab_apid == NULL || strcmp(fab_apid, IBNEX_FABRIC) != 0) {
12830Sstevel@tonic-gate DPRINTF("cfga_private_func: fabric apid needed\n");
12840Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR,
12850Sstevel@tonic-gate ap_id, errno));
12860Sstevel@tonic-gate }
12870Sstevel@tonic-gate
12880Sstevel@tonic-gate /* Check w/ user if it is ok to do this operation */
12890Sstevel@tonic-gate len = strlen(IB_CONFIRM4) + 10;
12900Sstevel@tonic-gate if ((msg = (char *)calloc(len, 1)) != NULL) {
12910Sstevel@tonic-gate (void) snprintf(msg, len, "%s\nContinue", IB_CONFIRM4);
12920Sstevel@tonic-gate }
12930Sstevel@tonic-gate
12940Sstevel@tonic-gate /* If the user fails to confirm, return */
12950Sstevel@tonic-gate if (!ib_confirm(confp, msg)) {
12960Sstevel@tonic-gate free(msg);
12970Sstevel@tonic-gate return (CFGA_NACK);
12980Sstevel@tonic-gate }
12990Sstevel@tonic-gate free(msg);
13000Sstevel@tonic-gate
13010Sstevel@tonic-gate /* Update P_Key tables for all ports of all HCAs */
13020Sstevel@tonic-gate rv = ib_do_control_ioctl((char *)ap_id, IBNEX_UPDATE_PKEY_TBLS,
13030Sstevel@tonic-gate 0, 0, 0, &info_len);
13040Sstevel@tonic-gate
13050Sstevel@tonic-gate if (rv != 0) {
13060Sstevel@tonic-gate DPRINTF("cfga_private_func: ib_do_control_ioctl "
13070Sstevel@tonic-gate "failed :%d\n", rv);
13080Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_UPD_PKEY_TBLS_ERR,
13090Sstevel@tonic-gate ap_id, errno));
13100Sstevel@tonic-gate }
13110Sstevel@tonic-gate
13120Sstevel@tonic-gate /* -x [add_service|delete_service] */
13130Sstevel@tonic-gate } else if ((strncmp(func, IB_ADD_SERVICE, 12) == 0) ||
13140Sstevel@tonic-gate (strncmp(func, IB_DELETE_SERVICE, 15) == 0)) {
13150Sstevel@tonic-gate char *subopts, *val;
13160Sstevel@tonic-gate uint8_t cmd;
13170Sstevel@tonic-gate
13180Sstevel@tonic-gate /* check: Only supported on fabric ap_ids */
13190Sstevel@tonic-gate if (fab_apid == NULL || strcmp(fab_apid, IBNEX_FABRIC) != 0) {
13200Sstevel@tonic-gate DPRINTF("cfga_private_func: fabric apid needed\n");
13210Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR,
13220Sstevel@tonic-gate ap_id, errno));
13230Sstevel@tonic-gate }
13240Sstevel@tonic-gate
13250Sstevel@tonic-gate /* Check for root privileges. */
13260Sstevel@tonic-gate if (geteuid() != 0) {
13270Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_PRIV_ERR, ap_id,
13280Sstevel@tonic-gate errno));
13290Sstevel@tonic-gate }
13300Sstevel@tonic-gate
13310Sstevel@tonic-gate /* return error if no options are specified */
13320Sstevel@tonic-gate subopts = (char *)options;
13330Sstevel@tonic-gate if (subopts == (char *)NULL) {
13340Sstevel@tonic-gate DPRINTF("cfga_private_func: no sub-options\n");
13350Sstevel@tonic-gate (void) cfga_help(msgp, options, flags);
13360Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_INVAL_ARG_ERR,
13370Sstevel@tonic-gate ap_id, errno));
13380Sstevel@tonic-gate }
13390Sstevel@tonic-gate
13400Sstevel@tonic-gate /* parse options specified */
13410Sstevel@tonic-gate while (*subopts != '\0') {
13420Sstevel@tonic-gate switch (getsubopt(&subopts, ib_service_subopts, &val)) {
13430Sstevel@tonic-gate case 0: /* comm */
13440Sstevel@tonic-gate if (val == NULL) {
13450Sstevel@tonic-gate (void) cfga_help(msgp, options, flags);
13460Sstevel@tonic-gate S_FREE(service_name);
13470Sstevel@tonic-gate return (ib_err_msg(errstring,
13480Sstevel@tonic-gate CFGA_IB_INVAL_ARG_ERR,
13490Sstevel@tonic-gate ap_id, errno));
13500Sstevel@tonic-gate } else {
13510Sstevel@tonic-gate comm_name = strdup(val);
13520Sstevel@tonic-gate if (comm_name == NULL) {
13530Sstevel@tonic-gate DPRINTF("comm sub-opt invalid "
13540Sstevel@tonic-gate "arg\n");
13550Sstevel@tonic-gate S_FREE(service_name);
13560Sstevel@tonic-gate return (ib_err_msg(errstring,
13570Sstevel@tonic-gate CFGA_IB_COMM_INVAL_ERR,
13580Sstevel@tonic-gate ap_id, errno));
13590Sstevel@tonic-gate }
13600Sstevel@tonic-gate }
13610Sstevel@tonic-gate break;
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate case 1: /* service */
13640Sstevel@tonic-gate if (val == NULL) {
13650Sstevel@tonic-gate (void) cfga_help(msgp, options, flags);
13660Sstevel@tonic-gate S_FREE(comm_name);
13670Sstevel@tonic-gate return (ib_err_msg(errstring,
13680Sstevel@tonic-gate CFGA_IB_INVAL_ARG_ERR,
13690Sstevel@tonic-gate ap_id, errno));
13700Sstevel@tonic-gate } else {
13710Sstevel@tonic-gate /* service can be upto 4 long */
13720Sstevel@tonic-gate if (strlen(val) == 0 ||
13730Sstevel@tonic-gate strlen(val) > 4) {
13740Sstevel@tonic-gate DPRINTF("comm sub-opt invalid "
13750Sstevel@tonic-gate "service passed\n");
13760Sstevel@tonic-gate S_FREE(comm_name);
13770Sstevel@tonic-gate return (ib_err_msg(errstring,
13780Sstevel@tonic-gate CFGA_IB_SVC_LEN_ERR,
13790Sstevel@tonic-gate ap_id, errno));
13800Sstevel@tonic-gate }
13810Sstevel@tonic-gate service_name = strdup(val);
13820Sstevel@tonic-gate if (service_name == NULL) {
13830Sstevel@tonic-gate DPRINTF("comm sub-opt "
13840Sstevel@tonic-gate "internal error\n");
13850Sstevel@tonic-gate S_FREE(comm_name);
13860Sstevel@tonic-gate return (ib_err_msg(errstring,
13870Sstevel@tonic-gate CFGA_IB_SVC_INVAL_ERR,
13880Sstevel@tonic-gate ap_id, errno));
13890Sstevel@tonic-gate }
13900Sstevel@tonic-gate }
13910Sstevel@tonic-gate break;
13920Sstevel@tonic-gate
13930Sstevel@tonic-gate default:
13940Sstevel@tonic-gate (void) cfga_help(msgp, options, flags);
13950Sstevel@tonic-gate S_FREE(comm_name);
13960Sstevel@tonic-gate S_FREE(service_name);
13970Sstevel@tonic-gate return (ib_err_msg(errstring,
13980Sstevel@tonic-gate CFGA_IB_INVAL_ARG_ERR, ap_id, errno));
13990Sstevel@tonic-gate }
14000Sstevel@tonic-gate }
14010Sstevel@tonic-gate
14020Sstevel@tonic-gate /* figure out the "operation" */
14030Sstevel@tonic-gate if (strncasecmp(func, IB_ADD_SERVICE, 11) == 0)
14040Sstevel@tonic-gate cmd = IBCONF_ADD_ENTRY;
14050Sstevel@tonic-gate else if (strncasecmp(func, IB_DELETE_SERVICE, 14) == 0)
14060Sstevel@tonic-gate cmd = IBCONF_DELETE_ENTRY;
14070Sstevel@tonic-gate DPRINTF("Service = %s, Comm = %s, Operation = %s\n",
14080Sstevel@tonic-gate service_name, comm_name, func);
14090Sstevel@tonic-gate
14100Sstevel@tonic-gate if (strncasecmp(comm_name, IBNEX_PORT_STR, 4) == 0)
14110Sstevel@tonic-gate service_type = IB_PORT_SERVICE;
14120Sstevel@tonic-gate else if (strncasecmp(comm_name, IBNEX_VPPA_STR, 4) == 0)
14130Sstevel@tonic-gate service_type = IB_VPPA_SERVICE;
14140Sstevel@tonic-gate else if (strncasecmp(comm_name, IBNEX_HCASVC_STR, 4) == 0)
14150Sstevel@tonic-gate service_type = IB_HCASVC_SERVICE;
14160Sstevel@tonic-gate else {
14170Sstevel@tonic-gate (void) cfga_help(msgp, options, flags);
14180Sstevel@tonic-gate S_FREE(comm_name);
14190Sstevel@tonic-gate S_FREE(service_name);
14200Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_INVAL_ARG_ERR,
14210Sstevel@tonic-gate ap_id, errno));
14220Sstevel@tonic-gate }
14230Sstevel@tonic-gate
14240Sstevel@tonic-gate /* do the add/delete entry to the service */
14250Sstevel@tonic-gate if (cmd == IBCONF_ADD_ENTRY) {
14260Sstevel@tonic-gate if ((rv = ib_add_service(errstring)) != CFGA_IB_OK)
14270Sstevel@tonic-gate DPRINTF("cfga_private_func: add failed\n");
14280Sstevel@tonic-gate } else if (cmd == IBCONF_DELETE_ENTRY) {
14290Sstevel@tonic-gate if ((rv = ib_delete_service(errstring)) != CFGA_IB_OK)
14300Sstevel@tonic-gate DPRINTF("cfga_private_func: delete failed\n");
14310Sstevel@tonic-gate }
14320Sstevel@tonic-gate
14330Sstevel@tonic-gate S_FREE(comm_name);
14340Sstevel@tonic-gate S_FREE(service_name);
14350Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
14360Sstevel@tonic-gate
14370Sstevel@tonic-gate } else if (strncmp(func, IB_LIST_SERVICES, 13) == 0) {
14380Sstevel@tonic-gate
14390Sstevel@tonic-gate /* check: Only supported on fabric ap_ids */
14400Sstevel@tonic-gate if (fab_apid == NULL || strcmp(fab_apid, IBNEX_FABRIC) != 0) {
14410Sstevel@tonic-gate DPRINTF("cfga_private_func: fabric apid needed\n");
14420Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR,
14430Sstevel@tonic-gate ap_id, errno));
14440Sstevel@tonic-gate }
14450Sstevel@tonic-gate
14460Sstevel@tonic-gate /* do the list services */
14470Sstevel@tonic-gate rv = ib_list_services(msgp, errstring);
14480Sstevel@tonic-gate if (rv != CFGA_IB_OK) {
14490Sstevel@tonic-gate DPRINTF("cfga_private_func: ib_list_services failed\n");
14500Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
14510Sstevel@tonic-gate }
14520Sstevel@tonic-gate
14530Sstevel@tonic-gate /* -x update_ioc_conf */
14540Sstevel@tonic-gate } else if (strncmp(func, IB_UPDATE_IOC_CONF, 17) == 0) {
14550Sstevel@tonic-gate uint_t misc_arg;
14560Sstevel@tonic-gate
14570Sstevel@tonic-gate /* Supported only with root privilege */
14580Sstevel@tonic-gate if (geteuid() != 0) {
14590Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_PRIV_ERR, ap_id,
14600Sstevel@tonic-gate errno));
14610Sstevel@tonic-gate }
14620Sstevel@tonic-gate
14630Sstevel@tonic-gate /*
14640Sstevel@tonic-gate * check: Only supported on fabric ap_id or IOC APID
14650Sstevel@tonic-gate * IOC APID does not have any commas in it.
14660Sstevel@tonic-gate */
14670Sstevel@tonic-gate if (fab_apid == NULL ||
14680Sstevel@tonic-gate (fab_apid != NULL && strstr(fab_apid, ",") != NULL)) {
14690Sstevel@tonic-gate DPRINTF("cfga_private_func: fabric/IOC apid needed\n");
14700Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_INVALID_OP_ERR,
14710Sstevel@tonic-gate ap_id, errno));
14720Sstevel@tonic-gate }
14730Sstevel@tonic-gate
14740Sstevel@tonic-gate /* Check w/ user if it is ok to do this operation */
14750Sstevel@tonic-gate len = strlen(IB_CONFIRM5) + 10;
14760Sstevel@tonic-gate if ((msg = (char *)calloc(len, 1)) != NULL) {
14770Sstevel@tonic-gate (void) snprintf(msg, len, "%s\nContinue", IB_CONFIRM5);
14780Sstevel@tonic-gate }
14790Sstevel@tonic-gate
14800Sstevel@tonic-gate /* If the user fails to confirm, return */
14810Sstevel@tonic-gate if (!ib_confirm(confp, msg)) {
14820Sstevel@tonic-gate free(msg);
14830Sstevel@tonic-gate return (CFGA_NACK);
14840Sstevel@tonic-gate }
14850Sstevel@tonic-gate free(msg);
14860Sstevel@tonic-gate
14870Sstevel@tonic-gate misc_arg = (strcmp(fab_apid, IBNEX_FABRIC) == 0) ?
14886601Seota IBNEX_BASE_APID : IBNEX_DYN_APID;
14890Sstevel@tonic-gate
14900Sstevel@tonic-gate /* Reprobe and update IOC(s) configuration */
14910Sstevel@tonic-gate rv = ib_do_control_ioctl((char *)ap_id, IBNEX_UPDATE_IOC_CONF,
14920Sstevel@tonic-gate 0, misc_arg, 0, &info_len);
14930Sstevel@tonic-gate
14940Sstevel@tonic-gate if (rv != 0) {
14950Sstevel@tonic-gate DPRINTF("cfga_private_func: ib_do_control_ioctl "
14960Sstevel@tonic-gate "failed :%d\n", rv);
14970Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_DEVCTL_ERR,
14980Sstevel@tonic-gate ap_id, errno));
14990Sstevel@tonic-gate }
15000Sstevel@tonic-gate } else {
15010Sstevel@tonic-gate DPRINTF("cfga_private_func: unrecognized command.\n");
15020Sstevel@tonic-gate (void) cfga_help(msgp, options, flags);
15030Sstevel@tonic-gate errno = EINVAL;
15040Sstevel@tonic-gate return (CFGA_INVAL);
15050Sstevel@tonic-gate }
15060Sstevel@tonic-gate
15070Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
15080Sstevel@tonic-gate }
15090Sstevel@tonic-gate
15100Sstevel@tonic-gate
15110Sstevel@tonic-gate /*
15120Sstevel@tonic-gate * Function:
15130Sstevel@tonic-gate * cfga_test
15140Sstevel@tonic-gate * Input:
15150Sstevel@tonic-gate * ap_id - The attachment point of an IB fabric
15160Sstevel@tonic-gate * options - Test command options passed by the cfgadm(1M)
15170Sstevel@tonic-gate * msgp - cfgadm error message for this plugin
15180Sstevel@tonic-gate * errstring - This contains error msg if command fails
15190Sstevel@tonic-gate * flags - Cfgadm(1m) flags
15200Sstevel@tonic-gate * Output:
15210Sstevel@tonic-gate * NONE
15220Sstevel@tonic-gate * Returns:
15230Sstevel@tonic-gate * CFGA_OPNOTSUPP
15240Sstevel@tonic-gate * Description:
15250Sstevel@tonic-gate * Do "cfgadm -t"
15260Sstevel@tonic-gate */
15270Sstevel@tonic-gate /*ARGSUSED*/
15280Sstevel@tonic-gate cfga_err_t
cfga_test(const char * ap_id,const char * options,struct cfga_msg * msgp,char ** errstring,cfga_flags_t flags)15290Sstevel@tonic-gate cfga_test(const char *ap_id, const char *options, struct cfga_msg *msgp,
15300Sstevel@tonic-gate char **errstring, cfga_flags_t flags)
15310Sstevel@tonic-gate {
15320Sstevel@tonic-gate (void) cfga_help(msgp, options, flags);
15330Sstevel@tonic-gate return (CFGA_OPNOTSUPP);
15340Sstevel@tonic-gate }
15350Sstevel@tonic-gate
15360Sstevel@tonic-gate
15370Sstevel@tonic-gate /*
15380Sstevel@tonic-gate * Function:
15390Sstevel@tonic-gate * ib_fill_static_apids
15400Sstevel@tonic-gate * Input:
15410Sstevel@tonic-gate * ap_id - The static attachment point of an IB device
15420Sstevel@tonic-gate * clp - The returned "list" information array
15430Sstevel@tonic-gate * Output:
15440Sstevel@tonic-gate * NONE
15450Sstevel@tonic-gate * Returns:
15460Sstevel@tonic-gate * Fills up the "list" information array for the static attachment point
15470Sstevel@tonic-gate * Description:
15480Sstevel@tonic-gate * IB fabric supports two types of static attachment points.
15490Sstevel@tonic-gate * One is fabric and other is for the HCAs. This fills up
15500Sstevel@tonic-gate * "cfga_list_data_t" for static attachment points.
15510Sstevel@tonic-gate */
15520Sstevel@tonic-gate static cfga_ib_ret_t
ib_fill_static_apids(char * ap_id,cfga_list_data_t * clp)15530Sstevel@tonic-gate ib_fill_static_apids(char *ap_id, cfga_list_data_t *clp)
15540Sstevel@tonic-gate {
15550Sstevel@tonic-gate int rv, l_err;
15560Sstevel@tonic-gate char *ap_id_log = NULL;
15570Sstevel@tonic-gate
15580Sstevel@tonic-gate /* Get /dev/cfg path to corresponding to the physical ap_id */
15590Sstevel@tonic-gate /* Remember ap_id_log must be freed */
15600Sstevel@tonic-gate if ((cfga_ib_ret_t)ib_physpath_to_devlink(ap_id, &ap_id_log,
15610Sstevel@tonic-gate &l_err) != ICFGA_OK) {
15620Sstevel@tonic-gate DPRINTF("ib_fill_static_apids: "
15630Sstevel@tonic-gate "ib_physpath_to_devlink failed\n");
15640Sstevel@tonic-gate return (CFGA_IB_DEVLINK_ERR);
15650Sstevel@tonic-gate }
15660Sstevel@tonic-gate assert(ap_id_log != NULL);
15670Sstevel@tonic-gate
15680Sstevel@tonic-gate /* Get logical ap-id corresponding to the physical */
15690Sstevel@tonic-gate if (strstr(ap_id_log, CFGA_DEV_DIR) == NULL) {
15700Sstevel@tonic-gate DPRINTF("ib_fill_static_apids: devlink doesn't contain "
15710Sstevel@tonic-gate "/dev/cfg\n");
15720Sstevel@tonic-gate free(ap_id_log);
15730Sstevel@tonic-gate return (CFGA_IB_DEVLINK_ERR);
15740Sstevel@tonic-gate }
15750Sstevel@tonic-gate
15760Sstevel@tonic-gate clp->ap_cond = CFGA_COND_OK;
15770Sstevel@tonic-gate clp->ap_r_state = CFGA_STAT_CONNECTED;
15780Sstevel@tonic-gate clp->ap_o_state = CFGA_STAT_CONFIGURED;
15790Sstevel@tonic-gate clp->ap_class[0] = '\0'; /* Filled by libcfgadm */
15800Sstevel@tonic-gate clp->ap_busy = 0;
15810Sstevel@tonic-gate clp->ap_status_time = (time_t)-1;
15820Sstevel@tonic-gate (void) snprintf(clp->ap_log_id, sizeof (clp->ap_log_id), "%s",
15830Sstevel@tonic-gate /* Strip off /dev/cfg/ */ ap_id_log + strlen(CFGA_DEV_DIR) + 1);
15840Sstevel@tonic-gate (void) strlcpy(clp->ap_phys_id, ap_id, sizeof (clp->ap_phys_id));
15850Sstevel@tonic-gate
15860Sstevel@tonic-gate /* Static IB apid */
15870Sstevel@tonic-gate if (strstr((char *)ap_id, IB_FABRIC_APID_STR) != NULL) {
15880Sstevel@tonic-gate (void) strlcpy(clp->ap_type, IB_FABRIC_TYPE,
15890Sstevel@tonic-gate sizeof (clp->ap_type)); /* Fill in type */
15900Sstevel@tonic-gate (void) strlcpy(clp->ap_info, IB_FABRIC_INFO,
15910Sstevel@tonic-gate sizeof (clp->ap_info));
15920Sstevel@tonic-gate
15930Sstevel@tonic-gate } else { /* Static HCA apid */
15940Sstevel@tonic-gate size_t size = 0;
15950Sstevel@tonic-gate uchar_t *data = NULL;
15960Sstevel@tonic-gate
15970Sstevel@tonic-gate (void) strlcpy(clp->ap_type, IB_HCA_TYPE,
15980Sstevel@tonic-gate sizeof (clp->ap_type)); /* Fill in type */
15990Sstevel@tonic-gate
16000Sstevel@tonic-gate rv = ib_do_control_ioctl(ap_id, IBNEX_HCA_VERBOSE_SZ,
16010Sstevel@tonic-gate IBNEX_HCA_VERBOSE_INFO, 0, (void **)&data, &size);
16020Sstevel@tonic-gate if (rv != 0) {
16030Sstevel@tonic-gate DPRINTF("ib_fill_static_apids: ib_do_control_ioctl "
16040Sstevel@tonic-gate "failed :%d\n", rv);
16050Sstevel@tonic-gate free(ap_id_log);
16060Sstevel@tonic-gate S_FREE(data);
16070Sstevel@tonic-gate return (CFGA_IB_IOCTL_ERR);
16080Sstevel@tonic-gate }
16090Sstevel@tonic-gate
16100Sstevel@tonic-gate (void) strlcpy(clp->ap_info, (char *)data,
16110Sstevel@tonic-gate sizeof (clp->ap_info));
16120Sstevel@tonic-gate S_FREE(data);
16130Sstevel@tonic-gate }
16140Sstevel@tonic-gate free(ap_id_log);
16150Sstevel@tonic-gate return (CFGA_IB_OK);
16160Sstevel@tonic-gate }
16170Sstevel@tonic-gate
16180Sstevel@tonic-gate
16190Sstevel@tonic-gate /*
16200Sstevel@tonic-gate * Function:
16210Sstevel@tonic-gate * cfga_list_ext
16220Sstevel@tonic-gate * Input:
16230Sstevel@tonic-gate * ap_id - The attachment point of an IB fabric
16240Sstevel@tonic-gate * ap_id_list - The returned "list" information array
16250Sstevel@tonic-gate * nlistp - Number of elements in the "list" information array
16260Sstevel@tonic-gate * options - List command options passed by the cfgadm(1M)
16270Sstevel@tonic-gate * listopts - "-s" specific options
16280Sstevel@tonic-gate * errstring - This contains error msg if command fails
16290Sstevel@tonic-gate * flags - Cfgadm(1m) flags
16300Sstevel@tonic-gate * Output:
16310Sstevel@tonic-gate * NONE
16320Sstevel@tonic-gate * Returns:
16330Sstevel@tonic-gate * If the command succeeded, cfgadm -l output otherwise an error
16340Sstevel@tonic-gate * Description:
16350Sstevel@tonic-gate * Do cfgadm -l
16360Sstevel@tonic-gate */
16370Sstevel@tonic-gate /*ARGSUSED*/
16380Sstevel@tonic-gate cfga_err_t
cfga_list_ext(const char * ap_id,cfga_list_data_t ** ap_id_list,int * nlistp,const char * options,const char * listopts,char ** errstring,cfga_flags_t flags)16390Sstevel@tonic-gate cfga_list_ext(const char *ap_id, cfga_list_data_t **ap_id_list, int *nlistp,
16400Sstevel@tonic-gate const char *options, const char *listopts, char **errstring,
16410Sstevel@tonic-gate cfga_flags_t flags)
16420Sstevel@tonic-gate {
16430Sstevel@tonic-gate int expand = 0;
16440Sstevel@tonic-gate int i, index, count;
16450Sstevel@tonic-gate int show_dynamic = 0;
16460Sstevel@tonic-gate size_t num_devices = 0;
16470Sstevel@tonic-gate size_t num_hcas = 0;
16480Sstevel@tonic-gate size_t snap_size = 0;
16490Sstevel@tonic-gate uchar_t *snap_data = NULL;
16500Sstevel@tonic-gate nvpair_t *nvp = NULL; /* for lint purposes */
16510Sstevel@tonic-gate nvlist_t *nvl = NULL;
16520Sstevel@tonic-gate boolean_t apid_matched = B_FALSE; /* for valid ap_id */
16530Sstevel@tonic-gate cfga_ib_ret_t rv = CFGA_IB_OK;
16540Sstevel@tonic-gate cfga_list_data_t *clp = NULL;
16550Sstevel@tonic-gate
16560Sstevel@tonic-gate if ((rv = ib_verify_params(ap_id, options, errstring)) != CFGA_IB_OK) {
16570Sstevel@tonic-gate (void) cfga_help(NULL, options, flags);
16580Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
16590Sstevel@tonic-gate }
16600Sstevel@tonic-gate
16610Sstevel@tonic-gate /* make sure we have a valid ap_id_list */
16620Sstevel@tonic-gate if (ap_id_list == NULL || nlistp == NULL) {
16630Sstevel@tonic-gate DPRINTF("cfga_list_ext: list = NULL or nlistp = NULL\n");
16640Sstevel@tonic-gate (void) cfga_help(NULL, options, flags);
16650Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_INVAL_ARG_ERR,
16660Sstevel@tonic-gate ap_id, errno));
16670Sstevel@tonic-gate }
16680Sstevel@tonic-gate
16690Sstevel@tonic-gate DPRINTF("cfga_list_ext: ap_id = %s\n", ap_id);
16700Sstevel@tonic-gate
16710Sstevel@tonic-gate if ((flags & CFGA_FLAG_LIST_ALL) == CFGA_FLAG_LIST_ALL) {
16720Sstevel@tonic-gate expand = 1; /* -a flag passed */
16730Sstevel@tonic-gate }
16740Sstevel@tonic-gate
16750Sstevel@tonic-gate if (GET_DYN(ap_id) != NULL) {
16760Sstevel@tonic-gate show_dynamic = 1;
16770Sstevel@tonic-gate }
16780Sstevel@tonic-gate
16790Sstevel@tonic-gate if ((expand == 1) && /* -a option passed */
16800Sstevel@tonic-gate (strstr((char *)ap_id, IB_FABRIC_APID_STR) != NULL)) {
16810Sstevel@tonic-gate /*
16820Sstevel@tonic-gate * Figure out how many IOC/Port/Pseudo
16830Sstevel@tonic-gate * devices exist in the system?
16840Sstevel@tonic-gate */
16850Sstevel@tonic-gate if ((rv = ib_do_control_ioctl((char *)ap_id,
16860Sstevel@tonic-gate IBNEX_NUM_DEVICE_NODES, 0, 0, 0, &num_devices)) !=
16870Sstevel@tonic-gate CFGA_IB_OK) {
16880Sstevel@tonic-gate DPRINTF("cfga_list_ext: ib_do_control_ioctl "
16890Sstevel@tonic-gate "IBNEX_NUM_DEVICE_NODES failed :%d\n", rv);
16900Sstevel@tonic-gate if (errno == ENOENT)
16910Sstevel@tonic-gate return (CFGA_APID_NOEXIST);
16920Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
16930Sstevel@tonic-gate }
16940Sstevel@tonic-gate
16950Sstevel@tonic-gate DPRINTF("cfga_list_ext: num_devices = %d\n", num_devices);
16960Sstevel@tonic-gate }
16970Sstevel@tonic-gate
16980Sstevel@tonic-gate /* Figure out how many HCA nodes exist in the system. */
16990Sstevel@tonic-gate if ((rv = ib_do_control_ioctl((char *)ap_id, IBNEX_NUM_HCA_NODES, 0, 0,
17000Sstevel@tonic-gate 0, &num_hcas)) != CFGA_IB_OK) {
17010Sstevel@tonic-gate DPRINTF("cfga_list_ext: ib_do_control_ioctl "
17020Sstevel@tonic-gate "IBNEX_NUM_HCA_NODES failed :%d\n", rv);
17030Sstevel@tonic-gate if (errno == ENOENT)
17040Sstevel@tonic-gate return (CFGA_APID_NOEXIST);
17050Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
17060Sstevel@tonic-gate }
17070Sstevel@tonic-gate DPRINTF("cfga_list_ext: num_hcas = %d\n", num_hcas);
17080Sstevel@tonic-gate
17090Sstevel@tonic-gate /*
17100Sstevel@tonic-gate * No HCAs or IOC/VPPA/Port/HCA_SVC/Pseudo devices seen (non-IB system)
17110Sstevel@tonic-gate */
17120Sstevel@tonic-gate if (!(num_hcas || num_devices)) {
17130Sstevel@tonic-gate DPRINTF("cfga_list_ext: no IB devices found\n");
17140Sstevel@tonic-gate return (CFGA_APID_NOEXIST);
17150Sstevel@tonic-gate }
17160Sstevel@tonic-gate
17170Sstevel@tonic-gate /*
17180Sstevel@tonic-gate * *nlistp contains to how many APIDs to show w/ cfgadm -l.
17190Sstevel@tonic-gate * If ap_id is "fabric" then
17200Sstevel@tonic-gate * *nlistp is all Dynamic Apids + One more for "fabric"
17210Sstevel@tonic-gate * If ap_id is "HCA" ap_id then
17220Sstevel@tonic-gate * *nlistp is 1
17230Sstevel@tonic-gate * Note that each HCA is a static APID, so nlistp will be 1 always
17240Sstevel@tonic-gate * and this function will be called N times for each of the N HCAs
17250Sstevel@tonic-gate * in the host.
17260Sstevel@tonic-gate */
17270Sstevel@tonic-gate if (strstr((char *)ap_id, IB_FABRIC_APID_STR) != NULL) {
17280Sstevel@tonic-gate *nlistp = num_devices + 1;
17290Sstevel@tonic-gate
17300Sstevel@tonic-gate } else {
17310Sstevel@tonic-gate /* Assume it as a HCA ap_id */
17320Sstevel@tonic-gate *nlistp = 1;
17330Sstevel@tonic-gate }
17340Sstevel@tonic-gate
17350Sstevel@tonic-gate /* Allocate storage for passing "list" info back */
17360Sstevel@tonic-gate if ((*ap_id_list = (cfga_list_data_t *)calloc(*nlistp,
17370Sstevel@tonic-gate sizeof (cfga_list_data_t))) == NULL) {
17380Sstevel@tonic-gate DPRINTF("cfga_list_ext: malloc for cfga_list_data_t failed. "
17390Sstevel@tonic-gate "errno: %d\n", errno);
17400Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_ALLOC_FAIL,
17410Sstevel@tonic-gate ap_id, errno));
17420Sstevel@tonic-gate }
17430Sstevel@tonic-gate
17440Sstevel@tonic-gate /*
17450Sstevel@tonic-gate * Only static ap_id is ib_fabric:
17460Sstevel@tonic-gate * If -a options isn't specified then only show the static ap_id.
17470Sstevel@tonic-gate */
17480Sstevel@tonic-gate if (!show_dynamic) {
17490Sstevel@tonic-gate clp = &(*ap_id_list[0]);
17500Sstevel@tonic-gate
17510Sstevel@tonic-gate if ((rv = ib_fill_static_apids((char *)ap_id, clp)) !=
17520Sstevel@tonic-gate CFGA_IB_OK) {
17530Sstevel@tonic-gate S_FREE(*ap_id_list);
17540Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
17550Sstevel@tonic-gate }
17560Sstevel@tonic-gate apid_matched = B_TRUE;
17570Sstevel@tonic-gate }
17580Sstevel@tonic-gate
17590Sstevel@tonic-gate /*
17600Sstevel@tonic-gate * No -a specified
17610Sstevel@tonic-gate * No HCAs or IOC/VPPA/HCA_SVC/Port/Pseudo devices seen (non-IB system)
17620Sstevel@tonic-gate */
17630Sstevel@tonic-gate if (!expand || (!num_hcas && !num_devices)) {
17640Sstevel@tonic-gate if (!show_dynamic)
17650Sstevel@tonic-gate return (CFGA_OK);
17660Sstevel@tonic-gate }
17670Sstevel@tonic-gate
17680Sstevel@tonic-gate if (strstr((char *)ap_id, IB_FABRIC_APID_STR) != NULL) {
17690Sstevel@tonic-gate rv = ib_do_control_ioctl((char *)ap_id, IBNEX_SNAPSHOT_SIZE,
17700Sstevel@tonic-gate IBNEX_GET_SNAPSHOT, IBNEX_DONOT_PROBE_FLAG,
17710Sstevel@tonic-gate (void **)&snap_data, &snap_size);
17720Sstevel@tonic-gate if (rv != 0) {
17730Sstevel@tonic-gate DPRINTF("cfga_list_ext: ib_do_control_ioctl "
17740Sstevel@tonic-gate "failed :%d\n", rv);
17750Sstevel@tonic-gate S_FREE(*ap_id_list);
17760Sstevel@tonic-gate S_FREE(snap_data);
17770Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
17780Sstevel@tonic-gate }
17790Sstevel@tonic-gate
17800Sstevel@tonic-gate if (nvlist_unpack((char *)snap_data, snap_size, &nvl, 0)) {
17810Sstevel@tonic-gate DPRINTF("cfga_list_ext: nvlist_unpack 1 failed %p\n",
17820Sstevel@tonic-gate snap_data);
17830Sstevel@tonic-gate S_FREE(*ap_id_list);
17840Sstevel@tonic-gate S_FREE(snap_data);
17850Sstevel@tonic-gate return (ib_err_msg(errstring, CFGA_IB_NVLIST_ERR,
17860Sstevel@tonic-gate ap_id, errno));
17870Sstevel@tonic-gate }
17880Sstevel@tonic-gate
17890Sstevel@tonic-gate /*
17900Sstevel@tonic-gate * In kernel a nvlist is build per ap_id which contains
17910Sstevel@tonic-gate * information that is displayed using cfgadm -l.
17920Sstevel@tonic-gate * For IB devices only these 6 items are shown:
17930Sstevel@tonic-gate * ap_id, type, occupant, receptacle, condition and info
17940Sstevel@tonic-gate *
17950Sstevel@tonic-gate * In addition, one could specify a dynamic ap_id from
17960Sstevel@tonic-gate * command-line. Then cfgadm -l should show only that
17970Sstevel@tonic-gate * ap_id and skip rest.
17980Sstevel@tonic-gate */
17990Sstevel@tonic-gate index = 1; count = 0;
18000Sstevel@tonic-gate while (nvp = nvlist_next_nvpair(nvl, nvp)) {
18010Sstevel@tonic-gate int32_t intval = 0;
18020Sstevel@tonic-gate int32_t node_type;
18030Sstevel@tonic-gate char *info;
18040Sstevel@tonic-gate char *nv_apid;
18050Sstevel@tonic-gate char *name = nvpair_name(nvp);
18060Sstevel@tonic-gate
18070Sstevel@tonic-gate /* start of with next device */
18080Sstevel@tonic-gate if (count == IB_NUM_NVPAIRS) {
18090Sstevel@tonic-gate count = 0;
18100Sstevel@tonic-gate ++index;
18110Sstevel@tonic-gate }
18120Sstevel@tonic-gate
18136601Seota /*
18146601Seota * Check if the index doesn't go beyond the
18156601Seota * device number. If it goes, stop the loop
18166601Seota * here not to cause the heap corruption.
18176601Seota */
18186601Seota if (show_dynamic == 0 && index > num_devices)
18196601Seota break;
18206601Seota
18210Sstevel@tonic-gate /* fill up data into "clp" */
18220Sstevel@tonic-gate clp = (show_dynamic != 0) ? &(*ap_id_list[0]) :
18230Sstevel@tonic-gate &(ap_id_list[0][index]);
18240Sstevel@tonic-gate
18250Sstevel@tonic-gate /* First nvlist entry is "ap_id" always */
18260Sstevel@tonic-gate if (strcmp(name, IBNEX_NODE_APID_NVL) == 0) {
18270Sstevel@tonic-gate (void) nvpair_value_string(nvp, &nv_apid);
18280Sstevel@tonic-gate DPRINTF("cfga_list_ext: Name = %s, apid = %s\n",
18290Sstevel@tonic-gate name, nv_apid);
18300Sstevel@tonic-gate
18310Sstevel@tonic-gate /*
18320Sstevel@tonic-gate * If a dynamic ap_id is specified in the
18330Sstevel@tonic-gate * command-line, skip all entries until
18340Sstevel@tonic-gate * the one needed matches.
18350Sstevel@tonic-gate */
18360Sstevel@tonic-gate if (show_dynamic &&
18370Sstevel@tonic-gate strstr(ap_id, nv_apid) == NULL) {
18380Sstevel@tonic-gate DPRINTF("cfga_list_ext: NO MATCH\n");
18390Sstevel@tonic-gate
18400Sstevel@tonic-gate /*
18410Sstevel@tonic-gate * skip rest of the entries of this
18420Sstevel@tonic-gate * device.
18430Sstevel@tonic-gate */
18440Sstevel@tonic-gate for (i = 0; i < IB_NUM_NVPAIRS - 1; i++)
18450Sstevel@tonic-gate nvp = nvlist_next_nvpair(nvl,
18460Sstevel@tonic-gate nvp);
18470Sstevel@tonic-gate count = 0; /* reset it */
18480Sstevel@tonic-gate continue;
18490Sstevel@tonic-gate }
18500Sstevel@tonic-gate
18510Sstevel@tonic-gate apid_matched = B_TRUE;
18520Sstevel@tonic-gate
18530Sstevel@tonic-gate /* build the physical ap_id */
18540Sstevel@tonic-gate if (strstr(ap_id, DYN_SEP) == NULL) {
18550Sstevel@tonic-gate (void) snprintf(clp->ap_phys_id,
18560Sstevel@tonic-gate sizeof (clp->ap_phys_id), "%s%s%s",
18570Sstevel@tonic-gate ap_id, DYN_SEP, nv_apid);
18580Sstevel@tonic-gate } else {
18590Sstevel@tonic-gate (void) snprintf(clp->ap_phys_id,
18600Sstevel@tonic-gate sizeof (clp->ap_phys_id), "%s",
18610Sstevel@tonic-gate ap_id);
18620Sstevel@tonic-gate }
18630Sstevel@tonic-gate
18640Sstevel@tonic-gate /* ensure that this is a valid apid */
18650Sstevel@tonic-gate if (ib_verify_valid_apid(clp->ap_phys_id) !=
18660Sstevel@tonic-gate 0) {
18670Sstevel@tonic-gate DPRINTF("cfga_list_ext: "
18680Sstevel@tonic-gate "not a valid IB ap_id\n");
18690Sstevel@tonic-gate S_FREE(*ap_id_list);
18700Sstevel@tonic-gate S_FREE(snap_data);
18710Sstevel@tonic-gate nvlist_free(nvl);
18720Sstevel@tonic-gate return (ib_err_msg(errstring,
18730Sstevel@tonic-gate CFGA_IB_AP_ERR, ap_id, errno));
18740Sstevel@tonic-gate }
18750Sstevel@tonic-gate
18760Sstevel@tonic-gate /* build the logical ap_id */
18770Sstevel@tonic-gate (void) snprintf(clp->ap_log_id,
18780Sstevel@tonic-gate sizeof (clp->ap_log_id), "ib%s%s",
18790Sstevel@tonic-gate DYN_SEP, nv_apid);
18800Sstevel@tonic-gate DPRINTF("cfga_list_ext: ap_pi = %s, ap_li = %s,"
18810Sstevel@tonic-gate "\nap_info = %s\n", clp->ap_phys_id,
18820Sstevel@tonic-gate clp->ap_log_id, clp->ap_info);
18830Sstevel@tonic-gate ++count;
18840Sstevel@tonic-gate
18850Sstevel@tonic-gate } else if (strcmp(name, IBNEX_NODE_INFO_NVL) == 0) {
18860Sstevel@tonic-gate (void) nvpair_value_string(nvp, &info);
18870Sstevel@tonic-gate DPRINTF("cfga_list_ext: Name = %s, info = %s\n",
18880Sstevel@tonic-gate name, info);
18890Sstevel@tonic-gate (void) snprintf(clp->ap_info,
18900Sstevel@tonic-gate sizeof (clp->ap_info), "%s", info);
18910Sstevel@tonic-gate ++count;
18920Sstevel@tonic-gate
18930Sstevel@tonic-gate } else if (strcmp(name, IBNEX_NODE_TYPE_NVL) == 0) {
18940Sstevel@tonic-gate (void) nvpair_value_int32(nvp, &node_type);
18950Sstevel@tonic-gate if (node_type == IBNEX_PORT_NODE_TYPE) {
18960Sstevel@tonic-gate (void) snprintf(clp->ap_type,
18970Sstevel@tonic-gate sizeof (clp->ap_type), "%s",
18980Sstevel@tonic-gate IB_PORT_TYPE);
18990Sstevel@tonic-gate } else if (node_type == IBNEX_VPPA_NODE_TYPE) {
19000Sstevel@tonic-gate (void) snprintf(clp->ap_type,
19010Sstevel@tonic-gate sizeof (clp->ap_type), "%s",
19020Sstevel@tonic-gate IB_VPPA_TYPE);
19030Sstevel@tonic-gate } else if (node_type ==
19040Sstevel@tonic-gate IBNEX_HCASVC_NODE_TYPE) {
19050Sstevel@tonic-gate (void) snprintf(clp->ap_type,
19060Sstevel@tonic-gate sizeof (clp->ap_type), "%s",
19070Sstevel@tonic-gate IB_HCASVC_TYPE);
19080Sstevel@tonic-gate } else if (node_type == IBNEX_IOC_NODE_TYPE) {
19090Sstevel@tonic-gate (void) snprintf(clp->ap_type,
19100Sstevel@tonic-gate sizeof (clp->ap_type), "%s",
19110Sstevel@tonic-gate IB_IOC_TYPE);
19120Sstevel@tonic-gate } else if (node_type ==
19130Sstevel@tonic-gate IBNEX_PSEUDO_NODE_TYPE) {
19140Sstevel@tonic-gate (void) snprintf(clp->ap_type,
19150Sstevel@tonic-gate sizeof (clp->ap_type), "%s",
19160Sstevel@tonic-gate IB_PSEUDO_TYPE);
19170Sstevel@tonic-gate }
19180Sstevel@tonic-gate DPRINTF("cfga_list_ext: Name = %s, type = %x\n",
19190Sstevel@tonic-gate name, intval);
19200Sstevel@tonic-gate ++count;
19210Sstevel@tonic-gate
19220Sstevel@tonic-gate } else if (strcmp(name, IBNEX_NODE_RSTATE_NVL) == 0) {
19230Sstevel@tonic-gate (void) nvpair_value_int32(nvp, &intval);
19240Sstevel@tonic-gate
19250Sstevel@tonic-gate if (intval == AP_RSTATE_EMPTY)
19260Sstevel@tonic-gate clp->ap_r_state = CFGA_STAT_EMPTY;
19270Sstevel@tonic-gate else if (intval == AP_RSTATE_DISCONNECTED)
19280Sstevel@tonic-gate clp->ap_r_state =
19296601Seota CFGA_STAT_DISCONNECTED;
19300Sstevel@tonic-gate else if (intval == AP_RSTATE_CONNECTED)
19310Sstevel@tonic-gate clp->ap_r_state = CFGA_STAT_CONNECTED;
19320Sstevel@tonic-gate DPRINTF("cfga_list_ext: Name = %s, "
19330Sstevel@tonic-gate "rstate = %x\n", name, intval);
19340Sstevel@tonic-gate ++count;
19350Sstevel@tonic-gate
19360Sstevel@tonic-gate } else if (strcmp(name, IBNEX_NODE_OSTATE_NVL) == 0) {
19370Sstevel@tonic-gate (void) nvpair_value_int32(nvp, &intval);
19380Sstevel@tonic-gate
19390Sstevel@tonic-gate if (intval == AP_OSTATE_CONFIGURED)
19400Sstevel@tonic-gate clp->ap_o_state = CFGA_STAT_CONFIGURED;
19410Sstevel@tonic-gate else if (intval == AP_OSTATE_UNCONFIGURED)
19420Sstevel@tonic-gate clp->ap_o_state =
19436601Seota CFGA_STAT_UNCONFIGURED;
19440Sstevel@tonic-gate DPRINTF("cfga_list_ext: Name = %s, "
19450Sstevel@tonic-gate "ostate = %x\n", name, intval);
19460Sstevel@tonic-gate ++count;
19470Sstevel@tonic-gate
19480Sstevel@tonic-gate } else if (strcmp(name, IBNEX_NODE_COND_NVL) == 0) {
19490Sstevel@tonic-gate (void) nvpair_value_int32(nvp, &intval);
19500Sstevel@tonic-gate
19510Sstevel@tonic-gate if (intval == AP_COND_OK)
19520Sstevel@tonic-gate clp->ap_cond = CFGA_COND_OK;
19530Sstevel@tonic-gate else if (intval == AP_COND_FAILING)
19540Sstevel@tonic-gate clp->ap_cond = CFGA_COND_FAILING;
19550Sstevel@tonic-gate else if (intval == AP_COND_FAILED)
19560Sstevel@tonic-gate clp->ap_cond = CFGA_COND_FAILED;
19570Sstevel@tonic-gate else if (intval == AP_COND_UNUSABLE)
19580Sstevel@tonic-gate clp->ap_cond = CFGA_COND_UNUSABLE;
19590Sstevel@tonic-gate else if (intval == AP_COND_UNKNOWN)
19600Sstevel@tonic-gate clp->ap_cond = CFGA_COND_UNKNOWN;
19610Sstevel@tonic-gate DPRINTF("cfga_list_ext: Name = %s, "
19620Sstevel@tonic-gate "condition = %x\n", name, intval);
19630Sstevel@tonic-gate ++count;
19640Sstevel@tonic-gate }
19650Sstevel@tonic-gate
19660Sstevel@tonic-gate clp->ap_class[0] = '\0'; /* Filled by libcfgadm */
19670Sstevel@tonic-gate clp->ap_busy = 0;
19680Sstevel@tonic-gate clp->ap_status_time = (time_t)-1;
19690Sstevel@tonic-gate } /* end of while */
19700Sstevel@tonic-gate }
19710Sstevel@tonic-gate
19720Sstevel@tonic-gate S_FREE(snap_data);
19730Sstevel@tonic-gate if (nvl)
19740Sstevel@tonic-gate nvlist_free(nvl);
19750Sstevel@tonic-gate
19760Sstevel@tonic-gate /*
19770Sstevel@tonic-gate * if a cmdline specified ap_id doesn't match the known list of ap_ids
19780Sstevel@tonic-gate * then report an error right away
19790Sstevel@tonic-gate */
19800Sstevel@tonic-gate rv = (apid_matched == B_TRUE) ? CFGA_IB_OK : CFGA_IB_AP_ERR;
19810Sstevel@tonic-gate return (ib_err_msg(errstring, rv, ap_id, errno));
19820Sstevel@tonic-gate }
19830Sstevel@tonic-gate
19840Sstevel@tonic-gate
19850Sstevel@tonic-gate /*
19860Sstevel@tonic-gate * Function:
19870Sstevel@tonic-gate * cfga_msg
19880Sstevel@tonic-gate * Input:
19890Sstevel@tonic-gate * msgp - cfgadm error message for this plugin
19900Sstevel@tonic-gate * str - string to be passed on to the message
19910Sstevel@tonic-gate * Output:
19920Sstevel@tonic-gate * NONE
19930Sstevel@tonic-gate * Returns:
19940Sstevel@tonic-gate * NONE
19950Sstevel@tonic-gate * Description:
19960Sstevel@tonic-gate * This routine accepts a variable number of message IDs and
19970Sstevel@tonic-gate * constructs a corresponding error string which is printed
19980Sstevel@tonic-gate * via the message print routine argument.
19990Sstevel@tonic-gate */
20000Sstevel@tonic-gate void
cfga_msg(struct cfga_msg * msgp,const char * str)20010Sstevel@tonic-gate cfga_msg(struct cfga_msg *msgp, const char *str)
20020Sstevel@tonic-gate {
20030Sstevel@tonic-gate int len;
20040Sstevel@tonic-gate char *q;
20050Sstevel@tonic-gate
20060Sstevel@tonic-gate if (msgp == NULL || msgp->message_routine == NULL) {
20070Sstevel@tonic-gate DPRINTF("cfga_msg: msg\n");
20080Sstevel@tonic-gate return;
20090Sstevel@tonic-gate }
20100Sstevel@tonic-gate
20110Sstevel@tonic-gate if ((len = strlen(str)) == 0) {
20120Sstevel@tonic-gate DPRINTF("cfga_msg: null str\n");
20130Sstevel@tonic-gate return;
20140Sstevel@tonic-gate }
20150Sstevel@tonic-gate
20160Sstevel@tonic-gate if ((q = (char *)calloc(len + 1, 1)) == NULL) {
20170Sstevel@tonic-gate DPRINTF("cfga_msg: null q\n");
20180Sstevel@tonic-gate return;
20190Sstevel@tonic-gate }
20200Sstevel@tonic-gate
20210Sstevel@tonic-gate (void) strlcpy(q, str, len + 1);
20220Sstevel@tonic-gate (*msgp->message_routine)(msgp->appdata_ptr, q);
20230Sstevel@tonic-gate
20240Sstevel@tonic-gate free(q);
20250Sstevel@tonic-gate }
20260Sstevel@tonic-gate
20270Sstevel@tonic-gate
20280Sstevel@tonic-gate /*
20290Sstevel@tonic-gate * Function:
20300Sstevel@tonic-gate * cfga_help
20310Sstevel@tonic-gate * Input:
20320Sstevel@tonic-gate * msgp - Help message passed on to cfgadm(1M)
20330Sstevel@tonic-gate * options - Help message options passed on to cfgadm(1M)
20340Sstevel@tonic-gate * flags - Cfgadm(1m) flags
20350Sstevel@tonic-gate * Output:
20360Sstevel@tonic-gate * NONE
20370Sstevel@tonic-gate * Returns:
20380Sstevel@tonic-gate * Were we able to print cfgadm help or not for this plugin
20390Sstevel@tonic-gate * Description:
20400Sstevel@tonic-gate * Print cfgadm help for this plugin
20410Sstevel@tonic-gate */
20420Sstevel@tonic-gate /* ARGSUSED */
20430Sstevel@tonic-gate cfga_err_t
cfga_help(struct cfga_msg * msgp,const char * options,cfga_flags_t flags)20440Sstevel@tonic-gate cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
20450Sstevel@tonic-gate {
20460Sstevel@tonic-gate DPRINTF("cfga_help:\n");
20470Sstevel@tonic-gate
20480Sstevel@tonic-gate if (options) {
20490Sstevel@tonic-gate cfga_msg(msgp, dgettext(TEXT_DOMAIN, ib_help[
20500Sstevel@tonic-gate CFGA_IB_HELP_UNKNOWN]));
20510Sstevel@tonic-gate cfga_msg(msgp, options);
20520Sstevel@tonic-gate }
20530Sstevel@tonic-gate
20540Sstevel@tonic-gate /* Print messages array */
20550Sstevel@tonic-gate cfga_msg(msgp, dgettext(TEXT_DOMAIN, ib_help[CFGA_IB_HELP_HEADER]));
20560Sstevel@tonic-gate cfga_msg(msgp, ib_help[CFGA_IB_HELP_CONFIG]);
20570Sstevel@tonic-gate cfga_msg(msgp, ib_help[CFGA_IB_HELP_LIST]);
20580Sstevel@tonic-gate cfga_msg(msgp, ib_help[CFGA_IB_HELP_UPD_PKEY]);
20590Sstevel@tonic-gate cfga_msg(msgp, ib_help[CFGA_IB_HELP_CONF_FILE1]);
20600Sstevel@tonic-gate cfga_msg(msgp, ib_help[CFGA_IB_HELP_CONF_FILE2]);
20610Sstevel@tonic-gate cfga_msg(msgp, ib_help[CFGA_IB_HELP_UPD_IOC_CONF]);
20620Sstevel@tonic-gate cfga_msg(msgp, ib_help[CFGA_IB_HELP_UNCFG_CLNTS]);
20630Sstevel@tonic-gate
20640Sstevel@tonic-gate return (CFGA_OK);
20650Sstevel@tonic-gate }
20660Sstevel@tonic-gate
20670Sstevel@tonic-gate
20680Sstevel@tonic-gate /*
20690Sstevel@tonic-gate * Function:
20700Sstevel@tonic-gate * ib_confirm
20710Sstevel@tonic-gate * Input:
20720Sstevel@tonic-gate * confp - The "cfga" structure that confirms a cfgadm query
20730Sstevel@tonic-gate * msg - The message that needs confirmation
20740Sstevel@tonic-gate * Output:
20750Sstevel@tonic-gate * None
20760Sstevel@tonic-gate * Returns:
20770Sstevel@tonic-gate * If a user entered YES or NO
20780Sstevel@tonic-gate * Description:
20790Sstevel@tonic-gate * Queries a user if it is ok to proceed with an operation or not.
20800Sstevel@tonic-gate * Returns user's response.
20810Sstevel@tonic-gate */
20820Sstevel@tonic-gate static int
ib_confirm(struct cfga_confirm * confp,char * msg)20830Sstevel@tonic-gate ib_confirm(struct cfga_confirm *confp, char *msg)
20840Sstevel@tonic-gate {
20850Sstevel@tonic-gate int rval;
20860Sstevel@tonic-gate
20870Sstevel@tonic-gate /* check that "confirm" function exists */
20880Sstevel@tonic-gate if (confp == NULL || confp->confirm == NULL) {
20890Sstevel@tonic-gate return (0);
20900Sstevel@tonic-gate }
20910Sstevel@tonic-gate
20920Sstevel@tonic-gate /* Call cfgadm provided "confirm" function */
20930Sstevel@tonic-gate rval = (*confp->confirm)(confp->appdata_ptr, msg);
20940Sstevel@tonic-gate DPRINTF("ib_confirm: %d\n", rval);
20950Sstevel@tonic-gate
20960Sstevel@tonic-gate return (rval);
20970Sstevel@tonic-gate }
20980Sstevel@tonic-gate
20990Sstevel@tonic-gate
21000Sstevel@tonic-gate /*
21010Sstevel@tonic-gate * Function:
21020Sstevel@tonic-gate * ib_get_devicepath
21030Sstevel@tonic-gate * Input:
21040Sstevel@tonic-gate * ap_id - The dynamic attachment point of an IB device
21050Sstevel@tonic-gate * Output:
21060Sstevel@tonic-gate * None
21070Sstevel@tonic-gate * Returns:
21080Sstevel@tonic-gate * devpath if it exists; otherwise NULL
21090Sstevel@tonic-gate * Description:
21100Sstevel@tonic-gate * Returns the devicepath for a dynamic attachment point of an IB device
21110Sstevel@tonic-gate */
21120Sstevel@tonic-gate static char *
ib_get_devicepath(const char * ap_id)21130Sstevel@tonic-gate ib_get_devicepath(const char *ap_id)
21140Sstevel@tonic-gate {
21150Sstevel@tonic-gate char *devpath = NULL;
21160Sstevel@tonic-gate size_t size;
21170Sstevel@tonic-gate
21180Sstevel@tonic-gate /* Get device path sizes */
21190Sstevel@tonic-gate if (ib_do_control_ioctl((char *)ap_id, IBNEX_DEVICE_PATH_SZ,
21200Sstevel@tonic-gate IBNEX_GET_DEVICE_PATH, 0, (void **)&devpath, &size) == CFGA_IB_OK) {
21210Sstevel@tonic-gate DPRINTF("ib_get_devicepath: get device path ioctl ok\n");
21220Sstevel@tonic-gate return (devpath);
21230Sstevel@tonic-gate
21240Sstevel@tonic-gate } else {
21250Sstevel@tonic-gate DPRINTF("ib_get_devicepath: get device path ioctl failed\n");
21260Sstevel@tonic-gate return ((char *)NULL);
21270Sstevel@tonic-gate }
21280Sstevel@tonic-gate }
2129