1*1708Sstevel /*
2*1708Sstevel * CDDL HEADER START
3*1708Sstevel *
4*1708Sstevel * The contents of this file are subject to the terms of the
5*1708Sstevel * Common Development and Distribution License (the "License").
6*1708Sstevel * You may not use this file except in compliance with the License.
7*1708Sstevel *
8*1708Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1708Sstevel * or http://www.opensolaris.org/os/licensing.
10*1708Sstevel * See the License for the specific language governing permissions
11*1708Sstevel * and limitations under the License.
12*1708Sstevel *
13*1708Sstevel * When distributing Covered Code, include this CDDL HEADER in each
14*1708Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1708Sstevel * If applicable, add the following below this CDDL HEADER, with the
16*1708Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
17*1708Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
18*1708Sstevel *
19*1708Sstevel * CDDL HEADER END
20*1708Sstevel */
21*1708Sstevel
22*1708Sstevel /*
23*1708Sstevel * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*1708Sstevel * Use is subject to license terms.
25*1708Sstevel */
26*1708Sstevel
27*1708Sstevel #pragma ident "%Z%%M% %I% %E% SMI"
28*1708Sstevel
29*1708Sstevel #include <sys/cpuvar.h>
30*1708Sstevel #include <sys/cpu_module.h>
31*1708Sstevel #include <sys/kmem.h>
32*1708Sstevel #include <sys/sunddi.h>
33*1708Sstevel #include <sys/param.h>
34*1708Sstevel #include <sys/obpdefs.h>
35*1708Sstevel #include <sys/prom_plat.h>
36*1708Sstevel #include <sys/sgsbbc_mailbox.h>
37*1708Sstevel #include <sys/sbd_ioctl.h>
38*1708Sstevel #include <sys/sbdp_priv.h>
39*1708Sstevel #include <sys/sbdp_mbox.h>
40*1708Sstevel #include <sys/promif.h>
41*1708Sstevel #include <sys/plat_ecc_dimm.h>
42*1708Sstevel
43*1708Sstevel #define UNKNOWN "unknown"
44*1708Sstevel #define INITL_STATUS 0xdead
45*1708Sstevel
46*1708Sstevel int sbdp_mbox_wait = 86400; /* in seconds */
47*1708Sstevel int sbdp_shw_bd_wait = 5; /* in seconds */
48*1708Sstevel
49*1708Sstevel int sbdp_sc_err_translation(int);
50*1708Sstevel int sbdp_poweroff_wkaround = 1;
51*1708Sstevel
52*1708Sstevel /*
53*1708Sstevel * By default, DR of non-Panther procs is not allowed into a Panther
54*1708Sstevel * domain with large page sizes enabled. Setting this to 0 will remove
55*1708Sstevel * the restriction.
56*1708Sstevel */
57*1708Sstevel static int sbdp_large_page_restriction = 1;
58*1708Sstevel
59*1708Sstevel /*
60*1708Sstevel * Initialize the data structs for the common part of the pkts
61*1708Sstevel */
62*1708Sstevel void
sbdp_init_msg_pkt(sbbc_msg_t * msg,uint16_t sub_type,int len,caddr_t buf)63*1708Sstevel sbdp_init_msg_pkt(sbbc_msg_t *msg, uint16_t sub_type, int len, caddr_t buf)
64*1708Sstevel {
65*1708Sstevel msg->msg_type.type = DR_MBOX;
66*1708Sstevel msg->msg_type.sub_type = sub_type;
67*1708Sstevel msg->msg_status = INITL_STATUS;
68*1708Sstevel msg->msg_len = len;
69*1708Sstevel msg->msg_buf = buf;
70*1708Sstevel msg->msg_data[0] = 0;
71*1708Sstevel msg->msg_data[1] = 0;
72*1708Sstevel
73*1708Sstevel }
74*1708Sstevel
75*1708Sstevel /*
76*1708Sstevel * Convert a showboard data structure to the board structure shared
77*1708Sstevel * between sbd and sbdp
78*1708Sstevel */
79*1708Sstevel void
sbdp_showbd_2_sbd_stat(show_board_t * shbp,sbd_stat_t * stp,int board)80*1708Sstevel sbdp_showbd_2_sbd_stat(show_board_t *shbp, sbd_stat_t *stp, int board)
81*1708Sstevel {
82*1708Sstevel static fn_t f = "sbdp_showbd_2_sbd_stat";
83*1708Sstevel
84*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
85*1708Sstevel
86*1708Sstevel stp->s_board = board;
87*1708Sstevel (void) strcpy(stp->s_info, shbp->s_info);
88*1708Sstevel stp->s_power = shbp->s_power;
89*1708Sstevel
90*1708Sstevel (void) strcpy(stp->s_type, shbp->s_type);
91*1708Sstevel
92*1708Sstevel if (shbp->s_present == 0) {
93*1708Sstevel /*
94*1708Sstevel * This should go away since the SC should put the unknown
95*1708Sstevel * We leave this here so Symon and other scripts don't have
96*1708Sstevel * a problem
97*1708Sstevel */
98*1708Sstevel (void) strcpy(stp->s_type, UNKNOWN);
99*1708Sstevel stp->s_rstate = SBD_STAT_EMPTY;
100*1708Sstevel } else if (shbp->s_claimed == 0)
101*1708Sstevel stp->s_rstate = SBD_STAT_DISCONNECTED;
102*1708Sstevel else
103*1708Sstevel stp->s_rstate = SBD_STAT_CONNECTED;
104*1708Sstevel
105*1708Sstevel
106*1708Sstevel stp->s_assigned = shbp->s_assigned;
107*1708Sstevel stp->s_cond = shbp->s_cond;
108*1708Sstevel }
109*1708Sstevel
110*1708Sstevel /*
111*1708Sstevel * Entry point from sbd. Get the status from the SC and then convert
112*1708Sstevel * the info returned into something that sbd understands
113*1708Sstevel * If the request times out or fails other than an illegal transaction
114*1708Sstevel * copy the info from our inventory
115*1708Sstevel */
116*1708Sstevel int
sbdp_get_board_status(sbdp_handle_t * hp,sbd_stat_t * stp)117*1708Sstevel sbdp_get_board_status(sbdp_handle_t *hp, sbd_stat_t *stp)
118*1708Sstevel {
119*1708Sstevel int board = hp->h_board;
120*1708Sstevel int node = hp->h_wnode;
121*1708Sstevel sbbc_msg_t request, *reqp = &request;
122*1708Sstevel sbbc_msg_t response, *resp = &response;
123*1708Sstevel info_t inform, *informp = &inform;
124*1708Sstevel show_board_t show_bd, *shbp = &show_bd;
125*1708Sstevel int rv = 0;
126*1708Sstevel sbd_error_t *sep = hp->h_err;
127*1708Sstevel int len;
128*1708Sstevel sbdp_bd_t *bdp;
129*1708Sstevel static fn_t f = "sbdp_get_board_status";
130*1708Sstevel
131*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
132*1708Sstevel
133*1708Sstevel /*
134*1708Sstevel * Check for options. If there are any, fail the operation
135*1708Sstevel */
136*1708Sstevel if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
137*1708Sstevel sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
138*1708Sstevel return (-1);
139*1708Sstevel }
140*1708Sstevel
141*1708Sstevel bdp = sbdp_get_bd_info(node, board);
142*1708Sstevel
143*1708Sstevel informp->board = board;
144*1708Sstevel informp->node = node;
145*1708Sstevel informp->revision = 0xdead;
146*1708Sstevel len = sizeof (info_t);
147*1708Sstevel
148*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_SHOW_BOARD, len, (caddr_t)informp);
149*1708Sstevel
150*1708Sstevel bzero(shbp, sizeof (show_board_t));
151*1708Sstevel shbp->s_cond = -1;
152*1708Sstevel shbp->s_power = -1;
153*1708Sstevel shbp->s_assigned = -1;
154*1708Sstevel shbp->s_claimed = -1;
155*1708Sstevel shbp->s_present = -1;
156*1708Sstevel len = sizeof (show_board_t);
157*1708Sstevel
158*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_SHOW_BOARD, len, (caddr_t)shbp);
159*1708Sstevel
160*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_shw_bd_wait);
161*1708Sstevel
162*1708Sstevel SBDP_DBG_MISC("show board completed: rv = %d\n", rv);
163*1708Sstevel
164*1708Sstevel /*
165*1708Sstevel * This domain has no access to this board. Return failure
166*1708Sstevel */
167*1708Sstevel if ((resp->msg_status == SG_MBOX_STATUS_BOARD_ACCESS_DENIED) ||
168*1708Sstevel (resp->msg_status == SG_MBOX_STATUS_ILLEGAL_SLOT) ||
169*1708Sstevel (resp->msg_status == SG_MBOX_STATUS_ILLEGAL_NODE)) {
170*1708Sstevel
171*1708Sstevel /*
172*1708Sstevel * invalidate cached copy.
173*1708Sstevel */
174*1708Sstevel bdp->valid_cp = -1;
175*1708Sstevel
176*1708Sstevel sbdp_set_err(sep, ESGT_GET_BOARD_STAT, NULL);
177*1708Sstevel return (EIO);
178*1708Sstevel }
179*1708Sstevel
180*1708Sstevel /*
181*1708Sstevel * If we get any error see if we can return a cached copy of the
182*1708Sstevel * board info. If one exists turn the busy flag on
183*1708Sstevel */
184*1708Sstevel if (rv != 0) {
185*1708Sstevel mutex_enter(&bdp->bd_mutex);
186*1708Sstevel if (bdp->valid_cp == -1) {
187*1708Sstevel sbdp_set_err(sep, ESGT_GET_BOARD_STAT,
188*1708Sstevel NULL);
189*1708Sstevel mutex_exit(&bdp->bd_mutex);
190*1708Sstevel return (EIO);
191*1708Sstevel }
192*1708Sstevel
193*1708Sstevel /*
194*1708Sstevel * we have a valid copy. Return it and set the
195*1708Sstevel * busy flag on so the user know this is not the most
196*1708Sstevel * recent copy
197*1708Sstevel */
198*1708Sstevel bcopy(bdp->bd_sc, shbp, sizeof (show_board_t));
199*1708Sstevel mutex_exit(&bdp->bd_mutex);
200*1708Sstevel stp->s_busy = 1;
201*1708Sstevel /*
202*1708Sstevel * The sbbc returns the error in both parts (i.e rv and status)
203*1708Sstevel * so since we just took care of it reset rv
204*1708Sstevel */
205*1708Sstevel rv = 0;
206*1708Sstevel } else {
207*1708Sstevel /*
208*1708Sstevel * revalidate our copy of the returned data
209*1708Sstevel */
210*1708Sstevel if (bdp == NULL) {
211*1708Sstevel SBDP_DBG_MBOX("HUGE ERROR\n");
212*1708Sstevel } else {
213*1708Sstevel mutex_enter(&bdp->bd_mutex);
214*1708Sstevel bcopy(shbp, bdp->bd_sc, sizeof (show_board_t));
215*1708Sstevel bdp->valid_cp = 1;
216*1708Sstevel mutex_exit(&bdp->bd_mutex);
217*1708Sstevel }
218*1708Sstevel }
219*1708Sstevel
220*1708Sstevel
221*1708Sstevel SBDP_DBG_MBOX("Showboard: board\t%d\n\trevision\t%d\n\ts_cond\t%d\n\t"
222*1708Sstevel "s_power\t%d\n\ts_assigned\t%d\n\ts_claimed\t%d\n\t"
223*1708Sstevel "s_present\t%d\n\ts_ledstatus\t%d\n\ts_type\t%s\n\t"
224*1708Sstevel "s_info\t%s\n",
225*1708Sstevel board, shbp->revision, shbp->s_cond, shbp->s_power,
226*1708Sstevel shbp->s_assigned, shbp->s_claimed, shbp->s_present,
227*1708Sstevel shbp->s_ledstatus, shbp->s_type, shbp->s_info);
228*1708Sstevel
229*1708Sstevel /*
230*1708Sstevel * Now that we got the info run through the sbd-sbdp translator
231*1708Sstevel */
232*1708Sstevel sbdp_showbd_2_sbd_stat(shbp, stp, board);
233*1708Sstevel
234*1708Sstevel /*
235*1708Sstevel * Last add the platform options
236*1708Sstevel */
237*1708Sstevel SBDP_PLATFORM_OPTS(stp->s_platopts);
238*1708Sstevel
239*1708Sstevel return (rv);
240*1708Sstevel }
241*1708Sstevel
242*1708Sstevel /*
243*1708Sstevel * Entry point from sbd. Call down to the SC to assign the board
244*1708Sstevel * We simply return the status the SC told us
245*1708Sstevel */
246*1708Sstevel int
sbdp_assign_board(sbdp_handle_t * hp)247*1708Sstevel sbdp_assign_board(sbdp_handle_t *hp)
248*1708Sstevel {
249*1708Sstevel int board = hp->h_board;
250*1708Sstevel int node = hp->h_wnode;
251*1708Sstevel sbbc_msg_t request, *reqp = &request;
252*1708Sstevel sbbc_msg_t response, *resp = &response;
253*1708Sstevel int cmd_rev = -1;
254*1708Sstevel info2_t inform, *informp = &inform;
255*1708Sstevel int rv = 0;
256*1708Sstevel sbd_error_t *sep;
257*1708Sstevel int len;
258*1708Sstevel static fn_t f = "sbdp_assign_board";
259*1708Sstevel
260*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
261*1708Sstevel
262*1708Sstevel sep = hp->h_err;
263*1708Sstevel /*
264*1708Sstevel * Check for options. If there are any, fail the operation
265*1708Sstevel */
266*1708Sstevel if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
267*1708Sstevel sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
268*1708Sstevel return (-1);
269*1708Sstevel }
270*1708Sstevel
271*1708Sstevel informp->board = board;
272*1708Sstevel informp->node = node;
273*1708Sstevel informp->extra = SBDP_ASSIGN;
274*1708Sstevel len = sizeof (info2_t);
275*1708Sstevel
276*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_ASSIGN, len, (caddr_t)informp);
277*1708Sstevel
278*1708Sstevel len = sizeof (cmd_rev);
279*1708Sstevel
280*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_ASSIGN, len, (caddr_t)&cmd_rev);
281*1708Sstevel
282*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
283*1708Sstevel
284*1708Sstevel if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
285*1708Sstevel SBDP_DBG_MISC("failed to assign board: rv = %d\n", rv);
286*1708Sstevel sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
287*1708Sstevel NULL);
288*1708Sstevel }
289*1708Sstevel
290*1708Sstevel return (rv);
291*1708Sstevel }
292*1708Sstevel
293*1708Sstevel /*
294*1708Sstevel * Entry point from sbd. Call down to the SC to unassign the board
295*1708Sstevel * We simply return the status the SC told us
296*1708Sstevel */
297*1708Sstevel int
sbdp_unassign_board(sbdp_handle_t * hp)298*1708Sstevel sbdp_unassign_board(sbdp_handle_t *hp)
299*1708Sstevel {
300*1708Sstevel int board = hp->h_board;
301*1708Sstevel int node = hp->h_wnode;
302*1708Sstevel sbbc_msg_t request, *reqp = &request;
303*1708Sstevel sbbc_msg_t response, *resp = &response;
304*1708Sstevel int cmd_rev = -1;
305*1708Sstevel info2_t inform, *informp = &inform;
306*1708Sstevel int rv = 0;
307*1708Sstevel sbd_error_t *sep;
308*1708Sstevel int len;
309*1708Sstevel static fn_t f = "sbdp_unassign_board";
310*1708Sstevel
311*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
312*1708Sstevel
313*1708Sstevel sep = hp->h_err;
314*1708Sstevel /*
315*1708Sstevel * Check for options. If there are any, fail the operation
316*1708Sstevel */
317*1708Sstevel if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
318*1708Sstevel sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
319*1708Sstevel return (-1);
320*1708Sstevel }
321*1708Sstevel
322*1708Sstevel informp->board = board;
323*1708Sstevel informp->node = node;
324*1708Sstevel informp->extra = SBDP_UNASSIGN;
325*1708Sstevel len = sizeof (info2_t);
326*1708Sstevel
327*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_ASSIGN, len, (caddr_t)informp);
328*1708Sstevel
329*1708Sstevel len = sizeof (cmd_rev);
330*1708Sstevel
331*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_ASSIGN, len, (caddr_t)&cmd_rev);
332*1708Sstevel
333*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
334*1708Sstevel
335*1708Sstevel if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
336*1708Sstevel SBDP_DBG_MISC("failed to unassign board: rv = %d\n", rv);
337*1708Sstevel sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
338*1708Sstevel NULL);
339*1708Sstevel }
340*1708Sstevel
341*1708Sstevel return (rv);
342*1708Sstevel }
343*1708Sstevel
344*1708Sstevel static int
sg_attach_board(void * arg)345*1708Sstevel sg_attach_board(void *arg)
346*1708Sstevel {
347*1708Sstevel sbdp_handle_t *hp;
348*1708Sstevel cpuset_t cset;
349*1708Sstevel int rv;
350*1708Sstevel static fn_t f = "sg_attach_board";
351*1708Sstevel
352*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
353*1708Sstevel
354*1708Sstevel hp = (sbdp_handle_t *)arg;
355*1708Sstevel
356*1708Sstevel cset = cpu_ready_set;
357*1708Sstevel promsafe_xc_attention(cset);
358*1708Sstevel rv = prom_serengeti_attach_board(hp->h_wnode, hp->h_board);
359*1708Sstevel xc_dismissed(cset);
360*1708Sstevel
361*1708Sstevel return (rv);
362*1708Sstevel }
363*1708Sstevel
364*1708Sstevel static int
sg_detach_board(void * arg)365*1708Sstevel sg_detach_board(void *arg)
366*1708Sstevel {
367*1708Sstevel sbdp_handle_t *hp;
368*1708Sstevel cpuset_t cset;
369*1708Sstevel int rv;
370*1708Sstevel static fn_t f = "sg_detach_board";
371*1708Sstevel
372*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
373*1708Sstevel
374*1708Sstevel hp = (sbdp_handle_t *)arg;
375*1708Sstevel
376*1708Sstevel cset = cpu_ready_set;
377*1708Sstevel promsafe_xc_attention(cset);
378*1708Sstevel rv = prom_serengeti_detach_board(hp->h_wnode, hp->h_board);
379*1708Sstevel xc_dismissed(cset);
380*1708Sstevel
381*1708Sstevel return (rv);
382*1708Sstevel }
383*1708Sstevel
384*1708Sstevel /*
385*1708Sstevel * Entry point from sbd. First we call down to the SC to "attach/claim" this
386*1708Sstevel * board. As a side effect the SC updates the pda info so obp can create the
387*1708Sstevel * device tree. If we are successful, we ask OBP to probe the board. OBP
388*1708Sstevel * creates new nodes on its own obp tree
389*1708Sstevel * As an added bonus, since we don't use the inkernel prober, we need to create
390*1708Sstevel * the dev_info nodes but just to a point where they are created but
391*1708Sstevel * Solaris can't use them (i.e BIND)
392*1708Sstevel */
393*1708Sstevel int
sbdp_connect_board(sbdp_handle_t * hp)394*1708Sstevel sbdp_connect_board(sbdp_handle_t *hp)
395*1708Sstevel {
396*1708Sstevel sbbc_msg_t request, *reqp = &request;
397*1708Sstevel sbbc_msg_t response, *resp = &response;
398*1708Sstevel int rv = 0;
399*1708Sstevel int board, node;
400*1708Sstevel sbd_error_t *sep;
401*1708Sstevel static fn_t f = "sbdp_connect_board";
402*1708Sstevel int panther_pages_enabled;
403*1708Sstevel
404*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
405*1708Sstevel
406*1708Sstevel board = hp->h_board;
407*1708Sstevel node = hp->h_wnode;
408*1708Sstevel sep = hp->h_err;
409*1708Sstevel
410*1708Sstevel /*
411*1708Sstevel * Check for options. If there are any, fail the operation
412*1708Sstevel */
413*1708Sstevel if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
414*1708Sstevel sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
415*1708Sstevel return (-1);
416*1708Sstevel }
417*1708Sstevel
418*1708Sstevel /*
419*1708Sstevel * Currently, we pass the info in the extra data fields.
420*1708Sstevel * This may change in the SC. We need to change it then
421*1708Sstevel */
422*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_CLAIM, 0, (caddr_t)NULL);
423*1708Sstevel reqp->msg_data[0] = node;
424*1708Sstevel reqp->msg_data[1] = board;
425*1708Sstevel
426*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_CLAIM, 0, (caddr_t)NULL);
427*1708Sstevel
428*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
429*1708Sstevel
430*1708Sstevel if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
431*1708Sstevel SBDP_DBG_MISC("failed to claim board: rv = %d\n", rv);
432*1708Sstevel sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
433*1708Sstevel NULL);
434*1708Sstevel return (rv);
435*1708Sstevel }
436*1708Sstevel
437*1708Sstevel rv = prom_tree_update(sg_attach_board, hp);
438*1708Sstevel if (rv != 0) {
439*1708Sstevel SBDP_DBG_MISC("failed to prom attach board: rv = %d\n", rv);
440*1708Sstevel sbdp_set_err(sep, ESGT_PROM_ATTACH, NULL);
441*1708Sstevel /*
442*1708Sstevel * Clean up
443*1708Sstevel */
444*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_UNCLAIM, 0, (caddr_t)NULL);
445*1708Sstevel reqp->msg_data[0] = node;
446*1708Sstevel reqp->msg_data[1] = board;
447*1708Sstevel
448*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_UNCLAIM, 0, (caddr_t)NULL);
449*1708Sstevel
450*1708Sstevel (void) sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
451*1708Sstevel
452*1708Sstevel return (rv);
453*1708Sstevel }
454*1708Sstevel
455*1708Sstevel SBDP_DBG_MISC("prom attach worked\n");
456*1708Sstevel sbdp_attach_bd(node, board);
457*1708Sstevel
458*1708Sstevel /*
459*1708Sstevel * XXX Until the Solaris large pages support heterogeneous cpu
460*1708Sstevel * domains, DR needs to prevent the addition of non-Panther cpus
461*1708Sstevel * to an all-Panther domain with large pages enabled.
462*1708Sstevel */
463*1708Sstevel panther_pages_enabled = (page_num_pagesizes() > DEFAULT_MMU_PAGE_SIZES);
464*1708Sstevel if (sbdp_board_non_panther_cpus(node, board) > 0 &&
465*1708Sstevel panther_pages_enabled && sbdp_large_page_restriction) {
466*1708Sstevel cmn_err(CE_WARN, "Domain shutdown is required to add a non-"
467*1708Sstevel "UltraSPARC-IV+ board into an all UltraSPARC-IV+ domain");
468*1708Sstevel (void) sbdp_disconnect_board(hp);
469*1708Sstevel sbdp_set_err(sep, ESGT_NOT_SUPP, NULL);
470*1708Sstevel return (-1);
471*1708Sstevel }
472*1708Sstevel
473*1708Sstevel /*
474*1708Sstevel * Now that the board has been successfully attached, obtain
475*1708Sstevel * platform-specific DIMM serial id information for the board.
476*1708Sstevel */
477*1708Sstevel if (SG_BOARD_IS_CPU_TYPE(board) &&
478*1708Sstevel plat_ecc_capability_sc_get(PLAT_ECC_DIMM_SID_MESSAGE)) {
479*1708Sstevel (void) plat_request_mem_sids(board);
480*1708Sstevel }
481*1708Sstevel
482*1708Sstevel return (rv);
483*1708Sstevel }
484*1708Sstevel
485*1708Sstevel /*
486*1708Sstevel * Entry point from sbd. Undo the connect call. We first need to remove
487*1708Sstevel * the "dummy (i.e unusable)" nodes from solaris. We then call down to OBP
488*1708Sstevel * to prune its tree. After all has been cleaned up from OBP and Solaris
489*1708Sstevel * We call the SC to "detach/unclain" the board. A side effect is that the
490*1708Sstevel * SC will clear the pda entries for this board
491*1708Sstevel */
492*1708Sstevel int
sbdp_disconnect_board(sbdp_handle_t * hp)493*1708Sstevel sbdp_disconnect_board(sbdp_handle_t *hp)
494*1708Sstevel {
495*1708Sstevel sbbc_msg_t request, *reqp = &request;
496*1708Sstevel sbbc_msg_t response, *resp = &response;
497*1708Sstevel int rv = 0;
498*1708Sstevel int board, node;
499*1708Sstevel sbd_error_t *sep;
500*1708Sstevel static fn_t f = "sbdp_disconnect_board";
501*1708Sstevel
502*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
503*1708Sstevel
504*1708Sstevel board = hp->h_board;
505*1708Sstevel node = hp->h_wnode;
506*1708Sstevel sep = hp->h_err;
507*1708Sstevel
508*1708Sstevel SBDP_DBG_MISC("sbdp_disconnect_board: board = %d node = %d\n",
509*1708Sstevel board, node);
510*1708Sstevel
511*1708Sstevel /*
512*1708Sstevel * Check for options. If there are any, fail the operation
513*1708Sstevel */
514*1708Sstevel if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
515*1708Sstevel sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
516*1708Sstevel return (-1);
517*1708Sstevel }
518*1708Sstevel
519*1708Sstevel if (sbdp_detach_bd(node, board, sep)) {
520*1708Sstevel sbdp_attach_bd(node, board);
521*1708Sstevel SBDP_DBG_ALL("failed to detach board %d\n", board);
522*1708Sstevel return (-1);
523*1708Sstevel }
524*1708Sstevel
525*1708Sstevel rv = prom_tree_update(sg_detach_board, hp);
526*1708Sstevel if (rv == -1) {
527*1708Sstevel /*
528*1708Sstevel * Clean up
529*1708Sstevel */
530*1708Sstevel sbdp_attach_bd(node, board);
531*1708Sstevel SBDP_DBG_MISC("failed to prom detach board: rv = %d\n", rv);
532*1708Sstevel sbdp_set_err(sep, ESGT_PROM_DETACH, NULL);
533*1708Sstevel return (rv);
534*1708Sstevel }
535*1708Sstevel
536*1708Sstevel SBDP_DBG_MISC("prom detach worked\n");
537*1708Sstevel /*
538*1708Sstevel * Currently, we pass the info in the extra data fields.
539*1708Sstevel * This may change in the SC. We need to change it then
540*1708Sstevel */
541*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_UNCLAIM, 0, (caddr_t)NULL);
542*1708Sstevel reqp->msg_data[0] = node;
543*1708Sstevel reqp->msg_data[1] = board;
544*1708Sstevel
545*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_UNCLAIM, 0, (caddr_t)NULL);
546*1708Sstevel
547*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
548*1708Sstevel
549*1708Sstevel if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
550*1708Sstevel SBDP_DBG_MISC("failed to unclaim board: rv = %d\n", rv);
551*1708Sstevel sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
552*1708Sstevel NULL);
553*1708Sstevel /* bring back the obp tree to what it was */
554*1708Sstevel (void) prom_tree_update(sg_attach_board, hp);
555*1708Sstevel }
556*1708Sstevel
557*1708Sstevel /*
558*1708Sstevel * Now that the board has been successfully detached, discard
559*1708Sstevel * platform-specific DIMM serial id information for the board.
560*1708Sstevel */
561*1708Sstevel if (!rv && SG_BOARD_IS_CPU_TYPE(board) &&
562*1708Sstevel plat_ecc_capability_sc_get(PLAT_ECC_DIMM_SID_MESSAGE)) {
563*1708Sstevel (void) plat_discard_mem_sids(board);
564*1708Sstevel }
565*1708Sstevel
566*1708Sstevel return (rv);
567*1708Sstevel }
568*1708Sstevel
569*1708Sstevel /*
570*1708Sstevel * Entry point from sbd. Very simple. Just ask the SC to poweoff the board
571*1708Sstevel * Return the status from the SC
572*1708Sstevel */
573*1708Sstevel int
sbdp_poweroff_board(sbdp_handle_t * hp)574*1708Sstevel sbdp_poweroff_board(sbdp_handle_t *hp)
575*1708Sstevel {
576*1708Sstevel sbbc_msg_t request, *reqp = &request;
577*1708Sstevel sbbc_msg_t response, *resp = &response;
578*1708Sstevel int cmd_rev = -1;
579*1708Sstevel info2_t inform, *informp;
580*1708Sstevel int rv = 0;
581*1708Sstevel sbd_error_t *sep;
582*1708Sstevel int len;
583*1708Sstevel static fn_t f = "sbdp_poweroff_board";
584*1708Sstevel
585*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
586*1708Sstevel
587*1708Sstevel sep = hp->h_err;
588*1708Sstevel /*
589*1708Sstevel * Check for options. If there are any, fail the operation
590*1708Sstevel */
591*1708Sstevel if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
592*1708Sstevel sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
593*1708Sstevel return (-1);
594*1708Sstevel }
595*1708Sstevel
596*1708Sstevel /*
597*1708Sstevel * Can't check for bad options here since we use this for workaround
598*1708Sstevel * on poweron.
599*1708Sstevel */
600*1708Sstevel
601*1708Sstevel informp = &inform;
602*1708Sstevel informp->board = hp->h_board;
603*1708Sstevel informp->node = hp->h_wnode;
604*1708Sstevel informp->extra = SBDP_POWER_OFF;
605*1708Sstevel
606*1708Sstevel len = sizeof (info2_t);
607*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_POWER, len, (caddr_t)informp);
608*1708Sstevel
609*1708Sstevel len = sizeof (cmd_rev);
610*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_POWER, len, (caddr_t)&cmd_rev);
611*1708Sstevel
612*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
613*1708Sstevel
614*1708Sstevel if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
615*1708Sstevel SBDP_DBG_MISC("failed to poweroff board: rv = %d\n", rv);
616*1708Sstevel sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
617*1708Sstevel NULL);
618*1708Sstevel }
619*1708Sstevel
620*1708Sstevel return (rv);
621*1708Sstevel }
622*1708Sstevel
623*1708Sstevel /*
624*1708Sstevel * Entry point from sbd. Ask the SC to poweron the board
625*1708Sstevel * Return the status from the SC
626*1708Sstevel */
627*1708Sstevel int
sbdp_poweron_board(sbdp_handle_t * hp)628*1708Sstevel sbdp_poweron_board(sbdp_handle_t *hp)
629*1708Sstevel {
630*1708Sstevel sbbc_msg_t request, *reqp = &request;
631*1708Sstevel sbbc_msg_t response, *resp = &response;
632*1708Sstevel int cmd_rev = -1;
633*1708Sstevel info2_t inform, *informp;
634*1708Sstevel int rv = 0;
635*1708Sstevel sbd_error_t *sep;
636*1708Sstevel int len;
637*1708Sstevel int board = hp->h_board;
638*1708Sstevel static fn_t f = "sbdp_poweron_board";
639*1708Sstevel
640*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
641*1708Sstevel
642*1708Sstevel sep = hp->h_err;
643*1708Sstevel /*
644*1708Sstevel * Check for options. If there are any, fail the operation
645*1708Sstevel */
646*1708Sstevel if (hp->h_opts != NULL && hp->h_opts->copts != NULL) {
647*1708Sstevel sbdp_set_err(sep, ESBD_INVAL_OPT, hp->h_opts->copts);
648*1708Sstevel return (-1);
649*1708Sstevel }
650*1708Sstevel
651*1708Sstevel if (sbdp_poweroff_wkaround)
652*1708Sstevel if (SG_BOARD_IS_CPU_TYPE(board)) {
653*1708Sstevel
654*1708Sstevel if ((rv = sbdp_poweroff_board(hp)) != 0)
655*1708Sstevel return (rv);
656*1708Sstevel }
657*1708Sstevel
658*1708Sstevel informp = &inform;
659*1708Sstevel informp->board = hp->h_board;
660*1708Sstevel informp->node = hp->h_wnode;
661*1708Sstevel informp->extra = SBDP_POWER_ON;
662*1708Sstevel
663*1708Sstevel len = sizeof (info2_t);
664*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_POWER, len, (caddr_t)informp);
665*1708Sstevel
666*1708Sstevel len = sizeof (cmd_rev);
667*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_POWER, len, (caddr_t)&cmd_rev);
668*1708Sstevel
669*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
670*1708Sstevel
671*1708Sstevel if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
672*1708Sstevel SBDP_DBG_MISC("failed to poweron board: rv = %d\n", rv);
673*1708Sstevel sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
674*1708Sstevel NULL);
675*1708Sstevel }
676*1708Sstevel
677*1708Sstevel return (rv);
678*1708Sstevel }
679*1708Sstevel
680*1708Sstevel int
sbdp_get_diag(sbdp_opts_t * opts)681*1708Sstevel sbdp_get_diag(sbdp_opts_t *opts)
682*1708Sstevel {
683*1708Sstevel char *cptr;
684*1708Sstevel static fn_t f = "sbdp_get_diag";
685*1708Sstevel
686*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
687*1708Sstevel
688*1708Sstevel if ((opts == NULL) || (opts->copts == NULL))
689*1708Sstevel return (SBDP_DIAG_NVCI);
690*1708Sstevel
691*1708Sstevel if ((cptr = strstr(opts->copts, "diag=")) != NULL) {
692*1708Sstevel /*
693*1708Sstevel * We have args and need to process them
694*1708Sstevel */
695*1708Sstevel cptr += strlen("diag=");
696*1708Sstevel
697*1708Sstevel if (strncmp(cptr, "off", sizeof ("off")) == 0) {
698*1708Sstevel return (SBDP_DIAG_OFF);
699*1708Sstevel } else if (strncmp(cptr, "init", sizeof ("init")) == 0) {
700*1708Sstevel return (SBDP_DIAG_INIT);
701*1708Sstevel } else if (strncmp(cptr, "quick", sizeof ("quick")) == 0) {
702*1708Sstevel return (SBDP_DIAG_QUICK);
703*1708Sstevel } else if (strncmp(cptr, "min", sizeof ("min")) == 0) {
704*1708Sstevel return (SBDP_DIAG_MIN);
705*1708Sstevel } else if (strncmp(cptr, "default", sizeof ("default")) == 0 ||
706*1708Sstevel strncmp(cptr, "max", sizeof ("max")) == 0) {
707*1708Sstevel return (SBDP_DIAG_DEFAULT);
708*1708Sstevel } else if (strncmp(cptr, "mem1", sizeof ("mem1")) == 0) {
709*1708Sstevel return (SBDP_DIAG_MEM1);
710*1708Sstevel } else if (strncmp(cptr, "mem2", sizeof ("mem2")) == 0) {
711*1708Sstevel return (SBDP_DIAG_MEM2);
712*1708Sstevel }
713*1708Sstevel }
714*1708Sstevel SBDP_DBG_MISC("error: unrecognized arg\n");
715*1708Sstevel return (-1);
716*1708Sstevel }
717*1708Sstevel
718*1708Sstevel
719*1708Sstevel /*
720*1708Sstevel * Entry point from sbd. Ask the SC to test the board. We still need to
721*1708Sstevel * worry about the diag level. The user may have changed it
722*1708Sstevel *
723*1708Sstevel * NOTE: The flag field has 2 different meanings whether we are dealing
724*1708Sstevel * with a cpu/mem board or an io board. In the case of a cpu/mem board it
725*1708Sstevel * means retest the board to the diag level specified. In the case of an IO
726*1708Sstevel * board, it means: Perform the necessary steps to prepare the board
727*1708Sstevel * for the claim without running POST at the diag level specified.
728*1708Sstevel */
729*1708Sstevel int
sbdp_test_board(sbdp_handle_t * hp,sbdp_opts_t * opts)730*1708Sstevel sbdp_test_board(sbdp_handle_t *hp, sbdp_opts_t *opts)
731*1708Sstevel {
732*1708Sstevel int board = hp->h_board;
733*1708Sstevel int node = hp->h_wnode;
734*1708Sstevel sbbc_msg_t request, *reqp = &request;
735*1708Sstevel sbbc_msg_t response, *resp = &response;
736*1708Sstevel int cmd_rev = -1;
737*1708Sstevel testb_t inform, *informp = &inform;
738*1708Sstevel int rv = 0;
739*1708Sstevel sbd_error_t *sep;
740*1708Sstevel int diag;
741*1708Sstevel int len;
742*1708Sstevel static fn_t f = "sbdp_test_board";
743*1708Sstevel
744*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
745*1708Sstevel
746*1708Sstevel sep = hp->h_err;
747*1708Sstevel
748*1708Sstevel diag = sbdp_get_diag(opts);
749*1708Sstevel
750*1708Sstevel if (diag == -1) {
751*1708Sstevel sbdp_set_err(sep, ESBD_INVAL_OPT, opts != NULL ?
752*1708Sstevel opts->copts : NULL);
753*1708Sstevel return (-1);
754*1708Sstevel }
755*1708Sstevel
756*1708Sstevel SBDP_DBG_MISC("Diag level is 0x%x\n", diag);
757*1708Sstevel
758*1708Sstevel informp->info.board = board;
759*1708Sstevel informp->info.node = node;
760*1708Sstevel
761*1708Sstevel informp->info.extra = diag;
762*1708Sstevel
763*1708Sstevel /*
764*1708Sstevel * Only force retest on CPU boards
765*1708Sstevel */
766*1708Sstevel if (SG_BOARD_IS_CPU_TYPE(board))
767*1708Sstevel informp->flag = 1;
768*1708Sstevel else {
769*1708Sstevel /*
770*1708Sstevel * For CPULESS IO pass the force to the SC
771*1708Sstevel */
772*1708Sstevel if (hp->h_flags & SBDP_IOCTL_FLAG_FORCE)
773*1708Sstevel informp->flag = 1;
774*1708Sstevel else
775*1708Sstevel informp->flag = 0;
776*1708Sstevel
777*1708Sstevel }
778*1708Sstevel
779*1708Sstevel len = sizeof (testb_t);
780*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_TEST_BD, len, (caddr_t)informp);
781*1708Sstevel
782*1708Sstevel
783*1708Sstevel len = sizeof (cmd_rev);
784*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_TEST_BD, len, (caddr_t)&cmd_rev);
785*1708Sstevel
786*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
787*1708Sstevel
788*1708Sstevel if (rv != 0 || (resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
789*1708Sstevel SBDP_DBG_MISC("failed to test board: rv = %d status = %d\n",
790*1708Sstevel rv, resp->msg_status);
791*1708Sstevel rv = resp->msg_status;
792*1708Sstevel sbdp_set_err(sep, sbdp_sc_err_translation(resp->msg_status),
793*1708Sstevel NULL);
794*1708Sstevel }
795*1708Sstevel
796*1708Sstevel return (rv);
797*1708Sstevel }
798*1708Sstevel
799*1708Sstevel /*
800*1708Sstevel * Request the SC to update POST's memory slice table by swapping
801*1708Sstevel * the entries for the two board numbers given
802*1708Sstevel * This is used when performing a copy-rename operation.
803*1708Sstevel */
804*1708Sstevel int
sbdp_swap_slices(int bd1,int bd2)805*1708Sstevel sbdp_swap_slices(int bd1, int bd2)
806*1708Sstevel {
807*1708Sstevel sbbc_msg_t request, *reqp = &request;
808*1708Sstevel sbbc_msg_t response, *resp = &response;
809*1708Sstevel int cmd_rev = -1;
810*1708Sstevel swap_slices_t inform, *informp = &inform;
811*1708Sstevel int rv;
812*1708Sstevel int len;
813*1708Sstevel static fn_t f = "sbdp_swap_slices";
814*1708Sstevel
815*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
816*1708Sstevel
817*1708Sstevel informp->board1 = bd1;
818*1708Sstevel informp->board2 = bd2;
819*1708Sstevel
820*1708Sstevel len = sizeof (swap_slices_t);
821*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_SWAP_SLICES, len, (caddr_t)informp);
822*1708Sstevel
823*1708Sstevel len = sizeof (cmd_rev);
824*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_SWAP_SLICES, len, (caddr_t)&cmd_rev);
825*1708Sstevel
826*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
827*1708Sstevel
828*1708Sstevel if (rv != 0 || (resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
829*1708Sstevel SBDP_DBG_MISC("failed to swap slices %d<->%d: rv = %d "
830*1708Sstevel "status = %d\n", bd1, bd2, rv, resp->msg_status);
831*1708Sstevel rv = sbdp_sc_err_translation(resp->msg_status);
832*1708Sstevel }
833*1708Sstevel
834*1708Sstevel return (rv);
835*1708Sstevel }
836*1708Sstevel
837*1708Sstevel int
sbdp_sc_err_translation(int error)838*1708Sstevel sbdp_sc_err_translation(int error)
839*1708Sstevel {
840*1708Sstevel int err;
841*1708Sstevel static fn_t f = "sbdp_sc_err_translation";
842*1708Sstevel
843*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
844*1708Sstevel
845*1708Sstevel switch (error) {
846*1708Sstevel case SG_MBOX_STATUS_HARDWARE_FAILURE:
847*1708Sstevel err = ESGT_HW_FAIL;
848*1708Sstevel break;
849*1708Sstevel case SG_MBOX_STATUS_ILLEGAL_PARAMETER:
850*1708Sstevel case SG_MBOX_STATUS_ILLEGAL_NODE:
851*1708Sstevel case SG_MBOX_STATUS_ILLEGAL_SLOT:
852*1708Sstevel err = ESGT_INVAL;
853*1708Sstevel break;
854*1708Sstevel case SG_MBOX_STATUS_BOARD_ACCESS_DENIED:
855*1708Sstevel err = ESGT_BD_ACCESS;
856*1708Sstevel break;
857*1708Sstevel case SG_MBOX_STATUS_STALE_CONTENTS:
858*1708Sstevel err = ESGT_STALE_CMP;
859*1708Sstevel break;
860*1708Sstevel case SG_MBOX_STATUS_STALE_OBJECT:
861*1708Sstevel err = ESGT_STALE_OBJ;
862*1708Sstevel break;
863*1708Sstevel case SG_MBOX_STATUS_NO_SEPROM_SPACE:
864*1708Sstevel err = ESGT_NO_SEPROM_SPACE;
865*1708Sstevel break;
866*1708Sstevel case SG_MBOX_STATUS_NO_MEMORY:
867*1708Sstevel err = ESGT_NO_MEM;
868*1708Sstevel break;
869*1708Sstevel case SG_MBOX_STATUS_NOT_SUPPORTED:
870*1708Sstevel err = ESGT_NOT_SUPP;
871*1708Sstevel break;
872*1708Sstevel case SG_MBOX_STATUS_COMMAND_FAILURE:
873*1708Sstevel default:
874*1708Sstevel err = ESGT_INTERNAL;
875*1708Sstevel break;
876*1708Sstevel }
877*1708Sstevel
878*1708Sstevel return (err);
879*1708Sstevel }
880*1708Sstevel
881*1708Sstevel int
sbdp_stop_cpu(processorid_t cpu)882*1708Sstevel sbdp_stop_cpu(processorid_t cpu)
883*1708Sstevel {
884*1708Sstevel sbbc_msg_t request, *reqp = &request;
885*1708Sstevel sbbc_msg_t response, *resp = &response;
886*1708Sstevel int rv = 0;
887*1708Sstevel int len;
888*1708Sstevel static fn_t f = "sbdp_stop_cpu";
889*1708Sstevel
890*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
891*1708Sstevel
892*1708Sstevel len = sizeof (processorid_t);
893*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_STOP_CPU, len, (caddr_t)&cpu);
894*1708Sstevel
895*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_STOP_CPU, 0, (caddr_t)NULL);
896*1708Sstevel
897*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
898*1708Sstevel
899*1708Sstevel if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
900*1708Sstevel SBDP_DBG_MISC("failed to stop cpu: rv = %d\n", rv);
901*1708Sstevel }
902*1708Sstevel
903*1708Sstevel return (rv);
904*1708Sstevel }
905*1708Sstevel
906*1708Sstevel int
sbdp_start_cpu(processorid_t cpu)907*1708Sstevel sbdp_start_cpu(processorid_t cpu)
908*1708Sstevel {
909*1708Sstevel sbbc_msg_t request, *reqp = &request;
910*1708Sstevel sbbc_msg_t response, *resp = &response;
911*1708Sstevel int rv = 0;
912*1708Sstevel int len;
913*1708Sstevel static fn_t f = "sbdp_start_cpu";
914*1708Sstevel
915*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
916*1708Sstevel
917*1708Sstevel len = sizeof (cpu);
918*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_START_CPU, len, (caddr_t)&cpu);
919*1708Sstevel
920*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_START_CPU, 0, (caddr_t)NULL);
921*1708Sstevel
922*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
923*1708Sstevel
924*1708Sstevel if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
925*1708Sstevel SBDP_DBG_MISC("failed to start cpu: rv = %d\n", rv);
926*1708Sstevel }
927*1708Sstevel
928*1708Sstevel return (rv);
929*1708Sstevel }
930*1708Sstevel
931*1708Sstevel /*
932*1708Sstevel * With the SIR implementation for CPU unconfigure, this mailbox
933*1708Sstevel * call is obsolete.
934*1708Sstevel */
935*1708Sstevel int
sbdp_start_cpu_pairs(processorid_t cpu)936*1708Sstevel sbdp_start_cpu_pairs(processorid_t cpu)
937*1708Sstevel {
938*1708Sstevel sbbc_msg_t request, *reqp = &request;
939*1708Sstevel sbbc_msg_t response, *resp = &response;
940*1708Sstevel int rv = 0;
941*1708Sstevel int len;
942*1708Sstevel static fn_t f = "sbdp_start_cpu_pairs";
943*1708Sstevel
944*1708Sstevel SBDP_DBG_FUNC("%s\n", f);
945*1708Sstevel
946*1708Sstevel len = sizeof (cpu);
947*1708Sstevel sbdp_init_msg_pkt(reqp, DR_MBOX_START_CPU_PAIRS, len, (caddr_t)&cpu);
948*1708Sstevel
949*1708Sstevel sbdp_init_msg_pkt(resp, DR_MBOX_START_CPU_PAIRS, 0, (caddr_t)NULL);
950*1708Sstevel
951*1708Sstevel rv = sbbc_mbox_request_response(reqp, resp, sbdp_mbox_wait);
952*1708Sstevel
953*1708Sstevel if (rv != 0 || (rv = resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
954*1708Sstevel SBDP_DBG_MISC("failed to start cpu pair: rv = %d\n", rv);
955*1708Sstevel }
956*1708Sstevel
957*1708Sstevel return (rv);
958*1708Sstevel }
959