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