1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2023 Racktop Systems, Inc.
25 */
26
27 #include <sys/note.h>
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/buf.h>
32 #include <sys/kmem.h>
33 #include <sys/cmn_err.h>
34 #include <sys/debug.h>
35 #include <sys/sunndi.h>
36 #include <sys/kstat.h>
37 #include <sys/conf.h>
38 #include <sys/ddi_periodic.h>
39 #include <sys/devctl.h>
40 #include <sys/callb.h>
41 #include <sys/sysevent.h>
42 #include <sys/taskq.h>
43 #include <sys/ddi.h>
44 #include <sys/bitset.h>
45 #include <sys/damap.h>
46 #include <sys/damap_impl.h>
47
48 #ifdef DEBUG
49 static int damap_debug = 0;
50 #endif /* DEBUG */
51
52 extern taskq_t *system_taskq;
53
54 static void dam_addrset_activate(dam_t *, bitset_t *);
55 static void dam_addrset_deactivate(dam_t *, bitset_t *);
56 static void dam_stabilize_map(void *);
57 static void dam_addr_stable_cb(void *);
58 static void dam_addrset_stable_cb(void *);
59 static void dam_sched_timeout(void (*timeout_cb)(), dam_t *, clock_t);
60 static void dam_addr_report(dam_t *, dam_da_t *, id_t, int);
61 static void dam_addr_release(dam_t *, id_t);
62 static void dam_addr_report_release(dam_t *, id_t);
63 static void dam_addr_deactivate(dam_t *, id_t);
64 static void dam_deact_cleanup(dam_t *, id_t, char *, damap_deact_rsn_t);
65 static id_t dam_get_addrid(dam_t *, char *);
66 static int dam_kstat_create(dam_t *);
67 static int dam_map_alloc(dam_t *);
68
69 #define DAM_INCR_STAT(mapp, stat) \
70 if ((mapp)->dam_kstatsp) { \
71 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \
72 stp->stat.value.ui32++; \
73 }
74
75 #define DAM_SET_STAT(mapp, stat, val) \
76 if ((mapp)->dam_kstatsp) { \
77 struct dam_kstats *stp = (mapp)->dam_kstatsp->ks_data; \
78 stp->stat.value.ui32 = (val); \
79 }
80
81
82 /*
83 * increase damap size by 64 entries at a time
84 */
85 #define DAM_SIZE_BUMP 64
86
87 int damap_taskq_dispatch_retry_usec = 1000;
88
89 /*
90 * config/unconfig taskq data
91 */
92 typedef struct {
93 dam_t *tqd_mapp;
94 id_t tqd_id;
95 } cfg_tqd_t;
96
97 extern pri_t maxclsyspri;
98
99 /*
100 * Create new device address map
101 *
102 * name: map name (kstat unique)
103 * size: max # of map entries
104 * mode: style of address reports: per-address or fullset
105 * stable_usec: # of quiescent microseconds before report/map is stable
106 *
107 * activate_arg: address provider activation-callout private
108 * activate_cb: address provider activation callback handler
109 * deactivate_cb: address provider deactivation callback handler
110 *
111 * config_arg: configuration-callout private
112 * config_cb: class configuration callout
113 * unconfig_cb: class unconfiguration callout
114 *
115 * damapp: pointer to map handle (return)
116 *
117 * Returns: DAM_SUCCESS
118 * DAM_EINVAL Invalid argument(s)
119 * DAM_FAILURE General failure
120 */
121 int
damap_create(char * name,damap_rptmode_t mode,int map_opts,int stable_usec,void * activate_arg,damap_activate_cb_t activate_cb,damap_deactivate_cb_t deactivate_cb,void * config_arg,damap_configure_cb_t configure_cb,damap_unconfig_cb_t unconfig_cb,damap_t ** damapp)122 damap_create(char *name, damap_rptmode_t mode, int map_opts,
123 int stable_usec, void *activate_arg, damap_activate_cb_t activate_cb,
124 damap_deactivate_cb_t deactivate_cb,
125 void *config_arg, damap_configure_cb_t configure_cb,
126 damap_unconfig_cb_t unconfig_cb,
127 damap_t **damapp)
128 {
129 dam_t *mapp;
130
131 if (configure_cb == NULL || unconfig_cb == NULL || name == NULL)
132 return (DAM_EINVAL);
133
134 mapp = kmem_zalloc(sizeof (*mapp), KM_SLEEP);
135 mapp->dam_options = map_opts;
136 mapp->dam_stable_ticks = drv_usectohz(stable_usec);
137 mapp->dam_size = 0;
138 mapp->dam_rptmode = mode;
139 mapp->dam_activate_arg = activate_arg;
140 mapp->dam_activate_cb = (activate_cb_t)activate_cb;
141 mapp->dam_deactivate_cb = (deactivate_cb_t)deactivate_cb;
142 mapp->dam_config_arg = config_arg;
143 mapp->dam_configure_cb = (configure_cb_t)configure_cb;
144 mapp->dam_unconfig_cb = (unconfig_cb_t)unconfig_cb;
145 mapp->dam_name = i_ddi_strdup(name, KM_SLEEP);
146 mutex_init(&mapp->dam_lock, NULL, MUTEX_DRIVER, NULL);
147 cv_init(&mapp->dam_sync_cv, NULL, CV_DRIVER, NULL);
148 bitset_init(&mapp->dam_active_set);
149 bitset_init(&mapp->dam_stable_set);
150 bitset_init(&mapp->dam_report_set);
151 *damapp = (damap_t *)mapp;
152
153 DTRACE_PROBE5(damap__create,
154 char *, mapp->dam_name, damap_t *, mapp,
155 damap_rptmode_t, mode, int, map_opts, int, stable_usec);
156
157 return (DAM_SUCCESS);
158 }
159
160 /*
161 * Allocate backing resources
162 *
163 * DAMs are lightly backed on create - major allocations occur
164 * at the time a report is made to the map, and are extended on
165 * a demand basis.
166 */
167 static int
dam_map_alloc(dam_t * mapp)168 dam_map_alloc(dam_t *mapp)
169 {
170 void *softstate_p;
171
172 ASSERT(mutex_owned(&mapp->dam_lock));
173 if (mapp->dam_flags & DAM_DESTROYPEND)
174 return (DAM_FAILURE);
175
176 /*
177 * dam_high > 0 signals map allocation complete
178 */
179 if (mapp->dam_high)
180 return (DAM_SUCCESS);
181
182 mapp->dam_size = DAM_SIZE_BUMP;
183 if (ddi_soft_state_init(&softstate_p, sizeof (dam_da_t),
184 mapp->dam_size) != DDI_SUCCESS)
185 return (DAM_FAILURE);
186
187 if (ddi_strid_init(&mapp->dam_addr_hash, mapp->dam_size) !=
188 DDI_SUCCESS) {
189 ddi_soft_state_fini(&softstate_p);
190 return (DAM_FAILURE);
191 }
192 if (dam_kstat_create(mapp) != DDI_SUCCESS) {
193 ddi_soft_state_fini(&softstate_p);
194 ddi_strid_fini(&mapp->dam_addr_hash);
195 return (DAM_FAILURE);
196 }
197 mapp->dam_da = softstate_p;
198 mapp->dam_high = 1;
199 bitset_resize(&mapp->dam_active_set, mapp->dam_size);
200 bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
201 bitset_resize(&mapp->dam_report_set, mapp->dam_size);
202 return (DAM_SUCCESS);
203 }
204
205 /*
206 * Destroy address map
207 *
208 * damapp: address map
209 *
210 * Returns: DAM_SUCCESS
211 * DAM_EINVAL Invalid argument(s)
212 * DAM_FAILURE General failure
213 */
214 void
damap_destroy(damap_t * damapp)215 damap_destroy(damap_t *damapp)
216 {
217 int i;
218 dam_t *mapp = (dam_t *)damapp;
219
220 ASSERT(mapp);
221
222 DTRACE_PROBE2(damap__destroy,
223 char *, mapp->dam_name, damap_t *, mapp);
224
225 mutex_enter(&mapp->dam_lock);
226
227 /*
228 * prevent new reports from being added to the map
229 */
230 mapp->dam_flags |= DAM_DESTROYPEND;
231
232 if (mapp->dam_high) {
233 mutex_exit(&mapp->dam_lock);
234 /*
235 * wait for outstanding reports to stabilize and cancel
236 * the timer for this map
237 */
238 (void) damap_sync(damapp, 0);
239 mutex_enter(&mapp->dam_lock);
240 dam_sched_timeout(NULL, mapp, 0);
241
242 /*
243 * map is at full stop
244 * release the contents of the map, invoking the
245 * detactivation protocol as addresses are released
246 */
247 mutex_exit(&mapp->dam_lock);
248 for (i = 1; i < mapp->dam_high; i++) {
249 if (ddi_get_soft_state(mapp->dam_da, i) == NULL)
250 continue;
251
252 ASSERT(DAM_IN_REPORT(mapp, i) == 0);
253
254 if (DAM_IS_STABLE(mapp, i)) {
255 dam_addr_deactivate(mapp, i);
256 } else {
257 ddi_strid_free(mapp->dam_addr_hash, i);
258 ddi_soft_state_free(mapp->dam_da, i);
259 }
260 }
261 ddi_strid_fini(&mapp->dam_addr_hash);
262 ddi_soft_state_fini(&mapp->dam_da);
263 kstat_delete(mapp->dam_kstatsp);
264 } else
265 mutex_exit(&mapp->dam_lock);
266
267 bitset_fini(&mapp->dam_active_set);
268 bitset_fini(&mapp->dam_stable_set);
269 bitset_fini(&mapp->dam_report_set);
270 mutex_destroy(&mapp->dam_lock);
271 cv_destroy(&mapp->dam_sync_cv);
272 if (mapp->dam_name)
273 kmem_free(mapp->dam_name, strlen(mapp->dam_name) + 1);
274 kmem_free(mapp, sizeof (*mapp));
275 }
276
277 /*
278 * Wait for map stability. If sync was successfull then return 1.
279 * If called with a non-zero sync_usec, then a return value of 0 means a
280 * timeout occurred prior to sync completion. NOTE: if sync_usec is
281 * non-zero, it should be much longer than dam_stable_ticks.
282 *
283 * damapp: address map
284 * sync_usec: micorseconds until we give up on sync completion.
285 */
286 #define WAITFOR_FLAGS (DAM_SETADD | DAM_SPEND)
287 int
damap_sync(damap_t * damapp,int sync_usec)288 damap_sync(damap_t *damapp, int sync_usec)
289 {
290 dam_t *mapp = (dam_t *)damapp;
291 int rv;
292
293 ASSERT(mapp);
294 DTRACE_PROBE3(damap__map__sync__start,
295 char *, mapp->dam_name, dam_t *, mapp,
296 int, sync_usec);
297
298 /*
299 * Block when waiting for
300 * a) stabilization pending or a fullset update pending
301 * b) the report set to finalize (bitset is null)
302 * c) any scheduled timeouts to fire
303 */
304 rv = 1; /* return synced */
305 mutex_enter(&mapp->dam_lock);
306 again: while ((mapp->dam_flags & WAITFOR_FLAGS) ||
307 (!bitset_is_null(&mapp->dam_report_set)) ||
308 (mapp->dam_tid != 0)) {
309 DTRACE_PROBE2(damap__map__sync__waiting,
310 char *, mapp->dam_name, dam_t *, mapp);
311
312 /* Wait for condition relayed via timeout */
313 if (sync_usec) {
314 if (cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
315 drv_usectohz(sync_usec), TR_MICROSEC) == -1) {
316 mapp->dam_sync_to_cnt++;
317 rv = 0; /* return timeout */
318 break;
319 }
320 } else
321 cv_wait(&mapp->dam_sync_cv, &mapp->dam_lock);
322 }
323
324 if (rv) {
325 /*
326 * Delay one stabilization time after the apparent sync above
327 * and verify accuracy - resync if not accurate.
328 */
329 (void) cv_reltimedwait(&mapp->dam_sync_cv, &mapp->dam_lock,
330 mapp->dam_stable_ticks, TR_MICROSEC);
331 if (rv && ((mapp->dam_flags & WAITFOR_FLAGS) ||
332 (!bitset_is_null(&mapp->dam_report_set)) ||
333 (mapp->dam_tid != 0)))
334 goto again;
335 }
336 mutex_exit(&mapp->dam_lock);
337
338 DTRACE_PROBE3(damap__map__sync__end,
339 char *, mapp->dam_name, dam_t *, mapp,
340 int, rv);
341 return (rv);
342 }
343
344 /*
345 * Return 1 if active set is empty
346 */
347 int
damap_is_empty(damap_t * damapp)348 damap_is_empty(damap_t *damapp)
349 {
350 dam_t *mapp = (dam_t *)damapp;
351 int rv;
352
353 mutex_enter(&mapp->dam_lock);
354 rv = bitset_is_null(&mapp->dam_active_set);
355 mutex_exit(&mapp->dam_lock);
356 return (rv);
357 }
358
359 /*
360 * Get the name of a device address map
361 *
362 * damapp: address map
363 *
364 * Returns: name
365 */
366 char *
damap_name(damap_t * damapp)367 damap_name(damap_t *damapp)
368 {
369 dam_t *mapp = (dam_t *)damapp;
370
371 return (mapp ? mapp->dam_name : "UNKNOWN_damap");
372 }
373
374 /*
375 * Get the current size of the device address map
376 *
377 * damapp: address map
378 *
379 * Returns: size
380 */
381 int
damap_size(damap_t * damapp)382 damap_size(damap_t *damapp)
383 {
384 dam_t *mapp = (dam_t *)damapp;
385
386 return (mapp->dam_size);
387 }
388
389 /*
390 * Report an address to per-address report
391 *
392 * damapp: address map handle
393 * address: address in ascii string representation
394 * addridp: address ID
395 * nvl: optional nvlist of configuration-private data
396 * addr_priv: optional provider-private (passed to activate/deactivate cb)
397 *
398 * Returns: DAM_SUCCESS
399 * DAM_EINVAL Invalid argument(s)
400 * DAM_MAPFULL address map exhausted
401 */
402 int
damap_addr_add(damap_t * damapp,char * address,damap_id_t * addridp,nvlist_t * nvl,void * addr_priv)403 damap_addr_add(damap_t *damapp, char *address, damap_id_t *addridp,
404 nvlist_t *nvl, void *addr_priv)
405 {
406 dam_t *mapp = (dam_t *)damapp;
407 id_t addrid;
408 dam_da_t *passp;
409
410 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
411 return (DAM_EINVAL);
412
413 DTRACE_PROBE3(damap__addr__add,
414 char *, mapp->dam_name, dam_t *, mapp,
415 char *, address);
416
417 mutex_enter(&mapp->dam_lock);
418 if ((dam_map_alloc(mapp) != DAM_SUCCESS) ||
419 ((addrid = dam_get_addrid(mapp, address)) == 0)) {
420 mutex_exit(&mapp->dam_lock);
421 return (DAM_MAPFULL);
422 }
423
424 passp = ddi_get_soft_state(mapp->dam_da, addrid);
425 ASSERT(passp != NULL);
426
427 /*
428 * If re-reporting the same address (add or remove) clear
429 * the existing report
430 */
431 if (DAM_IN_REPORT(mapp, addrid)) {
432 DTRACE_PROBE3(damap__addr__add__jitter,
433 char *, mapp->dam_name, dam_t *, mapp,
434 char *, address);
435 DAM_INCR_STAT(mapp, dam_jitter);
436 dam_addr_report_release(mapp, addrid);
437 passp->da_jitter++;
438 }
439 passp->da_ppriv = addr_priv;
440 if (nvl)
441 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
442
443 dam_addr_report(mapp, passp, addrid, RPT_ADDR_ADD);
444 if (addridp != NULL)
445 *addridp = (damap_id_t)addrid;
446 mutex_exit(&mapp->dam_lock);
447 return (DAM_SUCCESS);
448 }
449
450 /*
451 * Report removal of address from per-address report
452 *
453 * damapp: address map
454 * address: address in ascii string representation
455 *
456 * Returns: DAM_SUCCESS
457 * DAM_EINVAL Invalid argument(s)
458 * DAM_FAILURE General failure
459 */
460 int
damap_addr_del(damap_t * damapp,char * address)461 damap_addr_del(damap_t *damapp, char *address)
462 {
463 dam_t *mapp = (dam_t *)damapp;
464 id_t addrid;
465 dam_da_t *passp;
466
467 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_PERADDR))
468 return (DAM_EINVAL);
469
470 DTRACE_PROBE3(damap__addr__del,
471 char *, mapp->dam_name, dam_t *, mapp,
472 char *, address);
473 mutex_enter(&mapp->dam_lock);
474 if (dam_map_alloc(mapp) != DAM_SUCCESS) {
475 mutex_exit(&mapp->dam_lock);
476 return (DAM_MAPFULL);
477 }
478
479 /*
480 * if reporting the removal of an address which is not in the map
481 * return success
482 */
483 if (!(addrid = ddi_strid_str2id(mapp->dam_addr_hash, address))) {
484 mutex_exit(&mapp->dam_lock);
485 return (DAM_SUCCESS);
486 }
487 passp = ddi_get_soft_state(mapp->dam_da, addrid);
488 ASSERT(passp);
489 if (DAM_IN_REPORT(mapp, addrid)) {
490 DTRACE_PROBE3(damap__addr__del__jitter,
491 char *, mapp->dam_name, dam_t *, mapp,
492 char *, address);
493 DAM_INCR_STAT(mapp, dam_jitter);
494 dam_addr_report_release(mapp, addrid);
495 passp->da_jitter++;
496 }
497 dam_addr_report(mapp, passp, addrid, RPT_ADDR_DEL);
498 mutex_exit(&mapp->dam_lock);
499 return (DAM_SUCCESS);
500 }
501
502 static int
damap_addrset_flush_locked(damap_t * damapp)503 damap_addrset_flush_locked(damap_t *damapp)
504 {
505 dam_t *mapp = (dam_t *)damapp;
506 int idx;
507
508 ASSERT(mapp);
509 ASSERT(mutex_owned(&mapp->dam_lock));
510 if (mapp->dam_rptmode != DAMAP_REPORT_FULLSET) {
511 return (DAM_EINVAL);
512 }
513
514 DTRACE_PROBE2(damap__addrset__flush__locked__enter,
515 char *, mapp->dam_name, dam_t *, mapp);
516 if (mapp->dam_flags & DAM_SETADD) {
517 DTRACE_PROBE2(damap__addrset__flush__locked__reset,
518 char *, mapp->dam_name, dam_t *, mapp);
519
520 /*
521 * cancel stabilization timeout
522 */
523 dam_sched_timeout(NULL, mapp, 0);
524 DAM_INCR_STAT(mapp, dam_jitter);
525
526 /*
527 * clear pending reports
528 */
529 for (idx = 1; idx < mapp->dam_high; idx++) {
530 if (DAM_IN_REPORT(mapp, idx)) {
531 dam_addr_report_release(mapp, idx);
532 }
533 }
534
535 bitset_zero(&mapp->dam_report_set);
536 mapp->dam_flags &= ~DAM_SETADD;
537 cv_signal(&mapp->dam_sync_cv);
538 }
539
540 return (DAM_SUCCESS);
541 }
542
543 /*
544 * Initiate full-set report
545 *
546 * damapp: address map
547 *
548 * Returns: DAM_SUCCESS
549 * DAM_EINVAL Invalid argument(s)
550 */
551 int
damap_addrset_begin(damap_t * damapp)552 damap_addrset_begin(damap_t *damapp)
553 {
554 dam_t *mapp = (dam_t *)damapp;
555 int rv;
556
557 if (mapp == NULL) {
558 return (DAM_EINVAL);
559 }
560
561 DTRACE_PROBE2(damap__addrset__begin,
562 char *, mapp->dam_name, dam_t *, mapp);
563
564 mutex_enter(&mapp->dam_lock);
565 if (dam_map_alloc(mapp) != DAM_SUCCESS) {
566 mutex_exit(&mapp->dam_lock);
567
568 return (DAM_MAPFULL);
569 }
570
571 rv = damap_addrset_flush_locked(damapp);
572 if (rv == DAM_SUCCESS) {
573 mapp->dam_flags |= DAM_SETADD;
574 }
575 mutex_exit(&mapp->dam_lock);
576
577 return (rv);
578 }
579
580 /*
581 * Cancel full-set report
582 *
583 * damapp: address map
584 *
585 * Returns: DAM_SUCCESS
586 * DAM_EINVAL Invalid argument(s)
587 */
588 int
damap_addrset_flush(damap_t * damapp)589 damap_addrset_flush(damap_t *damapp)
590 {
591 int rv;
592 dam_t *mapp = (dam_t *)damapp;
593
594 if (mapp == NULL) {
595 return (DAM_EINVAL);
596 }
597
598 DTRACE_PROBE2(damap__addrset__flush,
599 char *, mapp->dam_name, dam_t *, mapp);
600
601 mutex_enter(&mapp->dam_lock);
602 rv = damap_addrset_flush_locked(damapp);
603 mutex_exit(&mapp->dam_lock);
604
605 return (rv);
606 }
607
608 /*
609 * Report address to full-set report
610 *
611 * damapp: address map handle
612 * address: address in ascii string representation
613 * rindx: index if address stabilizes
614 * nvl: optional nvlist of configuration-private data
615 * addr_priv: optional provider-private data (passed to activate/release cb)
616 *
617 * Returns: DAM_SUCCESS
618 * DAM_EINVAL Invalid argument(s)
619 * DAM_MAPFULL address map exhausted
620 * DAM_FAILURE General failure
621 */
622 int
damap_addrset_add(damap_t * damapp,char * address,damap_id_t * ridx,nvlist_t * nvl,void * addr_priv)623 damap_addrset_add(damap_t *damapp, char *address, damap_id_t *ridx,
624 nvlist_t *nvl, void *addr_priv)
625 {
626 dam_t *mapp = (dam_t *)damapp;
627 id_t addrid;
628 dam_da_t *passp;
629
630 if (!mapp || !address || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
631 return (DAM_EINVAL);
632
633 DTRACE_PROBE3(damap__addrset__add,
634 char *, mapp->dam_name, dam_t *, mapp, char *, address);
635
636 mutex_enter(&mapp->dam_lock);
637 if (!(mapp->dam_flags & DAM_SETADD)) {
638 mutex_exit(&mapp->dam_lock);
639 return (DAM_FAILURE);
640 }
641
642 if ((addrid = dam_get_addrid(mapp, address)) == 0) {
643 mutex_exit(&mapp->dam_lock);
644 return (DAM_MAPFULL);
645 }
646
647 passp = ddi_get_soft_state(mapp->dam_da, addrid);
648 ASSERT(passp);
649 if (DAM_IN_REPORT(mapp, addrid)) {
650 DTRACE_PROBE3(damap__addrset__add__jitter,
651 char *, mapp->dam_name, dam_t *, mapp,
652 char *, address);
653 dam_addr_report_release(mapp, addrid);
654 passp->da_jitter++;
655 }
656 passp->da_ppriv = addr_priv;
657 if (nvl)
658 (void) nvlist_dup(nvl, &passp->da_nvl_rpt, KM_SLEEP);
659 bitset_add(&mapp->dam_report_set, addrid);
660 if (ridx)
661 *ridx = (damap_id_t)addrid;
662 mutex_exit(&mapp->dam_lock);
663 return (DAM_SUCCESS);
664 }
665
666 /*
667 * Commit full-set report for stabilization
668 *
669 * damapp: address map handle
670 * flags: (currently 0)
671 *
672 * Returns: DAM_SUCCESS
673 * DAM_EINVAL Invalid argument(s)
674 * DAM_FAILURE General failure
675 */
676 int
damap_addrset_end(damap_t * damapp,int flags)677 damap_addrset_end(damap_t *damapp, int flags)
678 {
679 dam_t *mapp = (dam_t *)damapp;
680 int i;
681
682 if (!mapp || (mapp->dam_rptmode != DAMAP_REPORT_FULLSET))
683 return (DAM_EINVAL);
684
685 DTRACE_PROBE2(damap__addrset__end,
686 char *, mapp->dam_name, dam_t *, mapp);
687
688 mutex_enter(&mapp->dam_lock);
689 if (!(mapp->dam_flags & DAM_SETADD)) {
690 mutex_exit(&mapp->dam_lock);
691 return (DAM_FAILURE);
692 }
693
694 if (flags & DAMAP_END_RESET) {
695 DTRACE_PROBE2(damap__addrset__end__reset,
696 char *, mapp->dam_name, dam_t *, mapp);
697 dam_sched_timeout(NULL, mapp, 0);
698 for (i = 1; i < mapp->dam_high; i++)
699 if (DAM_IN_REPORT(mapp, i))
700 dam_addr_report_release(mapp, i);
701 } else {
702 mapp->dam_last_update = gethrtime();
703 dam_sched_timeout(dam_addrset_stable_cb, mapp,
704 mapp->dam_stable_ticks);
705 }
706 mutex_exit(&mapp->dam_lock);
707 return (DAM_SUCCESS);
708 }
709
710 /*
711 * Return nvlist registered with reported address
712 *
713 * damapp: address map handle
714 * addrid: address ID
715 *
716 * Returns: nvlist_t * provider supplied via damap_addr{set}_add())
717 * NULL
718 */
719 nvlist_t *
damap_id2nvlist(damap_t * damapp,damap_id_t addrid)720 damap_id2nvlist(damap_t *damapp, damap_id_t addrid)
721 {
722 dam_t *mapp = (dam_t *)damapp;
723 dam_da_t *pass;
724
725 if (mapp->dam_high && ddi_strid_id2str(mapp->dam_addr_hash, addrid)) {
726 if (pass = ddi_get_soft_state(mapp->dam_da, addrid))
727 return (pass->da_nvl);
728 }
729 return (NULL);
730 }
731
732 /*
733 * Return address string
734 *
735 * damapp: address map handle
736 * addrid: address ID
737 *
738 * Returns: char * Address string
739 * NULL
740 */
741 char *
damap_id2addr(damap_t * damapp,damap_id_t addrid)742 damap_id2addr(damap_t *damapp, damap_id_t addrid)
743 {
744 dam_t *mapp = (dam_t *)damapp;
745
746 if (mapp->dam_high)
747 return (ddi_strid_id2str(mapp->dam_addr_hash, addrid));
748 else
749 return (NULL);
750 }
751
752 /*
753 * Release address reference in map
754 *
755 * damapp: address map handle
756 * addrid: address ID
757 */
758 void
damap_id_rele(damap_t * damapp,damap_id_t addrid)759 damap_id_rele(damap_t *damapp, damap_id_t addrid)
760 {
761 dam_t *mapp = (dam_t *)damapp;
762 dam_da_t *passp;
763 char *addr;
764
765 passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
766 ASSERT(passp);
767
768 addr = damap_id2addr(damapp, addrid);
769 DTRACE_PROBE4(damap__id__rele,
770 char *, mapp->dam_name, dam_t *, mapp,
771 char *, addr, int, passp->da_ref);
772
773 mutex_enter(&mapp->dam_lock);
774
775 /*
776 * teardown address if last outstanding reference
777 */
778 if (--passp->da_ref == 0)
779 dam_addr_release(mapp, (id_t)addrid);
780
781 mutex_exit(&mapp->dam_lock);
782 }
783
784 /*
785 * Return current reference count on address reference in map
786 *
787 * damapp: address map handle
788 * addrid: address ID
789 *
790 * Returns: DAM_SUCCESS
791 * DAM_FAILURE
792 */
793 int
damap_id_ref(damap_t * damapp,damap_id_t addrid)794 damap_id_ref(damap_t *damapp, damap_id_t addrid)
795 {
796 dam_t *mapp = (dam_t *)damapp;
797 dam_da_t *passp;
798 int ref = -1;
799
800 passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
801 if (passp)
802 ref = passp->da_ref;
803
804 return (ref);
805 }
806
807 /*
808 * Return next address ID in list
809 *
810 * damapp: address map handle
811 * damap_list: address ID list passed to config|unconfig
812 * returned by look by lookup_all
813 * last: last ID returned, 0 is start of list
814 *
815 * Returns: addrid Next ID from the list
816 * 0 End of the list
817 */
818 damap_id_t
damap_id_next(damap_t * damapp,damap_id_list_t damap_list,damap_id_t last)819 damap_id_next(damap_t *damapp, damap_id_list_t damap_list, damap_id_t last)
820 {
821 int i, start;
822 dam_t *mapp = (dam_t *)damapp;
823 bitset_t *dam_list = (bitset_t *)damap_list;
824
825 if (!mapp || !dam_list)
826 return ((damap_id_t)0);
827
828 start = (int)last + 1;
829 for (i = start; i < mapp->dam_high; i++) {
830 if (bitset_in_set(dam_list, i)) {
831 return ((damap_id_t)i);
832 }
833 }
834 return ((damap_id_t)0);
835 }
836
837 /*
838 * Set config private data
839 *
840 * damapp: address map handle
841 * addrid: address ID
842 * cfg_priv: configuration private data
843 *
844 */
845 void
damap_id_priv_set(damap_t * damapp,damap_id_t addrid,void * cfg_priv)846 damap_id_priv_set(damap_t *damapp, damap_id_t addrid, void *cfg_priv)
847 {
848 dam_t *mapp = (dam_t *)damapp;
849 dam_da_t *passp;
850
851 mutex_enter(&mapp->dam_lock);
852 passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
853 if (!passp) {
854 mutex_exit(&mapp->dam_lock);
855 return;
856 }
857 passp->da_cfg_priv = cfg_priv;
858 mutex_exit(&mapp->dam_lock);
859 }
860
861 /*
862 * Get config private data
863 *
864 * damapp: address map handle
865 * addrid: address ID
866 *
867 * Returns: configuration private data
868 */
869 void *
damap_id_priv_get(damap_t * damapp,damap_id_t addrid)870 damap_id_priv_get(damap_t *damapp, damap_id_t addrid)
871 {
872 dam_t *mapp = (dam_t *)damapp;
873 dam_da_t *passp;
874 void *rv;
875
876 mutex_enter(&mapp->dam_lock);
877 passp = ddi_get_soft_state(mapp->dam_da, (id_t)addrid);
878 if (!passp) {
879 mutex_exit(&mapp->dam_lock);
880 return (NULL);
881 }
882 rv = passp->da_cfg_priv;
883 mutex_exit(&mapp->dam_lock);
884 return (rv);
885 }
886
887 /*
888 * Lookup a single address in the active address map
889 *
890 * damapp: address map handle
891 * address: address string
892 *
893 * Returns: ID of active/stable address
894 * 0 Address not in stable set
895 *
896 * Future: Allow the caller to wait for stabilize before returning not found.
897 */
898 damap_id_t
damap_lookup(damap_t * damapp,char * address)899 damap_lookup(damap_t *damapp, char *address)
900 {
901 dam_t *mapp = (dam_t *)damapp;
902 id_t addrid = 0;
903 dam_da_t *passp = NULL;
904
905 DTRACE_PROBE3(damap__lookup,
906 char *, mapp->dam_name, dam_t *, mapp,
907 char *, address);
908 mutex_enter(&mapp->dam_lock);
909 if (!mapp->dam_high)
910 addrid = 0;
911 else
912 addrid = ddi_strid_str2id(mapp->dam_addr_hash, address);
913 if (addrid) {
914 if (DAM_IS_STABLE(mapp, addrid)) {
915 passp = ddi_get_soft_state(mapp->dam_da, addrid);
916 ASSERT(passp);
917 if (passp) {
918 passp->da_ref++;
919 } else {
920 addrid = 0;
921 }
922 } else {
923 addrid = 0;
924 }
925 }
926 mutex_exit(&mapp->dam_lock);
927 DTRACE_PROBE4(damap__lookup__return,
928 char *, mapp->dam_name, dam_t *, mapp,
929 char *, address, int, addrid);
930 return ((damap_id_t)addrid);
931 }
932
933
934 /*
935 * Return the list of stable addresses in the map
936 *
937 * damapp: address map handle
938 * id_listp: pointer to list of address IDs in stable map (returned)
939 *
940 * Returns: # of entries returned in alist
941 */
942 int
damap_lookup_all(damap_t * damapp,damap_id_list_t * id_listp)943 damap_lookup_all(damap_t *damapp, damap_id_list_t *id_listp)
944 {
945 dam_t *mapp = (dam_t *)damapp;
946 int mapsz = mapp->dam_size;
947 int n_ids, i;
948 bitset_t *bsp;
949 char *addrp;
950 dam_da_t *passp;
951
952 DTRACE_PROBE2(damap__lookup__all,
953 char *, mapp->dam_name, dam_t *, mapp);
954 mutex_enter(&mapp->dam_lock);
955 if (!mapp->dam_high) {
956 *id_listp = (damap_id_list_t)NULL;
957 mutex_exit(&mapp->dam_lock);
958 DTRACE_PROBE2(damap__lookup__all__nomap,
959 char *, mapp->dam_name, dam_t *, mapp);
960 return (0);
961 }
962 bsp = kmem_alloc(sizeof (*bsp), KM_SLEEP);
963 bitset_init(bsp);
964 bitset_resize(bsp, mapsz);
965 bitset_copy(&mapp->dam_active_set, bsp);
966 for (n_ids = 0, i = 1; i < mapsz; i++) {
967 if (bitset_in_set(bsp, i)) {
968 passp = ddi_get_soft_state(mapp->dam_da, i);
969 ASSERT(passp);
970 if (passp) {
971 addrp = damap_id2addr(damapp, i);
972 DTRACE_PROBE3(damap__lookup__all__item,
973 char *, mapp->dam_name, dam_t *, mapp,
974 char *, addrp);
975 passp->da_ref++;
976 n_ids++;
977 }
978 }
979 }
980 if (n_ids) {
981 *id_listp = (damap_id_list_t)bsp;
982 mutex_exit(&mapp->dam_lock);
983 return (n_ids);
984 } else {
985 *id_listp = (damap_id_list_t)NULL;
986 bitset_fini(bsp);
987 kmem_free(bsp, sizeof (*bsp));
988 mutex_exit(&mapp->dam_lock);
989 return (0);
990 }
991 }
992
993 /*
994 * Release the address list returned by damap_lookup_all()
995 *
996 * mapp: address map handle
997 * id_list: list of address IDs returned in damap_lookup_all()
998 */
999 void
damap_id_list_rele(damap_t * damapp,damap_id_list_t id_list)1000 damap_id_list_rele(damap_t *damapp, damap_id_list_t id_list)
1001 {
1002 dam_t *mapp = (dam_t *)damapp;
1003 int i;
1004
1005 if (id_list == NULL)
1006 return;
1007
1008 mutex_enter(&mapp->dam_lock);
1009 for (i = 1; i < mapp->dam_high; i++) {
1010 if (bitset_in_set((bitset_t *)id_list, i))
1011 (void) dam_addr_release(mapp, i);
1012 }
1013 mutex_exit(&mapp->dam_lock);
1014 bitset_fini((bitset_t *)id_list);
1015 kmem_free((void *)id_list, sizeof (bitset_t));
1016 }
1017
1018 /*
1019 * activate an address that has passed the stabilization interval
1020 */
1021 static void
dam_addr_activate(dam_t * mapp,id_t addrid)1022 dam_addr_activate(dam_t *mapp, id_t addrid)
1023 {
1024 dam_da_t *passp;
1025 int config_rv;
1026 char *addrstr;
1027
1028 mutex_enter(&mapp->dam_lock);
1029 bitset_add(&mapp->dam_active_set, addrid);
1030 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1031 ASSERT(passp);
1032
1033 /*
1034 * copy the reported nvlist and provider private data
1035 */
1036 addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1037 DTRACE_PROBE3(damap__addr__activate__start,
1038 char *, mapp->dam_name, dam_t *, mapp,
1039 char *, addrstr);
1040 passp->da_nvl = passp->da_nvl_rpt;
1041 passp->da_nvl_rpt = NULL;
1042 passp->da_last_stable = gethrtime();
1043 passp->da_stable_cnt++;
1044 mutex_exit(&mapp->dam_lock);
1045 if (mapp->dam_activate_cb) {
1046 (*mapp->dam_activate_cb)(mapp->dam_activate_arg, addrstr,
1047 addrid, &passp->da_ppriv);
1048 }
1049
1050 /*
1051 * call the address-specific configuration action as part of
1052 * activation.
1053 */
1054 config_rv = (*mapp->dam_configure_cb)(mapp->dam_config_arg, mapp,
1055 addrid);
1056 if (config_rv != DAM_SUCCESS) {
1057 mutex_enter(&mapp->dam_lock);
1058 passp->da_flags |= DA_FAILED_CONFIG;
1059 mutex_exit(&mapp->dam_lock);
1060 DTRACE_PROBE3(damap__addr__activate__config__failure,
1061 char *, mapp->dam_name, dam_t *, mapp,
1062 char *, addrstr);
1063 dam_deact_cleanup(mapp, addrid, addrstr,
1064 DAMAP_DEACT_RSN_CFG_FAIL);
1065 } else {
1066 DTRACE_PROBE3(damap__addr__activate__end,
1067 char *, mapp->dam_name, dam_t *, mapp,
1068 char *, addrstr);
1069 }
1070 }
1071
1072 /*
1073 * deactivate a previously stable address
1074 */
1075 static void
dam_addr_deactivate(dam_t * mapp,id_t addrid)1076 dam_addr_deactivate(dam_t *mapp, id_t addrid)
1077 {
1078 char *addrstr;
1079
1080 addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1081 DTRACE_PROBE3(damap__addr__deactivate__start,
1082 char *, mapp->dam_name, dam_t *, mapp,
1083 char *, addrstr);
1084
1085 /*
1086 * call the unconfiguration callback
1087 */
1088 (*mapp->dam_unconfig_cb)(mapp->dam_config_arg, mapp, addrid);
1089 dam_deact_cleanup(mapp, addrid, addrstr, DAMAP_DEACT_RSN_GONE);
1090 }
1091
1092 static void
dam_deact_cleanup(dam_t * mapp,id_t addrid,char * addrstr,damap_deact_rsn_t deact_rsn)1093 dam_deact_cleanup(dam_t *mapp, id_t addrid, char *addrstr,
1094 damap_deact_rsn_t deact_rsn)
1095 {
1096 dam_da_t *passp;
1097
1098 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1099 ASSERT(passp);
1100 if (mapp->dam_deactivate_cb)
1101 (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1102 ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1103 addrid, passp->da_ppriv, deact_rsn);
1104
1105 /*
1106 * clear the active bit and free the backing info for
1107 * this address
1108 */
1109 mutex_enter(&mapp->dam_lock);
1110 bitset_del(&mapp->dam_active_set, addrid);
1111 passp->da_ppriv = NULL;
1112 nvlist_free(passp->da_nvl);
1113 passp->da_nvl = NULL;
1114 nvlist_free(passp->da_nvl_rpt);
1115 passp->da_nvl_rpt = NULL;
1116
1117 DTRACE_PROBE3(damap__addr__deactivate__end,
1118 char *, mapp->dam_name, dam_t *, mapp,
1119 char *, addrstr);
1120
1121 (void) dam_addr_release(mapp, addrid);
1122 mutex_exit(&mapp->dam_lock);
1123 }
1124
1125 /*
1126 * taskq callback for multi-thread activation
1127 */
1128 static void
dam_tq_config(void * arg)1129 dam_tq_config(void *arg)
1130 {
1131 cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1132
1133 dam_addr_activate(tqd->tqd_mapp, tqd->tqd_id);
1134 kmem_free(tqd, sizeof (*tqd));
1135 }
1136
1137 /*
1138 * taskq callback for multi-thread deactivation
1139 */
1140 static void
dam_tq_unconfig(void * arg)1141 dam_tq_unconfig(void *arg)
1142 {
1143 cfg_tqd_t *tqd = (cfg_tqd_t *)arg;
1144
1145 dam_addr_deactivate(tqd->tqd_mapp, tqd->tqd_id);
1146 kmem_free(tqd, sizeof (*tqd));
1147 }
1148
1149 /*
1150 * Activate a set of stabilized addresses
1151 */
1152 static void
dam_addrset_activate(dam_t * mapp,bitset_t * activate)1153 dam_addrset_activate(dam_t *mapp, bitset_t *activate)
1154 {
1155
1156 int i, nset;
1157 taskq_t *tqp = NULL;
1158 cfg_tqd_t *tqd = NULL;
1159 char tqn[TASKQ_NAMELEN];
1160 extern pri_t maxclsyspri;
1161
1162 if (mapp->dam_options & DAMAP_MTCONFIG) {
1163 /*
1164 * calculate the # of taskq threads to create
1165 */
1166 for (i = 1, nset = 0; i < mapp->dam_high; i++)
1167 if (bitset_in_set(activate, i))
1168 nset++;
1169 ASSERT(nset);
1170 (void) snprintf(tqn, sizeof (tqn), "actv-%s", mapp->dam_name);
1171 tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1172 INT_MAX, TASKQ_PREPOPULATE);
1173 }
1174 for (i = 1; i < mapp->dam_high; i++) {
1175 if (bitset_in_set(activate, i)) {
1176 if (!tqp)
1177 dam_addr_activate(mapp, i);
1178 else {
1179 /*
1180 * multi-threaded activation
1181 */
1182 tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1183 tqd->tqd_mapp = mapp;
1184 tqd->tqd_id = i;
1185 (void) taskq_dispatch(tqp, dam_tq_config,
1186 tqd, TQ_SLEEP);
1187 }
1188 }
1189 }
1190 if (tqp) {
1191 taskq_wait(tqp);
1192 taskq_destroy(tqp);
1193 }
1194 }
1195
1196 /*
1197 * Deactivate a set of stabilized addresses
1198 */
1199 static void
dam_addrset_deactivate(dam_t * mapp,bitset_t * deactivate)1200 dam_addrset_deactivate(dam_t *mapp, bitset_t *deactivate)
1201 {
1202 int i, nset;
1203 taskq_t *tqp = NULL;
1204 cfg_tqd_t *tqd = NULL;
1205 char tqn[TASKQ_NAMELEN];
1206
1207 DTRACE_PROBE2(damap__addrset__deactivate,
1208 char *, mapp->dam_name, dam_t *, mapp);
1209
1210 if (mapp->dam_options & DAMAP_MTCONFIG) {
1211 /*
1212 * compute the # of taskq threads to dispatch
1213 */
1214 for (i = 1, nset = 0; i < mapp->dam_high; i++)
1215 if (bitset_in_set(deactivate, i))
1216 nset++;
1217 (void) snprintf(tqn, sizeof (tqn), "deactv-%s",
1218 mapp->dam_name);
1219 tqp = taskq_create(tqn, nset, maxclsyspri, 1,
1220 INT_MAX, TASKQ_PREPOPULATE);
1221 }
1222 for (i = 1; i < mapp->dam_high; i++) {
1223 if (bitset_in_set(deactivate, i)) {
1224 if (!tqp) {
1225 dam_addr_deactivate(mapp, i);
1226 } else {
1227 tqd = kmem_alloc(sizeof (*tqd), KM_SLEEP);
1228 tqd->tqd_mapp = mapp;
1229 tqd->tqd_id = i;
1230 (void) taskq_dispatch(tqp,
1231 dam_tq_unconfig, tqd, TQ_SLEEP);
1232 }
1233 }
1234 }
1235
1236 if (tqp) {
1237 taskq_wait(tqp);
1238 taskq_destroy(tqp);
1239 }
1240 }
1241
1242 /*
1243 * Release a previously activated address
1244 */
1245 static void
dam_addr_release(dam_t * mapp,id_t addrid)1246 dam_addr_release(dam_t *mapp, id_t addrid)
1247 {
1248 dam_da_t *passp;
1249 char *addrstr;
1250
1251
1252 ASSERT(mutex_owned(&mapp->dam_lock));
1253 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1254 ASSERT(passp);
1255
1256 addrstr = ddi_strid_id2str(mapp->dam_addr_hash, addrid);
1257 DTRACE_PROBE3(damap__addr__release,
1258 char *, mapp->dam_name, dam_t *, mapp,
1259 char *, addrstr);
1260
1261 /*
1262 * defer releasing the address until outstanding references
1263 * are released
1264 */
1265 if (passp->da_ref > 1) {
1266 DTRACE_PROBE4(damap__addr__release__outstanding__refs,
1267 char *, mapp->dam_name, dam_t *, mapp,
1268 char *, addrstr, int, passp->da_ref);
1269 return;
1270 }
1271
1272 /*
1273 * allow pending reports to stabilize
1274 */
1275 if (DAM_IN_REPORT(mapp, addrid)) {
1276 DTRACE_PROBE3(damap__addr__release__report__pending,
1277 char *, mapp->dam_name, dam_t *, mapp,
1278 char *, addrstr);
1279 return;
1280 }
1281
1282 ddi_strid_free(mapp->dam_addr_hash, addrid);
1283 ddi_soft_state_free(mapp->dam_da, addrid);
1284 }
1285
1286 /*
1287 * process stabilized address reports
1288 */
1289 static void
dam_stabilize_map(void * arg)1290 dam_stabilize_map(void *arg)
1291 {
1292 dam_t *mapp = (dam_t *)arg;
1293 bitset_t delta;
1294 bitset_t cfg;
1295 bitset_t uncfg;
1296 int has_cfg, has_uncfg;
1297 uint32_t i, n_active;
1298
1299 DTRACE_PROBE2(damap__stabilize__map,
1300 char *, mapp->dam_name, dam_t *, mapp);
1301
1302 bitset_init(&delta);
1303 bitset_resize(&delta, mapp->dam_size);
1304 bitset_init(&cfg);
1305 bitset_resize(&cfg, mapp->dam_size);
1306 bitset_init(&uncfg);
1307 bitset_resize(&uncfg, mapp->dam_size);
1308
1309 /*
1310 * determine which addresses have changed during
1311 * this stabilization cycle
1312 */
1313 mutex_enter(&mapp->dam_lock);
1314 ASSERT(mapp->dam_flags & DAM_SPEND);
1315 if (!bitset_xor(&mapp->dam_active_set, &mapp->dam_stable_set,
1316 &delta)) {
1317 /*
1318 * no difference
1319 */
1320 bitset_zero(&mapp->dam_stable_set);
1321 mapp->dam_flags &= ~DAM_SPEND;
1322 cv_signal(&mapp->dam_sync_cv);
1323 mutex_exit(&mapp->dam_lock);
1324
1325 bitset_fini(&uncfg);
1326 bitset_fini(&cfg);
1327 bitset_fini(&delta);
1328 DTRACE_PROBE2(damap__stabilize__map__nochange,
1329 char *, mapp->dam_name, dam_t *, mapp);
1330 return;
1331 }
1332
1333 /*
1334 * compute the sets of addresses to be activated and deactivated
1335 */
1336 has_cfg = bitset_and(&delta, &mapp->dam_stable_set, &cfg);
1337 has_uncfg = bitset_and(&delta, &mapp->dam_active_set, &uncfg);
1338
1339 /*
1340 * drop map lock while invoking callouts
1341 */
1342 mutex_exit(&mapp->dam_lock);
1343
1344 /*
1345 * activate all newly stable addresss
1346 */
1347 if (has_cfg)
1348 dam_addrset_activate(mapp, &cfg);
1349
1350 /*
1351 * deactivate addresss which are no longer in the map
1352 */
1353 if (has_uncfg)
1354 dam_addrset_deactivate(mapp, &uncfg);
1355
1356
1357 /*
1358 * timestamp the last stable time and increment the kstat keeping
1359 * the # of of stable cycles for the map
1360 */
1361 mutex_enter(&mapp->dam_lock);
1362 bitset_zero(&mapp->dam_stable_set);
1363 mapp->dam_last_stable = gethrtime();
1364 mapp->dam_stable_cnt++;
1365 DAM_INCR_STAT(mapp, dam_cycles);
1366
1367 /*
1368 * determine the number of stable addresses
1369 * and update the n_active kstat for this map
1370 */
1371 for (i = 1, n_active = 0; i < mapp->dam_high; i++)
1372 if (bitset_in_set(&mapp->dam_active_set, i))
1373 n_active++;
1374 DAM_SET_STAT(mapp, dam_active, n_active);
1375
1376 DTRACE_PROBE3(damap__map__stable__end,
1377 char *, mapp->dam_name, dam_t *, mapp,
1378 int, n_active);
1379
1380 mapp->dam_flags &= ~DAM_SPEND;
1381 cv_signal(&mapp->dam_sync_cv);
1382 mutex_exit(&mapp->dam_lock);
1383
1384 bitset_fini(&uncfg);
1385 bitset_fini(&cfg);
1386 bitset_fini(&delta);
1387 }
1388
1389 /*
1390 * per-address stabilization timeout
1391 */
1392 static void
dam_addr_stable_cb(void * arg)1393 dam_addr_stable_cb(void *arg)
1394 {
1395 dam_t *mapp = (dam_t *)arg;
1396 int i;
1397 dam_da_t *passp;
1398 int spend = 0;
1399 int tpend = 0;
1400 int64_t ts, next_ticks, delta_ticks;
1401
1402 mutex_enter(&mapp->dam_lock);
1403 if (mapp->dam_tid == 0) {
1404 DTRACE_PROBE2(damap__map__addr__stable__cancelled,
1405 char *, mapp->dam_name, dam_t *, mapp);
1406 mutex_exit(&mapp->dam_lock);
1407 return;
1408 }
1409 mapp->dam_tid = 0;
1410
1411 /*
1412 * If still under stabilization, reschedule timeout,
1413 * otherwise dispatch the task to activate and deactivate the
1414 * new stable address
1415 */
1416 if (mapp->dam_flags & DAM_SPEND) {
1417 DAM_INCR_STAT(mapp, dam_overrun);
1418 mapp->dam_stable_overrun++;
1419 DTRACE_PROBE2(damap__map__addr__stable__overrun,
1420 char *, mapp->dam_name, dam_t *, mapp);
1421 dam_sched_timeout(dam_addr_stable_cb, mapp,
1422 mapp->dam_stable_ticks);
1423 mutex_exit(&mapp->dam_lock);
1424 return;
1425 }
1426
1427 DAM_SET_STAT(mapp, dam_overrun, 0);
1428 mapp->dam_stable_overrun = 0;
1429
1430 /* See if any reports stabalized and compute next timeout. */
1431 ts = ddi_get_lbolt64();
1432 next_ticks = mapp->dam_stable_ticks;
1433 for (i = 1; i < mapp->dam_high; i++) {
1434 if (bitset_in_set(&mapp->dam_report_set, i)) {
1435 passp = ddi_get_soft_state(mapp->dam_da, i);
1436 ASSERT(passp);
1437
1438 if (passp->da_deadline <= ts)
1439 spend++; /* report has stabilized */
1440 else {
1441 /* not stabilized, determine next map timeout */
1442 tpend++;
1443 delta_ticks = passp->da_deadline - ts;
1444 if (delta_ticks < next_ticks)
1445 next_ticks = delta_ticks;
1446 }
1447 }
1448 }
1449
1450 /*
1451 * schedule system_taskq activation of stabilized reports
1452 */
1453 if (spend) {
1454 if (taskq_dispatch(system_taskq, dam_stabilize_map,
1455 mapp, TQ_NOSLEEP | TQ_NOQUEUE) != TASKQID_INVALID) {
1456 DTRACE_PROBE2(damap__map__addr__stable__start,
1457 char *, mapp->dam_name, dam_t *, mapp);
1458
1459 /*
1460 * The stable_set we compute below stays pending until
1461 * processed by dam_stabilize_map. We can't set
1462 * DAM_SPEND (or bitset_del things from the
1463 * report_set) until we *know* that we can handoff the
1464 * result to dam_stabilize_map. If dam_stabilize_map
1465 * starts executing before we are complete, it will
1466 * block on the dam_lock mutex until we are ready.
1467 */
1468 mapp->dam_flags |= DAM_SPEND;
1469
1470 /*
1471 * Copy the current active_set to the stable_set, then
1472 * add or remove stabilized report_set address from
1473 * the stable set (and delete them from the report_set).
1474 */
1475 bitset_copy(&mapp->dam_active_set,
1476 &mapp->dam_stable_set);
1477 for (i = 1; i < mapp->dam_high; i++) {
1478 if (!bitset_in_set(&mapp->dam_report_set, i))
1479 continue;
1480
1481 passp = ddi_get_soft_state(mapp->dam_da, i);
1482 if (passp->da_deadline > ts)
1483 continue; /* report not stabilized */
1484
1485 /* report has stabilized */
1486 if (passp->da_flags & DA_RELE)
1487 bitset_del(&mapp->dam_stable_set, i);
1488 else
1489 bitset_add(&mapp->dam_stable_set, i);
1490
1491 bitset_del(&mapp->dam_report_set, i);
1492 }
1493 } else {
1494 DTRACE_PROBE2(damap__map__addr__stable__spendfail,
1495 char *, mapp->dam_name, dam_t *, mapp);
1496
1497 /*
1498 * Avoid waiting the entire stabalization
1499 * time again if taskq_diskpatch fails.
1500 */
1501 tpend++;
1502 delta_ticks = drv_usectohz(
1503 damap_taskq_dispatch_retry_usec);
1504 if (delta_ticks < next_ticks)
1505 next_ticks = delta_ticks;
1506 }
1507 }
1508
1509 /*
1510 * reschedule the stabilization timer if there are reports
1511 * still pending
1512 */
1513 if (tpend) {
1514 DTRACE_PROBE2(damap__map__addr__stable__tpend, char *,
1515 mapp->dam_name, dam_t *, mapp);
1516 dam_sched_timeout(dam_addr_stable_cb, mapp,
1517 (clock_t)next_ticks);
1518 }
1519
1520 mutex_exit(&mapp->dam_lock);
1521 }
1522
1523 /*
1524 * fullset stabilization timeout callback
1525 */
1526 static void
dam_addrset_stable_cb(void * arg)1527 dam_addrset_stable_cb(void *arg)
1528 {
1529 dam_t *mapp = (dam_t *)arg;
1530
1531 mutex_enter(&mapp->dam_lock);
1532 if (mapp->dam_tid == 0) {
1533 mutex_exit(&mapp->dam_lock);
1534 DTRACE_PROBE2(damap__map__addrset__stable__cancelled,
1535 char *, mapp->dam_name, dam_t *, mapp);
1536 return;
1537 }
1538 mapp->dam_tid = 0;
1539
1540 /*
1541 * If map still underoing stabilization reschedule timeout,
1542 * else dispatch the task to configure the new stable set of
1543 * addresses.
1544 */
1545 if ((mapp->dam_flags & DAM_SPEND) ||
1546 (taskq_dispatch(system_taskq, dam_stabilize_map, mapp,
1547 TQ_NOSLEEP | TQ_NOQUEUE) == TASKQID_INVALID)) {
1548 DAM_INCR_STAT(mapp, dam_overrun);
1549 mapp->dam_stable_overrun++;
1550 dam_sched_timeout(dam_addrset_stable_cb, mapp,
1551 drv_usectohz(damap_taskq_dispatch_retry_usec));
1552
1553 DTRACE_PROBE2(damap__map__addrset__stable__overrun,
1554 char *, mapp->dam_name, dam_t *, mapp);
1555 mutex_exit(&mapp->dam_lock);
1556 return;
1557 }
1558
1559 DAM_SET_STAT(mapp, dam_overrun, 0);
1560 mapp->dam_stable_overrun = 0;
1561 bitset_copy(&mapp->dam_report_set, &mapp->dam_stable_set);
1562 bitset_zero(&mapp->dam_report_set);
1563 mapp->dam_flags |= DAM_SPEND;
1564 mapp->dam_flags &= ~DAM_SETADD;
1565 /* NOTE: don't need cv_signal since DAM_SPEND is still set */
1566
1567 DTRACE_PROBE2(damap__map__addrset__stable__start,
1568 char *, mapp->dam_name, dam_t *, mapp);
1569 mutex_exit(&mapp->dam_lock);
1570 }
1571
1572 /*
1573 * schedule map timeout in 'ticks' ticks
1574 * if map timer is currently running, cancel if ticks == 0
1575 */
1576 static void
dam_sched_timeout(void (* timeout_cb)(),dam_t * mapp,clock_t ticks)1577 dam_sched_timeout(void (*timeout_cb)(), dam_t *mapp, clock_t ticks)
1578 {
1579 timeout_id_t tid;
1580
1581 DTRACE_PROBE4(damap__sched__timeout,
1582 char *, mapp->dam_name, dam_t *, mapp,
1583 int, ticks, timeout_id_t, mapp->dam_tid);
1584
1585 ASSERT(mutex_owned(&mapp->dam_lock));
1586 if ((tid = mapp->dam_tid) != 0) {
1587 if (ticks == 0) {
1588 mapp->dam_tid = 0;
1589 mutex_exit(&mapp->dam_lock);
1590 (void) untimeout(tid);
1591 mutex_enter(&mapp->dam_lock);
1592 }
1593 } else {
1594 if (timeout_cb && (ticks != 0))
1595 mapp->dam_tid = timeout(timeout_cb, mapp, ticks);
1596 }
1597 }
1598
1599 /*
1600 * report addition or removal of an address
1601 */
1602 static void
dam_addr_report(dam_t * mapp,dam_da_t * passp,id_t addrid,int rpt_type)1603 dam_addr_report(dam_t *mapp, dam_da_t *passp, id_t addrid, int rpt_type)
1604 {
1605 char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1606
1607 DTRACE_PROBE4(damap__addr__report,
1608 char *, mapp->dam_name, dam_t *, mapp,
1609 char *, addrstr, int, rpt_type);
1610
1611 ASSERT(mutex_owned(&mapp->dam_lock));
1612 ASSERT(!DAM_IN_REPORT(mapp, addrid));
1613 passp->da_last_report = gethrtime();
1614 mapp->dam_last_update = gethrtime();
1615 passp->da_report_cnt++;
1616 passp->da_deadline = ddi_get_lbolt64() + mapp->dam_stable_ticks;
1617 if (rpt_type == RPT_ADDR_DEL)
1618 passp->da_flags |= DA_RELE;
1619 else if (rpt_type == RPT_ADDR_ADD)
1620 passp->da_flags &= ~DA_RELE;
1621 bitset_add(&mapp->dam_report_set, addrid);
1622 dam_sched_timeout(dam_addr_stable_cb, mapp, mapp->dam_stable_ticks);
1623 }
1624
1625 /*
1626 * release an address report
1627 */
1628 static void
dam_addr_report_release(dam_t * mapp,id_t addrid)1629 dam_addr_report_release(dam_t *mapp, id_t addrid)
1630 {
1631 dam_da_t *passp;
1632 char *addrstr = damap_id2addr((damap_t *)mapp, addrid);
1633
1634 DTRACE_PROBE3(damap__addr__report__release,
1635 char *, mapp->dam_name, dam_t *, mapp,
1636 char *, addrstr);
1637
1638 ASSERT(mutex_owned(&mapp->dam_lock));
1639 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1640 ASSERT(passp);
1641 /*
1642 * clear the report bit
1643 * if the address has a registered deactivation handler and
1644 * we are holding a private data pointer and the address has not
1645 * stabilized, deactivate the address (private data).
1646 */
1647 bitset_del(&mapp->dam_report_set, addrid);
1648 if (!DAM_IS_STABLE(mapp, addrid) && mapp->dam_deactivate_cb &&
1649 passp->da_ppriv) {
1650 mutex_exit(&mapp->dam_lock);
1651 (*mapp->dam_deactivate_cb)(mapp->dam_activate_arg,
1652 ddi_strid_id2str(mapp->dam_addr_hash, addrid),
1653 addrid, passp->da_ppriv, DAMAP_DEACT_RSN_UNSTBL);
1654 mutex_enter(&mapp->dam_lock);
1655 }
1656 passp->da_ppriv = NULL;
1657 nvlist_free(passp->da_nvl_rpt);
1658 }
1659
1660 /*
1661 * return the map ID of an address
1662 */
1663 static id_t
dam_get_addrid(dam_t * mapp,char * address)1664 dam_get_addrid(dam_t *mapp, char *address)
1665 {
1666 damap_id_t addrid;
1667 dam_da_t *passp;
1668
1669 ASSERT(mutex_owned(&mapp->dam_lock));
1670 if ((addrid = ddi_strid_str2id(mapp->dam_addr_hash, address)) == 0) {
1671 if ((addrid = ddi_strid_alloc(mapp->dam_addr_hash,
1672 address)) == (damap_id_t)0) {
1673 return (0);
1674 }
1675 if (ddi_soft_state_zalloc(mapp->dam_da, addrid) !=
1676 DDI_SUCCESS) {
1677 ddi_strid_free(mapp->dam_addr_hash, addrid);
1678 return (0);
1679 }
1680
1681 if (addrid >= mapp->dam_high)
1682 mapp->dam_high = addrid + 1;
1683
1684 /*
1685 * expand bitmaps if ID has outgrown old map size
1686 */
1687 if (mapp->dam_high > mapp->dam_size) {
1688 mapp->dam_size = mapp->dam_size + DAM_SIZE_BUMP;
1689 bitset_resize(&mapp->dam_active_set, mapp->dam_size);
1690 bitset_resize(&mapp->dam_stable_set, mapp->dam_size);
1691 bitset_resize(&mapp->dam_report_set, mapp->dam_size);
1692 }
1693
1694 passp = ddi_get_soft_state(mapp->dam_da, addrid);
1695 passp->da_ref = 1;
1696 passp->da_addr = ddi_strid_id2str(mapp->dam_addr_hash,
1697 addrid); /* for mdb */
1698 }
1699 return (addrid);
1700 }
1701
1702 /*
1703 * create and install map statistics
1704 */
1705 static int
dam_kstat_create(dam_t * mapp)1706 dam_kstat_create(dam_t *mapp)
1707 {
1708 kstat_t *mapsp;
1709 struct dam_kstats *statsp;
1710
1711 mapsp = kstat_create("dam", 0, mapp->dam_name, "damap",
1712 KSTAT_TYPE_NAMED,
1713 sizeof (struct dam_kstats) / sizeof (kstat_named_t), 0);
1714
1715 if (mapsp == NULL)
1716 return (DDI_FAILURE);
1717
1718 statsp = (struct dam_kstats *)mapsp->ks_data;
1719 kstat_named_init(&statsp->dam_cycles, "cycles", KSTAT_DATA_UINT32);
1720 kstat_named_init(&statsp->dam_overrun, "overrun", KSTAT_DATA_UINT32);
1721 kstat_named_init(&statsp->dam_jitter, "jitter", KSTAT_DATA_UINT32);
1722 kstat_named_init(&statsp->dam_active, "active", KSTAT_DATA_UINT32);
1723 kstat_install(mapsp);
1724 mapp->dam_kstatsp = mapsp;
1725 return (DDI_SUCCESS);
1726 }
1727