1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte * CDDL HEADER START
3*fcf3ce44SJohn Forte *
4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte *
8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte * and limitations under the License.
12*fcf3ce44SJohn Forte *
13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte *
19*fcf3ce44SJohn Forte * CDDL HEADER END
20*fcf3ce44SJohn Forte */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23*fcf3ce44SJohn Forte * Use is subject to license terms.
24*fcf3ce44SJohn Forte */
25*fcf3ce44SJohn Forte
26*fcf3ce44SJohn Forte
27*fcf3ce44SJohn Forte #include "cfga_fp.h"
28*fcf3ce44SJohn Forte
29*fcf3ce44SJohn Forte static fpcfga_ret_t fp_rcm_init(char *, cfga_flags_t, char **, uint_t *,
30*fcf3ce44SJohn Forte char **rsrc_fixed);
31*fcf3ce44SJohn Forte static int fp_rcm_process_node(di_node_t, void *);
32*fcf3ce44SJohn Forte static fpcfga_ret_t fp_rcm_info_table(rcm_info_t *, char **);
33*fcf3ce44SJohn Forte static char *chop_minor(char *);
34*fcf3ce44SJohn Forte
35*fcf3ce44SJohn Forte #define MAX_FORMAT 80
36*fcf3ce44SJohn Forte #define DEVICES "/devices"
37*fcf3ce44SJohn Forte
38*fcf3ce44SJohn Forte typedef struct {
39*fcf3ce44SJohn Forte char *bus_path;
40*fcf3ce44SJohn Forte char *filter;
41*fcf3ce44SJohn Forte char **errstring;
42*fcf3ce44SJohn Forte fpcfga_ret_t ret;
43*fcf3ce44SJohn Forte cfga_flags_t flags;
44*fcf3ce44SJohn Forte fpcfga_ret_t (*func)(char *, char *, char **, cfga_flags_t);
45*fcf3ce44SJohn Forte } walkargs_t;
46*fcf3ce44SJohn Forte
47*fcf3ce44SJohn Forte static fpcfga_ret_t fp_rcm_info_table(rcm_info_t *, char **);
48*fcf3ce44SJohn Forte static int fp_rcm_process_node(di_node_t, void *);
49*fcf3ce44SJohn Forte static fpcfga_ret_t fp_rcm_init(char *, cfga_flags_t, char **, uint_t *,
50*fcf3ce44SJohn Forte char **);
51*fcf3ce44SJohn Forte static char *chop_minor(char *);
52*fcf3ce44SJohn Forte
53*fcf3ce44SJohn Forte static rcm_handle_t *rcm_handle = NULL;
54*fcf3ce44SJohn Forte static mutex_t rcm_handle_lock;
55*fcf3ce44SJohn Forte
56*fcf3ce44SJohn Forte /*
57*fcf3ce44SJohn Forte * fp_rcm_offline()
58*fcf3ce44SJohn Forte *
59*fcf3ce44SJohn Forte * Offline FP resource consumers.
60*fcf3ce44SJohn Forte */
61*fcf3ce44SJohn Forte fpcfga_ret_t
fp_rcm_offline(char * rsrc,char ** errstring,cfga_flags_t flags)62*fcf3ce44SJohn Forte fp_rcm_offline(char *rsrc, char **errstring, cfga_flags_t flags)
63*fcf3ce44SJohn Forte {
64*fcf3ce44SJohn Forte int rret;
65*fcf3ce44SJohn Forte uint_t rflags = 0;
66*fcf3ce44SJohn Forte char *rsrc_fixed;
67*fcf3ce44SJohn Forte rcm_info_t *rinfo = NULL;
68*fcf3ce44SJohn Forte fpcfga_ret_t ret = FPCFGA_OK;
69*fcf3ce44SJohn Forte
70*fcf3ce44SJohn Forte if ((ret = fp_rcm_init(rsrc, flags, errstring, &rflags, &rsrc_fixed))
71*fcf3ce44SJohn Forte != FPCFGA_OK)
72*fcf3ce44SJohn Forte return (ret);
73*fcf3ce44SJohn Forte
74*fcf3ce44SJohn Forte if ((rret = rcm_request_offline(rcm_handle, rsrc_fixed, rflags, &rinfo))
75*fcf3ce44SJohn Forte != RCM_SUCCESS) {
76*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_RCM_OFFLINE, rsrc_fixed, 0);
77*fcf3ce44SJohn Forte if (rinfo) {
78*fcf3ce44SJohn Forte (void) fp_rcm_info_table(rinfo, errstring);
79*fcf3ce44SJohn Forte rcm_free_info(rinfo);
80*fcf3ce44SJohn Forte }
81*fcf3ce44SJohn Forte if (rret == RCM_FAILURE)
82*fcf3ce44SJohn Forte (void) fp_rcm_online(rsrc, errstring, flags);
83*fcf3ce44SJohn Forte ret = FPCFGA_BUSY;
84*fcf3ce44SJohn Forte }
85*fcf3ce44SJohn Forte
86*fcf3ce44SJohn Forte S_FREE(rsrc_fixed);
87*fcf3ce44SJohn Forte
88*fcf3ce44SJohn Forte return (ret);
89*fcf3ce44SJohn Forte }
90*fcf3ce44SJohn Forte
91*fcf3ce44SJohn Forte /*
92*fcf3ce44SJohn Forte * fp_rcm_online()
93*fcf3ce44SJohn Forte *
94*fcf3ce44SJohn Forte * Online FP resource consumers that were previously offlined.
95*fcf3ce44SJohn Forte */
96*fcf3ce44SJohn Forte fpcfga_ret_t
fp_rcm_online(char * rsrc,char ** errstring,cfga_flags_t flags)97*fcf3ce44SJohn Forte fp_rcm_online(char *rsrc, char **errstring, cfga_flags_t flags)
98*fcf3ce44SJohn Forte {
99*fcf3ce44SJohn Forte char *rsrc_fixed;
100*fcf3ce44SJohn Forte rcm_info_t *rinfo = NULL;
101*fcf3ce44SJohn Forte fpcfga_ret_t ret = FPCFGA_OK;
102*fcf3ce44SJohn Forte
103*fcf3ce44SJohn Forte if ((ret = fp_rcm_init(rsrc, flags, errstring, NULL, &rsrc_fixed))
104*fcf3ce44SJohn Forte != FPCFGA_OK)
105*fcf3ce44SJohn Forte return (ret);
106*fcf3ce44SJohn Forte
107*fcf3ce44SJohn Forte if (rcm_notify_online(rcm_handle, rsrc_fixed, 0, &rinfo)
108*fcf3ce44SJohn Forte != RCM_SUCCESS && rinfo != NULL) {
109*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_RCM_ONLINE, rsrc_fixed, 0);
110*fcf3ce44SJohn Forte (void) fp_rcm_info_table(rinfo, errstring);
111*fcf3ce44SJohn Forte rcm_free_info(rinfo);
112*fcf3ce44SJohn Forte ret = FPCFGA_ERR;
113*fcf3ce44SJohn Forte }
114*fcf3ce44SJohn Forte
115*fcf3ce44SJohn Forte S_FREE(rsrc_fixed);
116*fcf3ce44SJohn Forte
117*fcf3ce44SJohn Forte return (ret);
118*fcf3ce44SJohn Forte }
119*fcf3ce44SJohn Forte
120*fcf3ce44SJohn Forte /*
121*fcf3ce44SJohn Forte * fp_rcm_remove()
122*fcf3ce44SJohn Forte *
123*fcf3ce44SJohn Forte * Remove FP resource consumers after their kernel removal.
124*fcf3ce44SJohn Forte */
125*fcf3ce44SJohn Forte fpcfga_ret_t
fp_rcm_remove(char * rsrc,char ** errstring,cfga_flags_t flags)126*fcf3ce44SJohn Forte fp_rcm_remove(char *rsrc, char **errstring, cfga_flags_t flags)
127*fcf3ce44SJohn Forte {
128*fcf3ce44SJohn Forte char *rsrc_fixed;
129*fcf3ce44SJohn Forte rcm_info_t *rinfo = NULL;
130*fcf3ce44SJohn Forte fpcfga_ret_t ret = FPCFGA_OK;
131*fcf3ce44SJohn Forte
132*fcf3ce44SJohn Forte if ((ret = fp_rcm_init(rsrc, flags, errstring, NULL, &rsrc_fixed))
133*fcf3ce44SJohn Forte != FPCFGA_OK)
134*fcf3ce44SJohn Forte return (ret);
135*fcf3ce44SJohn Forte
136*fcf3ce44SJohn Forte if (rcm_notify_remove(rcm_handle, rsrc_fixed, 0, &rinfo)
137*fcf3ce44SJohn Forte != RCM_SUCCESS) {
138*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_RCM_REMOVE, rsrc_fixed, 0);
139*fcf3ce44SJohn Forte if (rinfo) {
140*fcf3ce44SJohn Forte (void) fp_rcm_info_table(rinfo, errstring);
141*fcf3ce44SJohn Forte rcm_free_info(rinfo);
142*fcf3ce44SJohn Forte }
143*fcf3ce44SJohn Forte ret = FPCFGA_ERR;
144*fcf3ce44SJohn Forte }
145*fcf3ce44SJohn Forte
146*fcf3ce44SJohn Forte S_FREE(rsrc_fixed);
147*fcf3ce44SJohn Forte
148*fcf3ce44SJohn Forte return (ret);
149*fcf3ce44SJohn Forte }
150*fcf3ce44SJohn Forte
151*fcf3ce44SJohn Forte /*
152*fcf3ce44SJohn Forte * fp_rcm_suspend()
153*fcf3ce44SJohn Forte *
154*fcf3ce44SJohn Forte * Suspend FP resource consumers before a bus quiesce.
155*fcf3ce44SJohn Forte */
156*fcf3ce44SJohn Forte fpcfga_ret_t
fp_rcm_suspend(char * rsrc,char * filter,char ** errstring,cfga_flags_t flags)157*fcf3ce44SJohn Forte fp_rcm_suspend(char *rsrc, char *filter, char **errstring, cfga_flags_t flags)
158*fcf3ce44SJohn Forte {
159*fcf3ce44SJohn Forte int rret;
160*fcf3ce44SJohn Forte uint_t rflags = 0;
161*fcf3ce44SJohn Forte char *rsrc_fixed;
162*fcf3ce44SJohn Forte char *filter_fixed;
163*fcf3ce44SJohn Forte char *rsrc_devpath;
164*fcf3ce44SJohn Forte rcm_info_t *rinfo = NULL;
165*fcf3ce44SJohn Forte di_node_t node;
166*fcf3ce44SJohn Forte fpcfga_ret_t ret = FPCFGA_OK;
167*fcf3ce44SJohn Forte walkargs_t walkargs;
168*fcf3ce44SJohn Forte timespec_t zerotime = { 0, 0 };
169*fcf3ce44SJohn Forte
170*fcf3ce44SJohn Forte if ((ret = fp_rcm_init(rsrc, flags, errstring, &rflags, &rsrc_fixed))
171*fcf3ce44SJohn Forte != FPCFGA_OK)
172*fcf3ce44SJohn Forte return (ret);
173*fcf3ce44SJohn Forte
174*fcf3ce44SJohn Forte /* If a filter is provided, ensure that it makes sense */
175*fcf3ce44SJohn Forte if (filter != NULL && strstr(filter, rsrc) != filter) {
176*fcf3ce44SJohn Forte S_FREE(rsrc_fixed);
177*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERR_APID_INVAL, 0);
178*fcf3ce44SJohn Forte return (FPCFGA_ERR);
179*fcf3ce44SJohn Forte }
180*fcf3ce44SJohn Forte
181*fcf3ce44SJohn Forte /*
182*fcf3ce44SJohn Forte * If no filter is specified: attempt a suspension on the resource,
183*fcf3ce44SJohn Forte * directly.
184*fcf3ce44SJohn Forte */
185*fcf3ce44SJohn Forte if (filter == NULL) {
186*fcf3ce44SJohn Forte if ((rret = rcm_request_suspend(rcm_handle, rsrc_fixed, rflags,
187*fcf3ce44SJohn Forte &zerotime, &rinfo)) != RCM_SUCCESS) {
188*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_RCM_SUSPEND, rsrc_fixed,
189*fcf3ce44SJohn Forte 0);
190*fcf3ce44SJohn Forte if (rinfo) {
191*fcf3ce44SJohn Forte (void) fp_rcm_info_table(rinfo, errstring);
192*fcf3ce44SJohn Forte rcm_free_info(rinfo);
193*fcf3ce44SJohn Forte }
194*fcf3ce44SJohn Forte if (rret == RCM_FAILURE)
195*fcf3ce44SJohn Forte (void) fp_rcm_resume(rsrc, filter, errstring,
196*fcf3ce44SJohn Forte (flags & (~CFGA_FLAG_FORCE)));
197*fcf3ce44SJohn Forte ret = FPCFGA_BUSY;
198*fcf3ce44SJohn Forte }
199*fcf3ce44SJohn Forte S_FREE(rsrc_fixed);
200*fcf3ce44SJohn Forte return (ret);
201*fcf3ce44SJohn Forte }
202*fcf3ce44SJohn Forte
203*fcf3ce44SJohn Forte /*
204*fcf3ce44SJohn Forte * If a filter is specified: open the resource with libdevinfo, walk
205*fcf3ce44SJohn Forte * through its nodes, and attempt a suspension of each node that
206*fcf3ce44SJohn Forte * mismatches the filter.
207*fcf3ce44SJohn Forte */
208*fcf3ce44SJohn Forte
209*fcf3ce44SJohn Forte /* Chop off the filter's minor name */
210*fcf3ce44SJohn Forte if ((filter_fixed = chop_minor(filter)) == NULL)
211*fcf3ce44SJohn Forte return (FPCFGA_ERR);
212*fcf3ce44SJohn Forte
213*fcf3ce44SJohn Forte /* get a libdevinfo snapshot of the resource's subtree */
214*fcf3ce44SJohn Forte rsrc_devpath = rsrc_fixed;
215*fcf3ce44SJohn Forte if (strstr(rsrc_fixed, DEVICES) != NULL)
216*fcf3ce44SJohn Forte rsrc_devpath += strlen(DEVICES);
217*fcf3ce44SJohn Forte node = di_init(rsrc_devpath, DINFOSUBTREE | DINFOMINOR);
218*fcf3ce44SJohn Forte if (node == DI_NODE_NIL) {
219*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_DEVINFO, rsrc_fixed, 0);
220*fcf3ce44SJohn Forte ret = FPCFGA_ERR;
221*fcf3ce44SJohn Forte }
222*fcf3ce44SJohn Forte
223*fcf3ce44SJohn Forte /* apply the filter, and suspend all resources not filtered out */
224*fcf3ce44SJohn Forte if (ret == FPCFGA_OK) {
225*fcf3ce44SJohn Forte
226*fcf3ce44SJohn Forte walkargs.bus_path = rsrc_fixed;
227*fcf3ce44SJohn Forte walkargs.filter = filter_fixed;
228*fcf3ce44SJohn Forte walkargs.errstring = errstring;
229*fcf3ce44SJohn Forte walkargs.ret = FPCFGA_OK;
230*fcf3ce44SJohn Forte walkargs.flags = rflags;
231*fcf3ce44SJohn Forte walkargs.func = fp_rcm_suspend;
232*fcf3ce44SJohn Forte
233*fcf3ce44SJohn Forte if (di_walk_node(node, 0, &walkargs, fp_rcm_process_node) < 0)
234*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_DEVINFO, rsrc_fixed, 0);
235*fcf3ce44SJohn Forte
236*fcf3ce44SJohn Forte ret = walkargs.ret;
237*fcf3ce44SJohn Forte }
238*fcf3ce44SJohn Forte
239*fcf3ce44SJohn Forte if (node != DI_NODE_NIL)
240*fcf3ce44SJohn Forte di_fini(node);
241*fcf3ce44SJohn Forte
242*fcf3ce44SJohn Forte S_FREE(rsrc_fixed);
243*fcf3ce44SJohn Forte S_FREE(filter_fixed);
244*fcf3ce44SJohn Forte
245*fcf3ce44SJohn Forte if (ret != FPCFGA_OK)
246*fcf3ce44SJohn Forte (void) fp_rcm_resume(rsrc, filter, errstring,
247*fcf3ce44SJohn Forte (flags & (~CFGA_FLAG_FORCE)));
248*fcf3ce44SJohn Forte
249*fcf3ce44SJohn Forte return (ret);
250*fcf3ce44SJohn Forte }
251*fcf3ce44SJohn Forte
252*fcf3ce44SJohn Forte /*
253*fcf3ce44SJohn Forte * fp_rcm_resume()
254*fcf3ce44SJohn Forte *
255*fcf3ce44SJohn Forte * Resume FP resource consumers after a bus has been unquiesced.
256*fcf3ce44SJohn Forte */
257*fcf3ce44SJohn Forte fpcfga_ret_t
fp_rcm_resume(char * rsrc,char * filter,char ** errstring,cfga_flags_t flags)258*fcf3ce44SJohn Forte fp_rcm_resume(char *rsrc, char *filter, char **errstring, cfga_flags_t flags)
259*fcf3ce44SJohn Forte {
260*fcf3ce44SJohn Forte uint_t rflags = 0;
261*fcf3ce44SJohn Forte char *rsrc_fixed;
262*fcf3ce44SJohn Forte char *filter_fixed;
263*fcf3ce44SJohn Forte char *rsrc_devpath;
264*fcf3ce44SJohn Forte rcm_info_t *rinfo = NULL;
265*fcf3ce44SJohn Forte di_node_t node;
266*fcf3ce44SJohn Forte fpcfga_ret_t ret = FPCFGA_OK;
267*fcf3ce44SJohn Forte walkargs_t walkargs;
268*fcf3ce44SJohn Forte
269*fcf3ce44SJohn Forte if ((ret = fp_rcm_init(rsrc, flags, errstring, &rflags, &rsrc_fixed))
270*fcf3ce44SJohn Forte != FPCFGA_OK)
271*fcf3ce44SJohn Forte return (ret);
272*fcf3ce44SJohn Forte
273*fcf3ce44SJohn Forte /* If a filter is provided, ensure that it makes sense */
274*fcf3ce44SJohn Forte if (filter != NULL && strstr(filter, rsrc) != filter) {
275*fcf3ce44SJohn Forte S_FREE(rsrc_fixed);
276*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERR_APID_INVAL, 0);
277*fcf3ce44SJohn Forte return (FPCFGA_ERR);
278*fcf3ce44SJohn Forte }
279*fcf3ce44SJohn Forte
280*fcf3ce44SJohn Forte /*
281*fcf3ce44SJohn Forte * If no filter is specified: resume the resource directly.
282*fcf3ce44SJohn Forte */
283*fcf3ce44SJohn Forte if (filter == NULL) {
284*fcf3ce44SJohn Forte if (rcm_notify_resume(rcm_handle, rsrc_fixed, rflags, &rinfo)
285*fcf3ce44SJohn Forte != RCM_SUCCESS && rinfo != NULL) {
286*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_RCM_RESUME, rsrc_fixed,
287*fcf3ce44SJohn Forte 0);
288*fcf3ce44SJohn Forte (void) fp_rcm_info_table(rinfo, errstring);
289*fcf3ce44SJohn Forte rcm_free_info(rinfo);
290*fcf3ce44SJohn Forte ret = FPCFGA_BUSY;
291*fcf3ce44SJohn Forte }
292*fcf3ce44SJohn Forte S_FREE(rsrc_fixed);
293*fcf3ce44SJohn Forte return (ret);
294*fcf3ce44SJohn Forte }
295*fcf3ce44SJohn Forte
296*fcf3ce44SJohn Forte /*
297*fcf3ce44SJohn Forte * If a filter is specified: open the resource with libdevinfo, walk
298*fcf3ce44SJohn Forte * through its nodes, and resume each of its nodes that mismatches
299*fcf3ce44SJohn Forte * the filter.
300*fcf3ce44SJohn Forte */
301*fcf3ce44SJohn Forte
302*fcf3ce44SJohn Forte /* Chop off the filter's minor name */
303*fcf3ce44SJohn Forte if ((filter_fixed = chop_minor(filter)) == NULL)
304*fcf3ce44SJohn Forte return (FPCFGA_ERR);
305*fcf3ce44SJohn Forte
306*fcf3ce44SJohn Forte /* get a libdevinfo snapshot of the resource's subtree */
307*fcf3ce44SJohn Forte rsrc_devpath = rsrc_fixed;
308*fcf3ce44SJohn Forte if (strstr(rsrc_fixed, DEVICES) != NULL)
309*fcf3ce44SJohn Forte rsrc_devpath += strlen(DEVICES);
310*fcf3ce44SJohn Forte node = di_init(rsrc_devpath, DINFOSUBTREE | DINFOMINOR);
311*fcf3ce44SJohn Forte if (node == DI_NODE_NIL) {
312*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_DEVINFO, rsrc_fixed, 0);
313*fcf3ce44SJohn Forte ret = FPCFGA_ERR;
314*fcf3ce44SJohn Forte }
315*fcf3ce44SJohn Forte
316*fcf3ce44SJohn Forte /* apply the filter, and resume all resources not filtered out */
317*fcf3ce44SJohn Forte if (ret == FPCFGA_OK) {
318*fcf3ce44SJohn Forte
319*fcf3ce44SJohn Forte walkargs.bus_path = rsrc_fixed;
320*fcf3ce44SJohn Forte walkargs.filter = filter_fixed;
321*fcf3ce44SJohn Forte walkargs.errstring = errstring;
322*fcf3ce44SJohn Forte walkargs.ret = FPCFGA_OK;
323*fcf3ce44SJohn Forte walkargs.flags = rflags;
324*fcf3ce44SJohn Forte walkargs.func = fp_rcm_resume;
325*fcf3ce44SJohn Forte
326*fcf3ce44SJohn Forte if (di_walk_node(node, 0, &walkargs, fp_rcm_process_node) < 0)
327*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_DEVINFO, rsrc_fixed, 0);
328*fcf3ce44SJohn Forte
329*fcf3ce44SJohn Forte ret = walkargs.ret;
330*fcf3ce44SJohn Forte }
331*fcf3ce44SJohn Forte
332*fcf3ce44SJohn Forte if (node != DI_NODE_NIL)
333*fcf3ce44SJohn Forte di_fini(node);
334*fcf3ce44SJohn Forte
335*fcf3ce44SJohn Forte S_FREE(rsrc_fixed);
336*fcf3ce44SJohn Forte S_FREE(filter_fixed);
337*fcf3ce44SJohn Forte
338*fcf3ce44SJohn Forte return (ret);
339*fcf3ce44SJohn Forte }
340*fcf3ce44SJohn Forte
341*fcf3ce44SJohn Forte /*
342*fcf3ce44SJohn Forte * fp_rcm_info
343*fcf3ce44SJohn Forte *
344*fcf3ce44SJohn Forte * Queries RCM information for resources, and formats it into a table.
345*fcf3ce44SJohn Forte * The table is appended to the info argument. If the info argument is a
346*fcf3ce44SJohn Forte * null pointer, then a new string is malloc'ed. If the info argument is
347*fcf3ce44SJohn Forte * not a null pointer, then it is realloc'ed to the required size.
348*fcf3ce44SJohn Forte */
349*fcf3ce44SJohn Forte fpcfga_ret_t
fp_rcm_info(char * rsrc,char ** errstring,char ** info)350*fcf3ce44SJohn Forte fp_rcm_info(char *rsrc, char **errstring, char **info)
351*fcf3ce44SJohn Forte {
352*fcf3ce44SJohn Forte char *rsrc_fixed;
353*fcf3ce44SJohn Forte rcm_info_t *rinfo = NULL;
354*fcf3ce44SJohn Forte fpcfga_ret_t ret = FPCFGA_OK;
355*fcf3ce44SJohn Forte
356*fcf3ce44SJohn Forte if ((ret = fp_rcm_init(rsrc, 0, errstring, NULL, &rsrc_fixed))
357*fcf3ce44SJohn Forte != FPCFGA_OK)
358*fcf3ce44SJohn Forte return (ret);
359*fcf3ce44SJohn Forte
360*fcf3ce44SJohn Forte if (info == NULL) {
361*fcf3ce44SJohn Forte S_FREE(rsrc_fixed);
362*fcf3ce44SJohn Forte return (FPCFGA_ERR);
363*fcf3ce44SJohn Forte }
364*fcf3ce44SJohn Forte
365*fcf3ce44SJohn Forte if (rcm_get_info(rcm_handle, rsrc_fixed, 0, &rinfo)
366*fcf3ce44SJohn Forte != RCM_SUCCESS) {
367*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_RCM_INFO, rsrc_fixed, 0);
368*fcf3ce44SJohn Forte ret = FPCFGA_ERR;
369*fcf3ce44SJohn Forte } else if (rinfo == NULL)
370*fcf3ce44SJohn Forte ret = FPCFGA_OK;
371*fcf3ce44SJohn Forte
372*fcf3ce44SJohn Forte if (rinfo) {
373*fcf3ce44SJohn Forte if ((ret = fp_rcm_info_table(rinfo, info)) != FPCFGA_OK)
374*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERRARG_RCM_INFO, rsrc_fixed, 0);
375*fcf3ce44SJohn Forte rcm_free_info(rinfo);
376*fcf3ce44SJohn Forte }
377*fcf3ce44SJohn Forte
378*fcf3ce44SJohn Forte S_FREE(rsrc_fixed);
379*fcf3ce44SJohn Forte
380*fcf3ce44SJohn Forte return (ret);
381*fcf3ce44SJohn Forte }
382*fcf3ce44SJohn Forte
383*fcf3ce44SJohn Forte /*
384*fcf3ce44SJohn Forte * fp_rcm_init()
385*fcf3ce44SJohn Forte *
386*fcf3ce44SJohn Forte * Contains common initialization code for entering a fp_rcm_xx()
387*fcf3ce44SJohn Forte * routine.
388*fcf3ce44SJohn Forte */
389*fcf3ce44SJohn Forte static fpcfga_ret_t
fp_rcm_init(char * rsrc,cfga_flags_t flags,char ** errstring,uint_t * rflags,char ** rsrc_fixed)390*fcf3ce44SJohn Forte fp_rcm_init(char *rsrc, cfga_flags_t flags, char **errstring, uint_t *rflags,
391*fcf3ce44SJohn Forte char **rsrc_fixed)
392*fcf3ce44SJohn Forte {
393*fcf3ce44SJohn Forte /* Validate the rsrc argument */
394*fcf3ce44SJohn Forte if (rsrc == NULL) {
395*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERR_APID_INVAL, 0);
396*fcf3ce44SJohn Forte return (FPCFGA_ERR);
397*fcf3ce44SJohn Forte }
398*fcf3ce44SJohn Forte
399*fcf3ce44SJohn Forte /* Translate the cfgadm flags to RCM flags */
400*fcf3ce44SJohn Forte if (rflags && (flags & CFGA_FLAG_FORCE))
401*fcf3ce44SJohn Forte *rflags |= RCM_FORCE;
402*fcf3ce44SJohn Forte
403*fcf3ce44SJohn Forte /* Get a handle for the RCM operations */
404*fcf3ce44SJohn Forte (void) mutex_lock(&rcm_handle_lock);
405*fcf3ce44SJohn Forte if (rcm_handle == NULL) {
406*fcf3ce44SJohn Forte if (rcm_alloc_handle(NULL, RCM_NOPID, NULL, &rcm_handle) !=
407*fcf3ce44SJohn Forte RCM_SUCCESS) {
408*fcf3ce44SJohn Forte cfga_err(errstring, 0, ERR_RCM_HANDLE, 0);
409*fcf3ce44SJohn Forte (void) mutex_unlock(&rcm_handle_lock);
410*fcf3ce44SJohn Forte return (FPCFGA_LIB_ERR);
411*fcf3ce44SJohn Forte }
412*fcf3ce44SJohn Forte }
413*fcf3ce44SJohn Forte (void) mutex_unlock(&rcm_handle_lock);
414*fcf3ce44SJohn Forte
415*fcf3ce44SJohn Forte /* Chop off the rsrc's minor, if it has one */
416*fcf3ce44SJohn Forte if ((*rsrc_fixed = chop_minor(rsrc)) == NULL)
417*fcf3ce44SJohn Forte return (FPCFGA_ERR);
418*fcf3ce44SJohn Forte
419*fcf3ce44SJohn Forte return (FPCFGA_OK);
420*fcf3ce44SJohn Forte }
421*fcf3ce44SJohn Forte
422*fcf3ce44SJohn Forte /*
423*fcf3ce44SJohn Forte * fp_rcm_process_node
424*fcf3ce44SJohn Forte *
425*fcf3ce44SJohn Forte * Helper routine for fp_rcm_{suspend,resume}. This is a di_walk_node()
426*fcf3ce44SJohn Forte * callback that will apply a filter to every node it sees, and either suspend
427*fcf3ce44SJohn Forte * or resume it if it doesn't match the filter.
428*fcf3ce44SJohn Forte */
429*fcf3ce44SJohn Forte static int
fp_rcm_process_node(di_node_t node,void * argp)430*fcf3ce44SJohn Forte fp_rcm_process_node(di_node_t node, void *argp)
431*fcf3ce44SJohn Forte {
432*fcf3ce44SJohn Forte char *devfs_path;
433*fcf3ce44SJohn Forte walkargs_t *walkargs;
434*fcf3ce44SJohn Forte fpcfga_ret_t ret = FPCFGA_OK;
435*fcf3ce44SJohn Forte char disk_path[MAXPATHLEN];
436*fcf3ce44SJohn Forte
437*fcf3ce44SJohn Forte /* Guard against bad arguments */
438*fcf3ce44SJohn Forte if ((walkargs = (walkargs_t *)argp) == NULL)
439*fcf3ce44SJohn Forte return (DI_WALK_TERMINATE);
440*fcf3ce44SJohn Forte if (walkargs->filter == NULL || walkargs->errstring == NULL) {
441*fcf3ce44SJohn Forte walkargs->ret = FPCFGA_ERR;
442*fcf3ce44SJohn Forte return (DI_WALK_TERMINATE);
443*fcf3ce44SJohn Forte }
444*fcf3ce44SJohn Forte
445*fcf3ce44SJohn Forte /* If the node has no minors, then skip it */
446*fcf3ce44SJohn Forte if (di_minor_next(node, DI_MINOR_NIL) == DI_MINOR_NIL)
447*fcf3ce44SJohn Forte return (DI_WALK_CONTINUE);
448*fcf3ce44SJohn Forte
449*fcf3ce44SJohn Forte /* Construct the devices path */
450*fcf3ce44SJohn Forte if ((devfs_path = di_devfs_path(node)) == NULL)
451*fcf3ce44SJohn Forte return (DI_WALK_CONTINUE);
452*fcf3ce44SJohn Forte (void) snprintf(disk_path, MAXPATHLEN, "%s%s", DEVICES, devfs_path);
453*fcf3ce44SJohn Forte di_devfs_path_free(devfs_path);
454*fcf3ce44SJohn Forte
455*fcf3ce44SJohn Forte /*
456*fcf3ce44SJohn Forte * If the node does not correspond to the targeted FP bus or the
457*fcf3ce44SJohn Forte * disk being filtered out, then use the appropriate suspend/resume
458*fcf3ce44SJohn Forte * function.
459*fcf3ce44SJohn Forte */
460*fcf3ce44SJohn Forte if (strcmp(disk_path, walkargs->bus_path) != 0 &&
461*fcf3ce44SJohn Forte strcmp(disk_path, walkargs->filter) != 0)
462*fcf3ce44SJohn Forte ret = (*walkargs->func)(disk_path, NULL, walkargs->errstring,
463*fcf3ce44SJohn Forte walkargs->flags);
464*fcf3ce44SJohn Forte
465*fcf3ce44SJohn Forte /* Stop the walk early if the above operation failed */
466*fcf3ce44SJohn Forte if (ret != FPCFGA_OK) {
467*fcf3ce44SJohn Forte walkargs->ret = ret;
468*fcf3ce44SJohn Forte return (DI_WALK_TERMINATE);
469*fcf3ce44SJohn Forte }
470*fcf3ce44SJohn Forte
471*fcf3ce44SJohn Forte return (DI_WALK_CONTINUE);
472*fcf3ce44SJohn Forte }
473*fcf3ce44SJohn Forte
474*fcf3ce44SJohn Forte /*
475*fcf3ce44SJohn Forte * fp_rcm_info_table
476*fcf3ce44SJohn Forte *
477*fcf3ce44SJohn Forte * Takes an opaque rcm_info_t pointer and a character pointer, and appends
478*fcf3ce44SJohn Forte * the rcm_info_t data in the form of a table to the given character pointer.
479*fcf3ce44SJohn Forte */
480*fcf3ce44SJohn Forte static fpcfga_ret_t
fp_rcm_info_table(rcm_info_t * rinfo,char ** table)481*fcf3ce44SJohn Forte fp_rcm_info_table(rcm_info_t *rinfo, char **table)
482*fcf3ce44SJohn Forte {
483*fcf3ce44SJohn Forte int i;
484*fcf3ce44SJohn Forte size_t w;
485*fcf3ce44SJohn Forte size_t width = 0;
486*fcf3ce44SJohn Forte size_t w_rsrc = 0;
487*fcf3ce44SJohn Forte size_t w_info = 0;
488*fcf3ce44SJohn Forte size_t table_size = 0;
489*fcf3ce44SJohn Forte uint_t tuples = 0;
490*fcf3ce44SJohn Forte rcm_info_tuple_t *tuple = NULL;
491*fcf3ce44SJohn Forte char *rsrc;
492*fcf3ce44SJohn Forte char *info;
493*fcf3ce44SJohn Forte char *newtable;
494*fcf3ce44SJohn Forte static char format[MAX_FORMAT];
495*fcf3ce44SJohn Forte const char *info_info_str, *info_rsrc_str;
496*fcf3ce44SJohn Forte
497*fcf3ce44SJohn Forte /* Protect against invalid arguments */
498*fcf3ce44SJohn Forte if (rinfo == NULL || table == NULL)
499*fcf3ce44SJohn Forte return (FPCFGA_ERR);
500*fcf3ce44SJohn Forte
501*fcf3ce44SJohn Forte /* Set localized table header strings */
502*fcf3ce44SJohn Forte rsrc = gettext("Resource");
503*fcf3ce44SJohn Forte info = gettext("Information");
504*fcf3ce44SJohn Forte
505*fcf3ce44SJohn Forte /* A first pass, to size up the RCM information */
506*fcf3ce44SJohn Forte while (tuple = rcm_info_next(rinfo, tuple)) {
507*fcf3ce44SJohn Forte info_info_str = rcm_info_info(tuple);
508*fcf3ce44SJohn Forte info_rsrc_str = rcm_info_rsrc(tuple);
509*fcf3ce44SJohn Forte if ((info_info_str != NULL) && (info_rsrc_str != NULL)) {
510*fcf3ce44SJohn Forte tuples++;
511*fcf3ce44SJohn Forte if ((w = strlen(info_rsrc_str)) > w_rsrc)
512*fcf3ce44SJohn Forte w_rsrc = w;
513*fcf3ce44SJohn Forte if ((w = strlen(info_info_str)) > w_info)
514*fcf3ce44SJohn Forte w_info = w;
515*fcf3ce44SJohn Forte }
516*fcf3ce44SJohn Forte }
517*fcf3ce44SJohn Forte
518*fcf3ce44SJohn Forte /* If nothing was sized up above, stop early */
519*fcf3ce44SJohn Forte if (tuples == 0)
520*fcf3ce44SJohn Forte return (FPCFGA_OK);
521*fcf3ce44SJohn Forte
522*fcf3ce44SJohn Forte /* Adjust column widths for column headings */
523*fcf3ce44SJohn Forte if ((w = strlen(rsrc)) > w_rsrc)
524*fcf3ce44SJohn Forte w_rsrc = w;
525*fcf3ce44SJohn Forte else if ((w_rsrc - w) % 2)
526*fcf3ce44SJohn Forte w_rsrc++;
527*fcf3ce44SJohn Forte if ((w = strlen(info)) > w_info)
528*fcf3ce44SJohn Forte w_info = w;
529*fcf3ce44SJohn Forte else if ((w_info - w) % 2)
530*fcf3ce44SJohn Forte w_info++;
531*fcf3ce44SJohn Forte
532*fcf3ce44SJohn Forte /*
533*fcf3ce44SJohn Forte * Compute the total line width of each line,
534*fcf3ce44SJohn Forte * accounting for intercolumn spacing.
535*fcf3ce44SJohn Forte */
536*fcf3ce44SJohn Forte width = w_info + w_rsrc + 4;
537*fcf3ce44SJohn Forte
538*fcf3ce44SJohn Forte /* Allocate space for the table */
539*fcf3ce44SJohn Forte table_size = (2 + tuples) * (width + 1) + 2;
540*fcf3ce44SJohn Forte if (*table == NULL)
541*fcf3ce44SJohn Forte *table = malloc(table_size);
542*fcf3ce44SJohn Forte else {
543*fcf3ce44SJohn Forte newtable = realloc(*table, strlen(*table) + table_size);
544*fcf3ce44SJohn Forte if (newtable != NULL)
545*fcf3ce44SJohn Forte *table = newtable;
546*fcf3ce44SJohn Forte }
547*fcf3ce44SJohn Forte if (*table == NULL)
548*fcf3ce44SJohn Forte return (FPCFGA_ERR);
549*fcf3ce44SJohn Forte
550*fcf3ce44SJohn Forte /* Place a table header into the string */
551*fcf3ce44SJohn Forte
552*fcf3ce44SJohn Forte /* The resource header */
553*fcf3ce44SJohn Forte (void) strcat(*table, "\n");
554*fcf3ce44SJohn Forte w = strlen(rsrc);
555*fcf3ce44SJohn Forte for (i = 0; i < ((w_rsrc - w) / 2); i++)
556*fcf3ce44SJohn Forte (void) strcat(*table, " ");
557*fcf3ce44SJohn Forte (void) strcat(*table, rsrc);
558*fcf3ce44SJohn Forte for (i = 0; i < ((w_rsrc - w) / 2); i++)
559*fcf3ce44SJohn Forte (void) strcat(*table, " ");
560*fcf3ce44SJohn Forte
561*fcf3ce44SJohn Forte /* The information header */
562*fcf3ce44SJohn Forte (void) strcat(*table, " ");
563*fcf3ce44SJohn Forte w = strlen(info);
564*fcf3ce44SJohn Forte for (i = 0; i < ((w_info - w) / 2); i++)
565*fcf3ce44SJohn Forte (void) strcat(*table, " ");
566*fcf3ce44SJohn Forte (void) strcat(*table, info);
567*fcf3ce44SJohn Forte for (i = 0; i < ((w_info - w) / 2); i++)
568*fcf3ce44SJohn Forte (void) strcat(*table, " ");
569*fcf3ce44SJohn Forte
570*fcf3ce44SJohn Forte /* Underline the headers */
571*fcf3ce44SJohn Forte (void) strcat(*table, "\n");
572*fcf3ce44SJohn Forte for (i = 0; i < w_rsrc; i++)
573*fcf3ce44SJohn Forte (void) strcat(*table, "-");
574*fcf3ce44SJohn Forte (void) strcat(*table, " ");
575*fcf3ce44SJohn Forte for (i = 0; i < w_info; i++)
576*fcf3ce44SJohn Forte (void) strcat(*table, "-");
577*fcf3ce44SJohn Forte
578*fcf3ce44SJohn Forte /* Construct the format string */
579*fcf3ce44SJohn Forte (void) snprintf(format, MAX_FORMAT, "%%-%ds %%-%ds", w_rsrc, w_info);
580*fcf3ce44SJohn Forte
581*fcf3ce44SJohn Forte /* Add the tuples to the table string */
582*fcf3ce44SJohn Forte tuple = NULL;
583*fcf3ce44SJohn Forte while ((tuple = rcm_info_next(rinfo, tuple)) != NULL) {
584*fcf3ce44SJohn Forte info_info_str = rcm_info_info(tuple);
585*fcf3ce44SJohn Forte info_rsrc_str = rcm_info_rsrc(tuple);
586*fcf3ce44SJohn Forte if ((info_info_str != NULL) && (info_rsrc_str != NULL)) {
587*fcf3ce44SJohn Forte (void) strcat(*table, "\n");
588*fcf3ce44SJohn Forte (void) sprintf(&((*table)[strlen(*table)]),
589*fcf3ce44SJohn Forte format, info_rsrc_str, info_info_str);
590*fcf3ce44SJohn Forte }
591*fcf3ce44SJohn Forte }
592*fcf3ce44SJohn Forte
593*fcf3ce44SJohn Forte return (FPCFGA_OK);
594*fcf3ce44SJohn Forte }
595*fcf3ce44SJohn Forte
596*fcf3ce44SJohn Forte /*
597*fcf3ce44SJohn Forte * chop_minor()
598*fcf3ce44SJohn Forte *
599*fcf3ce44SJohn Forte * Chops off the minor name portion of a resource. Allocates storage for
600*fcf3ce44SJohn Forte * the returned string. Caller must free the storage if return is non-NULL.
601*fcf3ce44SJohn Forte */
602*fcf3ce44SJohn Forte static char *
chop_minor(char * rsrc)603*fcf3ce44SJohn Forte chop_minor(char *rsrc)
604*fcf3ce44SJohn Forte {
605*fcf3ce44SJohn Forte char *rsrc_fixed;
606*fcf3ce44SJohn Forte char *cp;
607*fcf3ce44SJohn Forte
608*fcf3ce44SJohn Forte if ((rsrc_fixed = strdup(rsrc)) == NULL)
609*fcf3ce44SJohn Forte return (NULL);
610*fcf3ce44SJohn Forte if ((cp = strrchr(rsrc_fixed, ':')) != NULL)
611*fcf3ce44SJohn Forte *cp = '\0';
612*fcf3ce44SJohn Forte return (rsrc_fixed);
613*fcf3ce44SJohn Forte }
614