1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 30 #include "cfga_ib.h" 31 32 33 #define MAX_FORMAT 80 /* for info table */ 34 35 cfga_ib_ret_t ib_rcm_offline(const char *, char **, char *, 36 cfga_flags_t); 37 cfga_ib_ret_t ib_rcm_online(const char *, char **, char *, 38 cfga_flags_t); 39 cfga_ib_ret_t ib_rcm_remove(const char *, char **, char *, 40 cfga_flags_t); 41 static cfga_ib_ret_t ib_rcm_info_table(rcm_info_t *, char **); 42 static cfga_ib_ret_t ib_rcm_init(const char *, cfga_flags_t, char **, 43 uint_t *); 44 45 46 static rcm_handle_t *rcm_handle = NULL; 47 static mutex_t rcm_handle_lock = DEFAULTMUTEX; 48 49 50 /* 51 * Function: 52 * ib_rcm_offline 53 * Input: 54 * rsrc - Resource name (typically an ap_id) 55 * errstring - Error message filled in case of a failure 56 * rsrc_fixed - Pointer to fixed path 57 * flags - flags to RCM 58 * Output: 59 * NONE 60 * Returns: 61 * CFGA_IB_OK on success or an appropriate error 62 * Description: 63 * Offline IB resource consumers. 64 */ 65 cfga_ib_ret_t 66 ib_rcm_offline(const char *rsrc, char **errstring, char *rsrc_fixed, 67 cfga_flags_t flags) 68 { 69 int rret; 70 uint_t rflags = 0; 71 rcm_info_t *rinfo = NULL; 72 cfga_ib_ret_t ret = CFGA_IB_OK; 73 74 DPRINTF("ib_rcm_offline:\n"); 75 76 if ((ret = ib_rcm_init(rsrc, flags, errstring, &rflags)) != 77 CFGA_IB_OK) { 78 return (ret); 79 } 80 81 DPRINTF("ib_rcm_offline: rsrc_fixed: %s\n", rsrc_fixed); 82 83 if ((rret = rcm_request_offline(rcm_handle, rsrc_fixed, rflags, &rinfo)) 84 != RCM_SUCCESS) { 85 DPRINTF("ib_rcm_offline: rcm_request_offline failed\n"); 86 87 if (rinfo) { 88 (void) ib_rcm_info_table(rinfo, errstring); 89 rcm_free_info(rinfo); 90 rinfo = NULL; 91 } 92 93 DPRINTF("ib_rcm_offline: table = %s\n", *errstring); 94 95 if (rret == RCM_FAILURE) { 96 (void) ib_rcm_online(rsrc, errstring, 97 rsrc_fixed, flags); 98 } 99 ret = CFGA_IB_RCM_OFFLINE_ERR; 100 } 101 102 return (ret); 103 } 104 105 106 /* 107 * Function: 108 * ib_rcm_online 109 * Input: 110 * rsrc - Resource name (typically an ap_id) 111 * errstring - Error message filled in case of a failure 112 * rsrc_fixed - Pointer to fixed path 113 * flags - flags to RCM 114 * Output: 115 * NONE 116 * Returns: 117 * CFGA_IB_OK on success or an appropriate error 118 * Description: 119 * Online IB resource consumers that were previously offlined. 120 */ 121 cfga_ib_ret_t 122 ib_rcm_online(const char *rsrc, char **errstring, char *rsrc_fixed, 123 cfga_flags_t flags) 124 { 125 rcm_info_t *rinfo = NULL; 126 cfga_ib_ret_t ret = CFGA_IB_OK; 127 128 DPRINTF("ib_rcm_online:\n"); 129 130 if ((ret = ib_rcm_init(rsrc, flags, errstring, NULL)) != CFGA_IB_OK) { 131 return (ret); 132 } 133 134 if (rcm_notify_online(rcm_handle, rsrc_fixed, 0, &rinfo) != 135 RCM_SUCCESS && (rinfo != NULL)) { 136 DPRINTF("ib_rcm_online: rcm_notify_online failed\n"); 137 138 (void) ib_rcm_info_table(rinfo, errstring); 139 rcm_free_info(rinfo); 140 rinfo = NULL; 141 ret = CFGA_IB_RCM_ONLINE_ERR; 142 } 143 144 return (ret); 145 } 146 147 148 /* 149 * Function: 150 * ib_rcm_remove 151 * Input: 152 * rsrc - Resource name (typically an ap_id) 153 * errstring - Error message filled in case of a failure 154 * rsrc_fixed - Pointer to fixed path 155 * flags - flags to RCM 156 * Output: 157 * NONE 158 * Returns: 159 * CFGA_IB_OK on success or an appropriate error 160 * Description: 161 * Remove IB resource consumers after their kernel removal. 162 */ 163 cfga_ib_ret_t 164 ib_rcm_remove(const char *rsrc, char **errstring, char *rsrc_fixed, 165 cfga_flags_t flags) 166 { 167 rcm_info_t *rinfo = NULL; 168 cfga_ib_ret_t ret = CFGA_IB_OK; 169 170 DPRINTF("ib_rcm_remove:\n"); 171 172 if ((ret = ib_rcm_init(rsrc, flags, errstring, NULL)) != CFGA_IB_OK) { 173 return (ret); 174 } 175 176 if (rcm_notify_remove(rcm_handle, rsrc_fixed, 0, &rinfo) != 177 RCM_SUCCESS && (rinfo != NULL)) { 178 DPRINTF("ib_rcm_remove: rcm_notify_remove failed\n"); 179 180 (void) ib_rcm_info_table(rinfo, errstring); 181 rcm_free_info(rinfo); 182 rinfo = NULL; 183 ret = CFGA_IB_RCM_ONLINE_ERR; 184 } 185 186 return (ret); 187 } 188 189 190 /* 191 * Function: 192 * ib_rcm_init 193 * Input: 194 * rsrc - Resource name (typically an ap_id) 195 * flags - flags to RCM 196 * errstring - Error message filled in case of a failure 197 * rflags - Flags filled up in case of a failure 198 * Output: 199 * NONE 200 * Returns: 201 * CFGA_IB_OK on success or an appropriate error 202 * Description: 203 * Contains common initialization code for entering a ib_rcm_xx() routine. 204 */ 205 /* ARGSUSED */ 206 static cfga_ib_ret_t 207 ib_rcm_init(const char *rsrc, cfga_flags_t flags, char **errstring, 208 uint_t *rflags) 209 { 210 DPRINTF("ib_rcm_init:\n"); 211 212 /* Validate the rsrc argument */ 213 if (rsrc == NULL) { 214 DPRINTF("ib_rcm_init: rsrc is NULL\n"); 215 return (CFGA_IB_INTERNAL_ERR); 216 } 217 218 /* Translate the cfgadm flags to RCM flags */ 219 if (rflags && (flags & CFGA_FLAG_FORCE)) { 220 *rflags |= RCM_FORCE; 221 } 222 223 /* Get a handle for the RCM operations */ 224 (void) mutex_lock(&rcm_handle_lock); 225 if (rcm_handle == NULL) { 226 if (rcm_alloc_handle(NULL, RCM_NOPID, NULL, &rcm_handle) != 227 RCM_SUCCESS) { 228 DPRINTF("ib_rcm_init: alloc_handle failed\n"); 229 (void) mutex_unlock(&rcm_handle_lock); 230 return (CFGA_IB_RCM_HANDLE_ERR); 231 } 232 } 233 (void) mutex_unlock(&rcm_handle_lock); 234 return (CFGA_IB_OK); 235 } 236 237 238 /* 239 * Function: 240 * ib_rcm_info_table 241 * Input: 242 * rinfo - Resource information 243 * table - table to be printed 244 * Output: 245 * NONE 246 * Returns: 247 * CFGA_IB_OK on success or an appropriate error 248 * Description: 249 * Takes an opaque rcm_info_t pointer and a character pointer, 250 * and appends the rcm_info_t data in the form of a table to the 251 * given character pointer. 252 */ 253 static cfga_ib_ret_t 254 ib_rcm_info_table(rcm_info_t *rinfo, char **table) 255 { 256 int i; 257 size_t w; 258 size_t width = 0; 259 size_t w_rsrc = 0; 260 size_t w_info = 0; 261 size_t table_size = 0; 262 uint_t tuples = 0; 263 rcm_info_tuple_t *tuple = NULL; 264 char *rsrc; 265 char *info; 266 char *newtable; 267 static char format[MAX_FORMAT]; 268 const char *infostr; 269 270 DPRINTF("ib_rcm_info_table:\n"); 271 272 /* Protect against invalid arguments */ 273 if (rinfo == NULL || table == NULL) { 274 return (CFGA_IB_INTERNAL_ERR); 275 } 276 277 /* Set localized table header strings */ 278 rsrc = dgettext(TEXT_DOMAIN, "Resource"); 279 info = dgettext(TEXT_DOMAIN, "Information"); 280 281 /* A first pass, to size up the RCM information */ 282 while (tuple = rcm_info_next(rinfo, tuple)) { 283 if ((infostr = rcm_info_info(tuple)) != NULL) { 284 tuples++; 285 if ((w = strlen(rcm_info_rsrc(tuple))) > w_rsrc) 286 w_rsrc = w; 287 if ((w = strlen(infostr)) > w_info) 288 w_info = w; 289 } 290 } 291 292 /* If nothing was sized up above, stop early */ 293 if (tuples == 0) { 294 DPRINTF("ib_rcm_info_table: no tuples\n"); 295 return (CFGA_IB_OK); 296 } 297 298 /* Adjust column widths for column headings */ 299 if ((w = strlen(rsrc)) > w_rsrc) { 300 w_rsrc = w; 301 } else if ((w_rsrc - w) % 2) { 302 w_rsrc++; 303 } 304 305 if ((w = strlen(info)) > w_info) { 306 w_info = w; 307 } else if ((w_info - w) % 2) { 308 w_info++; 309 } 310 311 /* 312 * Compute the total line width of each line, 313 * accounting for intercolumn spacing. 314 */ 315 width = w_info + w_rsrc + 4; 316 317 /* Allocate space for the table */ 318 table_size = (2 + tuples) * (width + 1) + 2; 319 if (*table == NULL) { 320 *table = malloc(table_size); 321 } else { 322 newtable = realloc(*table, strlen(*table) + table_size); 323 if (newtable != NULL) 324 *table = newtable; 325 else { 326 free(*table); 327 *table = NULL; 328 return (CFGA_IB_ALLOC_FAIL); 329 } 330 } 331 332 if (*table == NULL) { 333 DPRINTF("ib_rcm_info_table: no table\n"); 334 return (CFGA_IB_ALLOC_FAIL); 335 } 336 337 /* Place a table header into the string */ 338 339 /* The resource header */ 340 (void) strlcat(*table, "\n", sizeof (*table)); 341 w = strlen(rsrc); 342 343 for (i = 0; i < ((w_rsrc - w) / 2); i++) { 344 (void) strcat(*table, " "); 345 } 346 (void) strlcat(*table, rsrc, sizeof (*table)); 347 348 for (i = 0; i < ((w_rsrc - w) / 2); i++) { 349 (void) strcat(*table, " "); 350 } 351 352 /* The information header */ 353 (void) strcat(*table, " "); 354 w = strlen(info); 355 for (i = 0; i < ((w_info - w) / 2); i++) { 356 (void) strcat(*table, " "); 357 } 358 (void) strlcat(*table, info, sizeof (*table)); 359 360 for (i = 0; i < ((w_info - w) / 2); i++) { 361 (void) strcat(*table, " "); 362 } 363 364 (void) strcat(*table, "\n"); 365 366 /* Underline the headers */ 367 for (i = 0; i < w_rsrc; i++) { 368 (void) strcat(*table, "-"); 369 } 370 371 (void) strcat(*table, " "); 372 for (i = 0; i < w_info; i++) { 373 (void) strcat(*table, "-"); 374 } 375 376 (void) strcat(*table, "\n"); 377 378 /* Construct the format string */ 379 (void) snprintf(format, MAX_FORMAT, "%%-%ds %%-%ds", 380 (int)w_rsrc, (int)w_info); 381 382 /* Add the tuples to the table string */ 383 tuple = NULL; 384 while ((tuple = rcm_info_next(rinfo, tuple)) != NULL) { 385 if ((infostr = rcm_info_info(tuple)) != NULL) { 386 (void) sprintf(&((*table)[strlen(*table)]), 387 format, rcm_info_rsrc(tuple), infostr); 388 (void) strcat(*table, "\n"); 389 } 390 } 391 392 return (CFGA_IB_OK); 393 } 394