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