xref: /onnv-gate/usr/src/uts/common/os/damap.c (revision 10696:cd0f390dd9e2)
1*10696SDavid.Hollister@Sun.COM /*
2*10696SDavid.Hollister@Sun.COM  * CDDL HEADER START
3*10696SDavid.Hollister@Sun.COM  *
4*10696SDavid.Hollister@Sun.COM  * The contents of this file are subject to the terms of the
5*10696SDavid.Hollister@Sun.COM  * Common Development and Distribution License (the "License").
6*10696SDavid.Hollister@Sun.COM  * You may not use this file except in compliance with the License.
7*10696SDavid.Hollister@Sun.COM  *
8*10696SDavid.Hollister@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10696SDavid.Hollister@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*10696SDavid.Hollister@Sun.COM  * See the License for the specific language governing permissions
11*10696SDavid.Hollister@Sun.COM  * and limitations under the License.
12*10696SDavid.Hollister@Sun.COM  *
13*10696SDavid.Hollister@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*10696SDavid.Hollister@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10696SDavid.Hollister@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*10696SDavid.Hollister@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*10696SDavid.Hollister@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*10696SDavid.Hollister@Sun.COM  *
19*10696SDavid.Hollister@Sun.COM  * CDDL HEADER END
20*10696SDavid.Hollister@Sun.COM  */
21*10696SDavid.Hollister@Sun.COM 
22*10696SDavid.Hollister@Sun.COM /*
23*10696SDavid.Hollister@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*10696SDavid.Hollister@Sun.COM  * Use is subject to license terms.
25*10696SDavid.Hollister@Sun.COM  */
26*10696SDavid.Hollister@Sun.COM 
27*10696SDavid.Hollister@Sun.COM #include <sys/note.h>
28*10696SDavid.Hollister@Sun.COM #include <sys/types.h>
29*10696SDavid.Hollister@Sun.COM #include <sys/param.h>
30*10696SDavid.Hollister@Sun.COM #include <sys/systm.h>
31*10696SDavid.Hollister@Sun.COM #include <sys/buf.h>
32*10696SDavid.Hollister@Sun.COM #include <sys/kmem.h>
33*10696SDavid.Hollister@Sun.COM #include <sys/cmn_err.h>
34*10696SDavid.Hollister@Sun.COM #include <sys/debug.h>
35*10696SDavid.Hollister@Sun.COM #include <sys/sunndi.h>
36*10696SDavid.Hollister@Sun.COM #include <sys/kstat.h>
37*10696SDavid.Hollister@Sun.COM #include <sys/conf.h>
38*10696SDavid.Hollister@Sun.COM #include <sys/ddi_timer.h>
39*10696SDavid.Hollister@Sun.COM #include <sys/devctl.h>
40*10696SDavid.Hollister@Sun.COM #include <sys/callb.h>
41*10696SDavid.Hollister@Sun.COM #include <sys/sysevent.h>
42*10696SDavid.Hollister@Sun.COM #include <sys/taskq.h>
43*10696SDavid.Hollister@Sun.COM #include <sys/ddi.h>
44*10696SDavid.Hollister@Sun.COM #include <sys/bitset.h>
45*10696SDavid.Hollister@Sun.COM #include <sys/damap.h>
46*10696SDavid.Hollister@Sun.COM #include <sys/damap_impl.h>
47*10696SDavid.Hollister@Sun.COM 
48*10696SDavid.Hollister@Sun.COM #ifdef DEBUG
49*10696SDavid.Hollister@Sun.COM static int damap_debug = 0;
50*10696SDavid.Hollister@Sun.COM #endif /* DEBUG */
51*10696SDavid.Hollister@Sun.COM 
52*10696SDavid.Hollister@Sun.COM static void dam_addrset_activate(dam_t *, bitset_t *);
53*10696SDavid.Hollister@Sun.COM static void dam_addrset_release(dam_t *, bitset_t *);
54*10696SDavid.Hollister@Sun.COM static void dam_activate_taskq(void *);
55*10696SDavid.Hollister@Sun.COM static void dam_addr_stable_cb(void *);
56*10696SDavid.Hollister@Sun.COM static void dam_set_stable_cb(void *);
57*10696SDavid.Hollister@Sun.COM static void dam_sched_tmo(dam_t *, clock_t, void (*tmo_cb)());
58*10696SDavid.Hollister@Sun.COM static void dam_add_report(dam_t *, dam_da_t *, id_t, int);
59*10696SDavid.Hollister@Sun.COM static void dam_release(dam_t *, id_t);
60*10696SDavid.Hollister@Sun.COM static void dam_release_report(dam_t *, id_t);
61*10696SDavid.Hollister@Sun.COM static void dam_deactivate_addr(dam_t *, id_t);
62*10696SDavid.Hollister@Sun.COM static id_t dam_get_addrid(dam_t *, char *);
63*10696SDavid.Hollister@Sun.COM static int dam_kstat_create(dam_t *);
64*10696SDavid.Hollister@Sun.COM static void dam_kstat_destroy(dam_t *);
65*10696SDavid.Hollister@Sun.COM 
66*10696SDavid.Hollister@Sun.COM #define	DAM_INCR_STAT(mapp, stat)				\
67*10696SDavid.Hollister@Sun.COM 	if ((mapp)->dam_kstatsp) {				\
68*10696SDavid.Hollister@Sun.COM 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
69*10696SDavid.Hollister@Sun.COM 		stp->stat.value.ui32++;				\
70*10696SDavid.Hollister@Sun.COM 	}
71*10696SDavid.Hollister@Sun.COM 
72*10696SDavid.Hollister@Sun.COM #define	DAM_SET_STAT(mapp, stat, val)				\
73*10696SDavid.Hollister@Sun.COM 	if ((mapp)->dam_kstatsp) {				\
74*10696SDavid.Hollister@Sun.COM 		struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data;	\
75*10696SDavid.Hollister@Sun.COM 		stp->stat.value.ui32 = (val);			\
76*10696SDavid.Hollister@Sun.COM 	}
77*10696SDavid.Hollister@Sun.COM 
78*10696SDavid.Hollister@Sun.COM /*
79*10696SDavid.Hollister@Sun.COM  * Create new device address map
80*10696SDavid.Hollister@Sun.COM  *
81*10696SDavid.Hollister@Sun.COM  * ident:		map name (kstat)
82*10696SDavid.Hollister@Sun.COM  * size:		max # of map entries
83*10696SDavid.Hollister@Sun.COM  * rptmode:		type or mode of reporting
84*10696SDavid.Hollister@Sun.COM  * stable_usec:		# of quiescent microseconds before report/map is stable
85*10696SDavid.Hollister@Sun.COM  *
86*10696SDavid.Hollister@Sun.COM  * activate_arg:	address provider activation-callout private
87*10696SDavid.Hollister@Sun.COM  * activate_cb:		address provider activation callback handler
88*10696SDavid.Hollister@Sun.COM  * deactivate_cb:	address provider deactivation callback handler
89*10696SDavid.Hollister@Sun.COM  *
90*10696SDavid.Hollister@Sun.COM  * config_arg:		configuration-callout private
91*10696SDavid.Hollister@Sun.COM  * config_cb:		class configuration callout
92*10696SDavid.Hollister@Sun.COM  * unconfig_cb:		class unconfiguration callout
93*10696SDavid.Hollister@Sun.COM  *
94*10696SDavid.Hollister@Sun.COM  * damapp:		pointer to map handle (return)
95*10696SDavid.Hollister@Sun.COM  *
96*10696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
97*10696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
98*10696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
99*10696SDavid.Hollister@Sun.COM  */
100*10696SDavid.Hollister@Sun.COM int
101*10696SDavid.Hollister@Sun.COM damap_create(char *ident, size_t size, damap_rptmode_t rptmode,
102*10696SDavid.Hollister@Sun.COM     clock_t stable_usec,
103*10696SDavid.Hollister@Sun.COM     void *activate_arg, damap_activate_cb_t activate_cb,
104*10696SDavid.Hollister@Sun.COM     damap_deactivate_cb_t deactivate_cb,
105*10696SDavid.Hollister@Sun.COM     void *config_arg, damap_configure_cb_t configure_cb,
106*10696SDavid.Hollister@Sun.COM     damap_unconfig_cb_t unconfig_cb,
107*10696SDavid.Hollister@Sun.COM     damap_t **damapp)
108*10696SDavid.Hollister@Sun.COM {
109*10696SDavid.Hollister@Sun.COM 	dam_t *mapp;
110*10696SDavid.Hollister@Sun.COM 	void *softstate_p;
111*10696SDavid.Hollister@Sun.COM 
112*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE1(damap__create__entry, char *, ident);
113*10696SDavid.Hollister@Sun.COM 	if ((configure_cb == NULL) || (unconfig_cb == NULL))
114*10696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
115*10696SDavid.Hollister@Sun.COM 
116*10696SDavid.Hollister@Sun.COM 	if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t), size) !=
117*10696SDavid.Hollister@Sun.COM 	    DDI_SUCCESS)
118*10696SDavid.Hollister@Sun.COM 		return (DAM_FAILURE);
119*10696SDavid.Hollister@Sun.COM 
120*10696SDavid.Hollister@Sun.COM 	mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
121*10696SDavid.Hollister@Sun.COM 	if (ddi_strid_init(&mapp->dam_addr_hash, size) != DDI_SUCCESS) {
122*10696SDavid.Hollister@Sun.COM 		ddi_soft_state_fini(&softstate_p);
123*10696SDavid.Hollister@Sun.COM 		kmem_free(mapp, sizeof (*mapp));
124*10696SDavid.Hollister@Sun.COM 		return (DAM_FAILURE);
125*10696SDavid.Hollister@Sun.COM 	}
126*10696SDavid.Hollister@Sun.COM 
127*10696SDavid.Hollister@Sun.COM 	mapp->dam_da = softstate_p;
128*10696SDavid.Hollister@Sun.COM 	mapp->dam_stabletmo = drv_usectohz(stable_usec);
129*10696SDavid.Hollister@Sun.COM 	mapp->dam_size = size;
130*10696SDavid.Hollister@Sun.COM 	mapp->dam_high = 1;
131*10696SDavid.Hollister@Sun.COM 	mapp->dam_rptmode = rptmode;
132*10696SDavid.Hollister@Sun.COM 
133*10696SDavid.Hollister@Sun.COM 	mapp->dam_activate_arg = activate_arg;
134*10696SDavid.Hollister@Sun.COM 	mapp->dam_activate_cb = (activate_cb_t)activate_cb;
135*10696SDavid.Hollister@Sun.COM 	mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
136*10696SDavid.Hollister@Sun.COM 
137*10696SDavid.Hollister@Sun.COM 	mapp->dam_config_arg = config_arg;
138*10696SDavid.Hollister@Sun.COM 	mapp->dam_configure_cb = (configure_cb_t)configure_cb;
139*10696SDavid.Hollister@Sun.COM 	mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
140*10696SDavid.Hollister@Sun.COM 
141*10696SDavid.Hollister@Sun.COM 	if (ident)
142*10696SDavid.Hollister@Sun.COM 		mapp->dam_name = i_ddi_strdup(ident, KM_SLEEP);
143*10696SDavid.Hollister@Sun.COM 
144*10696SDavid.Hollister@Sun.COM 	bitset_init(&mapp->dam_active_set);
145*10696SDavid.Hollister@Sun.COM 	bitset_resize(&mapp->dam_active_set, size);
146*10696SDavid.Hollister@Sun.COM 	bitset_init(&mapp->dam_stable_set);
147*10696SDavid.Hollister@Sun.COM 	bitset_resize(&mapp->dam_stable_set, size);
148*10696SDavid.Hollister@Sun.COM 	bitset_init(&mapp->dam_report_set);
149*10696SDavid.Hollister@Sun.COM 	bitset_resize(&mapp->dam_report_set, size);
150*10696SDavid.Hollister@Sun.COM 	mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
151*10696SDavid.Hollister@Sun.COM 	cv_init(&mapp->dam_cv, NULL, CV_DRIVER, NULL);
152*10696SDavid.Hollister@Sun.COM 	mapp->dam_taskqp = ddi_taskq_create(NULL, ident, 1, TASKQ_DEFAULTPRI,
153*10696SDavid.Hollister@Sun.COM 	    0);
154*10696SDavid.Hollister@Sun.COM 	*damapp = (damap_t *)mapp;
155*10696SDavid.Hollister@Sun.COM 	if (dam_kstat_create(mapp) != DDI_SUCCESS) {
156*10696SDavid.Hollister@Sun.COM 		damap_destroy((damap_t *)mapp);
157*10696SDavid.Hollister@Sun.COM 		return (DAM_FAILURE);
158*10696SDavid.Hollister@Sun.COM 	}
159*10696SDavid.Hollister@Sun.COM 
160*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE1(damap__create__exit, dam_t *, mapp);
161*10696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
162*10696SDavid.Hollister@Sun.COM }
163*10696SDavid.Hollister@Sun.COM 
164*10696SDavid.Hollister@Sun.COM /*
165*10696SDavid.Hollister@Sun.COM  * Destroy device address map
166*10696SDavid.Hollister@Sun.COM  *
167*10696SDavid.Hollister@Sun.COM  * damapp:	address map
168*10696SDavid.Hollister@Sun.COM  *
169*10696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
170*10696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
171*10696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
172*10696SDavid.Hollister@Sun.COM  */
173*10696SDavid.Hollister@Sun.COM void
174*10696SDavid.Hollister@Sun.COM damap_destroy(damap_t *damapp)
175*10696SDavid.Hollister@Sun.COM {
176*10696SDavid.Hollister@Sun.COM 	int i;
177*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
178*10696SDavid.Hollister@Sun.COM 
179*10696SDavid.Hollister@Sun.COM 	ASSERT(mapp);
180*10696SDavid.Hollister@Sun.COM 
181*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE2(damap__destroy__entry, dam_t *, mapp, char *,
182*10696SDavid.Hollister@Sun.COM 	    mapp->dam_name);
183*10696SDavid.Hollister@Sun.COM 
184*10696SDavid.Hollister@Sun.COM 	DAM_FLAG_SET(mapp, DAM_DESTROYPEND);
185*10696SDavid.Hollister@Sun.COM 	(void) damap_sync(damapp);
186*10696SDavid.Hollister@Sun.COM 
187*10696SDavid.Hollister@Sun.COM 	/*
188*10696SDavid.Hollister@Sun.COM 	 * cancel pending timeouts and kill off the taskq
189*10696SDavid.Hollister@Sun.COM 	 */
190*10696SDavid.Hollister@Sun.COM 	dam_sched_tmo(mapp, 0, NULL);
191*10696SDavid.Hollister@Sun.COM 	ddi_taskq_wait(mapp->dam_taskqp);
192*10696SDavid.Hollister@Sun.COM 	ddi_taskq_destroy(mapp->dam_taskqp);
193*10696SDavid.Hollister@Sun.COM 
194*10696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
195*10696SDavid.Hollister@Sun.COM 		if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
196*10696SDavid.Hollister@Sun.COM 			continue;
197*10696SDavid.Hollister@Sun.COM 		if (DAM_IN_REPORT(mapp, i))
198*10696SDavid.Hollister@Sun.COM 			dam_release_report(mapp, i);
199*10696SDavid.Hollister@Sun.COM 		if (DAM_IS_STABLE(mapp, i))
200*10696SDavid.Hollister@Sun.COM 			dam_deactivate_addr(mapp, i);
201*10696SDavid.Hollister@Sun.COM 		ddi_strid_free(mapp->dam_addr_hash, i);
202*10696SDavid.Hollister@Sun.COM 		ddi_soft_state_free(mapp->dam_da, i);
203*10696SDavid.Hollister@Sun.COM 	}
204*10696SDavid.Hollister@Sun.COM 	ddi_strid_fini(&mapp->dam_addr_hash);
205*10696SDavid.Hollister@Sun.COM 	ddi_soft_state_fini(&mapp->dam_da);
206*10696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_active_set);
207*10696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_stable_set);
208*10696SDavid.Hollister@Sun.COM 	bitset_fini(&mapp->dam_report_set);
209*10696SDavid.Hollister@Sun.COM 	dam_kstat_destroy(mapp);
210*10696SDavid.Hollister@Sun.COM 	mutex_destroy(&mapp->dam_lock);
211*10696SDavid.Hollister@Sun.COM 	cv_destroy(&mapp->dam_cv);
212*10696SDavid.Hollister@Sun.COM 	if (mapp->dam_name)
213*10696SDavid.Hollister@Sun.COM 		kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
214*10696SDavid.Hollister@Sun.COM 	kmem_free(mapp, sizeof (*mapp));
215*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE(damap__destroy__exit);
216*10696SDavid.Hollister@Sun.COM }
217*10696SDavid.Hollister@Sun.COM 
218*10696SDavid.Hollister@Sun.COM /*
219*10696SDavid.Hollister@Sun.COM  * Wait for map stability.
220*10696SDavid.Hollister@Sun.COM  *
221*10696SDavid.Hollister@Sun.COM  * damapp:	address map
222*10696SDavid.Hollister@Sun.COM  */
223*10696SDavid.Hollister@Sun.COM int
224*10696SDavid.Hollister@Sun.COM damap_sync(damap_t *damapp)
225*10696SDavid.Hollister@Sun.COM {
226*10696SDavid.Hollister@Sun.COM 
227*10696SDavid.Hollister@Sun.COM #define	WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND | MAP_LOCK)
228*10696SDavid.Hollister@Sun.COM 
229*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
230*10696SDavid.Hollister@Sun.COM 	int   none_active;
231*10696SDavid.Hollister@Sun.COM 
232*10696SDavid.Hollister@Sun.COM 	ASSERT(mapp);
233*10696SDavid.Hollister@Sun.COM 
234*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE1(damap__sync__entry, dam_t *, mapp);
235*10696SDavid.Hollister@Sun.COM 
236*10696SDavid.Hollister@Sun.COM 	mutex_enter(&mapp->dam_lock);
237*10696SDavid.Hollister@Sun.COM 	while ((mapp->dam_flags & WAITFOR_FLAGS) ||
238*10696SDavid.Hollister@Sun.COM 	    (!bitset_is_null(&mapp->dam_report_set)) || (mapp->dam_tid != 0)) {
239*10696SDavid.Hollister@Sun.COM 		cv_wait(&mapp->dam_cv, &mapp->dam_lock);
240*10696SDavid.Hollister@Sun.COM 	}
241*10696SDavid.Hollister@Sun.COM 
242*10696SDavid.Hollister@Sun.COM 	none_active = bitset_is_null(&mapp->dam_active_set);
243*10696SDavid.Hollister@Sun.COM 
244*10696SDavid.Hollister@Sun.COM 	mutex_exit(&mapp->dam_lock);
245*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE2(damap__sync__exit, dam_t *, mapp, int, none_active);
246*10696SDavid.Hollister@Sun.COM 
247*10696SDavid.Hollister@Sun.COM 	return (none_active);
248*10696SDavid.Hollister@Sun.COM }
249*10696SDavid.Hollister@Sun.COM 
250*10696SDavid.Hollister@Sun.COM /*
251*10696SDavid.Hollister@Sun.COM  * Get the name of a device address map
252*10696SDavid.Hollister@Sun.COM  *
253*10696SDavid.Hollister@Sun.COM  * damapp:	address map
254*10696SDavid.Hollister@Sun.COM  *
255*10696SDavid.Hollister@Sun.COM  * Returns:	name
256*10696SDavid.Hollister@Sun.COM  */
257*10696SDavid.Hollister@Sun.COM char *
258*10696SDavid.Hollister@Sun.COM damap_name(damap_t *damapp)
259*10696SDavid.Hollister@Sun.COM {
260*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
261*10696SDavid.Hollister@Sun.COM 
262*10696SDavid.Hollister@Sun.COM 	return (mapp ? mapp->dam_name : "UNKNOWN_damap");
263*10696SDavid.Hollister@Sun.COM }
264*10696SDavid.Hollister@Sun.COM 
265*10696SDavid.Hollister@Sun.COM /*
266*10696SDavid.Hollister@Sun.COM  * Report an address to per-address report
267*10696SDavid.Hollister@Sun.COM  *
268*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
269*10696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
270*10696SDavid.Hollister@Sun.COM  * rindx:	index if address stabilizes
271*10696SDavid.Hollister@Sun.COM  * nvl:		optional nvlist of configuration-private data
272*10696SDavid.Hollister@Sun.COM  * addr_priv:	optional provider-private (passed to activate/deactivate cb)
273*10696SDavid.Hollister@Sun.COM  *
274*10696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
275*10696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
276*10696SDavid.Hollister@Sun.COM  *		DAM_MAPFULL	address map exhausted
277*10696SDavid.Hollister@Sun.COM  */
278*10696SDavid.Hollister@Sun.COM int
279*10696SDavid.Hollister@Sun.COM damap_addr_add(damap_t *damapp, char *address, damap_id_t *ridx, nvlist_t *nvl,
280*10696SDavid.Hollister@Sun.COM     void *addr_priv)
281*10696SDavid.Hollister@Sun.COM {
282*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
283*10696SDavid.Hollister@Sun.COM 	id_t addrid;
284*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
285*10696SDavid.Hollister@Sun.COM 
286*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE2(damap__addr__add__entry, dam_t *, mapp,
287*10696SDavid.Hollister@Sun.COM 	    char *, address);
288*10696SDavid.Hollister@Sun.COM 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) ||
289*10696SDavid.Hollister@Sun.COM 	    (mapp->dam_flags & DAM_DESTROYPEND))
290*10696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
291*10696SDavid.Hollister@Sun.COM 
292*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
293*10696SDavid.Hollister@Sun.COM 	if ((addrid = dam_get_addrid(mapp, address)) == 0) {
294*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, ADDR_LOCK);
295*10696SDavid.Hollister@Sun.COM 		return (DAM_MAPFULL);
296*10696SDavid.Hollister@Sun.COM 	}
297*10696SDavid.Hollister@Sun.COM 
298*10696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
299*10696SDavid.Hollister@Sun.COM 	ASSERT(passp != NULL);
300*10696SDavid.Hollister@Sun.COM 
301*10696SDavid.Hollister@Sun.COM 	/*
302*10696SDavid.Hollister@Sun.COM 	 * If re-reporting the same address (add or remove) clear
303*10696SDavid.Hollister@Sun.COM 	 * the existing report
304*10696SDavid.Hollister@Sun.COM 	 */
305*10696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
306*10696SDavid.Hollister@Sun.COM 		DAM_INCR_STAT(mapp, dam_rereport);
307*10696SDavid.Hollister@Sun.COM 		dam_release_report(mapp, addrid);
308*10696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
309*10696SDavid.Hollister@Sun.COM 	}
310*10696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = addr_priv;
311*10696SDavid.Hollister@Sun.COM 	if (nvl)
312*10696SDavid.Hollister@Sun.COM 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
313*10696SDavid.Hollister@Sun.COM 
314*10696SDavid.Hollister@Sun.COM 	dam_add_report(mapp, passp, addrid, RPT_ADDR_ADD);
315*10696SDavid.Hollister@Sun.COM 	if (ridx != NULL)
316*10696SDavid.Hollister@Sun.COM 		*ridx = (damap_id_t)addrid;
317*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
318*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE3(damap__addr__add__exit, dam_t *, mapp, char *,
319*10696SDavid.Hollister@Sun.COM 	    address, int, addrid);
320*10696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
321*10696SDavid.Hollister@Sun.COM }
322*10696SDavid.Hollister@Sun.COM 
323*10696SDavid.Hollister@Sun.COM /*
324*10696SDavid.Hollister@Sun.COM  * Report removal of address from per-address report
325*10696SDavid.Hollister@Sun.COM  *
326*10696SDavid.Hollister@Sun.COM  * damapp:	address map
327*10696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
328*10696SDavid.Hollister@Sun.COM  *
329*10696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
330*10696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
331*10696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
332*10696SDavid.Hollister@Sun.COM  */
333*10696SDavid.Hollister@Sun.COM int
334*10696SDavid.Hollister@Sun.COM damap_addr_del(damap_t *damapp, char *address)
335*10696SDavid.Hollister@Sun.COM {
336*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
337*10696SDavid.Hollister@Sun.COM 	id_t addrid;
338*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
339*10696SDavid.Hollister@Sun.COM 
340*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE2(damap__addr__del__entry, dam_t *, mapp,
341*10696SDavid.Hollister@Sun.COM 	    char *, address);
342*10696SDavid.Hollister@Sun.COM 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR) ||
343*10696SDavid.Hollister@Sun.COM 	    (mapp->dam_flags & DAM_DESTROYPEND))
344*10696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
345*10696SDavid.Hollister@Sun.COM 
346*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
347*10696SDavid.Hollister@Sun.COM 	if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
348*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, ADDR_LOCK);
349*10696SDavid.Hollister@Sun.COM 		return (DAM_SUCCESS);
350*10696SDavid.Hollister@Sun.COM 	}
351*10696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
352*10696SDavid.Hollister@Sun.COM 	ASSERT(passp);
353*10696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
354*10696SDavid.Hollister@Sun.COM 		DAM_INCR_STAT(mapp, dam_rereport);
355*10696SDavid.Hollister@Sun.COM 		dam_release_report(mapp, addrid);
356*10696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
357*10696SDavid.Hollister@Sun.COM 	}
358*10696SDavid.Hollister@Sun.COM 	dam_add_report(mapp, passp, addrid, RPT_ADDR_DEL);
359*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
360*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE3(damap__addr__del__exit, dam_t *, mapp,
361*10696SDavid.Hollister@Sun.COM 	    char *, address, int, addrid);
362*10696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
363*10696SDavid.Hollister@Sun.COM }
364*10696SDavid.Hollister@Sun.COM 
365*10696SDavid.Hollister@Sun.COM /*
366*10696SDavid.Hollister@Sun.COM  * Initiate full-set report
367*10696SDavid.Hollister@Sun.COM  *
368*10696SDavid.Hollister@Sun.COM  * damapp:	address map
369*10696SDavid.Hollister@Sun.COM  *
370*10696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
371*10696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
372*10696SDavid.Hollister@Sun.COM  */
373*10696SDavid.Hollister@Sun.COM int
374*10696SDavid.Hollister@Sun.COM damap_addrset_begin(damap_t *damapp)
375*10696SDavid.Hollister@Sun.COM {
376*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
377*10696SDavid.Hollister@Sun.COM 	int i;
378*10696SDavid.Hollister@Sun.COM 
379*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE1(damap__addrset__begin__entry, dam_t *, mapp);
380*10696SDavid.Hollister@Sun.COM 
381*10696SDavid.Hollister@Sun.COM 	if ((mapp->dam_rptmode != DAMAP_REPORT_FULLSET) ||
382*10696SDavid.Hollister@Sun.COM 	    (mapp->dam_flags & DAM_DESTROYPEND))
383*10696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
384*10696SDavid.Hollister@Sun.COM 
385*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, MAP_LOCK);
386*10696SDavid.Hollister@Sun.COM 	/*
387*10696SDavid.Hollister@Sun.COM 	 * reset any pending reports
388*10696SDavid.Hollister@Sun.COM 	 */
389*10696SDavid.Hollister@Sun.COM 	if (mapp->dam_flags & DAM_SETADD) {
390*10696SDavid.Hollister@Sun.COM 		/*
391*10696SDavid.Hollister@Sun.COM 		 * cancel stabilization timeout
392*10696SDavid.Hollister@Sun.COM 		 */
393*10696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, 0, NULL);
394*10696SDavid.Hollister@Sun.COM 		DAM_INCR_STAT(mapp, dam_rereport);
395*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, MAP_LOCK);
396*10696SDavid.Hollister@Sun.COM 		DAM_LOCK(mapp, ADDR_LOCK);
397*10696SDavid.Hollister@Sun.COM 		for (i = 1; i < mapp->dam_high; i++) {
398*10696SDavid.Hollister@Sun.COM 			if (DAM_IN_REPORT(mapp, i))
399*10696SDavid.Hollister@Sun.COM 				dam_release_report(mapp, i);
400*10696SDavid.Hollister@Sun.COM 		}
401*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, ADDR_LOCK);
402*10696SDavid.Hollister@Sun.COM 		DAM_LOCK(mapp, MAP_LOCK);
403*10696SDavid.Hollister@Sun.COM 	}
404*10696SDavid.Hollister@Sun.COM 	DAM_FLAG_SET(mapp, DAM_SETADD);
405*10696SDavid.Hollister@Sun.COM 	bitset_zero(&mapp->dam_report_set);
406*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, MAP_LOCK);
407*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE(damap__addrset__begin__exit);
408*10696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
409*10696SDavid.Hollister@Sun.COM }
410*10696SDavid.Hollister@Sun.COM 
411*10696SDavid.Hollister@Sun.COM /*
412*10696SDavid.Hollister@Sun.COM  * Report address to full-set report
413*10696SDavid.Hollister@Sun.COM  *
414*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
415*10696SDavid.Hollister@Sun.COM  * address:	address in ascii string representation
416*10696SDavid.Hollister@Sun.COM  * rindx:	index if address stabilizes
417*10696SDavid.Hollister@Sun.COM  * nvl:		optional nvlist of configuration-private data
418*10696SDavid.Hollister@Sun.COM  * addr_priv:	optional provider-private data (passed to activate/release cb)
419*10696SDavid.Hollister@Sun.COM  *
420*10696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
421*10696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
422*10696SDavid.Hollister@Sun.COM  *		DAM_MAPFULL	address map exhausted
423*10696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
424*10696SDavid.Hollister@Sun.COM  */
425*10696SDavid.Hollister@Sun.COM int
426*10696SDavid.Hollister@Sun.COM damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
427*10696SDavid.Hollister@Sun.COM     nvlist_t *nvl, void *addr_priv)
428*10696SDavid.Hollister@Sun.COM {
429*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
430*10696SDavid.Hollister@Sun.COM 	id_t addrid;
431*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
432*10696SDavid.Hollister@Sun.COM 
433*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE2(damap__addrset__add__entry, dam_t *, mapp,
434*10696SDavid.Hollister@Sun.COM 	    char *, address);
435*10696SDavid.Hollister@Sun.COM 
436*10696SDavid.Hollister@Sun.COM 	if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) ||
437*10696SDavid.Hollister@Sun.COM 	    (mapp->dam_flags & DAM_DESTROYPEND))
438*10696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
439*10696SDavid.Hollister@Sun.COM 
440*10696SDavid.Hollister@Sun.COM 	if (!(mapp->dam_flags & DAM_SETADD))
441*10696SDavid.Hollister@Sun.COM 		return (DAM_FAILURE);
442*10696SDavid.Hollister@Sun.COM 
443*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
444*10696SDavid.Hollister@Sun.COM 	if ((addrid = dam_get_addrid(mapp, address)) == 0) {
445*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, ADDR_LOCK);
446*10696SDavid.Hollister@Sun.COM 		return (DAM_MAPFULL);
447*10696SDavid.Hollister@Sun.COM 	}
448*10696SDavid.Hollister@Sun.COM 
449*10696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
450*10696SDavid.Hollister@Sun.COM 	ASSERT(passp);
451*10696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid)) {
452*10696SDavid.Hollister@Sun.COM 		dam_release_report(mapp, addrid);
453*10696SDavid.Hollister@Sun.COM 		passp->da_jitter++;
454*10696SDavid.Hollister@Sun.COM 	}
455*10696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = addr_priv;
456*10696SDavid.Hollister@Sun.COM 	if (nvl)
457*10696SDavid.Hollister@Sun.COM 		(void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
458*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, MAP_LOCK);
459*10696SDavid.Hollister@Sun.COM 	bitset_add(&mapp->dam_report_set, addrid);
460*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, MAP_LOCK);
461*10696SDavid.Hollister@Sun.COM 	if (ridx)
462*10696SDavid.Hollister@Sun.COM 		*ridx = (damap_id_t)addrid;
463*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
464*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE3(damap__addr__addset__exit, dam_t *, mapp, char *,
465*10696SDavid.Hollister@Sun.COM 	    address, int, addrid);
466*10696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
467*10696SDavid.Hollister@Sun.COM }
468*10696SDavid.Hollister@Sun.COM 
469*10696SDavid.Hollister@Sun.COM /*
470*10696SDavid.Hollister@Sun.COM  * Commit full-set report for stabilization
471*10696SDavid.Hollister@Sun.COM  *
472*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
473*10696SDavid.Hollister@Sun.COM  * flags:	(currently 0)
474*10696SDavid.Hollister@Sun.COM  *
475*10696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
476*10696SDavid.Hollister@Sun.COM  *		DAM_EINVAL	Invalid argument(s)
477*10696SDavid.Hollister@Sun.COM  *		DAM_FAILURE	General failure
478*10696SDavid.Hollister@Sun.COM  */
479*10696SDavid.Hollister@Sun.COM int
480*10696SDavid.Hollister@Sun.COM damap_addrset_end(damap_t *damapp, int flags)
481*10696SDavid.Hollister@Sun.COM {
482*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
483*10696SDavid.Hollister@Sun.COM 	int i;
484*10696SDavid.Hollister@Sun.COM 
485*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE1(damap__addrset__end__entry, dam_t *, mapp);
486*10696SDavid.Hollister@Sun.COM 
487*10696SDavid.Hollister@Sun.COM 	if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) ||
488*10696SDavid.Hollister@Sun.COM 	    (mapp->dam_flags & DAM_DESTROYPEND))
489*10696SDavid.Hollister@Sun.COM 		return (DAM_EINVAL);
490*10696SDavid.Hollister@Sun.COM 
491*10696SDavid.Hollister@Sun.COM 	if (!(mapp->dam_flags & DAM_SETADD))
492*10696SDavid.Hollister@Sun.COM 		return (DAM_FAILURE);
493*10696SDavid.Hollister@Sun.COM 
494*10696SDavid.Hollister@Sun.COM 	if (flags & DAMAP_RESET) {
495*10696SDavid.Hollister@Sun.COM 		DAM_LOCK(mapp, MAP_LOCK);
496*10696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, 0, NULL);
497*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, MAP_LOCK);
498*10696SDavid.Hollister@Sun.COM 		DAM_LOCK(mapp, ADDR_LOCK);
499*10696SDavid.Hollister@Sun.COM 		for (i = 1; i < mapp->dam_high; i++)
500*10696SDavid.Hollister@Sun.COM 			if (DAM_IN_REPORT(mapp, i))
501*10696SDavid.Hollister@Sun.COM 				dam_release_report(mapp, i);
502*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, ADDR_LOCK);
503*10696SDavid.Hollister@Sun.COM 	} else {
504*10696SDavid.Hollister@Sun.COM 		mapp->dam_last_update = gethrtime();
505*10696SDavid.Hollister@Sun.COM 		DAM_LOCK(mapp, MAP_LOCK);
506*10696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb);
507*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, MAP_LOCK);
508*10696SDavid.Hollister@Sun.COM 	}
509*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE(damap__addrset__end__exit);
510*10696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
511*10696SDavid.Hollister@Sun.COM }
512*10696SDavid.Hollister@Sun.COM 
513*10696SDavid.Hollister@Sun.COM /*
514*10696SDavid.Hollister@Sun.COM  * Return nvlist registered with reported address
515*10696SDavid.Hollister@Sun.COM  *
516*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
517*10696SDavid.Hollister@Sun.COM  * aid:		address ID
518*10696SDavid.Hollister@Sun.COM  *
519*10696SDavid.Hollister@Sun.COM  * Returns:	nvlist_t *	provider supplied via damap_addr{set}_add())
520*10696SDavid.Hollister@Sun.COM  *		NULL
521*10696SDavid.Hollister@Sun.COM  */
522*10696SDavid.Hollister@Sun.COM nvlist_t *
523*10696SDavid.Hollister@Sun.COM damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
524*10696SDavid.Hollister@Sun.COM {
525*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
526*10696SDavid.Hollister@Sun.COM 	id_t aid = (id_t)addrid;
527*10696SDavid.Hollister@Sun.COM 	dam_da_t *pass;
528*10696SDavid.Hollister@Sun.COM 
529*10696SDavid.Hollister@Sun.COM 	if (ddi_strid_id2str(mapp->dam_addr_hash, aid)) {
530*10696SDavid.Hollister@Sun.COM 		if (pass = ddi_get_soft_state(mapp->dam_da, aid))
531*10696SDavid.Hollister@Sun.COM 			return (pass->da_nvl);
532*10696SDavid.Hollister@Sun.COM 	}
533*10696SDavid.Hollister@Sun.COM 	return (NULL);
534*10696SDavid.Hollister@Sun.COM }
535*10696SDavid.Hollister@Sun.COM 
536*10696SDavid.Hollister@Sun.COM /*
537*10696SDavid.Hollister@Sun.COM  * Return address string
538*10696SDavid.Hollister@Sun.COM  *
539*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
540*10696SDavid.Hollister@Sun.COM  * aid:		address ID
541*10696SDavid.Hollister@Sun.COM  *
542*10696SDavid.Hollister@Sun.COM  * Returns:	char *		Address string
543*10696SDavid.Hollister@Sun.COM  *		NULL
544*10696SDavid.Hollister@Sun.COM  */
545*10696SDavid.Hollister@Sun.COM char *
546*10696SDavid.Hollister@Sun.COM damap_id2addr(damap_t *damapp, damap_id_t aid)
547*10696SDavid.Hollister@Sun.COM {
548*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
549*10696SDavid.Hollister@Sun.COM 
550*10696SDavid.Hollister@Sun.COM 	return (ddi_strid_id2str(mapp->dam_addr_hash, (id_t)aid));
551*10696SDavid.Hollister@Sun.COM }
552*10696SDavid.Hollister@Sun.COM 
553*10696SDavid.Hollister@Sun.COM /*
554*10696SDavid.Hollister@Sun.COM  * Hold address reference in map
555*10696SDavid.Hollister@Sun.COM  *
556*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
557*10696SDavid.Hollister@Sun.COM  * aid:		address ID
558*10696SDavid.Hollister@Sun.COM  *
559*10696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
560*10696SDavid.Hollister@Sun.COM  *		DAM_FAILURE
561*10696SDavid.Hollister@Sun.COM  */
562*10696SDavid.Hollister@Sun.COM int
563*10696SDavid.Hollister@Sun.COM damap_id_hold(damap_t *damapp, damap_id_t aid)
564*10696SDavid.Hollister@Sun.COM {
565*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
566*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
567*10696SDavid.Hollister@Sun.COM 
568*10696SDavid.Hollister@Sun.COM 
569*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
570*10696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid);
571*10696SDavid.Hollister@Sun.COM 	if (!passp) {
572*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, ADDR_LOCK);
573*10696SDavid.Hollister@Sun.COM 		return (DAM_FAILURE);
574*10696SDavid.Hollister@Sun.COM 	}
575*10696SDavid.Hollister@Sun.COM 	passp->da_ref++;
576*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
577*10696SDavid.Hollister@Sun.COM 	return (DAM_SUCCESS);
578*10696SDavid.Hollister@Sun.COM }
579*10696SDavid.Hollister@Sun.COM 
580*10696SDavid.Hollister@Sun.COM /*
581*10696SDavid.Hollister@Sun.COM  * Release address reference in map
582*10696SDavid.Hollister@Sun.COM  *
583*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
584*10696SDavid.Hollister@Sun.COM  * aid:		address ID
585*10696SDavid.Hollister@Sun.COM  */
586*10696SDavid.Hollister@Sun.COM void
587*10696SDavid.Hollister@Sun.COM damap_id_rele(damap_t *damapp, damap_id_t addrid)
588*10696SDavid.Hollister@Sun.COM {
589*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
590*10696SDavid.Hollister@Sun.COM 
591*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
592*10696SDavid.Hollister@Sun.COM 	dam_release(mapp, (id_t)addrid);
593*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
594*10696SDavid.Hollister@Sun.COM }
595*10696SDavid.Hollister@Sun.COM 
596*10696SDavid.Hollister@Sun.COM /*
597*10696SDavid.Hollister@Sun.COM  * Return current reference count on address reference in map
598*10696SDavid.Hollister@Sun.COM  *
599*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
600*10696SDavid.Hollister@Sun.COM  * aid:		address ID
601*10696SDavid.Hollister@Sun.COM  *
602*10696SDavid.Hollister@Sun.COM  * Returns:	DAM_SUCCESS
603*10696SDavid.Hollister@Sun.COM  *		DAM_FAILURE
604*10696SDavid.Hollister@Sun.COM  */
605*10696SDavid.Hollister@Sun.COM int
606*10696SDavid.Hollister@Sun.COM damap_id_ref(damap_t *damapp, damap_id_t aid)
607*10696SDavid.Hollister@Sun.COM {
608*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
609*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
610*10696SDavid.Hollister@Sun.COM 	int ref = -1;
611*10696SDavid.Hollister@Sun.COM 
612*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
613*10696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid);
614*10696SDavid.Hollister@Sun.COM 	if (passp)
615*10696SDavid.Hollister@Sun.COM 		ref = passp->da_ref;
616*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
617*10696SDavid.Hollister@Sun.COM 	return (ref);
618*10696SDavid.Hollister@Sun.COM }
619*10696SDavid.Hollister@Sun.COM 
620*10696SDavid.Hollister@Sun.COM /*
621*10696SDavid.Hollister@Sun.COM  * Return next address ID in list
622*10696SDavid.Hollister@Sun.COM  *
623*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
624*10696SDavid.Hollister@Sun.COM  * damap_list:	address ID list passed to config|unconfig
625*10696SDavid.Hollister@Sun.COM  *		returned by look by lookup_all
626*10696SDavid.Hollister@Sun.COM  * last:	last ID returned, 0 is start of list
627*10696SDavid.Hollister@Sun.COM  *
628*10696SDavid.Hollister@Sun.COM  * Returns:	addrid		Next ID from the list
629*10696SDavid.Hollister@Sun.COM  *		0		End of the list
630*10696SDavid.Hollister@Sun.COM  */
631*10696SDavid.Hollister@Sun.COM damap_id_t
632*10696SDavid.Hollister@Sun.COM damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
633*10696SDavid.Hollister@Sun.COM {
634*10696SDavid.Hollister@Sun.COM 	int i, start;
635*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
636*10696SDavid.Hollister@Sun.COM 	bitset_t *dam_list = (bitset_t *)damap_list;
637*10696SDavid.Hollister@Sun.COM 
638*10696SDavid.Hollister@Sun.COM 	if (!mapp || !dam_list)
639*10696SDavid.Hollister@Sun.COM 		return ((damap_id_t)0);
640*10696SDavid.Hollister@Sun.COM 
641*10696SDavid.Hollister@Sun.COM 	start = (int)last + 1;
642*10696SDavid.Hollister@Sun.COM 	for (i = start; i < mapp->dam_high; i++)
643*10696SDavid.Hollister@Sun.COM 		if (bitset_in_set(dam_list, i))
644*10696SDavid.Hollister@Sun.COM 			return ((damap_id_t)i);
645*10696SDavid.Hollister@Sun.COM 	return ((damap_id_t)0);
646*10696SDavid.Hollister@Sun.COM }
647*10696SDavid.Hollister@Sun.COM 
648*10696SDavid.Hollister@Sun.COM /*
649*10696SDavid.Hollister@Sun.COM  * Set config private data
650*10696SDavid.Hollister@Sun.COM  *
651*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
652*10696SDavid.Hollister@Sun.COM  * aid:		address ID
653*10696SDavid.Hollister@Sun.COM  * cfg_priv:	configuration private data
654*10696SDavid.Hollister@Sun.COM  *
655*10696SDavid.Hollister@Sun.COM  */
656*10696SDavid.Hollister@Sun.COM void
657*10696SDavid.Hollister@Sun.COM damap_id_priv_set(damap_t *damapp, damap_id_t aid, void *cfg_priv)
658*10696SDavid.Hollister@Sun.COM {
659*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
660*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
661*10696SDavid.Hollister@Sun.COM 
662*10696SDavid.Hollister@Sun.COM 
663*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
664*10696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid);
665*10696SDavid.Hollister@Sun.COM 	if (!passp) {
666*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, ADDR_LOCK);
667*10696SDavid.Hollister@Sun.COM 		return;
668*10696SDavid.Hollister@Sun.COM 	}
669*10696SDavid.Hollister@Sun.COM 	passp->da_cfg_priv = cfg_priv;
670*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
671*10696SDavid.Hollister@Sun.COM }
672*10696SDavid.Hollister@Sun.COM 
673*10696SDavid.Hollister@Sun.COM /*
674*10696SDavid.Hollister@Sun.COM  * Get config private data
675*10696SDavid.Hollister@Sun.COM  *
676*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
677*10696SDavid.Hollister@Sun.COM  * aid:		address ID
678*10696SDavid.Hollister@Sun.COM  *
679*10696SDavid.Hollister@Sun.COM  * Returns:	configuration private data
680*10696SDavid.Hollister@Sun.COM  */
681*10696SDavid.Hollister@Sun.COM void *
682*10696SDavid.Hollister@Sun.COM damap_id_priv_get(damap_t *damapp, damap_id_t aid)
683*10696SDavid.Hollister@Sun.COM {
684*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
685*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
686*10696SDavid.Hollister@Sun.COM 	void *rv;
687*10696SDavid.Hollister@Sun.COM 
688*10696SDavid.Hollister@Sun.COM 
689*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
690*10696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, (id_t)aid);
691*10696SDavid.Hollister@Sun.COM 	if (!passp) {
692*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, ADDR_LOCK);
693*10696SDavid.Hollister@Sun.COM 		return (NULL);
694*10696SDavid.Hollister@Sun.COM 	}
695*10696SDavid.Hollister@Sun.COM 	rv = passp->da_cfg_priv;
696*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
697*10696SDavid.Hollister@Sun.COM 	return (rv);
698*10696SDavid.Hollister@Sun.COM }
699*10696SDavid.Hollister@Sun.COM 
700*10696SDavid.Hollister@Sun.COM /*
701*10696SDavid.Hollister@Sun.COM  * Lookup a single address in the active address map
702*10696SDavid.Hollister@Sun.COM  *
703*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
704*10696SDavid.Hollister@Sun.COM  * address:	address string
705*10696SDavid.Hollister@Sun.COM  *
706*10696SDavid.Hollister@Sun.COM  * Returns:	ID of active/stable address
707*10696SDavid.Hollister@Sun.COM  *		0	Address not in stable set
708*10696SDavid.Hollister@Sun.COM  *
709*10696SDavid.Hollister@Sun.COM  * Future: Allow the caller to wait for stabilize before returning not found.
710*10696SDavid.Hollister@Sun.COM  */
711*10696SDavid.Hollister@Sun.COM damap_id_t
712*10696SDavid.Hollister@Sun.COM damap_lookup(damap_t *damapp, char *address)
713*10696SDavid.Hollister@Sun.COM {
714*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
715*10696SDavid.Hollister@Sun.COM 	id_t addrid = 0;
716*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp = NULL;
717*10696SDavid.Hollister@Sun.COM 
718*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
719*10696SDavid.Hollister@Sun.COM 	addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
720*10696SDavid.Hollister@Sun.COM 	if (addrid) {
721*10696SDavid.Hollister@Sun.COM 		DAM_LOCK(mapp, MAP_LOCK);
722*10696SDavid.Hollister@Sun.COM 		if (DAM_IS_STABLE(mapp, addrid)) {
723*10696SDavid.Hollister@Sun.COM 			passp = ddi_get_soft_state(mapp->dam_da, addrid);
724*10696SDavid.Hollister@Sun.COM 			ASSERT(passp);
725*10696SDavid.Hollister@Sun.COM 			if (passp) {
726*10696SDavid.Hollister@Sun.COM 				passp->da_ref++;
727*10696SDavid.Hollister@Sun.COM 			} else {
728*10696SDavid.Hollister@Sun.COM 				addrid = 0;
729*10696SDavid.Hollister@Sun.COM 			}
730*10696SDavid.Hollister@Sun.COM 		} else {
731*10696SDavid.Hollister@Sun.COM 			addrid = 0;
732*10696SDavid.Hollister@Sun.COM 		}
733*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, MAP_LOCK);
734*10696SDavid.Hollister@Sun.COM 	}
735*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
736*10696SDavid.Hollister@Sun.COM 	return ((damap_id_t)addrid);
737*10696SDavid.Hollister@Sun.COM }
738*10696SDavid.Hollister@Sun.COM 
739*10696SDavid.Hollister@Sun.COM 
740*10696SDavid.Hollister@Sun.COM /*
741*10696SDavid.Hollister@Sun.COM  * Return the list of stable addresses in the map
742*10696SDavid.Hollister@Sun.COM  *
743*10696SDavid.Hollister@Sun.COM  * damapp:	address map handle
744*10696SDavid.Hollister@Sun.COM  * id_listp:	pointer to list of address IDs in stable map (returned)
745*10696SDavid.Hollister@Sun.COM  *
746*10696SDavid.Hollister@Sun.COM  * Returns:	# of entries returned in alist
747*10696SDavid.Hollister@Sun.COM  */
748*10696SDavid.Hollister@Sun.COM int
749*10696SDavid.Hollister@Sun.COM damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
750*10696SDavid.Hollister@Sun.COM {
751*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
752*10696SDavid.Hollister@Sun.COM 	int mapsz = mapp->dam_size;
753*10696SDavid.Hollister@Sun.COM 	int n_ids, i;
754*10696SDavid.Hollister@Sun.COM 	bitset_t *bsp;
755*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
756*10696SDavid.Hollister@Sun.COM 
757*10696SDavid.Hollister@Sun.COM 	bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
758*10696SDavid.Hollister@Sun.COM 	bitset_init(bsp);
759*10696SDavid.Hollister@Sun.COM 	bitset_resize(bsp, mapsz);
760*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, MAP_LOCK);
761*10696SDavid.Hollister@Sun.COM 	bitset_copy(&mapp->dam_active_set, bsp);
762*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, MAP_LOCK);
763*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
764*10696SDavid.Hollister@Sun.COM 	for (n_ids = 0, i = 1; i < mapsz; i++) {
765*10696SDavid.Hollister@Sun.COM 		if (bitset_in_set(bsp, i)) {
766*10696SDavid.Hollister@Sun.COM 			passp = ddi_get_soft_state(mapp->dam_da, i);
767*10696SDavid.Hollister@Sun.COM 			ASSERT(passp);
768*10696SDavid.Hollister@Sun.COM 			if (passp) {
769*10696SDavid.Hollister@Sun.COM 				passp->da_ref++;
770*10696SDavid.Hollister@Sun.COM 				n_ids++;
771*10696SDavid.Hollister@Sun.COM 			}
772*10696SDavid.Hollister@Sun.COM 		}
773*10696SDavid.Hollister@Sun.COM 	}
774*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
775*10696SDavid.Hollister@Sun.COM 	if (n_ids) {
776*10696SDavid.Hollister@Sun.COM 		*id_listp = (damap_id_list_t)bsp;
777*10696SDavid.Hollister@Sun.COM 		return (n_ids);
778*10696SDavid.Hollister@Sun.COM 	} else {
779*10696SDavid.Hollister@Sun.COM 		*id_listp = (damap_id_list_t)NULL;
780*10696SDavid.Hollister@Sun.COM 		bitset_fini(bsp);
781*10696SDavid.Hollister@Sun.COM 		kmem_free(bsp, sizeof (*bsp));
782*10696SDavid.Hollister@Sun.COM 		return (0);
783*10696SDavid.Hollister@Sun.COM 	}
784*10696SDavid.Hollister@Sun.COM }
785*10696SDavid.Hollister@Sun.COM 
786*10696SDavid.Hollister@Sun.COM /*
787*10696SDavid.Hollister@Sun.COM  * Release the address list returned by damap_lookup_all()
788*10696SDavid.Hollister@Sun.COM  *
789*10696SDavid.Hollister@Sun.COM  * mapp:	address map handle
790*10696SDavid.Hollister@Sun.COM  * id_list:	list of address IDs returned in damap_lookup_all()
791*10696SDavid.Hollister@Sun.COM  */
792*10696SDavid.Hollister@Sun.COM void
793*10696SDavid.Hollister@Sun.COM damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
794*10696SDavid.Hollister@Sun.COM {
795*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)damapp;
796*10696SDavid.Hollister@Sun.COM 	int i;
797*10696SDavid.Hollister@Sun.COM 
798*10696SDavid.Hollister@Sun.COM 	if (id_list == NULL)
799*10696SDavid.Hollister@Sun.COM 		return;
800*10696SDavid.Hollister@Sun.COM 
801*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
802*10696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
803*10696SDavid.Hollister@Sun.COM 		if (bitset_in_set((bitset_t *)id_list, i))
804*10696SDavid.Hollister@Sun.COM 			(void) dam_release(mapp, i);
805*10696SDavid.Hollister@Sun.COM 	}
806*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
807*10696SDavid.Hollister@Sun.COM 	bitset_fini((bitset_t *)id_list);
808*10696SDavid.Hollister@Sun.COM 	kmem_free((void *)id_list, sizeof (bitset_t));
809*10696SDavid.Hollister@Sun.COM }
810*10696SDavid.Hollister@Sun.COM 
811*10696SDavid.Hollister@Sun.COM /*
812*10696SDavid.Hollister@Sun.COM  * Activate a set of stabilized addresses
813*10696SDavid.Hollister@Sun.COM  */
814*10696SDavid.Hollister@Sun.COM static void
815*10696SDavid.Hollister@Sun.COM dam_addrset_activate(dam_t *mapp, bitset_t *active_set)
816*10696SDavid.Hollister@Sun.COM {
817*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
818*10696SDavid.Hollister@Sun.COM 	char *addrstr;
819*10696SDavid.Hollister@Sun.COM 	int i;
820*10696SDavid.Hollister@Sun.COM 	uint32_t n_active = 0;
821*10696SDavid.Hollister@Sun.COM 
822*10696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
823*10696SDavid.Hollister@Sun.COM 		if (bitset_in_set(&mapp->dam_active_set, i))
824*10696SDavid.Hollister@Sun.COM 			n_active++;
825*10696SDavid.Hollister@Sun.COM 		if (!bitset_in_set(active_set, i))
826*10696SDavid.Hollister@Sun.COM 			continue;
827*10696SDavid.Hollister@Sun.COM 		n_active++;
828*10696SDavid.Hollister@Sun.COM 		passp = ddi_get_soft_state(mapp->dam_da, i);
829*10696SDavid.Hollister@Sun.COM 		ASSERT(passp);
830*10696SDavid.Hollister@Sun.COM 		if (mapp->dam_activate_cb) {
831*10696SDavid.Hollister@Sun.COM 			addrstr = ddi_strid_id2str(mapp->dam_addr_hash, i);
832*10696SDavid.Hollister@Sun.COM 			(*mapp->dam_activate_cb)(
833*10696SDavid.Hollister@Sun.COM 			    mapp->dam_activate_arg, addrstr, i,
834*10696SDavid.Hollister@Sun.COM 			    &passp->da_ppriv_rpt);
835*10696SDavid.Hollister@Sun.COM 		}
836*10696SDavid.Hollister@Sun.COM 		DTRACE_PROBE2(damap__addrset__activate, dam_t *, mapp, int, i);
837*10696SDavid.Hollister@Sun.COM 		DAM_LOCK(mapp, MAP_LOCK);
838*10696SDavid.Hollister@Sun.COM 		bitset_add(&mapp->dam_active_set, i);
839*10696SDavid.Hollister@Sun.COM 		/*
840*10696SDavid.Hollister@Sun.COM 		 * copy the reported nvlist and provider private data
841*10696SDavid.Hollister@Sun.COM 		 */
842*10696SDavid.Hollister@Sun.COM 		passp->da_nvl = passp->da_nvl_rpt;
843*10696SDavid.Hollister@Sun.COM 		passp->da_ppriv = passp->da_ppriv_rpt;
844*10696SDavid.Hollister@Sun.COM 		passp->da_ppriv_rpt = NULL;
845*10696SDavid.Hollister@Sun.COM 		passp->da_nvl_rpt = NULL;
846*10696SDavid.Hollister@Sun.COM 		passp->da_last_stable = gethrtime();
847*10696SDavid.Hollister@Sun.COM 		passp->da_stable_cnt++;
848*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, MAP_LOCK);
849*10696SDavid.Hollister@Sun.COM 		DAM_SET_STAT(mapp, dam_numstable, n_active);
850*10696SDavid.Hollister@Sun.COM 	}
851*10696SDavid.Hollister@Sun.COM }
852*10696SDavid.Hollister@Sun.COM 
853*10696SDavid.Hollister@Sun.COM /*
854*10696SDavid.Hollister@Sun.COM  * Release a set of stabilized addresses
855*10696SDavid.Hollister@Sun.COM  */
856*10696SDavid.Hollister@Sun.COM static void
857*10696SDavid.Hollister@Sun.COM dam_addrset_release(dam_t *mapp, bitset_t *release_set)
858*10696SDavid.Hollister@Sun.COM {
859*10696SDavid.Hollister@Sun.COM 	int i;
860*10696SDavid.Hollister@Sun.COM 
861*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
862*10696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
863*10696SDavid.Hollister@Sun.COM 		if (bitset_in_set(release_set, i)) {
864*10696SDavid.Hollister@Sun.COM 			DTRACE_PROBE2(damap__addrset__release, dam_t *, mapp,
865*10696SDavid.Hollister@Sun.COM 			    int, i);
866*10696SDavid.Hollister@Sun.COM 			DAM_LOCK(mapp, MAP_LOCK);
867*10696SDavid.Hollister@Sun.COM 			bitset_del(&mapp->dam_active_set, i);
868*10696SDavid.Hollister@Sun.COM 			DAM_UNLOCK(mapp, MAP_LOCK);
869*10696SDavid.Hollister@Sun.COM 			(void) dam_release(mapp, i);
870*10696SDavid.Hollister@Sun.COM 		}
871*10696SDavid.Hollister@Sun.COM 	}
872*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
873*10696SDavid.Hollister@Sun.COM }
874*10696SDavid.Hollister@Sun.COM 
875*10696SDavid.Hollister@Sun.COM /*
876*10696SDavid.Hollister@Sun.COM  * release a previously activated address
877*10696SDavid.Hollister@Sun.COM  */
878*10696SDavid.Hollister@Sun.COM static void
879*10696SDavid.Hollister@Sun.COM dam_release(dam_t *mapp, id_t addrid)
880*10696SDavid.Hollister@Sun.COM {
881*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
882*10696SDavid.Hollister@Sun.COM 
883*10696SDavid.Hollister@Sun.COM 	DAM_ASSERT_LOCKED(mapp, ADDR_LOCK);
884*10696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
885*10696SDavid.Hollister@Sun.COM 	ASSERT(passp);
886*10696SDavid.Hollister@Sun.COM 
887*10696SDavid.Hollister@Sun.COM 	/*
888*10696SDavid.Hollister@Sun.COM 	 * invoke the deactivation callback to notify
889*10696SDavid.Hollister@Sun.COM 	 * this address is no longer active
890*10696SDavid.Hollister@Sun.COM 	 */
891*10696SDavid.Hollister@Sun.COM 	dam_deactivate_addr(mapp, addrid);
892*10696SDavid.Hollister@Sun.COM 
893*10696SDavid.Hollister@Sun.COM 	/*
894*10696SDavid.Hollister@Sun.COM 	 * allow pending reports for this address to stabilize
895*10696SDavid.Hollister@Sun.COM 	 */
896*10696SDavid.Hollister@Sun.COM 	if (DAM_IN_REPORT(mapp, addrid))
897*10696SDavid.Hollister@Sun.COM 		return;
898*10696SDavid.Hollister@Sun.COM 
899*10696SDavid.Hollister@Sun.COM 	/*
900*10696SDavid.Hollister@Sun.COM 	 * defer teardown until outstanding references are released
901*10696SDavid.Hollister@Sun.COM 	 */
902*10696SDavid.Hollister@Sun.COM 	if (--passp->da_ref) {
903*10696SDavid.Hollister@Sun.COM 		passp->da_flags |= DA_RELE;
904*10696SDavid.Hollister@Sun.COM 		return;
905*10696SDavid.Hollister@Sun.COM 	}
906*10696SDavid.Hollister@Sun.COM 	ddi_strid_free(mapp->dam_addr_hash, addrid);
907*10696SDavid.Hollister@Sun.COM 	ddi_soft_state_free(mapp->dam_da, addrid);
908*10696SDavid.Hollister@Sun.COM }
909*10696SDavid.Hollister@Sun.COM 
910*10696SDavid.Hollister@Sun.COM /*
911*10696SDavid.Hollister@Sun.COM  * process stabilized address reports
912*10696SDavid.Hollister@Sun.COM  */
913*10696SDavid.Hollister@Sun.COM static void
914*10696SDavid.Hollister@Sun.COM dam_activate_taskq(void *arg)
915*10696SDavid.Hollister@Sun.COM {
916*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
917*10696SDavid.Hollister@Sun.COM 	bitset_t delta;
918*10696SDavid.Hollister@Sun.COM 	bitset_t cfg;
919*10696SDavid.Hollister@Sun.COM 	bitset_t uncfg;
920*10696SDavid.Hollister@Sun.COM 	int has_cfg, has_uncfg;
921*10696SDavid.Hollister@Sun.COM 
922*10696SDavid.Hollister@Sun.COM 	bitset_init(&delta);
923*10696SDavid.Hollister@Sun.COM 	bitset_resize(&delta, mapp->dam_size);
924*10696SDavid.Hollister@Sun.COM 	bitset_init(&cfg);
925*10696SDavid.Hollister@Sun.COM 	bitset_resize(&cfg, mapp->dam_size);
926*10696SDavid.Hollister@Sun.COM 	bitset_init(&uncfg);
927*10696SDavid.Hollister@Sun.COM 	bitset_resize(&uncfg, mapp->dam_size);
928*10696SDavid.Hollister@Sun.COM 
929*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE1(damap__activate__taskq__entry, dam_t, mapp);
930*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, MAP_LOCK);
931*10696SDavid.Hollister@Sun.COM 	if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
932*10696SDavid.Hollister@Sun.COM 	    &delta)) {
933*10696SDavid.Hollister@Sun.COM 		bitset_zero(&mapp->dam_stable_set);
934*10696SDavid.Hollister@Sun.COM 		DAM_FLAG_CLR(mapp, DAM_SPEND);
935*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, MAP_LOCK);
936*10696SDavid.Hollister@Sun.COM 		bitset_fini(&uncfg);
937*10696SDavid.Hollister@Sun.COM 		bitset_fini(&cfg);
938*10696SDavid.Hollister@Sun.COM 		bitset_fini(&delta);
939*10696SDavid.Hollister@Sun.COM 		return;
940*10696SDavid.Hollister@Sun.COM 	}
941*10696SDavid.Hollister@Sun.COM 	has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
942*10696SDavid.Hollister@Sun.COM 	has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
943*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, MAP_LOCK);
944*10696SDavid.Hollister@Sun.COM 	if (has_cfg) {
945*10696SDavid.Hollister@Sun.COM 		dam_addrset_activate(mapp, &cfg);
946*10696SDavid.Hollister@Sun.COM 		(*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp, &cfg);
947*10696SDavid.Hollister@Sun.COM 	}
948*10696SDavid.Hollister@Sun.COM 	if (has_uncfg) {
949*10696SDavid.Hollister@Sun.COM 		(*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, &uncfg);
950*10696SDavid.Hollister@Sun.COM 		dam_addrset_release(mapp, &uncfg);
951*10696SDavid.Hollister@Sun.COM 	}
952*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, MAP_LOCK);
953*10696SDavid.Hollister@Sun.COM 	bitset_zero(&mapp->dam_stable_set);
954*10696SDavid.Hollister@Sun.COM 	DAM_FLAG_CLR(mapp, DAM_SPEND);
955*10696SDavid.Hollister@Sun.COM 	mapp->dam_last_stable = gethrtime();
956*10696SDavid.Hollister@Sun.COM 	mapp->dam_stable_cnt++;
957*10696SDavid.Hollister@Sun.COM 	DAM_INCR_STAT(mapp, dam_stable);
958*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, MAP_LOCK);
959*10696SDavid.Hollister@Sun.COM 	bitset_fini(&uncfg);
960*10696SDavid.Hollister@Sun.COM 	bitset_fini(&cfg);
961*10696SDavid.Hollister@Sun.COM 	bitset_fini(&delta);
962*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE1(damap__activate__taskq__exit, dam_t, mapp);
963*10696SDavid.Hollister@Sun.COM }
964*10696SDavid.Hollister@Sun.COM 
965*10696SDavid.Hollister@Sun.COM /*
966*10696SDavid.Hollister@Sun.COM  * per-address stabilization timeout
967*10696SDavid.Hollister@Sun.COM  */
968*10696SDavid.Hollister@Sun.COM static void
969*10696SDavid.Hollister@Sun.COM dam_addr_stable_cb(void *arg)
970*10696SDavid.Hollister@Sun.COM {
971*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
972*10696SDavid.Hollister@Sun.COM 	int i;
973*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
974*10696SDavid.Hollister@Sun.COM 	int spend = 0;
975*10696SDavid.Hollister@Sun.COM 	int tpend = 0;
976*10696SDavid.Hollister@Sun.COM 	int64_t	next_tmov = mapp->dam_stabletmo;
977*10696SDavid.Hollister@Sun.COM 	int64_t tmo_delta;
978*10696SDavid.Hollister@Sun.COM 	int64_t ts = lbolt64;
979*10696SDavid.Hollister@Sun.COM 
980*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE1(damap__addr__stable__cb__entry, dam_t *, mapp);
981*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, MAP_LOCK);
982*10696SDavid.Hollister@Sun.COM 	if (mapp->dam_tid == 0) {
983*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, MAP_LOCK);
984*10696SDavid.Hollister@Sun.COM 		return;
985*10696SDavid.Hollister@Sun.COM 	}
986*10696SDavid.Hollister@Sun.COM 	mapp->dam_tid = 0;
987*10696SDavid.Hollister@Sun.COM 	/*
988*10696SDavid.Hollister@Sun.COM 	 * If still under stabilization, reschedule timeout,
989*10696SDavid.Hollister@Sun.COM 	 * else dispatch the task to activate & deactivate the stable
990*10696SDavid.Hollister@Sun.COM 	 * set.
991*10696SDavid.Hollister@Sun.COM 	 */
992*10696SDavid.Hollister@Sun.COM 	if (mapp->dam_flags & DAM_SPEND) {
993*10696SDavid.Hollister@Sun.COM 		DAM_INCR_STAT(mapp, dam_stable_blocked);
994*10696SDavid.Hollister@Sun.COM 		mapp->dam_stable_overrun++;
995*10696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
996*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, MAP_LOCK);
997*10696SDavid.Hollister@Sun.COM 		DTRACE_PROBE1(damap__addr__stable__cb__overrun,
998*10696SDavid.Hollister@Sun.COM 		    dam_t *, mapp);
999*10696SDavid.Hollister@Sun.COM 		return;
1000*10696SDavid.Hollister@Sun.COM 	}
1001*10696SDavid.Hollister@Sun.COM 
1002*10696SDavid.Hollister@Sun.COM 	bitset_copy(&mapp->dam_active_set, &mapp->dam_stable_set);
1003*10696SDavid.Hollister@Sun.COM 	for (i = 1; i < mapp->dam_high; i++) {
1004*10696SDavid.Hollister@Sun.COM 		if (!bitset_in_set(&mapp->dam_report_set, i))
1005*10696SDavid.Hollister@Sun.COM 			continue;
1006*10696SDavid.Hollister@Sun.COM 		/*
1007*10696SDavid.Hollister@Sun.COM 		 * Stabilize each address
1008*10696SDavid.Hollister@Sun.COM 		 */
1009*10696SDavid.Hollister@Sun.COM 		passp = ddi_get_soft_state(mapp->dam_da, i);
1010*10696SDavid.Hollister@Sun.COM 		ASSERT(passp);
1011*10696SDavid.Hollister@Sun.COM 		if (!passp) {
1012*10696SDavid.Hollister@Sun.COM 			cmn_err(CE_WARN, "Clearing report no softstate %d", i);
1013*10696SDavid.Hollister@Sun.COM 			bitset_del(&mapp->dam_report_set, i);
1014*10696SDavid.Hollister@Sun.COM 			continue;
1015*10696SDavid.Hollister@Sun.COM 		}
1016*10696SDavid.Hollister@Sun.COM 
1017*10696SDavid.Hollister@Sun.COM 		/* report has stabilized */
1018*10696SDavid.Hollister@Sun.COM 		if (passp->da_deadline <= ts) {
1019*10696SDavid.Hollister@Sun.COM 			bitset_del(&mapp->dam_report_set, i);
1020*10696SDavid.Hollister@Sun.COM 			if (passp->da_flags & DA_RELE) {
1021*10696SDavid.Hollister@Sun.COM 				DTRACE_PROBE2(damap__addr__stable__del,
1022*10696SDavid.Hollister@Sun.COM 				    dam_t *, mapp, int, i);
1023*10696SDavid.Hollister@Sun.COM 				bitset_del(&mapp->dam_stable_set, i);
1024*10696SDavid.Hollister@Sun.COM 			} else {
1025*10696SDavid.Hollister@Sun.COM 				DTRACE_PROBE2(damap__addr__stable__add,
1026*10696SDavid.Hollister@Sun.COM 				    dam_t *, mapp, int, i);
1027*10696SDavid.Hollister@Sun.COM 				bitset_add(&mapp->dam_stable_set, i);
1028*10696SDavid.Hollister@Sun.COM 			}
1029*10696SDavid.Hollister@Sun.COM 			spend++;
1030*10696SDavid.Hollister@Sun.COM 			continue;
1031*10696SDavid.Hollister@Sun.COM 		}
1032*10696SDavid.Hollister@Sun.COM 
1033*10696SDavid.Hollister@Sun.COM 		/*
1034*10696SDavid.Hollister@Sun.COM 		 * not stabilized, determine next (future) map timeout
1035*10696SDavid.Hollister@Sun.COM 		 */
1036*10696SDavid.Hollister@Sun.COM 		tpend++;
1037*10696SDavid.Hollister@Sun.COM 		tmo_delta = passp->da_deadline - ts;
1038*10696SDavid.Hollister@Sun.COM 		if (tmo_delta < next_tmov)
1039*10696SDavid.Hollister@Sun.COM 			next_tmov = tmo_delta;
1040*10696SDavid.Hollister@Sun.COM 	}
1041*10696SDavid.Hollister@Sun.COM 
1042*10696SDavid.Hollister@Sun.COM 	/*
1043*10696SDavid.Hollister@Sun.COM 	 * schedule taskq activation of stabilized reports
1044*10696SDavid.Hollister@Sun.COM 	 */
1045*10696SDavid.Hollister@Sun.COM 	if (spend) {
1046*10696SDavid.Hollister@Sun.COM 		if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq,
1047*10696SDavid.Hollister@Sun.COM 		    mapp, DDI_NOSLEEP) == DDI_SUCCESS) {
1048*10696SDavid.Hollister@Sun.COM 			DAM_FLAG_SET(mapp, DAM_SPEND);
1049*10696SDavid.Hollister@Sun.COM 		} else
1050*10696SDavid.Hollister@Sun.COM 			tpend++;
1051*10696SDavid.Hollister@Sun.COM 	}
1052*10696SDavid.Hollister@Sun.COM 
1053*10696SDavid.Hollister@Sun.COM 	/*
1054*10696SDavid.Hollister@Sun.COM 	 * schedule timeout to handle future stabalization of active reports
1055*10696SDavid.Hollister@Sun.COM 	 */
1056*10696SDavid.Hollister@Sun.COM 	if (tpend)
1057*10696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, (clock_t)next_tmov, dam_addr_stable_cb);
1058*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, MAP_LOCK);
1059*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE1(damap__addr__stable__cb__exit, dam_t *, mapp);
1060*10696SDavid.Hollister@Sun.COM }
1061*10696SDavid.Hollister@Sun.COM 
1062*10696SDavid.Hollister@Sun.COM /*
1063*10696SDavid.Hollister@Sun.COM  * fullset stabilization timeout
1064*10696SDavid.Hollister@Sun.COM  */
1065*10696SDavid.Hollister@Sun.COM static void
1066*10696SDavid.Hollister@Sun.COM dam_set_stable_cb(void *arg)
1067*10696SDavid.Hollister@Sun.COM {
1068*10696SDavid.Hollister@Sun.COM 	dam_t *mapp = (dam_t *)arg;
1069*10696SDavid.Hollister@Sun.COM 
1070*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE1(damap__set__stable__cb__enter, dam_t *, mapp);
1071*10696SDavid.Hollister@Sun.COM 
1072*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, MAP_LOCK);
1073*10696SDavid.Hollister@Sun.COM 	if (mapp->dam_tid == 0) {
1074*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, MAP_LOCK);
1075*10696SDavid.Hollister@Sun.COM 		return;
1076*10696SDavid.Hollister@Sun.COM 	}
1077*10696SDavid.Hollister@Sun.COM 	mapp->dam_tid = 0;
1078*10696SDavid.Hollister@Sun.COM 
1079*10696SDavid.Hollister@Sun.COM 	/*
1080*10696SDavid.Hollister@Sun.COM 	 * If still under stabilization, reschedule timeout,
1081*10696SDavid.Hollister@Sun.COM 	 * else dispatch the task to activate & deactivate the stable
1082*10696SDavid.Hollister@Sun.COM 	 * set.
1083*10696SDavid.Hollister@Sun.COM 	 */
1084*10696SDavid.Hollister@Sun.COM 	if (mapp->dam_flags & DAM_SPEND) {
1085*10696SDavid.Hollister@Sun.COM 		DAM_INCR_STAT(mapp, dam_stable_blocked);
1086*10696SDavid.Hollister@Sun.COM 		mapp->dam_stable_overrun++;
1087*10696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb);
1088*10696SDavid.Hollister@Sun.COM 		DTRACE_PROBE1(damap__set__stable__cb__overrun,
1089*10696SDavid.Hollister@Sun.COM 		    dam_t *, mapp);
1090*10696SDavid.Hollister@Sun.COM 	} else if (ddi_taskq_dispatch(mapp->dam_taskqp, dam_activate_taskq,
1091*10696SDavid.Hollister@Sun.COM 	    mapp, DDI_NOSLEEP) == DDI_FAILURE) {
1092*10696SDavid.Hollister@Sun.COM 		dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_set_stable_cb);
1093*10696SDavid.Hollister@Sun.COM 	} else {
1094*10696SDavid.Hollister@Sun.COM 		bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
1095*10696SDavid.Hollister@Sun.COM 		bitset_zero(&mapp->dam_report_set);
1096*10696SDavid.Hollister@Sun.COM 		DAM_FLAG_CLR(mapp, DAM_SETADD);
1097*10696SDavid.Hollister@Sun.COM 		DAM_FLAG_SET(mapp, DAM_SPEND);
1098*10696SDavid.Hollister@Sun.COM 	}
1099*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, MAP_LOCK);
1100*10696SDavid.Hollister@Sun.COM 	DTRACE_PROBE1(damap__set__stable__cb__exit, dam_t *, mapp);
1101*10696SDavid.Hollister@Sun.COM }
1102*10696SDavid.Hollister@Sun.COM 
1103*10696SDavid.Hollister@Sun.COM /*
1104*10696SDavid.Hollister@Sun.COM  * reschedule map timeout 'tmo_ms' ticks
1105*10696SDavid.Hollister@Sun.COM  */
1106*10696SDavid.Hollister@Sun.COM static void
1107*10696SDavid.Hollister@Sun.COM dam_sched_tmo(dam_t *mapp, clock_t tmo_ms, void (*tmo_cb)())
1108*10696SDavid.Hollister@Sun.COM {
1109*10696SDavid.Hollister@Sun.COM 	timeout_id_t tid;
1110*10696SDavid.Hollister@Sun.COM 
1111*10696SDavid.Hollister@Sun.COM 	if ((tid = mapp->dam_tid) != 0) {
1112*10696SDavid.Hollister@Sun.COM 		mapp->dam_tid = 0;
1113*10696SDavid.Hollister@Sun.COM 		DAM_UNLOCK(mapp, MAP_LOCK);
1114*10696SDavid.Hollister@Sun.COM 		(void) untimeout(tid);
1115*10696SDavid.Hollister@Sun.COM 		DAM_LOCK(mapp, MAP_LOCK);
1116*10696SDavid.Hollister@Sun.COM 	}
1117*10696SDavid.Hollister@Sun.COM 
1118*10696SDavid.Hollister@Sun.COM 	if (tmo_cb && (tmo_ms != 0))
1119*10696SDavid.Hollister@Sun.COM 		mapp->dam_tid = timeout(tmo_cb, mapp, tmo_ms);
1120*10696SDavid.Hollister@Sun.COM }
1121*10696SDavid.Hollister@Sun.COM 
1122*10696SDavid.Hollister@Sun.COM /*
1123*10696SDavid.Hollister@Sun.COM  * record report addition or removal of an address
1124*10696SDavid.Hollister@Sun.COM  */
1125*10696SDavid.Hollister@Sun.COM static void
1126*10696SDavid.Hollister@Sun.COM dam_add_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int report)
1127*10696SDavid.Hollister@Sun.COM {
1128*10696SDavid.Hollister@Sun.COM 	ASSERT(!DAM_IN_REPORT(mapp, addrid));
1129*10696SDavid.Hollister@Sun.COM 	passp->da_last_report = gethrtime();
1130*10696SDavid.Hollister@Sun.COM 	mapp->dam_last_update = gethrtime();
1131*10696SDavid.Hollister@Sun.COM 	passp->da_report_cnt++;
1132*10696SDavid.Hollister@Sun.COM 	passp->da_deadline = lbolt64 + mapp->dam_stabletmo;
1133*10696SDavid.Hollister@Sun.COM 	if (report == RPT_ADDR_DEL)
1134*10696SDavid.Hollister@Sun.COM 		passp->da_flags |= DA_RELE;
1135*10696SDavid.Hollister@Sun.COM 	else if (report == RPT_ADDR_ADD)
1136*10696SDavid.Hollister@Sun.COM 		passp->da_flags &= ~DA_RELE;
1137*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, MAP_LOCK);
1138*10696SDavid.Hollister@Sun.COM 	bitset_add(&mapp->dam_report_set, addrid);
1139*10696SDavid.Hollister@Sun.COM 	dam_sched_tmo(mapp, mapp->dam_stabletmo, dam_addr_stable_cb);
1140*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, MAP_LOCK);
1141*10696SDavid.Hollister@Sun.COM 
1142*10696SDavid.Hollister@Sun.COM }
1143*10696SDavid.Hollister@Sun.COM 
1144*10696SDavid.Hollister@Sun.COM /*
1145*10696SDavid.Hollister@Sun.COM  * release an address report
1146*10696SDavid.Hollister@Sun.COM  */
1147*10696SDavid.Hollister@Sun.COM static void
1148*10696SDavid.Hollister@Sun.COM dam_release_report(dam_t *mapp, id_t addrid)
1149*10696SDavid.Hollister@Sun.COM {
1150*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
1151*10696SDavid.Hollister@Sun.COM 
1152*10696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
1153*10696SDavid.Hollister@Sun.COM 	ASSERT(passp);
1154*10696SDavid.Hollister@Sun.COM 	passp->da_ppriv_rpt = NULL;
1155*10696SDavid.Hollister@Sun.COM 	if (passp->da_nvl_rpt)
1156*10696SDavid.Hollister@Sun.COM 		nvlist_free(passp->da_nvl_rpt);
1157*10696SDavid.Hollister@Sun.COM 	passp->da_nvl_rpt = NULL;
1158*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, MAP_LOCK);
1159*10696SDavid.Hollister@Sun.COM 	bitset_del(&mapp->dam_report_set, addrid);
1160*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, MAP_LOCK);
1161*10696SDavid.Hollister@Sun.COM }
1162*10696SDavid.Hollister@Sun.COM 
1163*10696SDavid.Hollister@Sun.COM /*
1164*10696SDavid.Hollister@Sun.COM  * deactivate a previously stable address
1165*10696SDavid.Hollister@Sun.COM  */
1166*10696SDavid.Hollister@Sun.COM static void
1167*10696SDavid.Hollister@Sun.COM dam_deactivate_addr(dam_t *mapp, id_t addrid)
1168*10696SDavid.Hollister@Sun.COM {
1169*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
1170*10696SDavid.Hollister@Sun.COM 
1171*10696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
1172*10696SDavid.Hollister@Sun.COM 	ASSERT(passp);
1173*10696SDavid.Hollister@Sun.COM 	if (passp == NULL)
1174*10696SDavid.Hollister@Sun.COM 		return;
1175*10696SDavid.Hollister@Sun.COM 	DAM_UNLOCK(mapp, ADDR_LOCK);
1176*10696SDavid.Hollister@Sun.COM 	if (mapp->dam_deactivate_cb)
1177*10696SDavid.Hollister@Sun.COM 		(*mapp->dam_deactivate_cb)(
1178*10696SDavid.Hollister@Sun.COM 		    mapp->dam_activate_arg,
1179*10696SDavid.Hollister@Sun.COM 		    ddi_strid_id2str(mapp->dam_addr_hash,
1180*10696SDavid.Hollister@Sun.COM 		    addrid), addrid, passp->da_ppriv);
1181*10696SDavid.Hollister@Sun.COM 	DAM_LOCK(mapp, ADDR_LOCK);
1182*10696SDavid.Hollister@Sun.COM 	passp->da_ppriv = NULL;
1183*10696SDavid.Hollister@Sun.COM 	if (passp->da_nvl)
1184*10696SDavid.Hollister@Sun.COM 		nvlist_free(passp->da_nvl);
1185*10696SDavid.Hollister@Sun.COM 	passp->da_nvl = NULL;
1186*10696SDavid.Hollister@Sun.COM }
1187*10696SDavid.Hollister@Sun.COM 
1188*10696SDavid.Hollister@Sun.COM /*
1189*10696SDavid.Hollister@Sun.COM  * return the map ID of an address
1190*10696SDavid.Hollister@Sun.COM  */
1191*10696SDavid.Hollister@Sun.COM static id_t
1192*10696SDavid.Hollister@Sun.COM dam_get_addrid(dam_t *mapp, char *address)
1193*10696SDavid.Hollister@Sun.COM {
1194*10696SDavid.Hollister@Sun.COM 	damap_id_t addrid;
1195*10696SDavid.Hollister@Sun.COM 	dam_da_t *passp;
1196*10696SDavid.Hollister@Sun.COM 
1197*10696SDavid.Hollister@Sun.COM 	if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
1198*10696SDavid.Hollister@Sun.COM 		if ((addrid = ddi_strid_fixed_alloc(mapp->dam_addr_hash,
1199*10696SDavid.Hollister@Sun.COM 		    address)) == (damap_id_t)0) {
1200*10696SDavid.Hollister@Sun.COM 			return (0);
1201*10696SDavid.Hollister@Sun.COM 		}
1202*10696SDavid.Hollister@Sun.COM 		if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
1203*10696SDavid.Hollister@Sun.COM 		    DDI_SUCCESS) {
1204*10696SDavid.Hollister@Sun.COM 			ddi_strid_free(mapp->dam_addr_hash, addrid);
1205*10696SDavid.Hollister@Sun.COM 			return (0);
1206*10696SDavid.Hollister@Sun.COM 		}
1207*10696SDavid.Hollister@Sun.COM 		if (addrid >= mapp->dam_high)
1208*10696SDavid.Hollister@Sun.COM 			mapp->dam_high = addrid + 1;
1209*10696SDavid.Hollister@Sun.COM 	}
1210*10696SDavid.Hollister@Sun.COM 	passp = ddi_get_soft_state(mapp->dam_da, addrid);
1211*10696SDavid.Hollister@Sun.COM 	if (passp == NULL)
1212*10696SDavid.Hollister@Sun.COM 		return (0);
1213*10696SDavid.Hollister@Sun.COM 	passp->da_ref++;
1214*10696SDavid.Hollister@Sun.COM 	if (passp->da_addr == NULL)
1215*10696SDavid.Hollister@Sun.COM 		passp->da_addr = ddi_strid_id2str(
1216*10696SDavid.Hollister@Sun.COM 		    mapp->dam_addr_hash, addrid); /* for mdb */
1217*10696SDavid.Hollister@Sun.COM 	return (addrid);
1218*10696SDavid.Hollister@Sun.COM }
1219*10696SDavid.Hollister@Sun.COM 
1220*10696SDavid.Hollister@Sun.COM /*
1221*10696SDavid.Hollister@Sun.COM  * create and install map statistics
1222*10696SDavid.Hollister@Sun.COM  */
1223*10696SDavid.Hollister@Sun.COM static int
1224*10696SDavid.Hollister@Sun.COM dam_kstat_create(dam_t *mapp)
1225*10696SDavid.Hollister@Sun.COM {
1226*10696SDavid.Hollister@Sun.COM 	kstat_t			*mapsp;
1227*10696SDavid.Hollister@Sun.COM 	struct dam_kstats	*statsp;
1228*10696SDavid.Hollister@Sun.COM 
1229*10696SDavid.Hollister@Sun.COM 	mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
1230*10696SDavid.Hollister@Sun.COM 	    KSTAT_TYPE_NAMED,
1231*10696SDavid.Hollister@Sun.COM 	    sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
1232*10696SDavid.Hollister@Sun.COM 	if (mapsp == NULL) {
1233*10696SDavid.Hollister@Sun.COM 		return (DDI_FAILURE);
1234*10696SDavid.Hollister@Sun.COM 	}
1235*10696SDavid.Hollister@Sun.COM 
1236*10696SDavid.Hollister@Sun.COM 	statsp = (struct dam_kstats *)mapsp->ks_data;
1237*10696SDavid.Hollister@Sun.COM 	kstat_named_init(&statsp->dam_stable, "stable cycles",
1238*10696SDavid.Hollister@Sun.COM 	    KSTAT_DATA_UINT32);
1239*10696SDavid.Hollister@Sun.COM 	kstat_named_init(&statsp->dam_stable_blocked,
1240*10696SDavid.Hollister@Sun.COM 	    "stable cycle overrun", KSTAT_DATA_UINT32);
1241*10696SDavid.Hollister@Sun.COM 	kstat_named_init(&statsp->dam_rereport,
1242*10696SDavid.Hollister@Sun.COM 	    "restarted reports", KSTAT_DATA_UINT32);
1243*10696SDavid.Hollister@Sun.COM 	kstat_named_init(&statsp->dam_numstable,
1244*10696SDavid.Hollister@Sun.COM 	    "# of stable map entries", KSTAT_DATA_UINT32);
1245*10696SDavid.Hollister@Sun.COM 	kstat_install(mapsp);
1246*10696SDavid.Hollister@Sun.COM 	mapp->dam_kstatsp = mapsp;
1247*10696SDavid.Hollister@Sun.COM 	return (DDI_SUCCESS);
1248*10696SDavid.Hollister@Sun.COM }
1249*10696SDavid.Hollister@Sun.COM 
1250*10696SDavid.Hollister@Sun.COM /*
1251*10696SDavid.Hollister@Sun.COM  * destroy map stats
1252*10696SDavid.Hollister@Sun.COM  */
1253*10696SDavid.Hollister@Sun.COM static void
1254*10696SDavid.Hollister@Sun.COM dam_kstat_destroy(dam_t *mapp)
1255*10696SDavid.Hollister@Sun.COM {
1256*10696SDavid.Hollister@Sun.COM 
1257*10696SDavid.Hollister@Sun.COM 	kstat_delete(mapp->dam_kstatsp);
1258*10696SDavid.Hollister@Sun.COM }
1259