xref: /onnv-gate/usr/src/lib/cfgadm_plugins/sata/common/cfga_rcm.c (revision 1258:9961d7d3ec8c)
1*1258Smlf /*
2*1258Smlf  * CDDL HEADER START
3*1258Smlf  *
4*1258Smlf  * The contents of this file are subject to the terms of the
5*1258Smlf  * Common Development and Distribution License (the "License").
6*1258Smlf  * You may not use this file except in compliance with the License.
7*1258Smlf  *
8*1258Smlf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1258Smlf  * or http://www.opensolaris.org/os/licensing.
10*1258Smlf  * See the License for the specific language governing permissions
11*1258Smlf  * and limitations under the License.
12*1258Smlf  *
13*1258Smlf  * When distributing Covered Code, include this CDDL HEADER in each
14*1258Smlf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1258Smlf  * If applicable, add the following below this CDDL HEADER, with the
16*1258Smlf  * fields enclosed by brackets "[]" replaced with your own identifying
17*1258Smlf  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1258Smlf  *
19*1258Smlf  * CDDL HEADER END
20*1258Smlf  */
21*1258Smlf 
22*1258Smlf /*
23*1258Smlf  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*1258Smlf  * Use is subject to license terms.
25*1258Smlf  */
26*1258Smlf 
27*1258Smlf #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*1258Smlf 
29*1258Smlf #include "cfga_sata.h"
30*1258Smlf 
31*1258Smlf 
32*1258Smlf 
33*1258Smlf #define	MAX_FORMAT	80	/* for info table */
34*1258Smlf 
35*1258Smlf cfga_sata_ret_t	sata_rcm_offline(const char *, char **, char *,
36*1258Smlf 				cfga_flags_t);
37*1258Smlf cfga_sata_ret_t	sata_rcm_online(const char *, char **, char *,
38*1258Smlf 				cfga_flags_t);
39*1258Smlf cfga_sata_ret_t	sata_rcm_remove(const char *, char **, char *,
40*1258Smlf 				cfga_flags_t);
41*1258Smlf static cfga_sata_ret_t	sata_rcm_info_table(rcm_info_t *, char **);
42*1258Smlf static cfga_sata_ret_t	sata_rcm_init(const char *, cfga_flags_t, char **,
43*1258Smlf 				uint_t *);
44*1258Smlf 
45*1258Smlf 
46*1258Smlf static rcm_handle_t *rcm_handle = NULL;
47*1258Smlf static mutex_t rcm_handle_lock = DEFAULTMUTEX;
48*1258Smlf 
49*1258Smlf /*
50*1258Smlf  * sata_rcm_offline:
51*1258Smlf  *      Offline SATA resource consumers.
52*1258Smlf  */
53*1258Smlf cfga_sata_ret_t
sata_rcm_offline(const char * rsrc,char ** errstring,char * rsrc_fixed,cfga_flags_t flags)54*1258Smlf sata_rcm_offline(const char *rsrc, char **errstring, char *rsrc_fixed,
55*1258Smlf 		cfga_flags_t flags)
56*1258Smlf {
57*1258Smlf 	int		rret;
58*1258Smlf 	uint_t		rflags = 0;
59*1258Smlf 	rcm_info_t	*rinfo = NULL;
60*1258Smlf 	cfga_sata_ret_t	ret = CFGA_SATA_OK;
61*1258Smlf 
62*1258Smlf 	if ((ret = sata_rcm_init(rsrc, flags, errstring, &rflags)) !=
63*1258Smlf 	    CFGA_SATA_OK) {
64*1258Smlf 
65*1258Smlf 		return (ret);
66*1258Smlf 	}
67*1258Smlf 
68*1258Smlf 	if ((rret = rcm_request_offline(rcm_handle, rsrc_fixed, rflags,
69*1258Smlf 	    &rinfo)) != RCM_SUCCESS) {
70*1258Smlf 		if (rinfo) {
71*1258Smlf 			(void) sata_rcm_info_table(rinfo, errstring);
72*1258Smlf 			rcm_free_info(rinfo);
73*1258Smlf 			rinfo = NULL;
74*1258Smlf 		}
75*1258Smlf 
76*1258Smlf 		if (rret == RCM_FAILURE) {
77*1258Smlf 			(void) sata_rcm_online(rsrc, errstring,
78*1258Smlf 					rsrc_fixed, flags);
79*1258Smlf 		}
80*1258Smlf 		ret = CFGA_SATA_RCM_OFFLINE;
81*1258Smlf 	}
82*1258Smlf 	return (ret);
83*1258Smlf }
84*1258Smlf 
85*1258Smlf 
86*1258Smlf /*
87*1258Smlf  * sata_rcm_online:
88*1258Smlf  *      Online SATA resource consumers that were previously offlined.
89*1258Smlf  */
90*1258Smlf cfga_sata_ret_t
sata_rcm_online(const char * rsrc,char ** errstring,char * rsrc_fixed,cfga_flags_t flags)91*1258Smlf sata_rcm_online(const char *rsrc, char **errstring, char *rsrc_fixed,
92*1258Smlf 		cfga_flags_t flags)
93*1258Smlf {
94*1258Smlf 	rcm_info_t	*rinfo = NULL;
95*1258Smlf 	cfga_sata_ret_t	ret = CFGA_SATA_OK;
96*1258Smlf 
97*1258Smlf 	if ((ret = sata_rcm_init(rsrc, flags, errstring, NULL)) !=
98*1258Smlf 	    CFGA_SATA_OK) {
99*1258Smlf 
100*1258Smlf 		return (ret);
101*1258Smlf 	}
102*1258Smlf 
103*1258Smlf 	if (rcm_notify_online(rcm_handle, rsrc_fixed, 0, &rinfo) !=
104*1258Smlf 	    RCM_SUCCESS && (rinfo != NULL)) {
105*1258Smlf 		(void) sata_rcm_info_table(rinfo, errstring);
106*1258Smlf 		rcm_free_info(rinfo);
107*1258Smlf 		rinfo = NULL;
108*1258Smlf 		ret = CFGA_SATA_RCM_ONLINE;
109*1258Smlf 	}
110*1258Smlf 
111*1258Smlf 	return (ret);
112*1258Smlf }
113*1258Smlf 
114*1258Smlf /*
115*1258Smlf  * sata_rcm_remove:
116*1258Smlf  *      Remove SATA resource consumers after their kernel removal.
117*1258Smlf  */
118*1258Smlf cfga_sata_ret_t
sata_rcm_remove(const char * rsrc,char ** errstring,char * rsrc_fixed,cfga_flags_t flags)119*1258Smlf sata_rcm_remove(const char *rsrc, char **errstring, char *rsrc_fixed,
120*1258Smlf 		cfga_flags_t flags)
121*1258Smlf {
122*1258Smlf 	rcm_info_t	*rinfo = NULL;
123*1258Smlf 	cfga_sata_ret_t	ret = CFGA_SATA_OK;
124*1258Smlf 
125*1258Smlf 	if ((ret = sata_rcm_init(rsrc, flags, errstring, NULL)) !=
126*1258Smlf 	    CFGA_SATA_OK) {
127*1258Smlf 
128*1258Smlf 		return (ret);
129*1258Smlf 	}
130*1258Smlf 
131*1258Smlf 	if (rcm_notify_remove(rcm_handle, rsrc_fixed, 0, &rinfo) !=
132*1258Smlf 	    RCM_SUCCESS && (rinfo != NULL)) {
133*1258Smlf 
134*1258Smlf 		(void) sata_rcm_info_table(rinfo, errstring);
135*1258Smlf 		rcm_free_info(rinfo);
136*1258Smlf 		rinfo = NULL;
137*1258Smlf 		ret = CFGA_SATA_RCM_ONLINE;
138*1258Smlf 	}
139*1258Smlf 
140*1258Smlf 	return (ret);
141*1258Smlf }
142*1258Smlf 
143*1258Smlf 
144*1258Smlf /*
145*1258Smlf  * sata_rcm_init:
146*1258Smlf  * Contains common initialization code for entering a sata_rcm_xx() routine.
147*1258Smlf  */
148*1258Smlf /* ARGSUSED */
149*1258Smlf static cfga_sata_ret_t
sata_rcm_init(const char * rsrc,cfga_flags_t flags,char ** errstring,uint_t * rflags)150*1258Smlf sata_rcm_init(const char *rsrc, cfga_flags_t flags, char **errstring,
151*1258Smlf 		uint_t *rflags)
152*1258Smlf {
153*1258Smlf 	/* Validate the rsrc argument */
154*1258Smlf 	if (rsrc == NULL) {
155*1258Smlf 		return (CFGA_SATA_INTERNAL_ERROR);
156*1258Smlf 	}
157*1258Smlf 
158*1258Smlf 	/* Translate the cfgadm flags to RCM flags */
159*1258Smlf 	if (rflags && (flags & CFGA_FLAG_FORCE)) {
160*1258Smlf 		*rflags |= RCM_FORCE;
161*1258Smlf 	}
162*1258Smlf 
163*1258Smlf 	/* Get a handle for the RCM operations */
164*1258Smlf 	(void) mutex_lock(&rcm_handle_lock);
165*1258Smlf 	if (rcm_handle == NULL) {
166*1258Smlf 		if (rcm_alloc_handle(NULL, RCM_NOPID, NULL, &rcm_handle) !=
167*1258Smlf 		    RCM_SUCCESS) {
168*1258Smlf 			(void) mutex_unlock(&rcm_handle_lock);
169*1258Smlf 
170*1258Smlf 			return (CFGA_SATA_RCM_HANDLE);
171*1258Smlf 		}
172*1258Smlf 	}
173*1258Smlf 	(void) mutex_unlock(&rcm_handle_lock);
174*1258Smlf 
175*1258Smlf 	return (CFGA_SATA_OK);
176*1258Smlf }
177*1258Smlf 
178*1258Smlf 
179*1258Smlf /*
180*1258Smlf  * sata_rcm_info_table:
181*1258Smlf  * Takes an opaque rcm_info_t pointer and a character pointer,
182*1258Smlf  * and appends the rcm_info_t data in the form of a table to the
183*1258Smlf  * given character pointer.
184*1258Smlf  */
185*1258Smlf static cfga_sata_ret_t
sata_rcm_info_table(rcm_info_t * rinfo,char ** table)186*1258Smlf sata_rcm_info_table(rcm_info_t *rinfo, char **table)
187*1258Smlf {
188*1258Smlf 	int i;
189*1258Smlf 	size_t w;
190*1258Smlf 	size_t width = 0;
191*1258Smlf 	size_t w_rsrc = 0;
192*1258Smlf 	size_t w_info = 0;
193*1258Smlf 	size_t table_size = 0;
194*1258Smlf 	uint_t tuples = 0;
195*1258Smlf 	rcm_info_tuple_t *tuple = NULL;
196*1258Smlf 	char *rsrc;
197*1258Smlf 	char *info;
198*1258Smlf 	char *newtable;
199*1258Smlf 	static char format[MAX_FORMAT];
200*1258Smlf 	const char *infostr;
201*1258Smlf 
202*1258Smlf 	/* Protect against invalid arguments */
203*1258Smlf 	if (rinfo == NULL || table == NULL) {
204*1258Smlf 		return (CFGA_SATA_INTERNAL_ERROR);
205*1258Smlf 	}
206*1258Smlf 
207*1258Smlf 	/* Set localized table header strings */
208*1258Smlf 	rsrc = dgettext(TEXT_DOMAIN, "Resource");
209*1258Smlf 	info = dgettext(TEXT_DOMAIN, "Information");
210*1258Smlf 
211*1258Smlf 
212*1258Smlf 	/* A first pass, to size up the RCM information */
213*1258Smlf 	while (tuple = rcm_info_next(rinfo, tuple)) {
214*1258Smlf 		if ((infostr = rcm_info_info(tuple)) != NULL) {
215*1258Smlf 			tuples++;
216*1258Smlf 			if ((w = strlen(rcm_info_rsrc(tuple))) > w_rsrc)
217*1258Smlf 				w_rsrc = w;
218*1258Smlf 			if ((w = strlen(infostr)) > w_info)
219*1258Smlf 				w_info = w;
220*1258Smlf 		}
221*1258Smlf 	}
222*1258Smlf 
223*1258Smlf 	/* If nothing was sized up above, stop early */
224*1258Smlf 	if (tuples == 0) {
225*1258Smlf 		return (CFGA_SATA_OK);
226*1258Smlf 	}
227*1258Smlf 
228*1258Smlf 	/* Adjust column widths for column headings */
229*1258Smlf 	if ((w = strlen(rsrc)) > w_rsrc) {
230*1258Smlf 		w_rsrc = w;
231*1258Smlf 	} else if ((w_rsrc - w) % 2) {
232*1258Smlf 		w_rsrc++;
233*1258Smlf 	}
234*1258Smlf 
235*1258Smlf 	if ((w = strlen(info)) > w_info) {
236*1258Smlf 		w_info = w;
237*1258Smlf 	} else if ((w_info - w) % 2) {
238*1258Smlf 		w_info++;
239*1258Smlf 	}
240*1258Smlf 
241*1258Smlf 
242*1258Smlf 	/*
243*1258Smlf 	 * Compute the total line width of each line,
244*1258Smlf 	 * accounting for intercolumn spacing.
245*1258Smlf 	 */
246*1258Smlf 	width = w_info + w_rsrc + 4;
247*1258Smlf 
248*1258Smlf 	/* Allocate space for the table */
249*1258Smlf 	table_size = (2 + tuples) * (width + 1) + 2;
250*1258Smlf 	if (*table == NULL) {
251*1258Smlf 		/* zero fill for the strcat() call below */
252*1258Smlf 		*table = calloc(table_size, sizeof (char));
253*1258Smlf 		if (*table == NULL) {
254*1258Smlf 			return (CFGA_SATA_ALLOC_FAIL);
255*1258Smlf 		}
256*1258Smlf 	} else {
257*1258Smlf 		newtable = realloc(*table, strlen(*table) + table_size);
258*1258Smlf 		if (newtable == NULL) {
259*1258Smlf 			return (CFGA_SATA_ALLOC_FAIL);
260*1258Smlf 		} else {
261*1258Smlf 			*table = newtable;
262*1258Smlf 		}
263*1258Smlf 	}
264*1258Smlf 
265*1258Smlf 	/* Place a table header into the string */
266*1258Smlf 
267*1258Smlf 
268*1258Smlf 	/* The resource header */
269*1258Smlf 	(void) strcat(*table, "\n");
270*1258Smlf 	w = strlen(rsrc);
271*1258Smlf 
272*1258Smlf 	for (i = 0; i < ((w_rsrc - w) / 2); i++) {
273*1258Smlf 		(void) strcat(*table, " ");
274*1258Smlf 	}
275*1258Smlf 	(void) strcat(*table, rsrc);
276*1258Smlf 
277*1258Smlf 	for (i = 0; i < ((w_rsrc - w) / 2); i++) {
278*1258Smlf 		(void) strcat(*table, " ");
279*1258Smlf 	}
280*1258Smlf 
281*1258Smlf 	/* The information header */
282*1258Smlf 	(void) strcat(*table, "  ");
283*1258Smlf 	w = strlen(info);
284*1258Smlf 	for (i = 0; i < ((w_info - w) / 2); i++) {
285*1258Smlf 		(void) strcat(*table, " ");
286*1258Smlf 	}
287*1258Smlf 	(void) strcat(*table, info);
288*1258Smlf 
289*1258Smlf 	for (i = 0; i < ((w_info - w) / 2); i++) {
290*1258Smlf 		(void) strcat(*table, " ");
291*1258Smlf 	}
292*1258Smlf 
293*1258Smlf 	(void) strcat(*table, "\n");
294*1258Smlf 
295*1258Smlf 	/* Underline the headers */
296*1258Smlf 	for (i = 0; i < w_rsrc; i++) {
297*1258Smlf 		(void) strcat(*table, "-");
298*1258Smlf 	}
299*1258Smlf 
300*1258Smlf 	(void) strcat(*table, "  ");
301*1258Smlf 	for (i = 0; i < w_info; i++) {
302*1258Smlf 		(void) strcat(*table, "-");
303*1258Smlf 	}
304*1258Smlf 
305*1258Smlf 
306*1258Smlf 	(void) strcat(*table, "\n");
307*1258Smlf 
308*1258Smlf 	/* Construct the format string */
309*1258Smlf 	(void) snprintf(format, MAX_FORMAT, "%%-%ds  %%-%ds",
310*1258Smlf 			(int)w_rsrc, (int)w_info);
311*1258Smlf 
312*1258Smlf 	/* Add the tuples to the table string */
313*1258Smlf 	tuple = NULL;
314*1258Smlf 	while ((tuple = rcm_info_next(rinfo, tuple)) != NULL) {
315*1258Smlf 		if ((infostr = rcm_info_info(tuple)) != NULL) {
316*1258Smlf 			(void) sprintf(&((*table)[strlen(*table)]),
317*1258Smlf 					format, rcm_info_rsrc(tuple), infostr);
318*1258Smlf 			(void) strcat(*table, "\n");
319*1258Smlf 		}
320*1258Smlf 	}
321*1258Smlf 
322*1258Smlf 	return (CFGA_SATA_OK);
323*1258Smlf }
324