xref: /onnv-gate/usr/src/lib/cfgadm_plugins/sbd/common/ap_seq.c (revision 12004:93f274d4a367)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*12004Sjiang.liu@intel.com  * Common Development and Distribution License (the "License").
6*12004Sjiang.liu@intel.com  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
220Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <assert.h>
270Sstevel@tonic-gate #include <ctype.h>
280Sstevel@tonic-gate #include <stdio.h>
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <string.h>
310Sstevel@tonic-gate #include <unistd.h>
320Sstevel@tonic-gate #include <macros.h>
330Sstevel@tonic-gate #include <dirent.h>
340Sstevel@tonic-gate #include <libgen.h>
350Sstevel@tonic-gate #include <libdevinfo.h>
360Sstevel@tonic-gate #define	CFGA_PLUGIN_LIB
370Sstevel@tonic-gate #include <config_admin.h>
380Sstevel@tonic-gate #include "ap.h"
390Sstevel@tonic-gate 
40*12004Sjiang.liu@intel.com #ifdef	__x86
41*12004Sjiang.liu@intel.com #include <libscf_priv.h>
42*12004Sjiang.liu@intel.com 
43*12004Sjiang.liu@intel.com static int fastreboot_disabled;
44*12004Sjiang.liu@intel.com #endif	/* __x86 */
45*12004Sjiang.liu@intel.com 
460Sstevel@tonic-gate static cfga_err_t
ap_suspend_check(apd_t * a,int cmd,int first,int last,int * suspend)470Sstevel@tonic-gate ap_suspend_check(apd_t *a, int cmd, int first, int last, int *suspend)
480Sstevel@tonic-gate {
490Sstevel@tonic-gate 	int c;
500Sstevel@tonic-gate 	int rc;
510Sstevel@tonic-gate 	int skip;
520Sstevel@tonic-gate 	int check;
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	skip = a->opts.skip;
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 	/*
570Sstevel@tonic-gate 	 * Check if any of the steps in the sequence
580Sstevel@tonic-gate 	 * may require a suspension of service and ask
590Sstevel@tonic-gate 	 * the user to confirm.
600Sstevel@tonic-gate 	 */
610Sstevel@tonic-gate 	for (check = 0, c = first; c <= last; c++)
620Sstevel@tonic-gate 		if (mask(c) & skip)
630Sstevel@tonic-gate 			continue;
640Sstevel@tonic-gate 		else if ((rc = ap_suspend_query(a, c, &check)) != CFGA_OK)
650Sstevel@tonic-gate 			return (rc);
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 	*suspend = check;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	/*
700Sstevel@tonic-gate 	 * If a suspend is required, ask for user confirmation.
710Sstevel@tonic-gate 	 * The force flag overrides the user confirmation.
720Sstevel@tonic-gate 	 */
730Sstevel@tonic-gate 	if (check && (!ap_getopt(a, OPT_FORCE)) && (!ap_confirm(a))) {
740Sstevel@tonic-gate 		ap_err(a, ERR_CMD_NACK, cmd);
750Sstevel@tonic-gate 		return (CFGA_NACK);
760Sstevel@tonic-gate 	}
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	return (CFGA_OK);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate 
810Sstevel@tonic-gate #define	AP_SEQ_OK	0
820Sstevel@tonic-gate #define	AP_SEQ_NULL	1
830Sstevel@tonic-gate #define	AP_SEQ_FAIL	-1
840Sstevel@tonic-gate 
850Sstevel@tonic-gate /*
860Sstevel@tonic-gate  * Sequence a cfgadm state change command into driver commands.
870Sstevel@tonic-gate  * The rstate and ostate of the AP are needed at this point
880Sstevel@tonic-gate  * in order to compute the proper sequence.
890Sstevel@tonic-gate  */
900Sstevel@tonic-gate static int
ap_seq_get(apd_t * a,int cmd,int * first,int * last)910Sstevel@tonic-gate ap_seq_get(apd_t *a, int cmd, int *first, int *last)
920Sstevel@tonic-gate {
930Sstevel@tonic-gate 	int done = 0;
940Sstevel@tonic-gate 	int f = CMD_NONE;
950Sstevel@tonic-gate 	int l = CMD_NONE;
960Sstevel@tonic-gate 	cfga_stat_t rs, os;
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	ap_state(a, &rs, &os);
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	switch (rs) {
1010Sstevel@tonic-gate 	case CFGA_STAT_EMPTY:
1020Sstevel@tonic-gate 		switch (os) {
1030Sstevel@tonic-gate 		case CFGA_STAT_UNCONFIGURED:
1040Sstevel@tonic-gate 			switch (cmd) {
1050Sstevel@tonic-gate 			case CMD_UNCONFIGURE:
1060Sstevel@tonic-gate 				done++;
1070Sstevel@tonic-gate 				break;
1080Sstevel@tonic-gate 			default:
1090Sstevel@tonic-gate 				break;
1100Sstevel@tonic-gate 			}
1110Sstevel@tonic-gate 			break;
1120Sstevel@tonic-gate 		default:
1130Sstevel@tonic-gate 			break;
1140Sstevel@tonic-gate 		}
1150Sstevel@tonic-gate 		break;
1160Sstevel@tonic-gate 	case CFGA_STAT_DISCONNECTED:
1170Sstevel@tonic-gate 		switch (os) {
1180Sstevel@tonic-gate 		case CFGA_STAT_UNCONFIGURED:
1190Sstevel@tonic-gate 			switch (cmd) {
1200Sstevel@tonic-gate 			case CMD_DISCONNECT:
1210Sstevel@tonic-gate 				/*
1220Sstevel@tonic-gate 				 * skip the disconnect command since
1230Sstevel@tonic-gate 				 * the rstate is already disconnected
1240Sstevel@tonic-gate 				 */
1250Sstevel@tonic-gate 				f = CMD_DISCONNECT;
1260Sstevel@tonic-gate 				a->opts.skip |= mask(CMD_DISCONNECT);
1270Sstevel@tonic-gate 				l = CMD_UNASSIGN;
1280Sstevel@tonic-gate 				break;
1290Sstevel@tonic-gate 			case CMD_UNCONFIGURE:
1300Sstevel@tonic-gate 				done++;
1310Sstevel@tonic-gate 				break;
1320Sstevel@tonic-gate 			case CMD_CONNECT:
1330Sstevel@tonic-gate 				f = CMD_ASSIGN;
1340Sstevel@tonic-gate 				l = CMD_CONNECT;
1350Sstevel@tonic-gate 				break;
1360Sstevel@tonic-gate 			case CMD_CONFIGURE:
1370Sstevel@tonic-gate 				f = CMD_ASSIGN;
1380Sstevel@tonic-gate 				l = CMD_RCM_CAP_ADD;
1390Sstevel@tonic-gate 				break;
1400Sstevel@tonic-gate 			default:
1410Sstevel@tonic-gate 				break;
1420Sstevel@tonic-gate 			}
1430Sstevel@tonic-gate 			break;
1440Sstevel@tonic-gate 		default:
1450Sstevel@tonic-gate 			break;
1460Sstevel@tonic-gate 		}
1470Sstevel@tonic-gate 		break;
1480Sstevel@tonic-gate 	case CFGA_STAT_CONNECTED:
1490Sstevel@tonic-gate 		switch (os) {
1500Sstevel@tonic-gate 		case CFGA_STAT_UNCONFIGURED:
1510Sstevel@tonic-gate 			switch (cmd) {
1520Sstevel@tonic-gate 			case CMD_CONNECT:
1530Sstevel@tonic-gate 			case CMD_UNCONFIGURE:
1540Sstevel@tonic-gate 				done++;
1550Sstevel@tonic-gate 				break;
1560Sstevel@tonic-gate 			case CMD_DISCONNECT:
1570Sstevel@tonic-gate 				f = CMD_DISCONNECT;
1580Sstevel@tonic-gate 				l = CMD_UNASSIGN;
1590Sstevel@tonic-gate 				break;
1600Sstevel@tonic-gate 			case CMD_CONFIGURE:
1610Sstevel@tonic-gate 				f = CMD_CONFIGURE;
1620Sstevel@tonic-gate 				l = CMD_RCM_CAP_ADD;
1630Sstevel@tonic-gate 				break;
1640Sstevel@tonic-gate 			default:
1650Sstevel@tonic-gate 				break;
1660Sstevel@tonic-gate 			}
1670Sstevel@tonic-gate 			break;
1680Sstevel@tonic-gate 		case CFGA_STAT_CONFIGURED:
1690Sstevel@tonic-gate 			switch (cmd) {
1700Sstevel@tonic-gate 			case CMD_CONNECT:
1710Sstevel@tonic-gate 				done++;
1720Sstevel@tonic-gate 				break;
1730Sstevel@tonic-gate 			case CMD_DISCONNECT:
1740Sstevel@tonic-gate 				f = CMD_SUSPEND_CHECK;
1750Sstevel@tonic-gate 				l = CMD_UNASSIGN;
1760Sstevel@tonic-gate 				break;
1770Sstevel@tonic-gate 			case CMD_CONFIGURE:
1780Sstevel@tonic-gate 				f = CMD_CONFIGURE;
1790Sstevel@tonic-gate 				l = CMD_RCM_CAP_ADD;
1800Sstevel@tonic-gate 				break;
1810Sstevel@tonic-gate 			case CMD_UNCONFIGURE:
1820Sstevel@tonic-gate 				f = CMD_SUSPEND_CHECK;
1830Sstevel@tonic-gate 				l = CMD_RCM_CAP_NOTIFY;
1840Sstevel@tonic-gate 				break;
1850Sstevel@tonic-gate 			default:
1860Sstevel@tonic-gate 				break;
1870Sstevel@tonic-gate 			}
1880Sstevel@tonic-gate 			break;
1890Sstevel@tonic-gate 		default:
1900Sstevel@tonic-gate 			break;
1910Sstevel@tonic-gate 		}
1920Sstevel@tonic-gate 		break;
1930Sstevel@tonic-gate 	default:
1940Sstevel@tonic-gate 		break;
1950Sstevel@tonic-gate 	}
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	if (f == CMD_NONE) {
1980Sstevel@tonic-gate 		if (done)
1990Sstevel@tonic-gate 			return (AP_SEQ_NULL);
2000Sstevel@tonic-gate 		ap_err(a, ERR_TRANS_INVAL, cmd);
2010Sstevel@tonic-gate 		return (AP_SEQ_FAIL);
2020Sstevel@tonic-gate 	}
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	*first = f;
2050Sstevel@tonic-gate 	*last = l;
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	DBG("ap_seq(%d, %d, %d, %p, %p) = (%d, %d)\n",
208*12004Sjiang.liu@intel.com 	    rs, os, cmd, (void *)first, (void *)last, f, l);
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	return (AP_SEQ_OK);
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate #define	DBG_RECOVER_MSG(f, l) \
2140Sstevel@tonic-gate 	DBG("Sequencing recovery: first = %s, last = %s\n", \
2150Sstevel@tonic-gate 	ap_cmd_name(f), ap_cmd_name(l))
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate cfga_err_t
ap_seq_exec(apd_t * a,int cmd,int first,int last)2180Sstevel@tonic-gate ap_seq_exec(apd_t *a, int cmd, int first, int last)
2190Sstevel@tonic-gate {
2200Sstevel@tonic-gate 	int c;
2210Sstevel@tonic-gate 	int skip;
2220Sstevel@tonic-gate 	int suspend;
2230Sstevel@tonic-gate 	int resume;
2240Sstevel@tonic-gate 	cfga_err_t rc;
2250Sstevel@tonic-gate 	int recover_f = CMD_NONE;	/* first recovery cmd */
2260Sstevel@tonic-gate 	int recover_l = CMD_NONE;	/* last recovery cmd */
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	suspend = 0;
2300Sstevel@tonic-gate 	resume = 0;
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	skip = a->opts.skip;
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	/*
2350Sstevel@tonic-gate 	 * The unassign step is skipped unless explicity requested
2360Sstevel@tonic-gate 	 * either by a -x request or as an option to a disconnect
2370Sstevel@tonic-gate 	 * request.
2380Sstevel@tonic-gate 	 */
2390Sstevel@tonic-gate 	if (cmd != CMD_UNASSIGN && ap_getopt(a, OPT_UNASSIGN) == 0)
2400Sstevel@tonic-gate 		skip |= mask(CMD_UNASSIGN);
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	/*
2430Sstevel@tonic-gate 	 * Check for platform options
2440Sstevel@tonic-gate 	 */
2450Sstevel@tonic-gate 	rc = ap_platopts_check(a, first, last);
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	if (rc != CFGA_OK) {
2480Sstevel@tonic-gate 		goto done;
2490Sstevel@tonic-gate 	}
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	for (c = first; c <= last; c++) {
2520Sstevel@tonic-gate 		if (mask(c) & skip) {
2530Sstevel@tonic-gate 			ap_msg(a, MSG_SKIP, c, a->target);
2540Sstevel@tonic-gate 			continue;
2550Sstevel@tonic-gate 		}
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 		DBG("exec %s\n", ap_cmd_name(c));
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 		/*
2600Sstevel@tonic-gate 		 * If the suspend operation does not
2610Sstevel@tonic-gate 		 * succeed, resume any devices already
2620Sstevel@tonic-gate 		 * suspended as well as the device on
2630Sstevel@tonic-gate 		 * which the operation failed.
2640Sstevel@tonic-gate 		 */
2650Sstevel@tonic-gate 		switch (c) {
2660Sstevel@tonic-gate 		case CMD_SUSPEND_CHECK:
2670Sstevel@tonic-gate 			/*
2680Sstevel@tonic-gate 			 * Check whether the user allows a suspend
2690Sstevel@tonic-gate 			 * operation if the suspend is required.
2700Sstevel@tonic-gate 			 * Next step is to allow RCM clients to
2710Sstevel@tonic-gate 			 * interpose on the suspend operation.
2720Sstevel@tonic-gate 			 */
2730Sstevel@tonic-gate 			rc = ap_suspend_check(a, cmd,
274*12004Sjiang.liu@intel.com 			    first + 1, last, &suspend);
2750Sstevel@tonic-gate 			break;
2760Sstevel@tonic-gate 		case CMD_RCM_SUSPEND:
2770Sstevel@tonic-gate 			if (suspend && ((rc = ap_rcm_ctl(a, c)) == CFGA_OK)) {
2780Sstevel@tonic-gate 				/*
2790Sstevel@tonic-gate 				 * Mark the fact that a suspend operation
2800Sstevel@tonic-gate 				 * is required, and that RCM clients have
2810Sstevel@tonic-gate 				 * allowed the suspend.
2820Sstevel@tonic-gate 				 */
2830Sstevel@tonic-gate 				ap_setopt(a, OPT_SUSPEND_OK);
2840Sstevel@tonic-gate 				resume++;
2850Sstevel@tonic-gate 			}
2860Sstevel@tonic-gate 			break;
2870Sstevel@tonic-gate 		case CMD_RCM_RESUME:
2880Sstevel@tonic-gate 			if (resume) {
2890Sstevel@tonic-gate 				(void) ap_rcm_ctl(a, c);
2900Sstevel@tonic-gate 				resume--;
2910Sstevel@tonic-gate 			}
2920Sstevel@tonic-gate 			break;
2930Sstevel@tonic-gate 		case CMD_RCM_OFFLINE:
2940Sstevel@tonic-gate 		case CMD_RCM_CAP_DEL:
2950Sstevel@tonic-gate 			rc = ap_rcm_ctl(a, c);
2960Sstevel@tonic-gate 			break;
2970Sstevel@tonic-gate 		case CMD_RCM_ONLINE:
2980Sstevel@tonic-gate 		case CMD_RCM_CAP_ADD:
2990Sstevel@tonic-gate 		case CMD_RCM_REMOVE:
3000Sstevel@tonic-gate 		case CMD_RCM_CAP_NOTIFY:
3010Sstevel@tonic-gate 			(void) ap_rcm_ctl(a, c);
3020Sstevel@tonic-gate 			break;
303*12004Sjiang.liu@intel.com 
304*12004Sjiang.liu@intel.com #ifdef	__x86
305*12004Sjiang.liu@intel.com 		/*
306*12004Sjiang.liu@intel.com 		 * Disable fast reboot if a CPU/MEM/IOH hotplug event happens.
307*12004Sjiang.liu@intel.com 		 * Note: this is a temporary solution and will be revised when
308*12004Sjiang.liu@intel.com 		 * fast reboot can support CPU/MEM/IOH DR operations in the
309*12004Sjiang.liu@intel.com 		 * future.
310*12004Sjiang.liu@intel.com 		 *
311*12004Sjiang.liu@intel.com 		 * ACPI BIOS generates some static ACPI tables, such as MADT,
312*12004Sjiang.liu@intel.com 		 * SRAT and SLIT, to describe the system hardware configuration
313*12004Sjiang.liu@intel.com 		 * on power-on. When a CPU/MEM/IOH hotplug event happens, those
314*12004Sjiang.liu@intel.com 		 * static tables won't be updated and will become stale.
315*12004Sjiang.liu@intel.com 		 *
316*12004Sjiang.liu@intel.com 		 * If we reset the system by fast reboot, BIOS will have no
317*12004Sjiang.liu@intel.com 		 * chance to regenerate those staled static tables. Fast reboot
318*12004Sjiang.liu@intel.com 		 * can't tolerate such inconsistency between staled ACPI tables
319*12004Sjiang.liu@intel.com 		 * and real hardware configuration yet.
320*12004Sjiang.liu@intel.com 		 *
321*12004Sjiang.liu@intel.com 		 * A temporary solution is introduced to disable fast reboot if
322*12004Sjiang.liu@intel.com 		 * CPU/MEM/IOH hotplug event happens. This solution should be
323*12004Sjiang.liu@intel.com 		 * revised when fast reboot is enhanced to support CPU/MEM/IOH
324*12004Sjiang.liu@intel.com 		 * DR operations.
325*12004Sjiang.liu@intel.com 		 */
326*12004Sjiang.liu@intel.com 		case CMD_ASSIGN:
327*12004Sjiang.liu@intel.com 		case CMD_POWERON:
328*12004Sjiang.liu@intel.com 		case CMD_POWEROFF:
329*12004Sjiang.liu@intel.com 		case CMD_UNASSIGN:
330*12004Sjiang.liu@intel.com 			if (!fastreboot_disabled &&
331*12004Sjiang.liu@intel.com 			    scf_fastreboot_default_set_transient(B_FALSE) ==
332*12004Sjiang.liu@intel.com 			    SCF_SUCCESS) {
333*12004Sjiang.liu@intel.com 				fastreboot_disabled = 1;
334*12004Sjiang.liu@intel.com 			}
335*12004Sjiang.liu@intel.com 			/* FALLTHROUGH */
336*12004Sjiang.liu@intel.com #endif	/* __x86 */
337*12004Sjiang.liu@intel.com 
3380Sstevel@tonic-gate 		default:
3390Sstevel@tonic-gate 			rc = ap_ioctl(a, c);
3400Sstevel@tonic-gate 			break;
3410Sstevel@tonic-gate 		}
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 		if (rc != CFGA_OK)
3440Sstevel@tonic-gate 			break;
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 	}
3470Sstevel@tonic-gate done:
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	if (resume)
3500Sstevel@tonic-gate 		(void) ap_rcm_ctl(a, CMD_RCM_RESUME);
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	/*
3530Sstevel@tonic-gate 	 * Check if any operations failed. If so, attempt to rollback
3540Sstevel@tonic-gate 	 * to previously known states.
3550Sstevel@tonic-gate 	 * Note: The rollback is currently limited to RCM operations.
3560Sstevel@tonic-gate 	 */
3570Sstevel@tonic-gate 	if (rc != CFGA_OK) {
3580Sstevel@tonic-gate 		if (c == CMD_UNCONFIGURE ||
3590Sstevel@tonic-gate 		    c == CMD_RCM_OFFLINE ||
3600Sstevel@tonic-gate 		    c == CMD_RCM_CAP_DEL) {
3610Sstevel@tonic-gate 			DBG("ap_seq_exec: %s failed\n", ap_cmd_name(c));
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 			switch (c) {
3640Sstevel@tonic-gate 			case CMD_UNCONFIGURE:
3650Sstevel@tonic-gate 				/*
3660Sstevel@tonic-gate 				 * If the unconfigure operation fails, perform
3670Sstevel@tonic-gate 				 * an RCM_ONLINE and RCM_CAP_NOTIFY only. This
3680Sstevel@tonic-gate 				 * keeps RCM clients consistent with the domain.
3690Sstevel@tonic-gate 				 */
3700Sstevel@tonic-gate 				recover_f = CMD_RCM_ONLINE;
3710Sstevel@tonic-gate 				recover_l = CMD_RCM_ONLINE;
3720Sstevel@tonic-gate 				DBG_RECOVER_MSG(recover_f, recover_l);
3730Sstevel@tonic-gate 				(void) ap_seq_exec(a, cmd, recover_f,
3740Sstevel@tonic-gate 				    recover_l);
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 				recover_f = CMD_RCM_CAP_NOTIFY;
3770Sstevel@tonic-gate 				recover_l = CMD_RCM_CAP_NOTIFY;
3780Sstevel@tonic-gate 				DBG_RECOVER_MSG(recover_f, recover_l);
3790Sstevel@tonic-gate 				(void) ap_seq_exec(a, cmd, recover_f,
3800Sstevel@tonic-gate 				    recover_l);
3810Sstevel@tonic-gate 				break;
3820Sstevel@tonic-gate 			case CMD_RCM_OFFLINE:
3830Sstevel@tonic-gate 				recover_f = CMD_RCM_ONLINE;
3840Sstevel@tonic-gate 				recover_l = CMD_RCM_CAP_ADD;
3850Sstevel@tonic-gate 				DBG_RECOVER_MSG(recover_f, recover_l);
3860Sstevel@tonic-gate 				(void) ap_seq_exec(a, cmd, recover_f,
3870Sstevel@tonic-gate 				    recover_l);
3880Sstevel@tonic-gate 				break;
3890Sstevel@tonic-gate 			case CMD_RCM_CAP_DEL:
3900Sstevel@tonic-gate 				recover_f = CMD_RCM_CAP_ADD;
3910Sstevel@tonic-gate 				recover_l = CMD_RCM_CAP_ADD;
3920Sstevel@tonic-gate 				DBG_RECOVER_MSG(recover_f, recover_l);
3930Sstevel@tonic-gate 				(void) ap_seq_exec(a, cmd, recover_f,
3940Sstevel@tonic-gate 				    recover_l);
3950Sstevel@tonic-gate 				break;
3960Sstevel@tonic-gate 			default:
3970Sstevel@tonic-gate 				break;
3980Sstevel@tonic-gate 			}
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 			DBG("recovery complete!\n");
4010Sstevel@tonic-gate 		}
4020Sstevel@tonic-gate 	}
4030Sstevel@tonic-gate 	return (rc);
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate cfga_err_t
ap_cmd_exec(apd_t * a,int cmd)4070Sstevel@tonic-gate ap_cmd_exec(apd_t *a, int cmd)
4080Sstevel@tonic-gate {
4090Sstevel@tonic-gate 	return (ap_seq_exec(a, cmd, cmd, cmd));
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate cfga_err_t
ap_cmd_seq(apd_t * a,int cmd)4130Sstevel@tonic-gate ap_cmd_seq(apd_t *a, int cmd)
4140Sstevel@tonic-gate {
4150Sstevel@tonic-gate 	int first, last;
4160Sstevel@tonic-gate 	cfga_err_t rc;
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	switch (ap_seq_get(a, cmd, &first, &last)) {
4190Sstevel@tonic-gate 	case AP_SEQ_OK:
4200Sstevel@tonic-gate 		rc = ap_seq_exec(a, cmd, first, last);
4210Sstevel@tonic-gate 		break;
4220Sstevel@tonic-gate 	case AP_SEQ_NULL:
4230Sstevel@tonic-gate 		rc = CFGA_OK;
4240Sstevel@tonic-gate 		break;
4250Sstevel@tonic-gate 	case AP_SEQ_FAIL:
4260Sstevel@tonic-gate 	default:
4270Sstevel@tonic-gate 		rc = CFGA_LIB_ERROR;
4280Sstevel@tonic-gate 		break;
4290Sstevel@tonic-gate 	}
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	return (rc);
4320Sstevel@tonic-gate }
433