xref: /onnv-gate/usr/src/uts/common/avs/ns/sdbc/sd_conf.c (revision 9093:cd587b0bd19c)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*9093SRamana.Srikanth@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237836SJohn.Forte@Sun.COM  * Use is subject to license terms.
247836SJohn.Forte@Sun.COM  */
257836SJohn.Forte@Sun.COM 
267836SJohn.Forte@Sun.COM #include <sys/types.h>
277836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
287836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
297836SJohn.Forte@Sun.COM #include <sys/errno.h>
307836SJohn.Forte@Sun.COM #include <sys/kmem.h>
317836SJohn.Forte@Sun.COM #include <sys/ddi.h>
327836SJohn.Forte@Sun.COM 
337836SJohn.Forte@Sun.COM #include <sys/nsc_thread.h>
347836SJohn.Forte@Sun.COM #include "sd_bcache.h"
357836SJohn.Forte@Sun.COM #include "sd_ft.h"
367836SJohn.Forte@Sun.COM #include "sd_misc.h"
377836SJohn.Forte@Sun.COM #include "sd_pcu.h"
387836SJohn.Forte@Sun.COM #include "sd_io.h"
397836SJohn.Forte@Sun.COM #include "sd_bio.h"
407836SJohn.Forte@Sun.COM #include "sd_trace.h"
417836SJohn.Forte@Sun.COM #include "sd_tdaemon.h"
427836SJohn.Forte@Sun.COM #include <sys/nsctl/nsctl.h>
437836SJohn.Forte@Sun.COM 
447836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
457836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_k.h>
467836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
477836SJohn.Forte@Sun.COM #include <sys/nsctl/safestore.h>
487836SJohn.Forte@Sun.COM 
497836SJohn.Forte@Sun.COM extern int sdbc_use_dmchain;
507836SJohn.Forte@Sun.COM 
517836SJohn.Forte@Sun.COM int _sd_cblock_shift = 0;
527836SJohn.Forte@Sun.COM 
537836SJohn.Forte@Sun.COM int _SD_SELF_HOST = _SD_NO_HOST;
547836SJohn.Forte@Sun.COM int _SD_MIRROR_HOST = _SD_NO_HOST;
557836SJohn.Forte@Sun.COM int _SD_NUM_REM;
567836SJohn.Forte@Sun.COM int _sd_nodes_configured;
577836SJohn.Forte@Sun.COM int _sdbc_gateway_wblocks;
587836SJohn.Forte@Sun.COM 
597836SJohn.Forte@Sun.COM int _SD_NETS = 0;
607836SJohn.Forte@Sun.COM 
617836SJohn.Forte@Sun.COM /*
627836SJohn.Forte@Sun.COM  * Normally we unregister memory at deconfig time. By setting this non-zero
637836SJohn.Forte@Sun.COM  * it will be delayed until unload time.
647836SJohn.Forte@Sun.COM  */
657836SJohn.Forte@Sun.COM int _sdbc_memtype_deconfigure_delayed = 0;
667836SJohn.Forte@Sun.COM 
677836SJohn.Forte@Sun.COM nsc_mem_t *sdbc_iobuf_mem, *sdbc_hash_mem;
687836SJohn.Forte@Sun.COM nsc_mem_t *sdbc_local_mem, *sdbc_stats_mem, *sdbc_cache_mem;
697836SJohn.Forte@Sun.COM nsc_mem_t *sdbc_info_mem;
707836SJohn.Forte@Sun.COM 
717836SJohn.Forte@Sun.COM _sd_cache_param_t _sd_cache_config;
727836SJohn.Forte@Sun.COM 
737836SJohn.Forte@Sun.COM kmutex_t _sdbc_config_lock;
747836SJohn.Forte@Sun.COM volatile int _sd_cache_dem_cnt;
757836SJohn.Forte@Sun.COM 
767836SJohn.Forte@Sun.COM #if !defined(m88k) || defined(lint)
777836SJohn.Forte@Sun.COM volatile int _sd_cache_initialized;
787836SJohn.Forte@Sun.COM #endif
797836SJohn.Forte@Sun.COM 
807836SJohn.Forte@Sun.COM static blind_t sdbc_power;
817836SJohn.Forte@Sun.COM 
827836SJohn.Forte@Sun.COM static
837836SJohn.Forte@Sun.COM nsc_def_t _sdbc_power_def[] = {
847836SJohn.Forte@Sun.COM 	"Power_Lost",	(uintptr_t)_sdbc_power_lost,	0,
857836SJohn.Forte@Sun.COM 	"Power_OK",	(uintptr_t)_sdbc_power_ok,	0,
867836SJohn.Forte@Sun.COM 	"Power_Down",	(uintptr_t)_sdbc_power_down,	0,
877836SJohn.Forte@Sun.COM 	0,		0,		0
887836SJohn.Forte@Sun.COM };
897836SJohn.Forte@Sun.COM 
907836SJohn.Forte@Sun.COM /*
917836SJohn.Forte@Sun.COM  * Forward declare all statics that are used before defined to enforce
927836SJohn.Forte@Sun.COM  * parameter checking
937836SJohn.Forte@Sun.COM  * Some (if not all) of these could be removed if the code were reordered
947836SJohn.Forte@Sun.COM  */
957836SJohn.Forte@Sun.COM 
967836SJohn.Forte@Sun.COM int _sd_fill_pattern(caddr_t addr, uint_t pat, uint_t size);
977836SJohn.Forte@Sun.COM static void _sdbc_nodeid_deconfigure(void);
987836SJohn.Forte@Sun.COM static void _sdbc_nodeid_configure(void);
997836SJohn.Forte@Sun.COM static void _sdbc_thread_deconfigure(void);
1007836SJohn.Forte@Sun.COM static int _sdbc_thread_configure(void);
1017836SJohn.Forte@Sun.COM void sst_deinit();
1027836SJohn.Forte@Sun.COM 
1037836SJohn.Forte@Sun.COM ss_common_config_t safestore_config;
1047836SJohn.Forte@Sun.COM safestore_ops_t *sdbc_safestore;
1057836SJohn.Forte@Sun.COM 
1067836SJohn.Forte@Sun.COM /*
1077836SJohn.Forte@Sun.COM  * _sdbc_memtype_configure - register with the sd layer the types of memory
1087836SJohn.Forte@Sun.COM  * we want to use. If any of the critical memory types can't be registered
1097836SJohn.Forte@Sun.COM  * we return non-zero otherwise 0.
1107836SJohn.Forte@Sun.COM  */
1117836SJohn.Forte@Sun.COM static int
_sdbc_memtype_configure(void)1127836SJohn.Forte@Sun.COM _sdbc_memtype_configure(void)
1137836SJohn.Forte@Sun.COM {
1147836SJohn.Forte@Sun.COM 
1157836SJohn.Forte@Sun.COM 	if ((sdbc_info_mem = nsc_register_mem("sdbc:info",
1167836SJohn.Forte@Sun.COM 	    NSC_MEM_GLOBAL, KM_NOSLEEP)) == NULL) {
1177836SJohn.Forte@Sun.COM 		return (EINVAL);
1187836SJohn.Forte@Sun.COM 	}
1197836SJohn.Forte@Sun.COM 
1207836SJohn.Forte@Sun.COM 	sdbc_local_mem = nsc_register_mem("sdbc:local", NSC_MEM_LOCAL, 0);
1217836SJohn.Forte@Sun.COM 	sdbc_stats_mem = nsc_register_mem("sdbc:stats", NSC_MEM_LOCAL, 0);
1227836SJohn.Forte@Sun.COM 	sdbc_iobuf_mem = nsc_register_mem("sdbc:iobuf", NSC_MEM_LOCAL, 0);
1237836SJohn.Forte@Sun.COM 
1247836SJohn.Forte@Sun.COM 	sdbc_cache_mem = nsc_register_mem("sdbc:cache", NSC_MEM_LOCAL, 0);
1257836SJohn.Forte@Sun.COM 
1267836SJohn.Forte@Sun.COM 	sdbc_hash_mem = nsc_register_mem("sdbc:hash", NSC_MEM_LOCAL, 0);
1277836SJohn.Forte@Sun.COM 
1287836SJohn.Forte@Sun.COM 	return (0);
1297836SJohn.Forte@Sun.COM }
1307836SJohn.Forte@Sun.COM 
1317836SJohn.Forte@Sun.COM /*
1327836SJohn.Forte@Sun.COM  * _sdbc_memtype_deconfigure - undo the effects of _sdbc_memtype_configure.
1337836SJohn.Forte@Sun.COM  */
1347836SJohn.Forte@Sun.COM void
_sdbc_memtype_deconfigure(void)1357836SJohn.Forte@Sun.COM _sdbc_memtype_deconfigure(void)
1367836SJohn.Forte@Sun.COM {
1377836SJohn.Forte@Sun.COM 
1387836SJohn.Forte@Sun.COM 	if (sdbc_hash_mem)
1397836SJohn.Forte@Sun.COM 		nsc_unregister_mem(sdbc_hash_mem);
1407836SJohn.Forte@Sun.COM 	if (sdbc_iobuf_mem)
1417836SJohn.Forte@Sun.COM 		nsc_unregister_mem(sdbc_iobuf_mem);
1427836SJohn.Forte@Sun.COM 	if (sdbc_cache_mem)
1437836SJohn.Forte@Sun.COM 		nsc_unregister_mem(sdbc_cache_mem);
1447836SJohn.Forte@Sun.COM 	if (sdbc_stats_mem)
1457836SJohn.Forte@Sun.COM 		nsc_unregister_mem(sdbc_stats_mem);
1467836SJohn.Forte@Sun.COM 	if (sdbc_local_mem)
1477836SJohn.Forte@Sun.COM 		nsc_unregister_mem(sdbc_local_mem);
1487836SJohn.Forte@Sun.COM 	if (sdbc_info_mem)
1497836SJohn.Forte@Sun.COM 		nsc_unregister_mem(sdbc_info_mem);
1507836SJohn.Forte@Sun.COM 
1517836SJohn.Forte@Sun.COM 	sdbc_info_mem = NULL;
1527836SJohn.Forte@Sun.COM 	sdbc_local_mem = sdbc_stats_mem = sdbc_cache_mem = NULL;
1537836SJohn.Forte@Sun.COM 	sdbc_iobuf_mem = sdbc_hash_mem = NULL;
1547836SJohn.Forte@Sun.COM 
1557836SJohn.Forte@Sun.COM }
1567836SJohn.Forte@Sun.COM 
1577836SJohn.Forte@Sun.COM 
1587836SJohn.Forte@Sun.COM /*
1597836SJohn.Forte@Sun.COM  * figure out what kind of safe storage we need
1607836SJohn.Forte@Sun.COM  */
1617836SJohn.Forte@Sun.COM uint_t
sdbc_determine_safestore()1627836SJohn.Forte@Sun.COM sdbc_determine_safestore()
1637836SJohn.Forte@Sun.COM {
1647836SJohn.Forte@Sun.COM 	return (SS_M_RAM | SS_T_NONE);
1657836SJohn.Forte@Sun.COM }
1667836SJohn.Forte@Sun.COM 
1677836SJohn.Forte@Sun.COM static void
sd_setup_ssconfig()1687836SJohn.Forte@Sun.COM sd_setup_ssconfig()
1697836SJohn.Forte@Sun.COM {
1707836SJohn.Forte@Sun.COM 	safestore_config.ssc_client_psize = BLK_SIZE(1);
1717836SJohn.Forte@Sun.COM 
1727836SJohn.Forte@Sun.COM 	if (_sd_cache_config.write_cache)
1737836SJohn.Forte@Sun.COM 		safestore_config.ssc_wsize =
174*9093SRamana.Srikanth@Sun.COM 		    _sd_cache_config.write_cache * MEGABYTE;
1757836SJohn.Forte@Sun.COM 	else
1767836SJohn.Forte@Sun.COM 		safestore_config.ssc_wsize =
177*9093SRamana.Srikanth@Sun.COM 		    (_sd_cache_config.cache_mem[_SD_NO_NET] * MEGABYTE)/2;
1787836SJohn.Forte@Sun.COM 	safestore_config.ssc_maxfiles = sdbc_max_devs;
1797836SJohn.Forte@Sun.COM 	safestore_config.ssc_pattern = _sd_cache_config.fill_pattern;
1807836SJohn.Forte@Sun.COM 	safestore_config.ssc_flag = _sd_cache_config.gen_pattern ?
1817836SJohn.Forte@Sun.COM 	    SS_GENPATTERN : 0;
1827836SJohn.Forte@Sun.COM }
1837836SJohn.Forte@Sun.COM 
1847836SJohn.Forte@Sun.COM /*
1857836SJohn.Forte@Sun.COM  * _sdbc_configure - process the ioctl that describes the configuration
1867836SJohn.Forte@Sun.COM  * for the cache. This is the main driver routine for cache configuration
1877836SJohn.Forte@Sun.COM  * Return 0 on success, otherwise nonzero.
1887836SJohn.Forte@Sun.COM  *
1897836SJohn.Forte@Sun.COM  */
1907836SJohn.Forte@Sun.COM int
_sdbc_configure(_sd_cache_param_t * uptr,_sdbc_config_t * mgmt,spcs_s_info_t spcs_kstatus)1917836SJohn.Forte@Sun.COM _sdbc_configure(_sd_cache_param_t *uptr,
1927836SJohn.Forte@Sun.COM 	_sdbc_config_t *mgmt, spcs_s_info_t spcs_kstatus)
1937836SJohn.Forte@Sun.COM {
1947836SJohn.Forte@Sun.COM 	int cache_bytes;
1957836SJohn.Forte@Sun.COM 	nsc_io_t *io;
1967836SJohn.Forte@Sun.COM 	char itmp[16];
1977836SJohn.Forte@Sun.COM 	char itmp2[16];
1987836SJohn.Forte@Sun.COM 	int i;
1997836SJohn.Forte@Sun.COM 	uint_t ss_type;
2007836SJohn.Forte@Sun.COM 	int rc;
2017836SJohn.Forte@Sun.COM 
2027836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&_sdbc_config_lock));
2037836SJohn.Forte@Sun.COM 
2047836SJohn.Forte@Sun.COM 	_sd_print(1, "sdbc(_sdbc_configure) _SD_MAGIC 0x%x\n", _SD_MAGIC);
2057836SJohn.Forte@Sun.COM 
2067836SJohn.Forte@Sun.COM 	_sd_ioset = 0;
2077836SJohn.Forte@Sun.COM 	if (_sd_cache_initialized) {
2087836SJohn.Forte@Sun.COM 		spcs_s_add(spcs_kstatus, SDBC_EALREADY);
2097836SJohn.Forte@Sun.COM 		rc = EALREADY;
2107836SJohn.Forte@Sun.COM 		goto out;
2117836SJohn.Forte@Sun.COM 	}
2127836SJohn.Forte@Sun.COM 
2137836SJohn.Forte@Sun.COM 	ASSERT((uptr != NULL) || (mgmt != NULL));
2147836SJohn.Forte@Sun.COM 
2157836SJohn.Forte@Sun.COM 	if (uptr) {
2167836SJohn.Forte@Sun.COM 		if (copyin(uptr, &_sd_cache_config,
2177836SJohn.Forte@Sun.COM 		    sizeof (_sd_cache_param_t))) {
2187836SJohn.Forte@Sun.COM 			rc = EFAULT;
2197836SJohn.Forte@Sun.COM 			goto out;
2207836SJohn.Forte@Sun.COM 		}
2217836SJohn.Forte@Sun.COM 	} else {
2227836SJohn.Forte@Sun.COM 		bzero(&_sd_cache_config, sizeof (_sd_cache_config));
2237836SJohn.Forte@Sun.COM 
2247836SJohn.Forte@Sun.COM 		/* copy in mgmt config info */
2257836SJohn.Forte@Sun.COM 
2267836SJohn.Forte@Sun.COM 		_sd_cache_config.magic = mgmt->magic;
2277836SJohn.Forte@Sun.COM 		_sd_cache_config.threads = mgmt->threads;
2287836SJohn.Forte@Sun.COM 
2297836SJohn.Forte@Sun.COM 		for (i = 0; i < CACHE_MEM_PAD; i++) {
2307836SJohn.Forte@Sun.COM 			_sd_cache_config.cache_mem[i] = mgmt->cache_mem[i];
2317836SJohn.Forte@Sun.COM 		}
2327836SJohn.Forte@Sun.COM 
2337836SJohn.Forte@Sun.COM 		/* fake the rest as a single node config */
2347836SJohn.Forte@Sun.COM 
2357836SJohn.Forte@Sun.COM 		_sd_cache_config.nodes_conf[0] = nsc_node_id();
2367836SJohn.Forte@Sun.COM 		_sd_cache_config.num_nodes = 1;
2377836SJohn.Forte@Sun.COM 	}
2387836SJohn.Forte@Sun.COM 
2397836SJohn.Forte@Sun.COM 	/*
2407836SJohn.Forte@Sun.COM 	 * Check that the requested cache size doesn't break the code.
2417836SJohn.Forte@Sun.COM 	 * This test can be refined once the cache size is stored in variables
2427836SJohn.Forte@Sun.COM 	 * larger than an int.
2437836SJohn.Forte@Sun.COM 	 */
2447836SJohn.Forte@Sun.COM 	for (i = 0; i < MAX_CACHE_NET; i++) {
2457836SJohn.Forte@Sun.COM 		if (_sd_cache_config.cache_mem[i] < 0) {
246*9093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!_sdbc_configure: "
2477836SJohn.Forte@Sun.COM 			    "negative cache size (%d) for net %d",
2487836SJohn.Forte@Sun.COM 			    _sd_cache_config.cache_mem[i], i);
2497836SJohn.Forte@Sun.COM 			spcs_s_add(spcs_kstatus, SDBC_ENONETMEM);
2507836SJohn.Forte@Sun.COM 			rc = SDBC_ENONETMEM;
2517836SJohn.Forte@Sun.COM 			goto out;
2527836SJohn.Forte@Sun.COM 		}
2537836SJohn.Forte@Sun.COM 		if (_sd_cache_config.cache_mem[i] > MAX_CACHE_SIZE) {
2547836SJohn.Forte@Sun.COM 			_sd_cache_config.cache_mem[i] = MAX_CACHE_SIZE;
255*9093SRamana.Srikanth@Sun.COM 			cmn_err(CE_WARN, "!_sdbc_configure: "
2567836SJohn.Forte@Sun.COM 			    "cache size limited to %d megabytes for net %d",
2577836SJohn.Forte@Sun.COM 			    MAX_CACHE_SIZE, i);
2587836SJohn.Forte@Sun.COM 		}
2597836SJohn.Forte@Sun.COM 	}
2607836SJohn.Forte@Sun.COM 
2617836SJohn.Forte@Sun.COM 	if (_sd_cache_config.blk_size == 0)
2627836SJohn.Forte@Sun.COM 		_sd_cache_config.blk_size = 8192;
2637836SJohn.Forte@Sun.COM 
2647836SJohn.Forte@Sun.COM 	if (_sd_cache_config.procs == 0)
2657836SJohn.Forte@Sun.COM 		_sd_cache_config.procs = 16;
2667836SJohn.Forte@Sun.COM 
2677836SJohn.Forte@Sun.COM #if !defined(_SD_8K_BLKSIZE)
2687836SJohn.Forte@Sun.COM 	if (_sd_cache_config.blk_size != 4096) {
2697836SJohn.Forte@Sun.COM #else
2707836SJohn.Forte@Sun.COM 	if (_sd_cache_config.blk_size != 8192) {
2717836SJohn.Forte@Sun.COM #endif
2727836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(_sd_cache_config.blk_size, itmp,
2737836SJohn.Forte@Sun.COM 		    sizeof (itmp), 0);
2747836SJohn.Forte@Sun.COM 		spcs_s_add(spcs_kstatus, SDBC_ESIZE, itmp);
2757836SJohn.Forte@Sun.COM 		rc = SDBC_EENABLEFAIL;
2767836SJohn.Forte@Sun.COM 		goto out;
2777836SJohn.Forte@Sun.COM 	}
2787836SJohn.Forte@Sun.COM 	if (((_sd_cblock_shift =
2797836SJohn.Forte@Sun.COM 	    get_high_bit(_sd_cache_config.blk_size)) == -1) ||
2807836SJohn.Forte@Sun.COM 	    (_sd_cache_config.blk_size != (1 << _sd_cblock_shift))) {
2817836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(_sd_cache_config.blk_size, itmp,
2827836SJohn.Forte@Sun.COM 		    sizeof (itmp), 0);
2837836SJohn.Forte@Sun.COM 		spcs_s_add(spcs_kstatus, SDBC_ESIZE, itmp);
2847836SJohn.Forte@Sun.COM 		rc = SDBC_EENABLEFAIL;
2857836SJohn.Forte@Sun.COM 		goto out;
2867836SJohn.Forte@Sun.COM 	}
2877836SJohn.Forte@Sun.COM 
2887836SJohn.Forte@Sun.COM 	if (_sd_cache_config.magic != _SD_MAGIC) {
2897836SJohn.Forte@Sun.COM 		rc = SDBC_EMAGIC;
2907836SJohn.Forte@Sun.COM 		goto out;
2917836SJohn.Forte@Sun.COM 	}
2927836SJohn.Forte@Sun.COM 
2937836SJohn.Forte@Sun.COM 	sdbc_use_dmchain = (_sd_cache_config.reserved1 & CFG_USE_DMCHAIN);
2947836SJohn.Forte@Sun.COM 	sdbc_static_cache =  (_sd_cache_config.reserved1 & CFG_STATIC_CACHE);
2957836SJohn.Forte@Sun.COM 
2967836SJohn.Forte@Sun.COM 	_sdbc_nodeid_configure();
2977836SJohn.Forte@Sun.COM 
2987836SJohn.Forte@Sun.COM 	if (_SD_SELF_HOST > nsc_max_nodeid ||
2997836SJohn.Forte@Sun.COM 	    _SD_MIRROR_HOST > nsc_max_nodeid) {
3007836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring((_SD_SELF_HOST > nsc_max_nodeid ?
3017836SJohn.Forte@Sun.COM 		    _SD_SELF_HOST : _SD_MIRROR_HOST), itmp, sizeof (itmp), 0);
3027836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(
3037836SJohn.Forte@Sun.COM 		    nsc_max_nodeid, itmp2, sizeof (itmp2), 0);
3047836SJohn.Forte@Sun.COM 		spcs_s_add(spcs_kstatus, SDBC_EINVHOSTID, itmp, itmp2);
3057836SJohn.Forte@Sun.COM 		rc = SDBC_EENABLEFAIL;
3067836SJohn.Forte@Sun.COM 		goto out;
3077836SJohn.Forte@Sun.COM 	}
3087836SJohn.Forte@Sun.COM 
3097836SJohn.Forte@Sun.COM 
3107836SJohn.Forte@Sun.COM 	if (_SD_SELF_HOST == _SD_MIRROR_HOST) {
3117836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(
3127836SJohn.Forte@Sun.COM 		    _SD_SELF_HOST, itmp, sizeof (itmp), 0);
3137836SJohn.Forte@Sun.COM 		(void) spcs_s_inttostring(
3147836SJohn.Forte@Sun.COM 		    _SD_MIRROR_HOST, itmp2, sizeof (itmp2), 0);
3157836SJohn.Forte@Sun.COM 		spcs_s_add(spcs_kstatus, SDBC_ENOTSAME, itmp, itmp2);
3167836SJohn.Forte@Sun.COM 		rc = SDBC_EENABLEFAIL;
3177836SJohn.Forte@Sun.COM 		goto out;
3187836SJohn.Forte@Sun.COM 	}
3197836SJohn.Forte@Sun.COM 
3207836SJohn.Forte@Sun.COM 	/* initialize the safestore modules */
3217836SJohn.Forte@Sun.COM 	sst_init();
3227836SJohn.Forte@Sun.COM 
3237836SJohn.Forte@Sun.COM 	/* figure out which kind of safestore we need to use */
3247836SJohn.Forte@Sun.COM 	ss_type = sdbc_determine_safestore();
3257836SJohn.Forte@Sun.COM 
3267836SJohn.Forte@Sun.COM tryss:
3277836SJohn.Forte@Sun.COM 	/* open and configure the safestore module */
3287836SJohn.Forte@Sun.COM 	if ((sdbc_safestore = sst_open(ss_type, 0)) == NULL) {
329*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!cannot open safestore module for type %x",
3307836SJohn.Forte@Sun.COM 		    ss_type);
3317836SJohn.Forte@Sun.COM 		rc = SDBC_EENABLEFAIL;
3327836SJohn.Forte@Sun.COM 		goto out;
3337836SJohn.Forte@Sun.COM 	} else {
3347836SJohn.Forte@Sun.COM 		sd_setup_ssconfig();
3357836SJohn.Forte@Sun.COM 		if (SSOP_CONFIGURE(sdbc_safestore, &safestore_config,
3367836SJohn.Forte@Sun.COM 		    spcs_kstatus)) {
3377836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
338*9093SRamana.Srikanth@Sun.COM 			    "!cannot configure safestore module for type %x",
3397836SJohn.Forte@Sun.COM 			    ss_type);
3407836SJohn.Forte@Sun.COM 			(void) sst_close(sdbc_safestore);
3417836SJohn.Forte@Sun.COM 
3427836SJohn.Forte@Sun.COM 			/* try ram if possible, otherwise return */
3437836SJohn.Forte@Sun.COM 			if ((ss_type & (SS_M_RAM | SS_T_NONE)) ==
3447836SJohn.Forte@Sun.COM 			    (SS_M_RAM | SS_T_NONE)) {
3457836SJohn.Forte@Sun.COM 				rc = SDBC_EENABLEFAIL;
3467836SJohn.Forte@Sun.COM 				goto out;
3477836SJohn.Forte@Sun.COM 			}
3487836SJohn.Forte@Sun.COM 
3497836SJohn.Forte@Sun.COM 			ss_type = (SS_M_RAM | SS_T_NONE);
3507836SJohn.Forte@Sun.COM 			goto tryss;
3517836SJohn.Forte@Sun.COM 		}
3527836SJohn.Forte@Sun.COM 	}
3537836SJohn.Forte@Sun.COM 
3547836SJohn.Forte@Sun.COM 	if (SAFESTORE_LOCAL(sdbc_safestore))
3557836SJohn.Forte@Sun.COM 		_SD_MIRROR_HOST = _SD_NO_HOST;
3567836SJohn.Forte@Sun.COM 
3577836SJohn.Forte@Sun.COM 	ASSERT(safestore_config.ssc_ss_psize <= UINT16_MAX);	/* LINTED */
3587836SJohn.Forte@Sun.COM 	_sd_net_config.sn_psize = safestore_config.ssc_ss_psize;
3597836SJohn.Forte@Sun.COM 
3607836SJohn.Forte@Sun.COM 
3617836SJohn.Forte@Sun.COM 	_sd_net_config.sn_csize =
362*9093SRamana.Srikanth@Sun.COM 	    _sd_cache_config.cache_mem[_SD_NO_NET] * MEGABYTE;
3637836SJohn.Forte@Sun.COM 	_sd_net_config.sn_cpages =
364*9093SRamana.Srikanth@Sun.COM 	    _sd_net_config.sn_csize / BLK_SIZE(1);
3657836SJohn.Forte@Sun.COM 
3667836SJohn.Forte@Sun.COM 	_sd_net_config.sn_configured = 1;
3677836SJohn.Forte@Sun.COM 	cache_bytes = _sd_net_config.sn_cpages * BLK_SIZE(1);
3687836SJohn.Forte@Sun.COM 
3697836SJohn.Forte@Sun.COM 	if (_sdbc_memtype_configure()) {
3707836SJohn.Forte@Sun.COM 		rc = EINVAL;
3717836SJohn.Forte@Sun.COM 		goto out;
3727836SJohn.Forte@Sun.COM 	}
3737836SJohn.Forte@Sun.COM 
3747836SJohn.Forte@Sun.COM 	if ((rc = _sdbc_iobuf_configure(_sd_cache_config.iobuf))) {
3757836SJohn.Forte@Sun.COM 		if (rc == -1) {
3767836SJohn.Forte@Sun.COM 			rc = SDBC_ENOIOBMEM;
3777836SJohn.Forte@Sun.COM 			goto out;
3787836SJohn.Forte@Sun.COM 		}
3797836SJohn.Forte@Sun.COM 		if (rc == -2) {
3807836SJohn.Forte@Sun.COM 			rc = SDBC_ENOIOBCB;
3817836SJohn.Forte@Sun.COM 			goto out;
3827836SJohn.Forte@Sun.COM 		}
3837836SJohn.Forte@Sun.COM 
3847836SJohn.Forte@Sun.COM 	}
3857836SJohn.Forte@Sun.COM 
3867836SJohn.Forte@Sun.COM 	if (_sdbc_handles_configure()) {
3877836SJohn.Forte@Sun.COM 		rc = SDBC_ENOHANDLEMEM;
3887836SJohn.Forte@Sun.COM 		goto out;
3897836SJohn.Forte@Sun.COM 	}
3907836SJohn.Forte@Sun.COM 
3917836SJohn.Forte@Sun.COM 	_sd_cache_dem_cnt = 0;
3927836SJohn.Forte@Sun.COM 
3937836SJohn.Forte@Sun.COM 
3947836SJohn.Forte@Sun.COM 	/*
3957836SJohn.Forte@Sun.COM 	 * nvmem support:
3967836SJohn.Forte@Sun.COM 	 * if the cache did not shutdown properly we mark it as dirty.
3977836SJohn.Forte@Sun.COM 	 * this must be done before _sdbc_cache_configure() so it can
3987836SJohn.Forte@Sun.COM 	 * refresh sd_info_mem and sd_file_mem from nvmem if necsssary,
3997836SJohn.Forte@Sun.COM 	 * and before _sdbc_ft_configure() so the ft thread will do a recovery.
4007836SJohn.Forte@Sun.COM 	 *
4017836SJohn.Forte@Sun.COM 	 */
4027836SJohn.Forte@Sun.COM 	if (SAFESTORE_RECOVERY(sdbc_safestore)) {
4037836SJohn.Forte@Sun.COM 		_sdbc_set_warm_start();
4047836SJohn.Forte@Sun.COM 		_sdbc_ft_hold_io = 1;
4057836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
406*9093SRamana.Srikanth@Sun.COM 		    "!sdbc(_sdbc_configure) cache marked dirty after"
4077836SJohn.Forte@Sun.COM 		    " incomplete shutdown");
4087836SJohn.Forte@Sun.COM 	}
4097836SJohn.Forte@Sun.COM 
4107836SJohn.Forte@Sun.COM 	if ((rc = _sdbc_cache_configure(cache_bytes / BLK_SIZE(1),
4117836SJohn.Forte@Sun.COM 	    spcs_kstatus))) {
4127836SJohn.Forte@Sun.COM 		goto out;
4137836SJohn.Forte@Sun.COM 	}
4147836SJohn.Forte@Sun.COM 
4157836SJohn.Forte@Sun.COM 
4167836SJohn.Forte@Sun.COM 	/* ST_ALERT trace buffer */
4177836SJohn.Forte@Sun.COM 	if (_sdbc_tr_configure(-1 /* SDT_INV_CD */) != 0) {
4187836SJohn.Forte@Sun.COM 		rc = EINVAL;
4197836SJohn.Forte@Sun.COM 		goto out;
4207836SJohn.Forte@Sun.COM 	}
4217836SJohn.Forte@Sun.COM 
4227836SJohn.Forte@Sun.COM 	if (_sdbc_thread_configure()) {
4237836SJohn.Forte@Sun.COM 		rc = SDBC_EFLUSHTHRD;
4247836SJohn.Forte@Sun.COM 		goto out;
4257836SJohn.Forte@Sun.COM 	}
4267836SJohn.Forte@Sun.COM 
4277836SJohn.Forte@Sun.COM 	if (_sdbc_flush_configure()) {
4287836SJohn.Forte@Sun.COM 		rc = EINVAL;
4297836SJohn.Forte@Sun.COM 		goto out;
4307836SJohn.Forte@Sun.COM 	}
4317836SJohn.Forte@Sun.COM 
4327836SJohn.Forte@Sun.COM 	if (rc = _sdbc_dealloc_configure_dm()) {
4337836SJohn.Forte@Sun.COM 		goto out;
4347836SJohn.Forte@Sun.COM 	}
4357836SJohn.Forte@Sun.COM 
4367836SJohn.Forte@Sun.COM 	if (_sd_cache_config.test_demons)
4377836SJohn.Forte@Sun.COM 		if (_sdbc_tdaemon_configure(_sd_cache_config.test_demons)) {
4387836SJohn.Forte@Sun.COM 			rc = EINVAL;
4397836SJohn.Forte@Sun.COM 			goto out;
4407836SJohn.Forte@Sun.COM 		}
4417836SJohn.Forte@Sun.COM 
4427836SJohn.Forte@Sun.COM 
4437836SJohn.Forte@Sun.COM 	_sd_cache_initialized = 1;
4447836SJohn.Forte@Sun.COM 
4457836SJohn.Forte@Sun.COM 	sdbc_power = nsc_register_power("sdbc", _sdbc_power_def);
4467836SJohn.Forte@Sun.COM 
4477836SJohn.Forte@Sun.COM 	if (_sdbc_ft_configure() != 0) {
4487836SJohn.Forte@Sun.COM 		rc = EINVAL;
4497836SJohn.Forte@Sun.COM 		goto out;
4507836SJohn.Forte@Sun.COM 	}
4517836SJohn.Forte@Sun.COM 
4527836SJohn.Forte@Sun.COM 	/*
4537836SJohn.Forte@Sun.COM 	 * try to control the race between the ft thread
4547836SJohn.Forte@Sun.COM 	 * and threads that will open the devices that the ft thread
4557836SJohn.Forte@Sun.COM 	 * may be recovering.  this synchronizing with the ft thread
4567836SJohn.Forte@Sun.COM 	 * prevents sd_cadmin from returning until ft has opened
4577836SJohn.Forte@Sun.COM 	 * the recovery devices, so if other apps wait for sd_cadmin
4587836SJohn.Forte@Sun.COM 	 * to complete the race is prevented.
4597836SJohn.Forte@Sun.COM 	 */
4607836SJohn.Forte@Sun.COM 	mutex_enter(&_sdbc_ft_hold_io_lk);
4617836SJohn.Forte@Sun.COM 	while (_sdbc_ft_hold_io) {
4627836SJohn.Forte@Sun.COM 		cv_wait(&_sdbc_ft_hold_io_cv, &_sdbc_ft_hold_io_lk);
4637836SJohn.Forte@Sun.COM 	}
4647836SJohn.Forte@Sun.COM 
4657836SJohn.Forte@Sun.COM 	io = nsc_register_io("sdbc", NSC_SDBC_ID|NSC_FILTER,
4667836SJohn.Forte@Sun.COM 	    _sd_sdbc_def);
4677836SJohn.Forte@Sun.COM 
4687836SJohn.Forte@Sun.COM 	if (io) sdbc_io = io;
4697836SJohn.Forte@Sun.COM 
4707836SJohn.Forte@Sun.COM 	mutex_exit(&_sdbc_ft_hold_io_lk);
4717836SJohn.Forte@Sun.COM 
4727836SJohn.Forte@Sun.COM #ifdef DEBUG
473*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!sd_config: Cache has been configured");
4747836SJohn.Forte@Sun.COM #endif
4757836SJohn.Forte@Sun.COM 
4767836SJohn.Forte@Sun.COM 	rc = 0;
4777836SJohn.Forte@Sun.COM 
4787836SJohn.Forte@Sun.COM out:
4797836SJohn.Forte@Sun.COM 	return (rc);
4807836SJohn.Forte@Sun.COM }
4817836SJohn.Forte@Sun.COM 
4827836SJohn.Forte@Sun.COM /*
4837836SJohn.Forte@Sun.COM  * _sdbc_deconfigure - Put the cache back to the unconfigured state. Release
4847836SJohn.Forte@Sun.COM  * any memory we allocated as part of the configuration process (but not the
4857836SJohn.Forte@Sun.COM  * load/init process).  Put globals back to unconfigured state and shut down
4867836SJohn.Forte@Sun.COM  * any processes/threads we have running.
4877836SJohn.Forte@Sun.COM  *
4887836SJohn.Forte@Sun.COM  * Since the cache has loaded we know that global lock/sv's are present and
4897836SJohn.Forte@Sun.COM  * we can use them to produce an orderly deconfiguration.
4907836SJohn.Forte@Sun.COM  *
4917836SJohn.Forte@Sun.COM  * NOTE: this routine and its callee should always be capable of reversing
4927836SJohn.Forte@Sun.COM  * the effects of _sdbc_configure no matter what partially configured
4937836SJohn.Forte@Sun.COM  * state might be present.
4947836SJohn.Forte@Sun.COM  *
4957836SJohn.Forte@Sun.COM  */
4967836SJohn.Forte@Sun.COM int
4977836SJohn.Forte@Sun.COM _sdbc_deconfigure(spcs_s_info_t spcs_kstatus)
4987836SJohn.Forte@Sun.COM {
4997836SJohn.Forte@Sun.COM 	int i;
5007836SJohn.Forte@Sun.COM 	_sd_cd_info_t *cdi;
5017836SJohn.Forte@Sun.COM 	int rc;
5027836SJohn.Forte@Sun.COM 	int pinneddata = 0;
5037836SJohn.Forte@Sun.COM 	uint_t saved_hint;
5047836SJohn.Forte@Sun.COM 
5057836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&_sdbc_config_lock));
5067836SJohn.Forte@Sun.COM 
5077836SJohn.Forte@Sun.COM #ifdef DEBUG
508*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!SD cache being deconfigured.");
5097836SJohn.Forte@Sun.COM #endif
5107836SJohn.Forte@Sun.COM 
5117836SJohn.Forte@Sun.COM 	/* check if there is pinned data and our mirror is down */
5127836SJohn.Forte@Sun.COM 	if (_sd_cache_files && _sd_is_mirror_down()) {
5137836SJohn.Forte@Sun.COM 		for (i = 0; i < sdbc_max_devs; i++) {
5147836SJohn.Forte@Sun.COM 			cdi = &(_sd_cache_files[i]);
5157836SJohn.Forte@Sun.COM 			if (cdi->cd_info == NULL)
5167836SJohn.Forte@Sun.COM 				continue;
5177836SJohn.Forte@Sun.COM 			/*
5187836SJohn.Forte@Sun.COM 			 * if (!(cdi->cd_info->sh_failed))
5197836SJohn.Forte@Sun.COM 			 *	continue;
5207836SJohn.Forte@Sun.COM 			 */
5217836SJohn.Forte@Sun.COM 			if (!(_SD_CD_ALL_WRITES(i)))
5227836SJohn.Forte@Sun.COM 				continue;
5237836SJohn.Forte@Sun.COM 			spcs_s_add(spcs_kstatus, SDBC_EPINNED,
524*9093SRamana.Srikanth@Sun.COM 			    cdi->cd_info->sh_filename);
5257836SJohn.Forte@Sun.COM 			rc = SDBC_EDISABLEFAIL;
5267836SJohn.Forte@Sun.COM 			goto out;
5277836SJohn.Forte@Sun.COM 		}
5287836SJohn.Forte@Sun.COM 	}
5297836SJohn.Forte@Sun.COM 
5307836SJohn.Forte@Sun.COM 	/* remember hint setting for restoration in case shutdown fails */
5317836SJohn.Forte@Sun.COM 	(void) _sd_get_node_hint(&saved_hint);
5327836SJohn.Forte@Sun.COM 
5337836SJohn.Forte@Sun.COM 	(void) _sd_set_node_hint(NSC_FORCED_WRTHRU);
5347836SJohn.Forte@Sun.COM 
5357836SJohn.Forte@Sun.COM 
5367836SJohn.Forte@Sun.COM 	/* TODO - there is a possible race between deconfig and power hits... */
5377836SJohn.Forte@Sun.COM 
5387836SJohn.Forte@Sun.COM 	if (sdbc_power)
5397836SJohn.Forte@Sun.COM 		(void) nsc_unregister_power(sdbc_power);
5407836SJohn.Forte@Sun.COM 
5417836SJohn.Forte@Sun.COM 
5427836SJohn.Forte@Sun.COM 	if (sdbc_io) {
5437836SJohn.Forte@Sun.COM 		rc = nsc_unregister_io(sdbc_io, NSC_PCATCH);
5447836SJohn.Forte@Sun.COM 		if (rc == 0)
5457836SJohn.Forte@Sun.COM 			sdbc_io = NULL;
5467836SJohn.Forte@Sun.COM 		else {
5477836SJohn.Forte@Sun.COM 			if (rc == EUSERS)
5487836SJohn.Forte@Sun.COM 				spcs_s_add(spcs_kstatus, SDBC_EABUFS);
5497836SJohn.Forte@Sun.COM 
5507836SJohn.Forte@Sun.COM 			spcs_s_add(spcs_kstatus, SDBC_EUNREG);
5517836SJohn.Forte@Sun.COM 
5527836SJohn.Forte@Sun.COM 			/* Re-register-power if it was register before. */
5537836SJohn.Forte@Sun.COM 			if (sdbc_power) {
5547836SJohn.Forte@Sun.COM 				sdbc_power = nsc_register_power("sdbc",
555*9093SRamana.Srikanth@Sun.COM 				    _sdbc_power_def);
5567836SJohn.Forte@Sun.COM 			}
5577836SJohn.Forte@Sun.COM 
5587836SJohn.Forte@Sun.COM 			/* Remove NSC_FORCED_WRTHRU if we set it */
5597836SJohn.Forte@Sun.COM 			(void) _sd_clear_node_hint(
560*9093SRamana.Srikanth@Sun.COM 			    (~saved_hint) & _SD_HINT_MASK);
5617836SJohn.Forte@Sun.COM 
5627836SJohn.Forte@Sun.COM 			rc = SDBC_EDISABLEFAIL;
5637836SJohn.Forte@Sun.COM 			goto out;
5647836SJohn.Forte@Sun.COM 		}
5657836SJohn.Forte@Sun.COM 	}
5667836SJohn.Forte@Sun.COM 
5677836SJohn.Forte@Sun.COM 	sdbc_power = NULL;
5687836SJohn.Forte@Sun.COM 
5697836SJohn.Forte@Sun.COM #if defined(_SD_FAULT_RES)
5707836SJohn.Forte@Sun.COM 	_sd_remote_disable(0);	/* notify mirror to forced_wrthru */
5717836SJohn.Forte@Sun.COM #endif
5727836SJohn.Forte@Sun.COM 	/*
5737836SJohn.Forte@Sun.COM 	 * close devices, deconfigure processes, wait for exits
5747836SJohn.Forte@Sun.COM 	 */
5757836SJohn.Forte@Sun.COM 	_sdbc_tdaemon_deconfigure();
5767836SJohn.Forte@Sun.COM 
5777836SJohn.Forte@Sun.COM 	if (_sd_cache_files) {
5787836SJohn.Forte@Sun.COM 		for (i = 0; i < sdbc_max_devs; i++) {
5797836SJohn.Forte@Sun.COM 			if (FILE_OPENED(i) && ((rc = _sd_close(i)) > 0)) {
580*9093SRamana.Srikanth@Sun.COM 				cmn_err(CE_WARN, "!sdbc(_sd_deconfigure)"
5817836SJohn.Forte@Sun.COM 				    " %d not closed (%d)\n", i, rc);
5827836SJohn.Forte@Sun.COM 			}
5837836SJohn.Forte@Sun.COM 		}
5847836SJohn.Forte@Sun.COM 	}
5857836SJohn.Forte@Sun.COM 
5867836SJohn.Forte@Sun.COM 	/*
5877836SJohn.Forte@Sun.COM 	 * look for pinned data
5887836SJohn.Forte@Sun.COM 	 * TODO sort this out for multinode systems.
5897836SJohn.Forte@Sun.COM 	 * cannot shutdown with pinned data on multinode.
5907836SJohn.Forte@Sun.COM 	 * the state of pinned data should be determined in
5917836SJohn.Forte@Sun.COM 	 * the close operation.
5927836SJohn.Forte@Sun.COM 	 */
5937836SJohn.Forte@Sun.COM 	if (_sd_cache_files) {
5947836SJohn.Forte@Sun.COM 		for (i = 0; i < sdbc_max_devs; i++) {
5957836SJohn.Forte@Sun.COM 			cdi = &(_sd_cache_files[i]);
5967836SJohn.Forte@Sun.COM 			if (cdi->cd_info == NULL)
5977836SJohn.Forte@Sun.COM 				continue;
5987836SJohn.Forte@Sun.COM 			/*
5997836SJohn.Forte@Sun.COM 			 * if (!(cdi->cd_info->sh_failed))
6007836SJohn.Forte@Sun.COM 			 *	continue;
6017836SJohn.Forte@Sun.COM 			 */
6027836SJohn.Forte@Sun.COM 			if (!(_SD_CD_ALL_WRITES(i)))
6037836SJohn.Forte@Sun.COM 				continue;
6047836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
605*9093SRamana.Srikanth@Sun.COM 			    "!sdbc(_sd_deconfigure) Pinned Data on cd %d(%s)",
6067836SJohn.Forte@Sun.COM 			    i, cdi->cd_info->sh_filename);
6077836SJohn.Forte@Sun.COM 			pinneddata++;
6087836SJohn.Forte@Sun.COM 		}
6097836SJohn.Forte@Sun.COM 	}
6107836SJohn.Forte@Sun.COM 
6117836SJohn.Forte@Sun.COM 	_sd_cache_initialized = 0;
6127836SJohn.Forte@Sun.COM 
6137836SJohn.Forte@Sun.COM 	_sdbc_ft_deconfigure();
6147836SJohn.Forte@Sun.COM 
6157836SJohn.Forte@Sun.COM 	_sdbc_flush_deconfigure();
6167836SJohn.Forte@Sun.COM 	_sdbc_thread_deconfigure();
6177836SJohn.Forte@Sun.COM 
6187836SJohn.Forte@Sun.COM 	mutex_enter(&_sd_cache_lock);
6197836SJohn.Forte@Sun.COM 
6207836SJohn.Forte@Sun.COM 	while (_sd_cache_dem_cnt > 0) {
6217836SJohn.Forte@Sun.COM 		mutex_exit(&_sd_cache_lock);
6227836SJohn.Forte@Sun.COM 		(void) nsc_delay_sig(HZ/2);
6237836SJohn.Forte@Sun.COM 		mutex_enter(&_sd_cache_lock);
6247836SJohn.Forte@Sun.COM 	}
6257836SJohn.Forte@Sun.COM 	mutex_exit(&_sd_cache_lock);
6267836SJohn.Forte@Sun.COM 
6277836SJohn.Forte@Sun.COM 	/*
6287836SJohn.Forte@Sun.COM 	 * remove all dynamically allocated cache data memory
6297836SJohn.Forte@Sun.COM 	 * there should be no i/o at this point
6307836SJohn.Forte@Sun.COM 	 */
6317836SJohn.Forte@Sun.COM 	_sdbc_dealloc_deconfigure_dm();
6327836SJohn.Forte@Sun.COM 	/*
6337836SJohn.Forte@Sun.COM 	 * At this point no thread of control should be active in the cache
6347836SJohn.Forte@Sun.COM 	 * but us (unless they are blocked on the config lock).
6357836SJohn.Forte@Sun.COM 	 */
6367836SJohn.Forte@Sun.COM 
6377836SJohn.Forte@Sun.COM 
6387836SJohn.Forte@Sun.COM #if defined(_SD_FAULT_RES)
6397836SJohn.Forte@Sun.COM 	_sd_remote_disable(1);	/* notify mirror I/O shutdown complete */
6407836SJohn.Forte@Sun.COM #endif
6417836SJohn.Forte@Sun.COM 
6427836SJohn.Forte@Sun.COM #define	KEEP_TRACES	0	/* set to 1 keep traces after deconfig */
6437836SJohn.Forte@Sun.COM #if !KEEP_TRACES
6447836SJohn.Forte@Sun.COM 	/*
6457836SJohn.Forte@Sun.COM 	 * This needs to happen before we unregister the memory.
6467836SJohn.Forte@Sun.COM 	 */
6477836SJohn.Forte@Sun.COM 	_sdbc_tr_deconfigure();
6487836SJohn.Forte@Sun.COM #endif
6497836SJohn.Forte@Sun.COM 
6507836SJohn.Forte@Sun.COM 
6517836SJohn.Forte@Sun.COM 	/* delete/free hash table, cache blocks, etc */
6527836SJohn.Forte@Sun.COM 	_sdbc_cache_deconfigure();
6537836SJohn.Forte@Sun.COM 
6547836SJohn.Forte@Sun.COM 	_sdbc_handles_deconfigure();
6557836SJohn.Forte@Sun.COM 
6567836SJohn.Forte@Sun.COM 	_sdbc_iobuf_deconfigure();
6577836SJohn.Forte@Sun.COM 
6587836SJohn.Forte@Sun.COM #if !KEEP_TRACES
6597836SJohn.Forte@Sun.COM 	if (!_sdbc_memtype_deconfigure_delayed)
6607836SJohn.Forte@Sun.COM 		_sdbc_memtype_deconfigure();
6617836SJohn.Forte@Sun.COM #else
6627836SJohn.Forte@Sun.COM 	_sdbc_memtype_deconfigure_delayed = 1;
6637836SJohn.Forte@Sun.COM #endif
6647836SJohn.Forte@Sun.COM 
6657836SJohn.Forte@Sun.COM 	/*
6667836SJohn.Forte@Sun.COM 	 * Call ss deconfig(),
6677836SJohn.Forte@Sun.COM 	 * check for valid pointer in case _sdbc_configure()
6687836SJohn.Forte@Sun.COM 	 * failed before safestrore system was initialized.
6697836SJohn.Forte@Sun.COM 	 */
6707836SJohn.Forte@Sun.COM 	if (sdbc_safestore)
6717836SJohn.Forte@Sun.COM 		SSOP_DECONFIGURE(sdbc_safestore, pinneddata);
6727836SJohn.Forte@Sun.COM 
6737836SJohn.Forte@Sun.COM 	/* tear down safestore system */
6747836SJohn.Forte@Sun.COM 	sst_deinit();
6757836SJohn.Forte@Sun.COM 
6767836SJohn.Forte@Sun.COM 	_sdbc_nodeid_deconfigure();
6777836SJohn.Forte@Sun.COM 
6787836SJohn.Forte@Sun.COM 	bzero(&_sd_cache_config, sizeof (_sd_cache_param_t));
6797836SJohn.Forte@Sun.COM 
6807836SJohn.Forte@Sun.COM 	_SD_SELF_HOST = _SD_MIRROR_HOST = _SD_NO_HOST;
6817836SJohn.Forte@Sun.COM 	_SD_NETS = 0;
6827836SJohn.Forte@Sun.COM 	_sd_cblock_shift = 0;
6837836SJohn.Forte@Sun.COM 	_sd_node_hint = 0;
6847836SJohn.Forte@Sun.COM 
6857836SJohn.Forte@Sun.COM #ifdef DEBUG
686*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_NOTE, "!SD cache deconfigured.");
6877836SJohn.Forte@Sun.COM #endif
6887836SJohn.Forte@Sun.COM 
6897836SJohn.Forte@Sun.COM 	rc = 0;
6907836SJohn.Forte@Sun.COM 
6917836SJohn.Forte@Sun.COM out:
6927836SJohn.Forte@Sun.COM 	return (rc);
6937836SJohn.Forte@Sun.COM }
6947836SJohn.Forte@Sun.COM 
6957836SJohn.Forte@Sun.COM 
6967836SJohn.Forte@Sun.COM 
6977836SJohn.Forte@Sun.COM static int
6987836SJohn.Forte@Sun.COM find_low_bit(int mask, int start)
6997836SJohn.Forte@Sun.COM {
7007836SJohn.Forte@Sun.COM 	for (; start < 32; start++)
7017836SJohn.Forte@Sun.COM 		if ((mask & (1 << start)))
7027836SJohn.Forte@Sun.COM 			break;
7037836SJohn.Forte@Sun.COM 
7047836SJohn.Forte@Sun.COM 	return (start);
7057836SJohn.Forte@Sun.COM }
7067836SJohn.Forte@Sun.COM 
7077836SJohn.Forte@Sun.COM int
7087836SJohn.Forte@Sun.COM get_high_bit(int size)
7097836SJohn.Forte@Sun.COM {
7107836SJohn.Forte@Sun.COM 	int lowbit;
7117836SJohn.Forte@Sun.COM 	int newblk = size;
7127836SJohn.Forte@Sun.COM 	int highbit = -1;
7137836SJohn.Forte@Sun.COM 	int next_high = 0;
7147836SJohn.Forte@Sun.COM 
7157836SJohn.Forte@Sun.COM 	while ((lowbit = find_low_bit(newblk, 0)) != 32) {
7167836SJohn.Forte@Sun.COM 		if (highbit >= 0) next_high = 1;
7177836SJohn.Forte@Sun.COM 		highbit = lowbit;
7187836SJohn.Forte@Sun.COM 		newblk &= ~(1 << highbit);
7197836SJohn.Forte@Sun.COM 	}
7207836SJohn.Forte@Sun.COM 
7217836SJohn.Forte@Sun.COM 	if (highbit <= 0) {
7227836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
723*9093SRamana.Srikanth@Sun.COM 		    "!sdbc(get_high_bit) invalid block size %x\n", size);
7247836SJohn.Forte@Sun.COM 		return (-1);
7257836SJohn.Forte@Sun.COM 	}
7267836SJohn.Forte@Sun.COM 
7277836SJohn.Forte@Sun.COM 	if (next_high) highbit++;
7287836SJohn.Forte@Sun.COM 
7297836SJohn.Forte@Sun.COM 	return (highbit);
7307836SJohn.Forte@Sun.COM }
7317836SJohn.Forte@Sun.COM 
7327836SJohn.Forte@Sun.COM 
7337836SJohn.Forte@Sun.COM int
7347836SJohn.Forte@Sun.COM _sd_fill_pattern(caddr_t addr, uint_t pat, uint_t size)
7357836SJohn.Forte@Sun.COM {
7367836SJohn.Forte@Sun.COM 	caddr_t fmt_page;
7377836SJohn.Forte@Sun.COM 	int i, page_size;
7387836SJohn.Forte@Sun.COM 
7397836SJohn.Forte@Sun.COM 	page_size = (int)ptob(1);
7407836SJohn.Forte@Sun.COM 
7417836SJohn.Forte@Sun.COM 	if ((fmt_page = (caddr_t)nsc_kmem_alloc(ptob(1),
7427836SJohn.Forte@Sun.COM 	    KM_SLEEP, sdbc_local_mem)) == NULL) {
743*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!sdbc(_sd_fill pattern) no more memory");
7447836SJohn.Forte@Sun.COM 		return (-1);
7457836SJohn.Forte@Sun.COM 	}
7467836SJohn.Forte@Sun.COM 	for (i = 0; i < page_size; i += 4)
7477836SJohn.Forte@Sun.COM 		*(int *)(void *)(fmt_page + i) = pat;
7487836SJohn.Forte@Sun.COM 
7497836SJohn.Forte@Sun.COM 	while (size >= page_size) {
7507836SJohn.Forte@Sun.COM 		bcopy(fmt_page, addr, ptob(1));
7517836SJohn.Forte@Sun.COM 		addr += page_size;
7527836SJohn.Forte@Sun.COM 		size -= page_size;
7537836SJohn.Forte@Sun.COM 	}
7547836SJohn.Forte@Sun.COM 	nsc_kmem_free(fmt_page, page_size);
7557836SJohn.Forte@Sun.COM 	return (0);
7567836SJohn.Forte@Sun.COM }
7577836SJohn.Forte@Sun.COM 
7587836SJohn.Forte@Sun.COM 
7597836SJohn.Forte@Sun.COM /*
7607836SJohn.Forte@Sun.COM  * _sdbc_nodeid_deconfigure - merely a place holder until
7617836SJohn.Forte@Sun.COM  * such time as there is something to be undone w.r.t.
7627836SJohn.Forte@Sun.COM  * _sdbc_nodeid_configure.
7637836SJohn.Forte@Sun.COM  *
7647836SJohn.Forte@Sun.COM  */
7657836SJohn.Forte@Sun.COM static void
7667836SJohn.Forte@Sun.COM _sdbc_nodeid_deconfigure(void)
7677836SJohn.Forte@Sun.COM {
7687836SJohn.Forte@Sun.COM 	/* My but we're quick */
7697836SJohn.Forte@Sun.COM }
7707836SJohn.Forte@Sun.COM 
7717836SJohn.Forte@Sun.COM /*
7727836SJohn.Forte@Sun.COM  * _sdbc_nodeid_configure - configure the nodeid's we need to connect
7737836SJohn.Forte@Sun.COM  * to any other nodes in the network.
7747836SJohn.Forte@Sun.COM  *
7757836SJohn.Forte@Sun.COM  */
7767836SJohn.Forte@Sun.COM void
7777836SJohn.Forte@Sun.COM _sdbc_nodeid_configure(void)
7787836SJohn.Forte@Sun.COM {
7797836SJohn.Forte@Sun.COM 
7807836SJohn.Forte@Sun.COM 	if (_sd_cache_config.num_nodes == 0) {
7817836SJohn.Forte@Sun.COM 		_sd_nodes_configured = 1;
7827836SJohn.Forte@Sun.COM 	} else {
7837836SJohn.Forte@Sun.COM 		_sd_nodes_configured = _sd_cache_config.num_nodes;
7847836SJohn.Forte@Sun.COM 	}
7857836SJohn.Forte@Sun.COM 
7867836SJohn.Forte@Sun.COM 	_SD_SELF_HOST   = nsc_node_id();
7877836SJohn.Forte@Sun.COM 	_SD_MIRROR_HOST = _sd_cache_config.mirror_host;
7887836SJohn.Forte@Sun.COM }
7897836SJohn.Forte@Sun.COM 
7907836SJohn.Forte@Sun.COM #define	STACK_SIZE	(32*1024)
7917836SJohn.Forte@Sun.COM #define	num_spin 0
7927836SJohn.Forte@Sun.COM nstset_t *_sd_ioset;
7937836SJohn.Forte@Sun.COM 
7947836SJohn.Forte@Sun.COM /*
7957836SJohn.Forte@Sun.COM  * _sdbc_thread_deconfigure - cache is being deconfigure, stop any
7967836SJohn.Forte@Sun.COM  * thread activity.
7977836SJohn.Forte@Sun.COM  *
7987836SJohn.Forte@Sun.COM  */
7997836SJohn.Forte@Sun.COM static void
8007836SJohn.Forte@Sun.COM _sdbc_thread_deconfigure(void)
8017836SJohn.Forte@Sun.COM {
8027836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&_sdbc_config_lock));
8037836SJohn.Forte@Sun.COM 	nst_destroy(_sd_ioset);
8047836SJohn.Forte@Sun.COM 	_sd_ioset = NULL;
8057836SJohn.Forte@Sun.COM }
8067836SJohn.Forte@Sun.COM 
8077836SJohn.Forte@Sun.COM /*
8087836SJohn.Forte@Sun.COM  * _sdbc_thread_configure - cache is being configured, initialize the
8097836SJohn.Forte@Sun.COM  * threads we need for flushing dirty cds.
8107836SJohn.Forte@Sun.COM  *
8117836SJohn.Forte@Sun.COM  */
8127836SJohn.Forte@Sun.COM static int
8137836SJohn.Forte@Sun.COM _sdbc_thread_configure(void)
8147836SJohn.Forte@Sun.COM {
8157836SJohn.Forte@Sun.COM 	ASSERT(MUTEX_HELD(&_sdbc_config_lock));
8167836SJohn.Forte@Sun.COM 
8177836SJohn.Forte@Sun.COM 	if (!_sd_ioset)
8187836SJohn.Forte@Sun.COM 		_sd_ioset = nst_init("sd_thr", _sd_cache_config.threads);
8197836SJohn.Forte@Sun.COM 
8207836SJohn.Forte@Sun.COM 	if (!_sd_ioset)
8217836SJohn.Forte@Sun.COM 		return (EINVAL);
8227836SJohn.Forte@Sun.COM 
8237836SJohn.Forte@Sun.COM 	return (0);
8247836SJohn.Forte@Sun.COM }
8257836SJohn.Forte@Sun.COM 
8267836SJohn.Forte@Sun.COM int
8277836SJohn.Forte@Sun.COM _sdbc_get_config(_sdbc_config_t *config_info)
8287836SJohn.Forte@Sun.COM {
8297836SJohn.Forte@Sun.COM 	int i;
8307836SJohn.Forte@Sun.COM 
8317836SJohn.Forte@Sun.COM 	config_info->enabled = _sd_cache_initialized;
8327836SJohn.Forte@Sun.COM 	config_info->magic = _SD_MAGIC;
8337836SJohn.Forte@Sun.COM 	for (i = 0; i < CACHE_MEM_PAD; i++) {
8347836SJohn.Forte@Sun.COM 		config_info->cache_mem[i] = _sd_cache_config.cache_mem[i];
8357836SJohn.Forte@Sun.COM 	}
8367836SJohn.Forte@Sun.COM 	config_info->threads = _sd_cache_config.threads;
8377836SJohn.Forte@Sun.COM 
8387836SJohn.Forte@Sun.COM 	return (0);
8397836SJohn.Forte@Sun.COM }
840