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