5045 use atomic_{inc,dec}_* instead of atomic_add_*
[illumos-gate.git] / usr / src / uts / common / ipp / ippconf.c
blob851a0ecca09713265e380399533167c5fc3479a8
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/param.h>
28 #include <sys/modctl.h>
29 #include <sys/sysmacros.h>
30 #include <sys/kmem.h>
31 #include <sys/cmn_err.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/spl.h>
35 #include <sys/time.h>
36 #include <sys/varargs.h>
37 #include <ipp/ipp.h>
38 #include <ipp/ipp_impl.h>
39 #include <ipp/ipgpc/ipgpc.h>
42 * Debug switch.
45 #if defined(DEBUG)
46 #define IPP_DBG
47 #endif
50 * Globals
54 * ipp_action_count is not static because it is imported by inet/ipp_common.h
56 uint32_t ipp_action_count = 0;
58 static kmem_cache_t *ipp_mod_cache = NULL;
59 static uint32_t ipp_mod_count = 0;
60 static uint32_t ipp_max_mod = IPP_NMOD;
61 static ipp_mod_t **ipp_mod_byid;
62 static krwlock_t ipp_mod_byid_lock[1];
64 static ipp_mod_id_t ipp_next_mid = IPP_MOD_RESERVED + 1;
65 static ipp_mod_id_t ipp_mid_limit;
67 static ipp_ref_t *ipp_mod_byname[IPP_NBUCKET];
68 static krwlock_t ipp_mod_byname_lock[1];
70 static kmem_cache_t *ipp_action_cache = NULL;
71 static uint32_t ipp_max_action = IPP_NACTION;
72 static ipp_action_t **ipp_action_byid;
73 static krwlock_t ipp_action_byid_lock[1];
75 static ipp_action_id_t ipp_next_aid = IPP_ACTION_RESERVED + 1;
76 static ipp_action_id_t ipp_aid_limit;
78 static ipp_ref_t *ipp_action_byname[IPP_NBUCKET];
79 static krwlock_t ipp_action_byname_lock[1];
80 static ipp_ref_t *ipp_action_noname;
82 static kmem_cache_t *ipp_packet_cache = NULL;
83 static uint_t ipp_packet_classes = IPP_NCLASS;
84 static uint_t ipp_packet_logging = 0;
85 static uint_t ipp_packet_log_entries = IPP_NLOG;
88 * Prototypes
91 void ipp_init(void);
93 int ipp_list_mods(ipp_mod_id_t **, int *);
95 ipp_mod_id_t ipp_mod_lookup(const char *);
96 int ipp_mod_name(ipp_mod_id_t, char **);
97 int ipp_mod_register(const char *, ipp_ops_t *);
98 int ipp_mod_unregister(ipp_mod_id_t);
99 int ipp_mod_list_actions(ipp_mod_id_t, ipp_action_id_t **,
100 int *);
102 ipp_action_id_t ipp_action_lookup(const char *);
103 int ipp_action_name(ipp_action_id_t, char **);
104 int ipp_action_mod(ipp_action_id_t, ipp_mod_id_t *);
105 int ipp_action_create(ipp_mod_id_t, const char *,
106 nvlist_t **, ipp_flags_t, ipp_action_id_t *);
107 int ipp_action_modify(ipp_action_id_t, nvlist_t **,
108 ipp_flags_t);
109 int ipp_action_destroy(ipp_action_id_t, ipp_flags_t);
110 int ipp_action_info(ipp_action_id_t, int (*)(nvlist_t *,
111 void *), void *, ipp_flags_t);
112 void ipp_action_set_ptr(ipp_action_id_t, void *);
113 void *ipp_action_get_ptr(ipp_action_id_t);
114 int ipp_action_ref(ipp_action_id_t, ipp_action_id_t,
115 ipp_flags_t);
116 int ipp_action_unref(ipp_action_id_t, ipp_action_id_t,
117 ipp_flags_t);
119 int ipp_packet_alloc(ipp_packet_t **, const char *,
120 ipp_action_id_t);
121 void ipp_packet_free(ipp_packet_t *);
122 int ipp_packet_add_class(ipp_packet_t *, const char *,
123 ipp_action_id_t);
124 int ipp_packet_process(ipp_packet_t **);
125 int ipp_packet_next(ipp_packet_t *, ipp_action_id_t);
126 void ipp_packet_set_data(ipp_packet_t *, mblk_t *);
127 mblk_t *ipp_packet_get_data(ipp_packet_t *);
128 void ipp_packet_set_private(ipp_packet_t *, void *,
129 void (*)(void *));
130 void *ipp_packet_get_private(ipp_packet_t *);
132 int ipp_stat_create(ipp_action_id_t, const char *, int,
133 int (*)(ipp_stat_t *, void *, int), void *, ipp_stat_t **);
134 void ipp_stat_install(ipp_stat_t *);
135 void ipp_stat_destroy(ipp_stat_t *);
136 int ipp_stat_named_init(ipp_stat_t *, const char *, uchar_t,
137 ipp_named_t *);
138 int ipp_stat_named_op(ipp_named_t *, void *, int);
140 static int ref_mod(ipp_action_t *, ipp_mod_t *);
141 static void unref_mod(ipp_action_t *, ipp_mod_t *);
142 static int is_mod_busy(ipp_mod_t *);
143 static int get_mod_ref(ipp_mod_t *, ipp_action_id_t **, int *);
144 static int get_mods(ipp_mod_id_t **bufp, int *);
145 static ipp_mod_id_t find_mod(const char *);
146 static int alloc_mod(const char *, ipp_mod_id_t *);
147 static void free_mod(ipp_mod_t *);
148 static ipp_mod_t *hold_mod(ipp_mod_id_t);
149 static void rele_mod(ipp_mod_t *);
150 static ipp_mod_id_t get_mid(void);
152 static int condemn_action(ipp_ref_t **, ipp_action_t *);
153 static int destroy_action(ipp_action_t *, ipp_flags_t);
154 static int ref_action(ipp_action_t *, ipp_action_t *);
155 static int unref_action(ipp_action_t *, ipp_action_t *);
156 static int is_action_refd(ipp_action_t *);
157 static ipp_action_id_t find_action(const char *);
158 static int alloc_action(const char *, ipp_action_id_t *);
159 static void free_action(ipp_action_t *);
160 static ipp_action_t *hold_action(ipp_action_id_t);
161 static void rele_action(ipp_action_t *);
162 static ipp_action_id_t get_aid(void);
164 static int alloc_packet(const char *, ipp_action_id_t,
165 ipp_packet_t **);
166 static int realloc_packet(ipp_packet_t *);
167 static void free_packet(ipp_packet_t *);
169 static int hash(const char *);
170 static int update_stats(kstat_t *, int);
171 static void init_mods(void);
172 static void init_actions(void);
173 static void init_packets(void);
174 static int mod_constructor(void *, void *, int);
175 static void mod_destructor(void *, void *);
176 static int action_constructor(void *, void *, int);
177 static void action_destructor(void *, void *);
178 static int packet_constructor(void *, void *, int);
179 static void packet_destructor(void *, void *);
182 * Debug message macros
185 #ifdef IPP_DBG
187 #define DBG_MOD 0x00000001ull
188 #define DBG_ACTION 0x00000002ull
189 #define DBG_PACKET 0x00000004ull
190 #define DBG_STATS 0x00000008ull
191 #define DBG_LIST 0x00000010ull
193 static uint64_t ipp_debug_flags =
195 * DBG_PACKET |
196 * DBG_STATS |
197 * DBG_LIST |
198 * DBG_MOD |
199 * DBG_ACTION |
203 static kmutex_t debug_mutex[1];
205 /*PRINTFLIKE3*/
206 static void ipp_debug(uint64_t, const char *, char *, ...)
207 __KPRINTFLIKE(3);
209 #define DBG0(_type, _fmt) \
210 ipp_debug((_type), __FN__, (_fmt));
212 #define DBG1(_type, _fmt, _a1) \
213 ipp_debug((_type), __FN__, (_fmt), (_a1));
215 #define DBG2(_type, _fmt, _a1, _a2) \
216 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2));
218 #define DBG3(_type, _fmt, _a1, _a2, _a3) \
219 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
220 (_a3));
222 #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) \
223 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
224 (_a3), (_a4));
226 #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) \
227 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
228 (_a3), (_a4), (_a5));
230 #else /* IPP_DBG */
232 #define DBG0(_type, _fmt)
233 #define DBG1(_type, _fmt, _a1)
234 #define DBG2(_type, _fmt, _a1, _a2)
235 #define DBG3(_type, _fmt, _a1, _a2, _a3)
236 #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4)
237 #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5)
239 #endif /* IPP_DBG */
242 * Lock macros
245 #define LOCK_MOD(_imp, _rw) \
246 rw_enter((_imp)->ippm_lock, (_rw))
247 #define UNLOCK_MOD(_imp) \
248 rw_exit((_imp)->ippm_lock)
250 #define LOCK_ACTION(_ap, _rw) \
251 rw_enter((_ap)->ippa_lock, (_rw))
252 #define UNLOCK_ACTION(_imp) \
253 rw_exit((_imp)->ippa_lock)
255 #define CONFIG_WRITE_START(_ap) \
256 CONFIG_LOCK_ENTER((_ap)->ippa_config_lock, CL_WRITE)
258 #define CONFIG_WRITE_END(_ap) \
259 CONFIG_LOCK_EXIT((_ap)->ippa_config_lock)
261 #define CONFIG_READ_START(_ap) \
262 CONFIG_LOCK_ENTER((_ap)->ippa_config_lock, CL_READ)
264 #define CONFIG_READ_END(_ap) \
265 CONFIG_LOCK_EXIT((_ap)->ippa_config_lock)
268 * Exported functions
271 #define __FN__ "ipp_init"
272 void
273 ipp_init(
274 void)
276 #ifdef IPP_DBG
277 mutex_init(debug_mutex, NULL, MUTEX_ADAPTIVE,
278 (void *)ipltospl(LOCK_LEVEL));
279 #endif /* IPP_DBG */
282 * Initialize module and action structure caches and associated locks.
285 init_mods();
286 init_actions();
287 init_packets();
289 #undef __FN__
291 #define __FN__ "ipp_list_mods"
293 ipp_list_mods(
294 ipp_mod_id_t **bufp,
295 int *neltp)
297 ASSERT(bufp != NULL);
298 ASSERT(neltp != NULL);
300 return (get_mods(bufp, neltp));
302 #undef __FN__
305 * Module manipulation interface.
308 #define __FN__ "ipp_mod_lookup"
309 ipp_mod_id_t
310 ipp_mod_lookup(
311 const char *modname)
313 ipp_mod_id_t mid;
314 #define FIRST_TIME 0
315 int try = FIRST_TIME;
318 * Sanity check the module name.
321 if (modname == NULL || strlen(modname) > MAXNAMELEN - 1)
322 return (IPP_MOD_INVAL);
324 try_again:
325 if ((mid = find_mod(modname)) == IPP_MOD_INVAL) {
328 * Module not installed.
331 if (try++ == FIRST_TIME) {
334 * This is the first attempt to find the module so
335 * try to 'demand load' it.
338 DBG1(DBG_MOD, "loading module '%s'\n", modname);
339 (void) modload("ipp", (char *)modname);
340 goto try_again;
344 return (mid);
346 #undef FIRST_TIME
348 #undef __FN__
350 #define __FN__ "ipp_mod_name"
352 ipp_mod_name(
353 ipp_mod_id_t mid,
354 char **modnamep)
356 ipp_mod_t *imp;
357 char *modname;
358 char *buf;
360 ASSERT(modnamep != NULL);
363 * Translate the module id into the module pointer.
366 if ((imp = hold_mod(mid)) == NULL)
367 return (ENOENT);
369 LOCK_MOD(imp, RW_READER);
370 modname = imp->ippm_name;
373 * Allocate a buffer to pass back to the caller.
376 if ((buf = kmem_zalloc(strlen(modname) + 1, KM_NOSLEEP)) == NULL) {
377 UNLOCK_MOD(imp);
378 rele_mod(imp);
379 return (ENOMEM);
383 * Copy the module name into the buffer.
386 (void) strcpy(buf, modname);
387 UNLOCK_MOD(imp);
389 *modnamep = buf;
391 rele_mod(imp);
392 return (0);
394 #undef __FN__
396 #define __FN__ "ipp_mod_register"
398 ipp_mod_register(
399 const char *modname,
400 ipp_ops_t *ipp_ops)
402 ipp_mod_id_t mid;
403 ipp_mod_t *imp;
404 int rc;
406 ASSERT(ipp_ops != NULL);
409 * Sanity check the module name.
412 if (modname == NULL || strlen(modname) > MAXNAMELEN - 1)
413 return (EINVAL);
416 * Allocate a module structure.
419 if ((rc = alloc_mod(modname, &mid)) != 0)
420 return (rc);
422 imp = hold_mod(mid);
423 ASSERT(imp != NULL);
426 * Make module available for use.
429 LOCK_MOD(imp, RW_WRITER);
430 DBG1(DBG_MOD, "registering module '%s'\n", imp->ippm_name);
431 imp->ippm_ops = ipp_ops;
432 imp->ippm_state = IPP_MODSTATE_AVAILABLE;
433 UNLOCK_MOD(imp);
435 rele_mod(imp);
436 return (0);
438 #undef __FN__
440 #define __FN__ "ipp_mod_unregister"
442 ipp_mod_unregister(
443 ipp_mod_id_t mid)
445 ipp_mod_t *imp;
448 * Translate the module id into the module pointer.
451 if ((imp = hold_mod(mid)) == NULL)
452 return (ENOENT);
454 LOCK_MOD(imp, RW_WRITER);
455 ASSERT(imp->ippm_state == IPP_MODSTATE_AVAILABLE);
458 * Check to see if there are any actions that reference the module.
461 if (is_mod_busy(imp)) {
462 UNLOCK_MOD(imp);
463 rele_mod(imp);
464 return (EBUSY);
468 * Prevent further use of the module.
471 DBG1(DBG_MOD, "unregistering module '%s'\n", imp->ippm_name);
472 imp->ippm_state = IPP_MODSTATE_PROTO;
473 imp->ippm_ops = NULL;
474 UNLOCK_MOD(imp);
477 * Free the module structure.
480 free_mod(imp);
481 rele_mod(imp);
483 return (0);
485 #undef __FN__
487 #define __FN__ "ipp_mod_list_actions"
489 ipp_mod_list_actions(
490 ipp_mod_id_t mid,
491 ipp_action_id_t **bufp,
492 int *neltp)
494 ipp_mod_t *imp;
495 int rc;
497 ASSERT(bufp != NULL);
498 ASSERT(neltp != NULL);
501 * Translate the module id into the module pointer.
504 if ((imp = hold_mod(mid)) == NULL)
505 return (ENOENT);
508 * Get the list of actions referencing the module.
511 LOCK_MOD(imp, RW_READER);
512 rc = get_mod_ref(imp, bufp, neltp);
513 UNLOCK_MOD(imp);
515 rele_mod(imp);
516 return (rc);
518 #undef __FN__
521 * Action manipulation interface.
524 #define __FN__ "ipp_action_lookup"
525 ipp_action_id_t
526 ipp_action_lookup(
527 const char *aname)
529 if (aname == NULL)
530 return (IPP_ACTION_INVAL);
533 * Check for special case 'virtual action' names.
536 if (strcmp(aname, IPP_ANAME_CONT) == 0)
537 return (IPP_ACTION_CONT);
538 else if (strcmp(aname, IPP_ANAME_DEFER) == 0)
539 return (IPP_ACTION_DEFER);
540 else if (strcmp(aname, IPP_ANAME_DROP) == 0)
541 return (IPP_ACTION_DROP);
544 * Now check real actions.
547 return (find_action(aname));
549 #undef __FN__
551 #define __FN__ "ipp_action_name"
553 ipp_action_name(
554 ipp_action_id_t aid,
555 char **anamep)
557 ipp_action_t *ap;
558 char *aname;
559 char *buf;
560 int rc;
562 ASSERT(anamep != NULL);
565 * Check for special case 'virtual action' ids.
568 switch (aid) {
569 case IPP_ACTION_CONT:
570 ap = NULL;
571 aname = IPP_ANAME_CONT;
572 break;
573 case IPP_ACTION_DEFER:
574 ap = NULL;
575 aname = IPP_ANAME_DEFER;
576 break;
577 case IPP_ACTION_DROP:
578 ap = NULL;
579 aname = IPP_ANAME_DROP;
580 break;
581 default:
584 * Not a special case. Check for a real action.
587 if ((ap = hold_action(aid)) == NULL)
588 return (ENOENT);
590 LOCK_ACTION(ap, RW_READER);
591 aname = ap->ippa_name;
592 break;
596 * Allocate a buffer to pass back to the caller.
599 if ((buf = kmem_zalloc(strlen(aname) + 1, KM_NOSLEEP)) == NULL) {
600 rc = ENOMEM;
601 goto done;
605 * Copy the action name into the buffer.
608 (void) strcpy(buf, aname);
609 *anamep = buf;
610 rc = 0;
611 done:
613 * Unlock the action if necessary (i.e. it wasn't a virtual action).
616 if (ap != NULL) {
617 UNLOCK_ACTION(ap);
618 rele_action(ap);
621 return (rc);
623 #undef __FN__
625 #define __FN__ "ipp_action_mod"
627 ipp_action_mod(
628 ipp_action_id_t aid,
629 ipp_mod_id_t *midp)
631 ipp_action_t *ap;
632 ipp_mod_t *imp;
634 ASSERT(midp != NULL);
637 * Return an error for 'virtual action' ids.
640 switch (aid) {
641 case IPP_ACTION_CONT:
642 /*FALLTHRU*/
643 case IPP_ACTION_DEFER:
644 /*FALLTHRU*/
645 case IPP_ACTION_DROP:
646 return (EINVAL);
647 default:
648 break;
652 * This is a real action.
655 if ((ap = hold_action(aid)) == NULL)
656 return (ENOENT);
659 * Check that the action is not in prototype state.
662 LOCK_ACTION(ap, RW_READER);
663 if (ap->ippa_state == IPP_ASTATE_PROTO) {
664 UNLOCK_ACTION(ap);
665 rele_action(ap);
666 return (ENOENT);
669 imp = ap->ippa_mod;
670 ASSERT(imp != NULL);
671 UNLOCK_ACTION(ap);
673 *midp = imp->ippm_id;
675 rele_action(ap);
676 return (0);
678 #undef __FN__
680 #define __FN__ "ipp_action_create"
682 ipp_action_create(
683 ipp_mod_id_t mid,
684 const char *aname,
685 nvlist_t **nvlpp,
686 ipp_flags_t flags,
687 ipp_action_id_t *aidp)
689 ipp_ops_t *ippo;
690 ipp_mod_t *imp;
691 ipp_action_id_t aid;
692 ipp_action_t *ap;
693 int rc;
695 ASSERT(nvlpp != NULL);
696 ASSERT(*nvlpp != NULL);
699 * Sanity check the action name (NULL means the framework chooses the
700 * name).
703 if (aname != NULL && strlen(aname) > MAXNAMELEN - 1)
704 return (EINVAL);
707 * Translate the module id into the module pointer.
710 if ((imp = hold_mod(mid)) == NULL)
711 return (ENOENT);
714 * Allocate an action.
717 if ((rc = alloc_action(aname, &aid)) != 0) {
718 rele_mod(imp);
719 return (rc);
722 ap = hold_action(aid);
723 ASSERT(ap != NULL);
726 * Note that the action is in the process of creation/destruction.
729 LOCK_ACTION(ap, RW_WRITER);
730 ap->ippa_state = IPP_ASTATE_CONFIG_PENDING;
733 * Reference the module for which the action is being created.
736 LOCK_MOD(imp, RW_WRITER);
737 if ((rc = ref_mod(ap, imp)) != 0) {
738 UNLOCK_MOD(imp);
739 ap->ippa_state = IPP_ASTATE_PROTO;
740 UNLOCK_ACTION(ap);
742 free_action(ap);
743 rele_action(ap);
744 rele_mod(imp);
745 return (rc);
748 UNLOCK_ACTION(ap);
750 ippo = imp->ippm_ops;
751 ASSERT(ippo != NULL);
752 UNLOCK_MOD(imp);
755 * Call into the module to create the action context.
758 CONFIG_WRITE_START(ap);
759 DBG2(DBG_ACTION, "creating action '%s' in module '%s'\n",
760 ap->ippa_name, imp->ippm_name);
761 if ((rc = ippo->ippo_action_create(ap->ippa_id, nvlpp, flags)) != 0) {
762 LOCK_ACTION(ap, RW_WRITER);
763 LOCK_MOD(imp, RW_WRITER);
764 unref_mod(ap, imp);
765 UNLOCK_MOD(imp);
766 ap->ippa_state = IPP_ASTATE_PROTO;
767 UNLOCK_ACTION(ap);
769 CONFIG_WRITE_END(ap);
771 free_action(ap);
772 rele_action(ap);
773 rele_mod(imp);
774 return (rc);
776 CONFIG_WRITE_END(ap);
779 * Make the action available for use.
782 LOCK_ACTION(ap, RW_WRITER);
783 ap->ippa_state = IPP_ASTATE_AVAILABLE;
784 if (aidp != NULL)
785 *aidp = ap->ippa_id;
786 UNLOCK_ACTION(ap);
788 rele_action(ap);
789 rele_mod(imp);
790 return (0);
792 #undef __FN__
794 #define __FN__ "ipp_action_destroy"
796 ipp_action_destroy(
797 ipp_action_id_t aid,
798 ipp_flags_t flags)
800 ipp_ref_t *rp = NULL;
801 ipp_ref_t *tmp;
802 ipp_action_t *ap;
803 int rc;
806 * Translate the action id into the action pointer.
809 if ((ap = hold_action(aid)) == NULL)
810 return (ENOENT);
813 * Set the condemned action list pointer and destroy the action.
816 ap->ippa_condemned = &rp;
817 if ((rc = destroy_action(ap, flags)) == 0) {
820 * Destroy any other actions condemned by the destruction of
821 * the first action.
824 for (tmp = rp; tmp != NULL; tmp = tmp->ippr_nextp) {
825 ap = tmp->ippr_action;
826 ap->ippa_condemned = &rp;
827 (void) destroy_action(ap, flags);
829 } else {
832 * Unreference any condemned actions since the destruction of
833 * the first action failed.
836 for (tmp = rp; tmp != NULL; tmp = tmp->ippr_nextp) {
837 ap = tmp->ippr_action;
838 rele_action(ap);
843 * Clean up the condemned list.
846 while (rp != NULL) {
847 tmp = rp;
848 rp = rp->ippr_nextp;
849 kmem_free(tmp, sizeof (ipp_ref_t));
852 return (rc);
854 #undef __FN__
856 #define __FN__ "ipp_action_modify"
858 ipp_action_modify(
859 ipp_action_id_t aid,
860 nvlist_t **nvlpp,
861 ipp_flags_t flags)
863 ipp_action_t *ap;
864 ipp_ops_t *ippo;
865 ipp_mod_t *imp;
866 int rc;
868 ASSERT(nvlpp != NULL);
869 ASSERT(*nvlpp != NULL);
872 * Translate the action id into the action pointer.
875 if ((ap = hold_action(aid)) == NULL)
876 return (ENOENT);
879 * Check that the action is either available for use or is in the
880 * process of creation/destruction.
882 * NOTE: It is up to the module to lock multiple configuration
883 * operations against each other if necessary.
886 LOCK_ACTION(ap, RW_READER);
887 if (ap->ippa_state != IPP_ASTATE_AVAILABLE &&
888 ap->ippa_state != IPP_ASTATE_CONFIG_PENDING) {
889 UNLOCK_ACTION(ap);
890 rele_action(ap);
891 return (EPROTO);
894 imp = ap->ippa_mod;
895 ASSERT(imp != NULL);
896 UNLOCK_ACTION(ap);
898 ippo = imp->ippm_ops;
899 ASSERT(ippo != NULL);
902 * Call into the module to modify the action context.
905 DBG1(DBG_ACTION, "modifying action '%s'\n", ap->ippa_name);
906 CONFIG_WRITE_START(ap);
907 rc = ippo->ippo_action_modify(aid, nvlpp, flags);
908 CONFIG_WRITE_END(ap);
910 rele_action(ap);
911 return (rc);
913 #undef __FN__
915 #define __FN__ "ipp_action_info"
917 ipp_action_info(
918 ipp_action_id_t aid,
919 int (*fn)(nvlist_t *, void *),
920 void *arg,
921 ipp_flags_t flags)
923 ipp_action_t *ap;
924 ipp_mod_t *imp;
925 ipp_ops_t *ippo;
926 int rc;
929 * Translate the action id into the action pointer.
932 if ((ap = hold_action(aid)) == NULL)
933 return (ENOENT);
936 * Check that the action is available for use. We don't want to
937 * read back parameters while the action is in the process of
938 * creation/destruction.
941 LOCK_ACTION(ap, RW_READER);
942 if (ap->ippa_state != IPP_ASTATE_AVAILABLE) {
943 UNLOCK_ACTION(ap);
944 rele_action(ap);
945 return (EPROTO);
948 imp = ap->ippa_mod;
949 ASSERT(imp != NULL);
950 UNLOCK_ACTION(ap);
952 ippo = imp->ippm_ops;
953 ASSERT(ippo != NULL);
956 * Call into the module to get the action configuration information.
959 DBG1(DBG_ACTION,
960 "getting configuration information from action '%s'\n",
961 ap->ippa_name);
962 CONFIG_READ_START(ap);
963 if ((rc = ippo->ippo_action_info(aid, fn, arg, flags)) != 0) {
964 CONFIG_READ_END(ap);
965 rele_action(ap);
966 return (rc);
968 CONFIG_READ_END(ap);
970 rele_action(ap);
971 return (0);
973 #undef __FN__
975 #define __FN__ "ipp_action_set_ptr"
976 void
977 ipp_action_set_ptr(
978 ipp_action_id_t aid,
979 void *ptr)
981 ipp_action_t *ap;
984 * Translate the action id into the action pointer.
987 ap = hold_action(aid);
988 ASSERT(ap != NULL);
991 * Set the private data pointer.
994 ap->ippa_ptr = ptr;
995 rele_action(ap);
997 #undef __FN__
999 #define __FN__ "ipp_action_get_ptr"
1000 void *
1001 ipp_action_get_ptr(
1002 ipp_action_id_t aid)
1004 ipp_action_t *ap;
1005 void *ptr;
1008 * Translate the action id into the action pointer.
1011 ap = hold_action(aid);
1012 ASSERT(ap != NULL);
1015 * Return the private data pointer.
1018 ptr = ap->ippa_ptr;
1019 rele_action(ap);
1021 return (ptr);
1023 #undef __FN__
1025 #define __FN__ "ipp_action_ref"
1026 /*ARGSUSED*/
1028 ipp_action_ref(
1029 ipp_action_id_t aid,
1030 ipp_action_id_t ref_aid,
1031 ipp_flags_t flags)
1033 ipp_action_t *ap;
1034 ipp_action_t *ref_ap;
1035 int rc;
1038 * Actions are not allowed to reference themselves.
1041 if (aid == ref_aid)
1042 return (EINVAL);
1045 * Check for a special case 'virtual action' id.
1048 switch (ref_aid) {
1049 case IPP_ACTION_CONT:
1050 /*FALLTHRU*/
1051 case IPP_ACTION_DEFER:
1052 /*FALLTHRU*/
1053 case IPP_ACTION_DROP:
1054 return (0);
1055 default:
1056 break;
1060 * Translate the action ids into action pointers.
1063 if ((ap = hold_action(aid)) == NULL)
1064 return (ENOENT);
1066 if ((ref_ap = hold_action(ref_aid)) == NULL) {
1067 rele_action(ap);
1068 return (ENOENT);
1071 LOCK_ACTION(ap, RW_WRITER);
1072 LOCK_ACTION(ref_ap, RW_WRITER);
1074 if (ref_ap->ippa_state != IPP_ASTATE_AVAILABLE) {
1075 UNLOCK_ACTION(ref_ap);
1076 UNLOCK_ACTION(ap);
1078 rele_action(ref_ap);
1079 rele_action(ap);
1080 return (EPROTO);
1084 * Create references between the two actions.
1087 rc = ref_action(ap, ref_ap);
1088 UNLOCK_ACTION(ref_ap);
1089 UNLOCK_ACTION(ap);
1091 rele_action(ref_ap);
1092 rele_action(ap);
1093 return (rc);
1095 #undef __FN__
1097 #define __FN__ "ipp_action_unref"
1099 ipp_action_unref(
1100 ipp_action_id_t aid,
1101 ipp_action_id_t ref_aid,
1102 ipp_flags_t flags)
1104 ipp_action_t *ap;
1105 ipp_action_t *ref_ap;
1106 int ref_is_busy;
1107 int rc;
1109 if (aid == ref_aid)
1110 return (EINVAL);
1113 * Check for a special case 'virtual action' id.
1116 switch (ref_aid) {
1117 case IPP_ACTION_CONT:
1118 /*FALLTHRU*/
1119 case IPP_ACTION_DEFER:
1120 /*FALLTHRU*/
1121 case IPP_ACTION_DROP:
1122 return (0);
1123 default:
1124 break;
1128 * Translate the action ids into action pointers.
1131 if ((ap = hold_action(aid)) == NULL)
1132 return (ENOENT);
1134 if ((ref_ap = hold_action(ref_aid)) == NULL) {
1135 rele_action(ap);
1136 return (ENOENT);
1139 LOCK_ACTION(ap, RW_WRITER);
1140 LOCK_ACTION(ref_ap, RW_WRITER);
1143 * Remove the reference between the actions.
1146 if ((rc = unref_action(ap, ref_ap)) != 0) {
1147 UNLOCK_ACTION(ref_ap);
1148 UNLOCK_ACTION(ap);
1149 rele_action(ref_ap);
1150 rele_action(ap);
1151 return (rc);
1154 ref_is_busy = is_action_refd(ref_ap);
1156 UNLOCK_ACTION(ref_ap);
1157 UNLOCK_ACTION(ap);
1159 if (flags & IPP_DESTROY_REF) {
1160 if (!ref_is_busy) {
1163 * Condemn the action so that it will be destroyed.
1166 (void) condemn_action(ap->ippa_condemned, ref_ap);
1167 return (0);
1171 rele_action(ref_ap);
1172 rele_action(ap);
1173 return (0);
1175 #undef __FN__
1178 * Packet manipulation interface.
1181 #define __FN__ "ipp_packet_alloc"
1183 ipp_packet_alloc(
1184 ipp_packet_t **ppp,
1185 const char *name,
1186 ipp_action_id_t aid)
1188 ipp_packet_t *pp;
1189 int rc;
1191 ASSERT(ppp != NULL);
1194 * A name is required.
1197 if (name == NULL || strlen(name) > MAXNAMELEN - 1)
1198 return (EINVAL);
1201 * Allocate a packet structure from the cache.
1204 if ((rc = alloc_packet(name, aid, &pp)) != 0)
1205 return (rc);
1207 if (ipp_packet_logging != 0 && pp->ippp_log == NULL) {
1210 * Logging is turned on but there's no log buffer. We need
1211 * to allocate one.
1213 if ((pp->ippp_log = kmem_alloc(
1214 ipp_packet_log_entries * sizeof (ipp_log_t),
1215 KM_NOSLEEP)) != NULL) {
1216 pp->ippp_log_limit = ipp_packet_log_entries - 1;
1217 pp->ippp_log_windex = 0;
1219 } else if (ipp_packet_logging == 0 && pp->ippp_log != NULL) {
1222 * A log buffer is present but logging has been turned off.
1223 * Free the buffer now,
1226 kmem_free(pp->ippp_log,
1227 (pp->ippp_log_limit + 1) * sizeof (ipp_log_t));
1228 pp->ippp_log = NULL;
1229 pp->ippp_log_limit = 0;
1230 pp->ippp_log_windex = 0;
1233 *ppp = pp;
1234 return (0);
1236 #undef __FN__
1238 #define __FN__ "ipp_packet_free"
1239 void
1240 ipp_packet_free(
1241 ipp_packet_t *pp)
1244 ASSERT(pp != NULL);
1247 * If there is a private structure pointer set, call its free
1248 * function.
1251 if (pp->ippp_private) {
1252 pp->ippp_private_free(pp->ippp_private);
1253 pp->ippp_private = NULL;
1254 pp->ippp_private_free = NULL;
1258 * Free the packet structure back to the cache.
1261 free_packet(pp);
1263 #undef __FN__
1265 #define __FN__ "ipp_packet_add_class"
1267 ipp_packet_add_class(
1268 ipp_packet_t *pp,
1269 const char *name,
1270 ipp_action_id_t aid)
1272 ipp_class_t *cp;
1273 int rc;
1275 ASSERT(pp != NULL);
1278 * A name is required.
1281 if (name == NULL || strlen(name) > MAXNAMELEN - 1)
1282 return (EINVAL);
1285 * Check if there is an available class structure.
1288 if (pp->ippp_class_windex == pp->ippp_class_limit) {
1291 * No more structures. Re-allocate the array.
1294 if ((rc = realloc_packet(pp)) != 0)
1295 return (rc);
1297 ASSERT(pp->ippp_class_windex < pp->ippp_class_limit);
1300 * Set up a new class structure.
1303 cp = &(pp->ippp_class_array[pp->ippp_class_windex++]);
1304 (void) strcpy(cp->ippc_name, name);
1305 cp->ippc_aid = aid;
1307 return (0);
1309 #undef __FN__
1311 #define __FN__ "ipp_packet_process"
1313 ipp_packet_process(
1314 ipp_packet_t **ppp)
1316 ipp_packet_t *pp;
1317 ipp_action_id_t aid;
1318 ipp_class_t *cp;
1319 ipp_log_t *lp;
1320 ipp_action_t *ap;
1321 ipp_mod_t *imp;
1322 ipp_ops_t *ippo;
1323 int rc;
1325 ASSERT(ppp != NULL);
1326 pp = *ppp;
1327 ASSERT(pp != NULL);
1330 * Walk the class list.
1333 while (pp->ippp_class_rindex < pp->ippp_class_windex) {
1334 cp = &(pp->ippp_class_array[pp->ippp_class_rindex]);
1337 * While there is a real action to invoke...
1340 aid = cp->ippc_aid;
1341 while (aid != IPP_ACTION_CONT &&
1342 aid != IPP_ACTION_DEFER &&
1343 aid != IPP_ACTION_DROP) {
1345 ASSERT(aid != IPP_ACTION_INVAL);
1348 * Translate the action id to the action pointer.
1351 if ((ap = hold_action(aid)) == NULL) {
1352 DBG1(DBG_PACKET,
1353 "action id '%d' not found\n", aid);
1354 return (ENOENT);
1358 * Check that the action is available for use...
1360 LOCK_ACTION(ap, RW_READER);
1361 if (ap->ippa_state != IPP_ASTATE_AVAILABLE) {
1362 UNLOCK_ACTION(ap);
1363 rele_action(ap);
1364 return (EPROTO);
1368 * Increment the action's packet count to note that
1369 * it's being used.
1371 * NOTE: We only have a read lock, so we need to use
1372 * atomic_add_32(). The read lock is still
1373 * important though as it is crucial to block
1374 * out a destroy operation between the action
1375 * state being checked and the packet count
1376 * being incremented.
1379 atomic_inc_32(&(ap->ippa_packets));
1381 imp = ap->ippa_mod;
1382 ASSERT(imp != NULL);
1383 UNLOCK_ACTION(ap);
1385 ippo = imp->ippm_ops;
1386 ASSERT(ippo != NULL);
1389 * If there's a log, grab the next entry and fill it
1390 * in.
1393 if (pp->ippp_log != NULL &&
1394 pp->ippp_log_windex <= pp->ippp_log_limit) {
1395 lp = &(pp->ippp_log[pp->ippp_log_windex++]);
1396 lp->ippl_aid = aid;
1397 (void) strcpy(lp->ippl_name, cp->ippc_name);
1398 gethrestime(&lp->ippl_begin);
1399 } else {
1400 lp = NULL;
1404 * Invoke the action.
1407 rc = ippo->ippo_action_invoke(aid, pp);
1410 * Also log the time that the action finished
1411 * processing.
1414 if (lp != NULL)
1415 gethrestime(&lp->ippl_end);
1418 * Decrement the packet count.
1421 atomic_dec_32(&(ap->ippa_packets));
1424 * If the class' action id is the same now as it was
1425 * before then clearly no 'next action' has been set.
1426 * This is a protocol error.
1429 if (cp->ippc_aid == aid) {
1430 DBG1(DBG_PACKET,
1431 "action '%s' did not set next action\n",
1432 ap->ippa_name);
1433 rele_action(ap);
1434 return (EPROTO);
1438 * The action did not complete successfully. Terminate
1439 * packet processing.
1442 if (rc != 0) {
1443 DBG2(DBG_PACKET,
1444 "action error '%d' from action '%s'\n",
1445 rc, ap->ippa_name);
1446 rele_action(ap);
1447 return (rc);
1450 rele_action(ap);
1453 * Look at the next action.
1456 aid = cp->ippc_aid;
1460 * No more real actions to invoke, check for 'virtual' ones.
1464 * Packet deferred: module has held onto packet for processing
1465 * later.
1468 if (cp->ippc_aid == IPP_ACTION_DEFER) {
1469 *ppp = NULL;
1470 return (0);
1474 * Packet dropped: free the packet and discontinue processing.
1477 if (cp->ippc_aid == IPP_ACTION_DROP) {
1478 freemsg(pp->ippp_data);
1479 ipp_packet_free(pp);
1480 *ppp = NULL;
1481 return (0);
1485 * Must be 'continue processing': move onto the next class.
1488 ASSERT(cp->ippc_aid == IPP_ACTION_CONT);
1489 pp->ippp_class_rindex++;
1492 return (0);
1494 #undef __FN__
1496 #define __FN__ "ipp_packet_next"
1498 ipp_packet_next(
1499 ipp_packet_t *pp,
1500 ipp_action_id_t aid)
1502 ipp_action_t *ap;
1503 ipp_class_t *cp;
1505 ASSERT(pp != NULL);
1507 cp = &(pp->ippp_class_array[pp->ippp_class_rindex]);
1508 ASSERT(cp != NULL);
1511 * Check for a special case 'virtual action' id.
1514 switch (aid) {
1515 case IPP_ACTION_INVAL:
1516 return (EINVAL);
1517 case IPP_ACTION_DEFER:
1518 /*FALLTHRU*/
1519 case IPP_ACTION_CONT:
1520 /*FALLTHRU*/
1521 case IPP_ACTION_DROP:
1522 break;
1523 default:
1526 * Not a virtual action so try to translate the action id
1527 * into the action pointer to confirm the actions existence.
1530 if ((ap = hold_action(aid)) == NULL) {
1531 DBG0(DBG_PACKET, "invalid action\n");
1532 return (ENOENT);
1534 rele_action(ap);
1536 break;
1540 * Set the class' new action id.
1543 cp->ippc_aid = aid;
1545 return (0);
1547 #undef __FN__
1549 #define __FN__ "ipp_packet_set_data"
1550 void
1551 ipp_packet_set_data(
1552 ipp_packet_t *pp,
1553 mblk_t *data)
1555 ASSERT(pp != NULL);
1556 pp->ippp_data = data;
1558 #undef __FN__
1560 #define __FN__ "ipp_packet_get_data"
1561 mblk_t *
1562 ipp_packet_get_data(
1563 ipp_packet_t *pp)
1565 ASSERT(pp != NULL);
1566 return (pp->ippp_data);
1568 #undef __FN__
1570 #define __FN__ "ipp_packet_set_private"
1571 void
1572 ipp_packet_set_private(
1573 ipp_packet_t *pp,
1574 void *buf,
1575 void (*free_func)(void *))
1577 ASSERT(pp != NULL);
1578 ASSERT(free_func != NULL);
1580 pp->ippp_private = buf;
1581 pp->ippp_private_free = free_func;
1583 #undef __FN__
1585 #define __FN__ "ipp_packet_get_private"
1586 void *
1587 ipp_packet_get_private(
1588 ipp_packet_t *pp)
1590 ASSERT(pp != NULL);
1591 return (pp->ippp_private);
1593 #undef __FN__
1596 * Statistics interface.
1599 #define __FN__ "ipp_stat_create"
1601 ipp_stat_create(
1602 ipp_action_id_t aid,
1603 const char *name,
1604 int nstat,
1605 int (*update)(ipp_stat_t *, void *, int),
1606 void *arg,
1607 ipp_stat_t **spp)
1609 ipp_action_t *ap;
1610 ipp_mod_t *imp;
1611 ipp_stat_impl_t *sip;
1612 ipp_stat_t *sp;
1613 kstat_t *ksp;
1614 char *class;
1615 char *modname;
1616 int instance;
1618 ASSERT(spp != NULL);
1621 * Sanity check the arguments.
1624 if (name == NULL || nstat <= 0 || update == NULL)
1625 return (EINVAL);
1628 * Translate the action id into the action pointer.
1631 if ((ap = hold_action(aid)) == NULL)
1632 return (ENOENT);
1635 * Grab relevant action and module information.
1638 LOCK_ACTION(ap, RW_READER);
1639 class = ap->ippa_name;
1640 instance = (int)ap->ippa_id;
1642 imp = ap->ippa_mod;
1643 ASSERT(imp != NULL);
1645 LOCK_MOD(imp, RW_READER);
1646 modname = imp->ippm_name;
1649 * Allocate a stats info structure.
1652 if ((sip = kmem_alloc(sizeof (ipp_stat_impl_t), KM_NOSLEEP)) == NULL)
1653 return (ENOMEM);
1656 * Create a set of kstats.
1659 DBG2(DBG_STATS, "creating stat set '%s' for action '%s'\n",
1660 name, class);
1661 if ((ksp = kstat_create(modname, instance, name, class,
1662 KSTAT_TYPE_NAMED, nstat, KSTAT_FLAG_WRITABLE)) == NULL) {
1663 kmem_free(sip, sizeof (ipp_stat_impl_t));
1664 UNLOCK_ACTION(ap);
1665 UNLOCK_MOD(imp);
1666 return (EINVAL); /* Assume EINVAL was the cause */
1669 UNLOCK_ACTION(ap);
1670 UNLOCK_MOD(imp);
1672 DBG1(DBG_STATS, "ks_data = %p\n", ksp->ks_data);
1675 * Set up the kstats structure with a private data pointer and an
1676 * 'update' function.
1679 ksp->ks_update = update_stats;
1680 ksp->ks_private = (void *)sip;
1683 * Keep a reference to the kstats structure in our own stats info
1684 * structure.
1687 sip->ippsi_ksp = ksp;
1688 sip->ippsi_data = ksp->ks_data;
1691 * Fill in the rest of the stats info structure.
1694 (void) strcpy(sip->ippsi_name, name);
1695 sip->ippsi_arg = arg;
1696 sip->ippsi_update = update;
1697 sip->ippsi_limit = nstat;
1698 sip->ippsi_count = 0;
1699 mutex_init(sip->ippsi_lock, NULL, MUTEX_ADAPTIVE,
1700 (void *)ipltospl(LOCK_LEVEL));
1703 * Case the stats info structure to a semi-opaque structure that
1704 * we pass back to the caller.
1707 sp = (ipp_stat_t *)sip;
1708 ASSERT(sp->ipps_data == sip->ippsi_data);
1709 *spp = sp;
1711 rele_action(ap);
1712 return (0);
1714 #undef __FN__
1716 #define __FN__ "ipp_stat_install"
1717 void
1718 ipp_stat_install(
1719 ipp_stat_t *sp)
1721 ipp_stat_impl_t *sip = (ipp_stat_impl_t *)sp;
1723 ASSERT(sp != NULL);
1726 * Install the set of kstats referenced by the stats info structure.
1729 DBG1(DBG_STATS, "installing stat set '%s'\n", sip->ippsi_name);
1730 kstat_install(sip->ippsi_ksp);
1732 #undef __FN__
1734 #define __FN__ "ipp_stat_destroy"
1735 void
1736 ipp_stat_destroy(
1737 ipp_stat_t *sp)
1739 ipp_stat_impl_t *sip = (ipp_stat_impl_t *)sp;
1741 ASSERT(sp != NULL);
1744 * Destroy the set of kstats referenced by the stats info structure.
1747 DBG1(DBG_STATS, "destroying stat set '%s'\n", sip->ippsi_name);
1748 kstat_delete(sip->ippsi_ksp);
1751 * Destroy the stats info structure itself.
1754 mutex_destroy(sip->ippsi_lock);
1755 kmem_free(sip, sizeof (ipp_stat_impl_t));
1757 #undef __FN__
1759 #define __FN__ "ipp_stat_named_init"
1761 ipp_stat_named_init(
1762 ipp_stat_t *sp,
1763 const char *name,
1764 uchar_t type,
1765 ipp_named_t *np)
1767 ipp_stat_impl_t *sip = (ipp_stat_impl_t *)sp;
1768 uchar_t ktype;
1770 ASSERT(sp != NULL);
1771 ASSERT(np != NULL);
1773 if (name == NULL)
1774 return (EINVAL);
1776 if ((type & IPP_STAT_TAG) == 0)
1777 return (EINVAL);
1778 ktype = type & ~IPP_STAT_TAG;
1781 * Check we will not exceed the maximum number of a stats that was
1782 * indicated during set creation.
1785 mutex_enter(sip->ippsi_lock);
1786 if (sip->ippsi_count >= sip->ippsi_limit) {
1787 mutex_exit(sip->ippsi_lock);
1788 return (ENOSPC);
1792 * Bump the count.
1795 sip->ippsi_count++;
1798 * Create a new named kstat.
1801 DBG3(DBG_STATS, "%s.%s: knp = %p\n", sip->ippsi_name, name, np);
1802 kstat_named_init(np, name, ktype);
1803 mutex_exit(sip->ippsi_lock);
1805 return (0);
1807 #undef __FN__
1809 #define __FN__ "ipp_stat_named_op"
1811 ipp_stat_named_op(
1812 ipp_named_t *np,
1813 void *valp,
1814 int rw)
1816 kstat_named_t *knp;
1817 uchar_t type;
1818 int rc = 0;
1820 ASSERT(np != NULL);
1821 ASSERT(valp != NULL);
1823 knp = np;
1824 type = knp->data_type | IPP_STAT_TAG;
1827 * Copy data to or from the named kstat, depending on the specified
1828 * opcode.
1831 switch (rw) {
1832 case IPP_STAT_WRITE:
1833 switch (type) {
1834 case IPP_STAT_INT32:
1835 *(int32_t *)valp = knp->value.i32;
1836 break;
1837 case IPP_STAT_UINT32:
1838 *(uint32_t *)valp = knp->value.ui32;
1839 break;
1840 case IPP_STAT_INT64:
1841 *(int64_t *)valp = knp->value.i64;
1842 break;
1843 case IPP_STAT_UINT64:
1844 *(uint64_t *)valp = knp->value.ui64;
1845 break;
1846 case IPP_STAT_STRING:
1847 (void) strncpy(valp, knp->value.c, 16);
1848 break;
1849 default:
1850 ASSERT(0); /* should not reach here */
1851 break;
1854 break;
1855 case IPP_STAT_READ:
1856 switch (type) {
1857 case IPP_STAT_INT32:
1858 knp->value.i32 = *(int32_t *)valp;
1859 break;
1860 case IPP_STAT_UINT32:
1861 knp->value.ui32 = *(uint32_t *)valp;
1862 break;
1863 case IPP_STAT_INT64:
1864 knp->value.i64 = *(int64_t *)valp;
1865 break;
1866 case IPP_STAT_UINT64:
1867 knp->value.ui64 = *(uint64_t *)valp;
1868 break;
1869 case IPP_STAT_STRING:
1870 (void) strncpy(knp->value.c, valp, 16);
1871 break;
1872 default:
1873 ASSERT(0); /* should not reach here */
1874 break;
1877 break;
1878 default:
1879 rc = EINVAL;
1882 return (rc);
1884 #undef __FN__
1887 * Local functions (for local people. There's nothing for you here!)
1890 #define __FN__ "ref_mod"
1891 static int
1892 ref_mod(
1893 ipp_action_t *ap,
1894 ipp_mod_t *imp)
1896 ipp_ref_t **rpp;
1897 ipp_ref_t *rp;
1899 ASSERT(rw_write_held(ap->ippa_lock));
1900 ASSERT(rw_write_held(imp->ippm_lock));
1903 * Add the new reference at the end of the module's list.
1906 rpp = &(imp->ippm_action);
1907 while ((rp = *rpp) != NULL) {
1908 ASSERT(rp->ippr_action != ap);
1909 rpp = &(rp->ippr_nextp);
1913 * Allocate a reference structure.
1916 if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL)
1917 return (ENOMEM);
1920 * Set the reference to the action and link it onto the module's list.
1923 rp->ippr_action = ap;
1924 *rpp = rp;
1927 * Keep a 'back pointer' from the action structure to the module
1928 * structure.
1931 ap->ippa_mod = imp;
1933 return (0);
1935 #undef __FN__
1937 #define __FN__ "unref_mod"
1938 static void
1939 unref_mod(
1940 ipp_action_t *ap,
1941 ipp_mod_t *imp)
1943 ipp_ref_t **rpp;
1944 ipp_ref_t *rp;
1946 ASSERT(rw_write_held(ap->ippa_lock));
1947 ASSERT(rw_write_held(imp->ippm_lock));
1950 * Scan the module's list for the reference to the action.
1953 rpp = &(imp->ippm_action);
1954 while ((rp = *rpp) != NULL) {
1955 if (rp->ippr_action == ap)
1956 break;
1957 rpp = &(rp->ippr_nextp);
1959 ASSERT(rp != NULL);
1962 * Unlink the reference structure and free it.
1965 *rpp = rp->ippr_nextp;
1966 kmem_free(rp, sizeof (ipp_ref_t));
1969 * NULL the 'back pointer'.
1972 ap->ippa_mod = NULL;
1974 #undef __FN__
1976 #define __FN__ "is_mod_busy"
1977 static int
1978 is_mod_busy(
1979 ipp_mod_t *imp)
1982 * Return a value which is true (non-zero) iff the module refers
1983 * to no actions.
1986 return (imp->ippm_action != NULL);
1988 #undef __FN__
1990 #define __FN__ "get_mod_ref"
1991 static int
1992 get_mod_ref(
1993 ipp_mod_t *imp,
1994 ipp_action_id_t **bufp,
1995 int *neltp)
1997 ipp_ref_t *rp;
1998 int nelt;
1999 ipp_action_t *ap;
2000 ipp_action_id_t *buf;
2001 int length;
2003 ASSERT(rw_lock_held(imp->ippm_lock));
2006 * Count the number of actions referred to from the module structure.
2009 nelt = 0;
2010 for (rp = imp->ippm_action; rp != NULL; rp = rp->ippr_nextp) {
2011 nelt++;
2013 DBG1(DBG_LIST, "%d actions found\n", nelt);
2016 * If there are no actions referred to then there's nothing to do.
2019 if (nelt == 0) {
2020 *bufp = NULL;
2021 *neltp = 0;
2022 return (0);
2026 * Allocate a buffer to pass back to the caller.
2029 length = nelt * sizeof (ipp_action_id_t);
2030 if ((buf = kmem_alloc(length, KM_NOSLEEP)) == NULL)
2031 return (ENOMEM);
2034 * Fill the buffer with an array of action ids.
2037 *bufp = buf;
2038 *neltp = nelt;
2040 for (rp = imp->ippm_action; rp != NULL; rp = rp->ippr_nextp) {
2041 ap = rp->ippr_action;
2042 *buf++ = ap->ippa_id;
2045 ASSERT((uintptr_t)buf == (uintptr_t)*bufp + length);
2046 return (0);
2048 #undef __FN__
2050 #define __FN__ "get_mods"
2051 static int
2052 get_mods(
2053 ipp_mod_id_t **bufp,
2054 int *neltp)
2056 ipp_mod_id_t *buf;
2057 int length;
2058 ipp_mod_id_t mid;
2059 ipp_mod_t *imp;
2062 rw_enter(ipp_mod_byname_lock, RW_READER);
2065 * If there are no modules registered then there's nothing to do.
2068 if (ipp_mod_count == 0) {
2069 DBG0(DBG_LIST, "no modules registered\n");
2070 *bufp = NULL;
2071 *neltp = 0;
2072 rw_exit(ipp_mod_byname_lock);
2073 return (0);
2077 * Allocate a buffer to pass back to the caller.
2080 DBG1(DBG_LIST, "%d modules registered\n", ipp_mod_count);
2081 length = ipp_mod_count * sizeof (ipp_mod_id_t);
2082 if ((buf = kmem_alloc(length, KM_NOSLEEP)) == NULL) {
2083 rw_exit(ipp_mod_byname_lock);
2084 return (ENOMEM);
2087 rw_enter(ipp_mod_byid_lock, RW_READER);
2090 * Search the array of all modules.
2093 *bufp = buf;
2094 *neltp = ipp_mod_count;
2096 for (mid = IPP_MOD_RESERVED + 1; mid <= ipp_mid_limit; mid++) {
2097 if ((imp = ipp_mod_byid[mid]) == NULL)
2098 continue;
2101 * If the module has 'destruct pending' set then it means it
2102 * is either still in the cache (i.e not allocated) or in the
2103 * process of being set up by alloc_mod().
2106 LOCK_MOD(imp, RW_READER);
2107 ASSERT(imp->ippm_id == mid);
2109 if (imp->ippm_destruct_pending) {
2110 UNLOCK_MOD(imp);
2111 continue;
2113 UNLOCK_MOD(imp);
2115 *buf++ = mid;
2118 rw_exit(ipp_mod_byid_lock);
2119 rw_exit(ipp_mod_byname_lock);
2121 ASSERT((uintptr_t)buf == (uintptr_t)*bufp + length);
2122 return (0);
2124 #undef __FN__
2126 #define __FN__ "find_mod"
2127 static ipp_mod_id_t
2128 find_mod(
2129 const char *modname)
2131 ipp_mod_id_t mid;
2132 ipp_mod_t *imp;
2133 ipp_ref_t *rp;
2134 int hb;
2136 ASSERT(modname != NULL);
2138 rw_enter(ipp_mod_byname_lock, RW_READER);
2141 * Quick return if no modules are registered.
2144 if (ipp_mod_count == 0) {
2145 rw_exit(ipp_mod_byname_lock);
2146 return (IPP_MOD_INVAL);
2150 * Find the hash bucket where the module structure should be.
2153 hb = hash(modname);
2154 rp = ipp_mod_byname[hb];
2157 * Scan the bucket for a match.
2160 while (rp != NULL) {
2161 imp = rp->ippr_mod;
2162 if (strcmp(imp->ippm_name, modname) == 0)
2163 break;
2164 rp = rp->ippr_nextp;
2167 if (rp == NULL) {
2168 rw_exit(ipp_mod_byname_lock);
2169 return (IPP_MOD_INVAL);
2172 if (imp->ippm_state == IPP_MODSTATE_PROTO) {
2173 rw_exit(ipp_mod_byname_lock);
2174 return (IPP_MOD_INVAL);
2177 mid = imp->ippm_id;
2178 rw_exit(ipp_mod_byname_lock);
2180 return (mid);
2182 #undef __FN__
2184 #define __FN__ "alloc_mod"
2185 static int
2186 alloc_mod(
2187 const char *modname,
2188 ipp_mod_id_t *midp)
2190 ipp_mod_t *imp;
2191 ipp_ref_t **rpp;
2192 ipp_ref_t *rp;
2193 int hb;
2195 ASSERT(modname != NULL);
2196 ASSERT(midp != NULL);
2198 rw_enter(ipp_mod_byname_lock, RW_WRITER);
2201 * Find the right hash bucket for a module of the given name.
2204 hb = hash(modname);
2205 rpp = &ipp_mod_byname[hb];
2208 * Scan the bucket making sure the module isn't already
2209 * registered.
2212 while ((rp = *rpp) != NULL) {
2213 imp = rp->ippr_mod;
2214 if (strcmp(imp->ippm_name, modname) == 0) {
2215 DBG1(DBG_MOD, "module '%s' already exists\n", modname);
2216 rw_exit(ipp_mod_byname_lock);
2217 return (EEXIST);
2219 rpp = &(rp->ippr_nextp);
2223 * Allocate a new reference structure and a new module structure.
2226 if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL) {
2227 rw_exit(ipp_mod_byname_lock);
2228 return (ENOMEM);
2231 if ((imp = kmem_cache_alloc(ipp_mod_cache, KM_NOSLEEP)) == NULL) {
2232 kmem_free(rp, sizeof (ipp_ref_t));
2233 rw_exit(ipp_mod_byname_lock);
2234 return (ENOMEM);
2238 * Set up the name of the new structure.
2241 (void) strcpy(imp->ippm_name, modname);
2244 * Make sure the 'destruct pending' flag is clear. This indicates
2245 * that the structure is no longer part of the cache.
2248 LOCK_MOD(imp, RW_WRITER);
2249 imp->ippm_destruct_pending = B_FALSE;
2250 UNLOCK_MOD(imp);
2253 * Set the reference and link it into the hash bucket.
2256 rp->ippr_mod = imp;
2257 *rpp = rp;
2260 * Increment the module count.
2263 ipp_mod_count++;
2265 *midp = imp->ippm_id;
2266 rw_exit(ipp_mod_byname_lock);
2267 return (0);
2269 #undef __FN__
2271 #define __FN__ "free_mod"
2272 static void
2273 free_mod(
2274 ipp_mod_t *imp)
2276 ipp_ref_t **rpp;
2277 ipp_ref_t *rp;
2278 int hb;
2280 rw_enter(ipp_mod_byname_lock, RW_WRITER);
2283 * Find the hash bucket where the module structure should be.
2286 hb = hash(imp->ippm_name);
2287 rpp = &ipp_mod_byname[hb];
2290 * Scan the bucket for a match.
2293 while ((rp = *rpp) != NULL) {
2294 if (rp->ippr_mod == imp)
2295 break;
2296 rpp = &(rp->ippr_nextp);
2298 ASSERT(rp != NULL);
2301 * Unlink the reference structure and free it.
2304 *rpp = rp->ippr_nextp;
2305 kmem_free(rp, sizeof (ipp_ref_t));
2308 * Decrement the module count.
2311 ipp_mod_count--;
2314 * Empty the name.
2317 *imp->ippm_name = '\0';
2320 * If the hold count is zero then we can free the structure
2321 * immediately, otherwise we defer to rele_mod().
2324 LOCK_MOD(imp, RW_WRITER);
2325 imp->ippm_destruct_pending = B_TRUE;
2326 if (imp->ippm_hold_count == 0) {
2327 UNLOCK_MOD(imp);
2328 kmem_cache_free(ipp_mod_cache, imp);
2329 rw_exit(ipp_mod_byname_lock);
2330 return;
2332 UNLOCK_MOD(imp);
2334 rw_exit(ipp_mod_byname_lock);
2336 #undef __FN__
2338 #define __FN__ "hold_mod"
2339 static ipp_mod_t *
2340 hold_mod(
2341 ipp_mod_id_t mid)
2343 ipp_mod_t *imp;
2345 if (mid < 0)
2346 return (NULL);
2349 * Use the module id as an index into the array of all module
2350 * structures.
2353 rw_enter(ipp_mod_byid_lock, RW_READER);
2354 if ((imp = ipp_mod_byid[mid]) == NULL) {
2355 rw_exit(ipp_mod_byid_lock);
2356 return (NULL);
2359 ASSERT(imp->ippm_id == mid);
2362 * If the modul has 'destruct pending' set then it means it is either
2363 * still in the cache (i.e not allocated) or in the process of
2364 * being set up by alloc_mod().
2367 LOCK_MOD(imp, RW_READER);
2368 if (imp->ippm_destruct_pending) {
2369 UNLOCK_MOD(imp);
2370 rw_exit(ipp_mod_byid_lock);
2371 return (NULL);
2373 UNLOCK_MOD(imp);
2376 * Increment the hold count to prevent the structure from being
2377 * freed.
2380 atomic_inc_32(&(imp->ippm_hold_count));
2381 rw_exit(ipp_mod_byid_lock);
2383 return (imp);
2385 #undef __FN__
2387 #define __FN__ "rele_mod"
2388 static void
2389 rele_mod(
2390 ipp_mod_t *imp)
2393 * This call means we're done with the pointer so we can drop the
2394 * hold count.
2397 ASSERT(imp->ippm_hold_count != 0);
2398 atomic_dec_32(&(imp->ippm_hold_count));
2401 * If the structure has 'destruct pending' set then we tried to free
2402 * it but couldn't, so do it now.
2405 LOCK_MOD(imp, RW_READER);
2406 if (imp->ippm_destruct_pending && imp->ippm_hold_count == 0) {
2407 UNLOCK_MOD(imp);
2408 kmem_cache_free(ipp_mod_cache, imp);
2409 return;
2412 UNLOCK_MOD(imp);
2414 #undef __FN__
2416 #define __FN__ "get_mid"
2417 static ipp_mod_id_t
2418 get_mid(
2419 void)
2421 int index;
2422 int start;
2423 int limit;
2425 ASSERT(rw_write_held(ipp_mod_byid_lock));
2428 * Start searching after the last module id we allocated.
2431 start = (int)ipp_next_mid;
2432 limit = (int)ipp_mid_limit;
2435 * Look for a spare slot in the array.
2438 index = start;
2439 while (ipp_mod_byid[index] != NULL) {
2440 index++;
2441 if (index > limit)
2442 index = IPP_MOD_RESERVED + 1;
2443 if (index == start)
2444 return (IPP_MOD_INVAL);
2448 * Note that we've just allocated a new module id so that we can
2449 * start our search there next time.
2452 index++;
2453 if (index > limit) {
2454 ipp_next_mid = IPP_MOD_RESERVED + 1;
2455 } else
2456 ipp_next_mid = (ipp_mod_id_t)index;
2458 return ((ipp_mod_id_t)(--index));
2460 #undef __FN__
2462 #define __FN__ "condemn_action"
2463 static int
2464 condemn_action(
2465 ipp_ref_t **rpp,
2466 ipp_action_t *ap)
2468 ipp_ref_t *rp;
2470 DBG1(DBG_ACTION, "condemning action '%s'\n", ap->ippa_name);
2473 * Check to see if the action is already condemned.
2476 while ((rp = *rpp) != NULL) {
2477 if (rp->ippr_action == ap)
2478 break;
2479 rpp = &(rp->ippr_nextp);
2483 * Create a new entry for the action.
2486 if (rp == NULL) {
2487 if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL)
2488 return (ENOMEM);
2490 rp->ippr_action = ap;
2491 *rpp = rp;
2494 return (0);
2496 #undef __FN__
2498 #define __FN__ "destroy_action"
2499 static int
2500 destroy_action(
2501 ipp_action_t *ap,
2502 ipp_flags_t flags)
2504 ipp_ops_t *ippo;
2505 ipp_mod_t *imp;
2506 #define MAXWAIT 10
2507 uint32_t wait;
2508 int rc;
2511 * Check that the action is available.
2514 LOCK_ACTION(ap, RW_WRITER);
2515 if (ap->ippa_state != IPP_ASTATE_AVAILABLE) {
2516 UNLOCK_ACTION(ap);
2517 rele_action(ap);
2518 return (EPROTO);
2522 * Note that the action is in the process of creation/destruction.
2525 ap->ippa_state = IPP_ASTATE_CONFIG_PENDING;
2528 * Wait for the in-transit packet count for this action to fall to
2529 * zero (checking at millisecond intervals).
2531 * NOTE: no new packets will enter the action now that the
2532 * state has been changed.
2535 for (wait = 0; ap->ippa_packets > 0 && wait < (MAXWAIT * 1000000);
2536 wait += 1000) {
2539 * NOTE: We can hang onto the lock because the packet count is
2540 * decremented without needing to take the lock.
2543 drv_usecwait(1000);
2547 * The packet count did not fall to zero.
2549 if (ap->ippa_packets > 0) {
2550 ap->ippa_state = IPP_ASTATE_AVAILABLE;
2551 UNLOCK_ACTION(ap);
2552 rele_action(ap);
2553 return (EAGAIN);
2557 * Check to see if any other action has a dependency on this one.
2560 if (is_action_refd(ap)) {
2561 ap->ippa_state = IPP_ASTATE_AVAILABLE;
2562 UNLOCK_ACTION(ap);
2563 rele_action(ap);
2564 return (EBUSY);
2567 imp = ap->ippa_mod;
2568 ASSERT(imp != NULL);
2569 UNLOCK_ACTION(ap);
2571 ippo = imp->ippm_ops;
2572 ASSERT(ippo != NULL);
2575 * Call into the module to destroy the action context.
2578 CONFIG_WRITE_START(ap);
2579 DBG1(DBG_ACTION, "destroying action '%s'\n", ap->ippa_name);
2580 if ((rc = ippo->ippo_action_destroy(ap->ippa_id, flags)) != 0) {
2581 LOCK_ACTION(ap, RW_WRITER);
2582 ap->ippa_state = IPP_ASTATE_AVAILABLE;
2583 UNLOCK_ACTION(ap);
2585 CONFIG_WRITE_END(ap);
2587 rele_action(ap);
2588 return (rc);
2590 CONFIG_WRITE_END(ap);
2592 LOCK_ACTION(ap, RW_WRITER);
2593 LOCK_MOD(imp, RW_WRITER);
2594 unref_mod(ap, imp);
2595 UNLOCK_MOD(imp);
2596 ap->ippa_state = IPP_ASTATE_PROTO;
2597 UNLOCK_ACTION(ap);
2600 * Free the action structure.
2603 ASSERT(ap->ippa_ref == NULL);
2604 free_action(ap);
2605 rele_action(ap);
2606 return (0);
2607 #undef MAXWAIT
2609 #undef __FN__
2611 #define __FN__ "ref_action"
2612 static int
2613 ref_action(
2614 ipp_action_t *refby_ap,
2615 ipp_action_t *ref_ap)
2617 ipp_ref_t **rpp;
2618 ipp_ref_t **save_rpp;
2619 ipp_ref_t *rp;
2621 ASSERT(rw_write_held(refby_ap->ippa_lock));
2622 ASSERT(rw_write_held(ref_ap->ippa_lock));
2625 * We want to add the new reference at the end of the refering
2626 * action's list.
2629 rpp = &(refby_ap->ippa_ref);
2630 while ((rp = *rpp) != NULL) {
2631 if (rp->ippr_action == ref_ap)
2632 break;
2633 rpp = &(rp->ippr_nextp);
2636 if ((rp = *rpp) != NULL) {
2639 * There is an existing reference so increment its counter.
2642 rp->ippr_count++;
2645 * Find the 'back pointer' and increment its counter too.
2648 rp = ref_ap->ippa_refby;
2649 while (rp != NULL) {
2650 if (rp->ippr_action == refby_ap)
2651 break;
2652 rp = rp->ippr_nextp;
2654 ASSERT(rp != NULL);
2656 rp->ippr_count++;
2657 } else {
2660 * Allocate, fill in and link a new reference structure.
2663 if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL)
2664 return (ENOMEM);
2666 rp->ippr_action = ref_ap;
2667 rp->ippr_count = 1;
2668 *rpp = rp;
2669 save_rpp = rpp;
2672 * We keep a 'back pointer' which we want to add at the end of
2673 * a list in the referred action's structure.
2676 rpp = &(ref_ap->ippa_refby);
2677 while ((rp = *rpp) != NULL) {
2678 ASSERT(rp->ippr_action != refby_ap);
2679 rpp = &(rp->ippr_nextp);
2683 * Allocate another reference structure and, if this fails,
2684 * remember to clean up the first reference structure we
2685 * allocated.
2688 if ((rp = kmem_zalloc(sizeof (ipp_ref_t),
2689 KM_NOSLEEP)) == NULL) {
2690 rpp = save_rpp;
2691 rp = *rpp;
2692 *rpp = NULL;
2693 kmem_free(rp, sizeof (ipp_ref_t));
2695 return (ENOMEM);
2699 * Fill in the reference structure with the 'back pointer' and
2700 * link it into the list.
2703 rp->ippr_action = refby_ap;
2704 rp->ippr_count = 1;
2705 *rpp = rp;
2708 return (0);
2710 #undef __FN__
2712 #define __FN__ "unref_action"
2713 static int
2714 unref_action(
2715 ipp_action_t *refby_ap,
2716 ipp_action_t *ref_ap)
2718 ipp_ref_t **rpp;
2719 ipp_ref_t *rp;
2721 ASSERT(rw_write_held(refby_ap->ippa_lock));
2722 ASSERT(rw_write_held(ref_ap->ippa_lock));
2725 * Scan for the reference in the referring action's list.
2728 rpp = &(refby_ap->ippa_ref);
2729 while ((rp = *rpp) != NULL) {
2730 if (rp->ippr_action == ref_ap)
2731 break;
2732 rpp = &(rp->ippr_nextp);
2735 if (rp == NULL)
2736 return (ENOENT);
2738 if (rp->ippr_count > 1) {
2741 * There are currently multiple references so decrement the
2742 * count.
2745 rp->ippr_count--;
2748 * Find the 'back pointer' and decrement its counter too.
2751 rp = ref_ap->ippa_refby;
2752 while (rp != NULL) {
2753 if (rp->ippr_action == refby_ap)
2754 break;
2755 rp = rp->ippr_nextp;
2757 ASSERT(rp != NULL);
2759 rp->ippr_count--;
2760 } else {
2763 * There is currently only a single reference, so unlink and
2764 * free the reference structure.
2767 *rpp = rp->ippr_nextp;
2768 kmem_free(rp, sizeof (ipp_ref_t));
2771 * Scan for the 'back pointer' in the referred action's list.
2774 rpp = &(ref_ap->ippa_refby);
2775 while ((rp = *rpp) != NULL) {
2776 if (rp->ippr_action == refby_ap)
2777 break;
2778 rpp = &(rp->ippr_nextp);
2780 ASSERT(rp != NULL);
2783 * Unlink and free this reference structure too.
2786 *rpp = rp->ippr_nextp;
2787 kmem_free(rp, sizeof (ipp_ref_t));
2790 return (0);
2792 #undef __FN__
2794 #define __FN__ "is_action_refd"
2795 static int
2796 is_action_refd(
2797 ipp_action_t *ap)
2800 * Return a value which is true (non-zero) iff the action is not
2801 * referred to by any other actions.
2804 return (ap->ippa_refby != NULL);
2806 #undef __FN__
2808 #define __FN__ "find_action"
2809 static ipp_action_id_t
2810 find_action(
2811 const char *aname)
2813 ipp_action_id_t aid;
2814 ipp_action_t *ap;
2815 ipp_ref_t *rp;
2816 int hb;
2818 ASSERT(aname != NULL);
2820 rw_enter(ipp_action_byname_lock, RW_READER);
2823 * Quick return if there are no actions defined at all.
2826 if (ipp_action_count == 0) {
2827 rw_exit(ipp_action_byname_lock);
2828 return (IPP_ACTION_INVAL);
2832 * Find the hash bucket where the action structure should be.
2835 hb = hash(aname);
2836 rp = ipp_action_byname[hb];
2839 * Scan the bucket looking for a match.
2842 while (rp != NULL) {
2843 ap = rp->ippr_action;
2844 if (strcmp(ap->ippa_name, aname) == 0)
2845 break;
2846 rp = rp->ippr_nextp;
2849 if (rp == NULL) {
2850 rw_exit(ipp_action_byname_lock);
2851 return (IPP_ACTION_INVAL);
2854 if (ap->ippa_state == IPP_ASTATE_PROTO) {
2855 rw_exit(ipp_action_byname_lock);
2856 return (IPP_ACTION_INVAL);
2859 aid = ap->ippa_id;
2860 rw_exit(ipp_action_byname_lock);
2862 return (aid);
2864 #undef __FN__
2866 #define __FN__ "alloc_action"
2867 static int
2868 alloc_action(
2869 const char *aname,
2870 ipp_action_id_t *aidp)
2872 ipp_action_t *ap;
2873 ipp_ref_t **rpp;
2874 ipp_ref_t *rp;
2875 int hb;
2877 ASSERT(aidp != NULL);
2879 rw_enter(ipp_action_byname_lock, RW_WRITER);
2882 * Find the right hash bucket for an action of the given name.
2883 * (Nameless actions always go in a special bucket).
2886 if (aname != NULL) {
2887 hb = hash(aname);
2888 rpp = &ipp_action_byname[hb];
2889 } else
2890 rpp = &ipp_action_noname;
2893 * Scan the bucket to make sure that an action with the given name
2894 * does not already exist.
2897 while ((rp = *rpp) != NULL) {
2898 ap = rp->ippr_action;
2899 if (aname != NULL && strcmp(ap->ippa_name, aname) == 0) {
2900 DBG1(DBG_ACTION, "action '%s' already exists\n",
2901 aname);
2902 rw_exit(ipp_action_byname_lock);
2903 return (EEXIST);
2905 rpp = &(rp->ippr_nextp);
2909 * Allocate a new reference structure and a new action structure.
2912 if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL) {
2913 rw_exit(ipp_action_byname_lock);
2914 return (ENOMEM);
2917 if ((ap = kmem_cache_alloc(ipp_action_cache, KM_NOSLEEP)) == NULL) {
2918 kmem_free(rp, sizeof (ipp_ref_t));
2919 rw_exit(ipp_action_byname_lock);
2920 return (ENOMEM);
2924 * Dream up a name if there isn't a real one and note that the action is
2925 * really nameless.
2928 if (aname == NULL) {
2929 (void) sprintf(ap->ippa_name, "$%08X", ap->ippa_id);
2930 ap->ippa_nameless = B_TRUE;
2931 } else
2932 (void) strcpy(ap->ippa_name, aname);
2935 * Make sure the 'destruct pending' flag is clear. This indicates that
2936 * the structure is no longer part of the cache.
2939 LOCK_ACTION(ap, RW_WRITER);
2940 ap->ippa_destruct_pending = B_FALSE;
2941 UNLOCK_ACTION(ap);
2944 * Fill in the reference structure and lint it onto the list.
2947 rp->ippr_action = ap;
2948 *rpp = rp;
2951 * Increment the action count.
2954 ipp_action_count++;
2956 *aidp = ap->ippa_id;
2957 rw_exit(ipp_action_byname_lock);
2958 return (0);
2960 #undef __FN__
2962 #define __FN__ "free_action"
2963 static void
2964 free_action(
2965 ipp_action_t *ap)
2967 ipp_ref_t **rpp;
2968 ipp_ref_t *rp;
2969 int hb;
2971 rw_enter(ipp_action_byname_lock, RW_WRITER);
2974 * Find the hash bucket where the action structure should be.
2977 if (!ap->ippa_nameless) {
2978 hb = hash(ap->ippa_name);
2979 rpp = &ipp_action_byname[hb];
2980 } else
2981 rpp = &ipp_action_noname;
2984 * Scan the bucket for a match.
2987 while ((rp = *rpp) != NULL) {
2988 if (rp->ippr_action == ap)
2989 break;
2990 rpp = &(rp->ippr_nextp);
2992 ASSERT(rp != NULL);
2995 * Unlink and free the reference structure.
2998 *rpp = rp->ippr_nextp;
2999 kmem_free(rp, sizeof (ipp_ref_t));
3002 * Decrement the action count.
3005 ipp_action_count--;
3008 * Empty the name.
3011 *ap->ippa_name = '\0';
3014 * If the hold count is zero then we can free the structure
3015 * immediately, otherwise we defer to rele_action().
3018 LOCK_ACTION(ap, RW_WRITER);
3019 ap->ippa_destruct_pending = B_TRUE;
3020 if (ap->ippa_hold_count == 0) {
3021 UNLOCK_ACTION(ap);
3022 kmem_cache_free(ipp_action_cache, ap);
3023 rw_exit(ipp_action_byname_lock);
3024 return;
3026 UNLOCK_ACTION(ap);
3028 rw_exit(ipp_action_byname_lock);
3030 #undef __FN__
3032 #define __FN__ "hold_action"
3033 static ipp_action_t *
3034 hold_action(
3035 ipp_action_id_t aid)
3037 ipp_action_t *ap;
3039 if (aid < 0)
3040 return (NULL);
3043 * Use the action id as an index into the array of all action
3044 * structures.
3047 rw_enter(ipp_action_byid_lock, RW_READER);
3048 if ((ap = ipp_action_byid[aid]) == NULL) {
3049 rw_exit(ipp_action_byid_lock);
3050 return (NULL);
3054 * If the action has 'destruct pending' set then it means it is either
3055 * still in the cache (i.e not allocated) or in the process of
3056 * being set up by alloc_action().
3059 LOCK_ACTION(ap, RW_READER);
3060 if (ap->ippa_destruct_pending) {
3061 UNLOCK_ACTION(ap);
3062 rw_exit(ipp_action_byid_lock);
3063 return (NULL);
3065 UNLOCK_ACTION(ap);
3068 * Increment the hold count to prevent the structure from being
3069 * freed.
3072 atomic_inc_32(&(ap->ippa_hold_count));
3073 rw_exit(ipp_action_byid_lock);
3075 return (ap);
3077 #undef __FN__
3079 #define __FN__ "rele_action"
3080 static void
3081 rele_action(
3082 ipp_action_t *ap)
3085 * This call means we're done with the pointer so we can drop the
3086 * hold count.
3089 ASSERT(ap->ippa_hold_count != 0);
3090 atomic_dec_32(&(ap->ippa_hold_count));
3093 * If the structure has 'destruct pending' set then we tried to free
3094 * it but couldn't, so do it now.
3097 LOCK_ACTION(ap, RW_READER);
3098 if (ap->ippa_destruct_pending && ap->ippa_hold_count == 0) {
3099 UNLOCK_ACTION(ap);
3100 kmem_cache_free(ipp_action_cache, ap);
3101 return;
3103 UNLOCK_ACTION(ap);
3105 #undef __FN__
3107 #define __FN__ "get_aid"
3108 static ipp_action_id_t
3109 get_aid(
3110 void)
3112 int index;
3113 int start;
3114 int limit;
3116 ASSERT(rw_write_held(ipp_action_byid_lock));
3119 * Start searching after the last action id that we allocated.
3122 start = (int)ipp_next_aid;
3123 limit = (int)ipp_aid_limit;
3126 * Look for a spare slot in the array.
3129 index = start;
3130 while (ipp_action_byid[index] != NULL) {
3131 index++;
3132 if (index > limit)
3133 index = IPP_ACTION_RESERVED + 1;
3134 if (index == start)
3135 return (IPP_ACTION_INVAL);
3139 * Note that we've just allocated a new action id so that we can
3140 * start our search there next time.
3143 index++;
3144 if (index > limit)
3145 ipp_next_aid = IPP_ACTION_RESERVED + 1;
3146 else
3147 ipp_next_aid = (ipp_action_id_t)index;
3149 return ((ipp_action_id_t)(--index));
3151 #undef __FN__
3153 #define __FN__ "alloc_packet"
3154 static int
3155 alloc_packet(
3156 const char *name,
3157 ipp_action_id_t aid,
3158 ipp_packet_t **ppp)
3160 ipp_packet_t *pp;
3161 ipp_class_t *cp;
3163 if ((pp = kmem_cache_alloc(ipp_packet_cache, KM_NOSLEEP)) == NULL)
3164 return (ENOMEM);
3167 * Set the packet up with a single class.
3170 cp = &(pp->ippp_class_array[0]);
3171 pp->ippp_class_windex = 1;
3173 (void) strcpy(cp->ippc_name, name);
3174 cp->ippc_aid = aid;
3176 *ppp = pp;
3177 return (0);
3179 #undef __FN__
3181 #define __FN__ "realloc_packet"
3182 static int
3183 realloc_packet(
3184 ipp_packet_t *pp)
3186 uint_t length;
3187 ipp_class_t *array;
3189 length = (pp->ippp_class_limit + 1) << 1;
3190 if ((array = kmem_alloc(length * sizeof (ipp_class_t),
3191 KM_NOSLEEP)) == NULL)
3192 return (ENOMEM);
3194 bcopy(pp->ippp_class_array, array,
3195 (length >> 1) * sizeof (ipp_class_t));
3197 kmem_free(pp->ippp_class_array,
3198 (length >> 1) * sizeof (ipp_class_t));
3200 pp->ippp_class_array = array;
3201 pp->ippp_class_limit = length - 1;
3203 return (0);
3205 #undef __FN__
3207 #define __FN__ "free_packet"
3208 static void
3209 free_packet(
3210 ipp_packet_t *pp)
3212 pp->ippp_class_windex = 0;
3213 pp->ippp_class_rindex = 0;
3215 pp->ippp_data = NULL;
3216 pp->ippp_private = NULL;
3218 kmem_cache_free(ipp_packet_cache, pp);
3220 #undef __FN__
3222 #define __FN__ "hash"
3223 static int
3224 hash(
3225 const char *name)
3227 int val = 0;
3228 char *ptr;
3231 * Make a hash value by XORing all the ascii codes in the text string.
3234 for (ptr = (char *)name; *ptr != NULL; ptr++) {
3235 val ^= *ptr;
3239 * Return the value modulo the number of hash buckets we allow.
3242 return (val % IPP_NBUCKET);
3244 #undef __FN__
3246 #define __FN__ "update_stats"
3247 static int
3248 update_stats(
3249 kstat_t *ksp,
3250 int rw)
3252 ipp_stat_impl_t *sip;
3254 ASSERT(ksp->ks_private != NULL);
3255 sip = (ipp_stat_impl_t *)ksp->ks_private;
3258 * Call the update function passed to ipp_stat_create() for the given
3259 * set of kstats.
3262 return (sip->ippsi_update((ipp_stat_t *)sip, sip->ippsi_arg, rw));
3264 #undef __FN__
3266 #define __FN__ "init_mods"
3267 static void
3268 init_mods(
3269 void)
3272 * Initialise the array of all module structures and the module
3273 * structure kmem cache.
3276 rw_init(ipp_mod_byid_lock, NULL, RW_DEFAULT,
3277 (void *)ipltospl(LOCK_LEVEL));
3278 ipp_mod_byid = kmem_zalloc(sizeof (ipp_mod_t *) * (ipp_max_mod + 1),
3279 KM_SLEEP);
3280 ipp_mod_byid[ipp_max_mod] = (ipp_mod_t *)-1;
3281 ipp_mid_limit = (ipp_mod_id_t)(ipp_max_mod - 1);
3283 ipp_mod_cache = kmem_cache_create("ipp_mod", sizeof (ipp_mod_t),
3284 IPP_ALIGN, mod_constructor, mod_destructor, NULL, NULL, NULL, 0);
3285 ASSERT(ipp_mod_cache != NULL);
3288 * Initialize the 'module by name' hash bucket array.
3291 rw_init(ipp_mod_byname_lock, NULL, RW_DEFAULT,
3292 (void *)ipltospl(LOCK_LEVEL));
3293 bzero(ipp_mod_byname, IPP_NBUCKET * sizeof (ipp_ref_t *));
3295 #undef __FN__
3297 #define __FN__ "init_actions"
3298 static void
3299 init_actions(
3300 void)
3303 * Initialise the array of all action structures and the action
3304 * structure cache.
3307 rw_init(ipp_action_byid_lock, NULL, RW_DEFAULT,
3308 (void *)ipltospl(LOCK_LEVEL));
3309 ipp_action_byid = kmem_zalloc(sizeof (ipp_action_t *) *
3310 (ipp_max_action + 1), KM_SLEEP);
3311 ipp_action_byid[ipp_max_action] = (ipp_action_t *)-1;
3312 ipp_aid_limit = (ipp_action_id_t)(ipp_max_action - 1);
3314 ipp_action_cache = kmem_cache_create("ipp_action",
3315 sizeof (ipp_action_t), IPP_ALIGN, action_constructor,
3316 action_destructor, NULL, NULL, NULL, 0);
3317 ASSERT(ipp_action_cache != NULL);
3320 * Initialize the 'action by name' hash bucket array (and the special
3321 * 'hash' bucket for nameless actions).
3324 rw_init(ipp_action_byname_lock, NULL, RW_DEFAULT,
3325 (void *)ipltospl(LOCK_LEVEL));
3326 bzero(ipp_action_byname, IPP_NBUCKET * sizeof (ipp_ref_t *));
3327 ipp_action_noname = NULL;
3329 #undef __FN__
3331 #define __FN__ "init_packets"
3332 static void
3333 init_packets(
3334 void)
3337 * Initialise the packet structure cache.
3340 ipp_packet_cache = kmem_cache_create("ipp_packet",
3341 sizeof (ipp_packet_t), IPP_ALIGN, packet_constructor,
3342 packet_destructor, NULL, NULL, NULL, 0);
3343 ASSERT(ipp_packet_cache != NULL);
3345 #undef __FN__
3348 * Kmem cache constructor/destructor functions.
3351 #define __FN__ "mod_constructor"
3352 /*ARGSUSED*/
3353 static int
3354 mod_constructor(
3355 void *buf,
3356 void *cdrarg,
3357 int kmflags)
3359 ipp_mod_t *imp;
3360 ipp_mod_id_t mid;
3362 ASSERT(buf != NULL);
3363 bzero(buf, sizeof (ipp_mod_t));
3364 imp = (ipp_mod_t *)buf;
3366 rw_enter(ipp_mod_byid_lock, RW_WRITER);
3369 * Get a new module id.
3372 if ((mid = get_mid()) <= IPP_MOD_RESERVED) {
3373 rw_exit(ipp_mod_byid_lock);
3374 return (-1);
3378 * Initialize the buffer as a module structure in PROTO form.
3381 imp->ippm_destruct_pending = B_TRUE;
3382 imp->ippm_state = IPP_MODSTATE_PROTO;
3383 rw_init(imp->ippm_lock, NULL, RW_DEFAULT,
3384 (void *)ipltospl(LOCK_LEVEL));
3387 * Insert it into the array of all module structures.
3390 imp->ippm_id = mid;
3391 ipp_mod_byid[mid] = imp;
3393 rw_exit(ipp_mod_byid_lock);
3395 return (0);
3397 #undef __FN__
3399 #define __FN__ "mod_destructor"
3400 /*ARGSUSED*/
3401 static void
3402 mod_destructor(
3403 void *buf,
3404 void *cdrarg)
3406 ipp_mod_t *imp;
3408 ASSERT(buf != NULL);
3409 imp = (ipp_mod_t *)buf;
3411 ASSERT(imp->ippm_state == IPP_MODSTATE_PROTO);
3412 ASSERT(imp->ippm_action == NULL);
3413 ASSERT(*imp->ippm_name == '\0');
3414 ASSERT(imp->ippm_destruct_pending);
3416 rw_enter(ipp_mod_byid_lock, RW_WRITER);
3417 ASSERT(imp->ippm_hold_count == 0);
3420 * NULL the entry in the array of all module structures.
3423 ipp_mod_byid[imp->ippm_id] = NULL;
3426 * Clean up any remnants of the module structure as the buffer is
3427 * about to disappear.
3430 rw_destroy(imp->ippm_lock);
3431 rw_exit(ipp_mod_byid_lock);
3433 #undef __FN__
3435 #define __FN__ "action_constructor"
3436 /*ARGSUSED*/
3437 static int
3438 action_constructor(
3439 void *buf,
3440 void *cdrarg,
3441 int kmflags)
3443 ipp_action_t *ap;
3444 ipp_action_id_t aid;
3446 ASSERT(buf != NULL);
3447 bzero(buf, sizeof (ipp_action_t));
3448 ap = (ipp_action_t *)buf;
3450 rw_enter(ipp_action_byid_lock, RW_WRITER);
3453 * Get a new action id.
3456 if ((aid = get_aid()) <= IPP_ACTION_RESERVED) {
3457 rw_exit(ipp_action_byid_lock);
3458 return (-1);
3462 * Initialize the buffer as an action structure in PROTO form.
3465 ap->ippa_state = IPP_ASTATE_PROTO;
3466 ap->ippa_destruct_pending = B_TRUE;
3467 rw_init(ap->ippa_lock, NULL, RW_DEFAULT,
3468 (void *)ipltospl(LOCK_LEVEL));
3469 CONFIG_LOCK_INIT(ap->ippa_config_lock);
3472 * Insert it into the array of all action structures.
3475 ap->ippa_id = aid;
3476 ipp_action_byid[aid] = ap;
3478 rw_exit(ipp_action_byid_lock);
3479 return (0);
3481 #undef __FN__
3483 #define __FN__ "action_destructor"
3484 /*ARGSUSED*/
3485 static void
3486 action_destructor(
3487 void *buf,
3488 void *cdrarg)
3490 ipp_action_t *ap;
3492 ASSERT(buf != NULL);
3493 ap = (ipp_action_t *)buf;
3495 ASSERT(ap->ippa_state == IPP_ASTATE_PROTO);
3496 ASSERT(ap->ippa_ref == NULL);
3497 ASSERT(ap->ippa_refby == NULL);
3498 ASSERT(ap->ippa_packets == 0);
3499 ASSERT(*ap->ippa_name == '\0');
3500 ASSERT(ap->ippa_destruct_pending);
3502 rw_enter(ipp_action_byid_lock, RW_WRITER);
3503 ASSERT(ap->ippa_hold_count == 0);
3506 * NULL the entry in the array of all action structures.
3509 ipp_action_byid[ap->ippa_id] = NULL;
3512 * Clean up any remnants of the action structure as the buffer is
3513 * about to disappear.
3516 CONFIG_LOCK_FINI(ap->ippa_config_lock);
3517 rw_destroy(ap->ippa_lock);
3519 rw_exit(ipp_action_byid_lock);
3521 #undef __FN__
3523 #define __FN__ "packet_constructor"
3524 /*ARGSUSED*/
3525 static int
3526 packet_constructor(
3527 void *buf,
3528 void *cdrarg,
3529 int kmflags)
3531 ipp_packet_t *pp;
3532 ipp_class_t *cp;
3534 ASSERT(buf != NULL);
3535 bzero(buf, sizeof (ipp_packet_t));
3536 pp = (ipp_packet_t *)buf;
3538 if ((cp = kmem_alloc(ipp_packet_classes * sizeof (ipp_class_t),
3539 KM_NOSLEEP)) == NULL)
3540 return (ENOMEM);
3542 pp->ippp_class_array = cp;
3543 pp->ippp_class_windex = 0;
3544 pp->ippp_class_rindex = 0;
3545 pp->ippp_class_limit = ipp_packet_classes - 1;
3547 return (0);
3549 #undef __FN__
3551 #define __FN__ "packet_destructor"
3552 /*ARGSUSED*/
3553 static void
3554 packet_destructor(
3555 void *buf,
3556 void *cdrarg)
3558 ipp_packet_t *pp;
3560 ASSERT(buf != NULL);
3561 pp = (ipp_packet_t *)buf;
3563 ASSERT(pp->ippp_data == NULL);
3564 ASSERT(pp->ippp_class_windex == 0);
3565 ASSERT(pp->ippp_class_rindex == 0);
3566 ASSERT(pp->ippp_private == NULL);
3567 ASSERT(pp->ippp_private_free == NULL);
3569 kmem_free(pp->ippp_class_array,
3570 (pp->ippp_class_limit + 1) * sizeof (ipp_class_t));
3572 if (pp->ippp_log != NULL) {
3573 kmem_free(pp->ippp_log,
3574 (pp->ippp_log_limit + 1) * sizeof (ipp_log_t));
3577 #undef __FN__
3580 * Debug message printout code.
3583 #ifdef IPP_DBG
3584 static void
3585 ipp_debug(
3586 uint64_t type,
3587 const char *fn,
3588 char *fmt,
3589 ...)
3591 char buf[255];
3592 va_list adx;
3594 if ((type & ipp_debug_flags) == 0)
3595 return;
3597 mutex_enter(debug_mutex);
3598 va_start(adx, fmt);
3599 (void) vsnprintf(buf, 255, fmt, adx);
3600 va_end(adx);
3602 printf("(%llx) %s: %s", (unsigned long long)curthread->t_did, fn,
3603 buf);
3604 mutex_exit(debug_mutex);
3606 #endif /* IPP_DBG */