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
ib_rcm_offline(const char * rsrc,char ** errstring,char * rsrc_fixed,cfga_flags_t flags)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
ib_rcm_online(const char * rsrc,char ** errstring,char * rsrc_fixed,cfga_flags_t flags)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
ib_rcm_remove(const char * rsrc,char ** errstring,char * rsrc_fixed,cfga_flags_t flags)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
ib_rcm_init(const char * rsrc,cfga_flags_t flags,char ** errstring,uint_t * rflags)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
ib_rcm_info_table(rcm_info_t * rinfo,char ** table)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