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]
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>
31 #include <sys/cmn_err.h>
33 #include <sys/sunddi.h>
36 #include <sys/varargs.h>
38 #include <ipp/ipp_impl.h>
39 #include <ipp/ipgpc/ipgpc.h>
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
;
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
**,
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
**,
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
,
116 int ipp_action_unref(ipp_action_id_t
, ipp_action_id_t
,
119 int ipp_packet_alloc(ipp_packet_t
**, const char *,
121 void ipp_packet_free(ipp_packet_t
*);
122 int ipp_packet_add_class(ipp_packet_t
*, const char *,
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 *,
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
,
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
,
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
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
=
203 static kmutex_t debug_mutex
[1];
206 static void ipp_debug(uint64_t, const char *, char *, ...)
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), \
222 #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) \
223 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
226 #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) \
227 ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
228 (_a3), (_a4), (_a5));
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)
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)
271 #define __FN__ "ipp_init"
277 mutex_init(debug_mutex
, NULL
, MUTEX_ADAPTIVE
,
278 (void *)ipltospl(LOCK_LEVEL
));
282 * Initialize module and action structure caches and associated locks.
291 #define __FN__ "ipp_list_mods"
297 ASSERT(bufp
!= NULL
);
298 ASSERT(neltp
!= NULL
);
300 return (get_mods(bufp
, neltp
));
305 * Module manipulation interface.
308 #define __FN__ "ipp_mod_lookup"
315 int try = FIRST_TIME
;
318 * Sanity check the module name.
321 if (modname
== NULL
|| strlen(modname
) > MAXNAMELEN
- 1)
322 return (IPP_MOD_INVAL
);
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
);
350 #define __FN__ "ipp_mod_name"
360 ASSERT(modnamep
!= NULL
);
363 * Translate the module id into the module pointer.
366 if ((imp
= hold_mod(mid
)) == NULL
)
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
) {
383 * Copy the module name into the buffer.
386 (void) strcpy(buf
, modname
);
396 #define __FN__ "ipp_mod_register"
406 ASSERT(ipp_ops
!= NULL
);
409 * Sanity check the module name.
412 if (modname
== NULL
|| strlen(modname
) > MAXNAMELEN
- 1)
416 * Allocate a module structure.
419 if ((rc
= alloc_mod(modname
, &mid
)) != 0)
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
;
440 #define __FN__ "ipp_mod_unregister"
448 * Translate the module id into the module pointer.
451 if ((imp
= hold_mod(mid
)) == NULL
)
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
)) {
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
;
477 * Free the module structure.
487 #define __FN__ "ipp_mod_list_actions"
489 ipp_mod_list_actions(
491 ipp_action_id_t
**bufp
,
497 ASSERT(bufp
!= NULL
);
498 ASSERT(neltp
!= NULL
);
501 * Translate the module id into the module pointer.
504 if ((imp
= hold_mod(mid
)) == NULL
)
508 * Get the list of actions referencing the module.
511 LOCK_MOD(imp
, RW_READER
);
512 rc
= get_mod_ref(imp
, bufp
, neltp
);
521 * Action manipulation interface.
524 #define __FN__ "ipp_action_lookup"
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
));
551 #define __FN__ "ipp_action_name"
562 ASSERT(anamep
!= NULL
);
565 * Check for special case 'virtual action' ids.
569 case IPP_ACTION_CONT
:
571 aname
= IPP_ANAME_CONT
;
573 case IPP_ACTION_DEFER
:
575 aname
= IPP_ANAME_DEFER
;
577 case IPP_ACTION_DROP
:
579 aname
= IPP_ANAME_DROP
;
584 * Not a special case. Check for a real action.
587 if ((ap
= hold_action(aid
)) == NULL
)
590 LOCK_ACTION(ap
, RW_READER
);
591 aname
= ap
->ippa_name
;
596 * Allocate a buffer to pass back to the caller.
599 if ((buf
= kmem_zalloc(strlen(aname
) + 1, KM_NOSLEEP
)) == NULL
) {
605 * Copy the action name into the buffer.
608 (void) strcpy(buf
, aname
);
613 * Unlock the action if necessary (i.e. it wasn't a virtual action).
625 #define __FN__ "ipp_action_mod"
634 ASSERT(midp
!= NULL
);
637 * Return an error for 'virtual action' ids.
641 case IPP_ACTION_CONT
:
643 case IPP_ACTION_DEFER
:
645 case IPP_ACTION_DROP
:
652 * This is a real action.
655 if ((ap
= hold_action(aid
)) == NULL
)
659 * Check that the action is not in prototype state.
662 LOCK_ACTION(ap
, RW_READER
);
663 if (ap
->ippa_state
== IPP_ASTATE_PROTO
) {
673 *midp
= imp
->ippm_id
;
680 #define __FN__ "ipp_action_create"
687 ipp_action_id_t
*aidp
)
695 ASSERT(nvlpp
!= NULL
);
696 ASSERT(*nvlpp
!= NULL
);
699 * Sanity check the action name (NULL means the framework chooses the
703 if (aname
!= NULL
&& strlen(aname
) > MAXNAMELEN
- 1)
707 * Translate the module id into the module pointer.
710 if ((imp
= hold_mod(mid
)) == NULL
)
714 * Allocate an action.
717 if ((rc
= alloc_action(aname
, &aid
)) != 0) {
722 ap
= hold_action(aid
);
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) {
739 ap
->ippa_state
= IPP_ASTATE_PROTO
;
750 ippo
= imp
->ippm_ops
;
751 ASSERT(ippo
!= NULL
);
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
);
766 ap
->ippa_state
= IPP_ASTATE_PROTO
;
769 CONFIG_WRITE_END(ap
);
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
;
794 #define __FN__ "ipp_action_destroy"
800 ipp_ref_t
*rp
= NULL
;
806 * Translate the action id into the action pointer.
809 if ((ap
= hold_action(aid
)) == NULL
)
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
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
);
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
;
843 * Clean up the condemned list.
849 kmem_free(tmp
, sizeof (ipp_ref_t
));
856 #define __FN__ "ipp_action_modify"
868 ASSERT(nvlpp
!= NULL
);
869 ASSERT(*nvlpp
!= NULL
);
872 * Translate the action id into the action pointer.
875 if ((ap
= hold_action(aid
)) == NULL
)
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
) {
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
);
915 #define __FN__ "ipp_action_info"
919 int (*fn
)(nvlist_t
*, void *),
929 * Translate the action id into the action pointer.
932 if ((ap
= hold_action(aid
)) == NULL
)
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
) {
952 ippo
= imp
->ippm_ops
;
953 ASSERT(ippo
!= NULL
);
956 * Call into the module to get the action configuration information.
960 "getting configuration information from action '%s'\n",
962 CONFIG_READ_START(ap
);
963 if ((rc
= ippo
->ippo_action_info(aid
, fn
, arg
, flags
)) != 0) {
975 #define __FN__ "ipp_action_set_ptr"
984 * Translate the action id into the action pointer.
987 ap
= hold_action(aid
);
991 * Set the private data pointer.
999 #define __FN__ "ipp_action_get_ptr"
1002 ipp_action_id_t aid
)
1008 * Translate the action id into the action pointer.
1011 ap
= hold_action(aid
);
1015 * Return the private data pointer.
1025 #define __FN__ "ipp_action_ref"
1029 ipp_action_id_t aid
,
1030 ipp_action_id_t ref_aid
,
1034 ipp_action_t
*ref_ap
;
1038 * Actions are not allowed to reference themselves.
1045 * Check for a special case 'virtual action' id.
1049 case IPP_ACTION_CONT
:
1051 case IPP_ACTION_DEFER
:
1053 case IPP_ACTION_DROP
:
1060 * Translate the action ids into action pointers.
1063 if ((ap
= hold_action(aid
)) == NULL
)
1066 if ((ref_ap
= hold_action(ref_aid
)) == NULL
) {
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
);
1078 rele_action(ref_ap
);
1084 * Create references between the two actions.
1087 rc
= ref_action(ap
, ref_ap
);
1088 UNLOCK_ACTION(ref_ap
);
1091 rele_action(ref_ap
);
1097 #define __FN__ "ipp_action_unref"
1100 ipp_action_id_t aid
,
1101 ipp_action_id_t ref_aid
,
1105 ipp_action_t
*ref_ap
;
1113 * Check for a special case 'virtual action' id.
1117 case IPP_ACTION_CONT
:
1119 case IPP_ACTION_DEFER
:
1121 case IPP_ACTION_DROP
:
1128 * Translate the action ids into action pointers.
1131 if ((ap
= hold_action(aid
)) == NULL
)
1134 if ((ref_ap
= hold_action(ref_aid
)) == NULL
) {
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
);
1149 rele_action(ref_ap
);
1154 ref_is_busy
= is_action_refd(ref_ap
);
1156 UNLOCK_ACTION(ref_ap
);
1159 if (flags
& IPP_DESTROY_REF
) {
1163 * Condemn the action so that it will be destroyed.
1166 (void) condemn_action(ap
->ippa_condemned
, ref_ap
);
1171 rele_action(ref_ap
);
1178 * Packet manipulation interface.
1181 #define __FN__ "ipp_packet_alloc"
1186 ipp_action_id_t aid
)
1191 ASSERT(ppp
!= NULL
);
1194 * A name is required.
1197 if (name
== NULL
|| strlen(name
) > MAXNAMELEN
- 1)
1201 * Allocate a packet structure from the cache.
1204 if ((rc
= alloc_packet(name
, aid
, &pp
)) != 0)
1207 if (ipp_packet_logging
!= 0 && pp
->ippp_log
== NULL
) {
1210 * Logging is turned on but there's no log buffer. We need
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;
1238 #define __FN__ "ipp_packet_free"
1247 * If there is a private structure pointer set, call its free
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.
1265 #define __FN__ "ipp_packet_add_class"
1267 ipp_packet_add_class(
1270 ipp_action_id_t aid
)
1278 * A name is required.
1281 if (name
== NULL
|| strlen(name
) > MAXNAMELEN
- 1)
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)
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
);
1311 #define __FN__ "ipp_packet_process"
1317 ipp_action_id_t aid
;
1325 ASSERT(ppp
!= 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...
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
) {
1353 "action id '%d' not found\n", aid
);
1358 * Check that the action is available for use...
1360 LOCK_ACTION(ap
, RW_READER
);
1361 if (ap
->ippa_state
!= IPP_ASTATE_AVAILABLE
) {
1368 * Increment the action's packet count to note that
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
));
1382 ASSERT(imp
!= NULL
);
1385 ippo
= imp
->ippm_ops
;
1386 ASSERT(ippo
!= NULL
);
1389 * If there's a log, grab the next entry and fill it
1393 if (pp
->ippp_log
!= NULL
&&
1394 pp
->ippp_log_windex
<= pp
->ippp_log_limit
) {
1395 lp
= &(pp
->ippp_log
[pp
->ippp_log_windex
++]);
1397 (void) strcpy(lp
->ippl_name
, cp
->ippc_name
);
1398 gethrestime(&lp
->ippl_begin
);
1404 * Invoke the action.
1407 rc
= ippo
->ippo_action_invoke(aid
, pp
);
1410 * Also log the time that the action finished
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
) {
1431 "action '%s' did not set next action\n",
1438 * The action did not complete successfully. Terminate
1439 * packet processing.
1444 "action error '%d' from action '%s'\n",
1453 * Look at the next action.
1460 * No more real actions to invoke, check for 'virtual' ones.
1464 * Packet deferred: module has held onto packet for processing
1468 if (cp
->ippc_aid
== IPP_ACTION_DEFER
) {
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
);
1485 * Must be 'continue processing': move onto the next class.
1488 ASSERT(cp
->ippc_aid
== IPP_ACTION_CONT
);
1489 pp
->ippp_class_rindex
++;
1496 #define __FN__ "ipp_packet_next"
1500 ipp_action_id_t aid
)
1507 cp
= &(pp
->ippp_class_array
[pp
->ippp_class_rindex
]);
1511 * Check for a special case 'virtual action' id.
1515 case IPP_ACTION_INVAL
:
1517 case IPP_ACTION_DEFER
:
1519 case IPP_ACTION_CONT
:
1521 case IPP_ACTION_DROP
:
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");
1540 * Set the class' new action id.
1549 #define __FN__ "ipp_packet_set_data"
1551 ipp_packet_set_data(
1556 pp
->ippp_data
= data
;
1560 #define __FN__ "ipp_packet_get_data"
1562 ipp_packet_get_data(
1566 return (pp
->ippp_data
);
1570 #define __FN__ "ipp_packet_set_private"
1572 ipp_packet_set_private(
1575 void (*free_func
)(void *))
1578 ASSERT(free_func
!= NULL
);
1580 pp
->ippp_private
= buf
;
1581 pp
->ippp_private_free
= free_func
;
1585 #define __FN__ "ipp_packet_get_private"
1587 ipp_packet_get_private(
1591 return (pp
->ippp_private
);
1596 * Statistics interface.
1599 #define __FN__ "ipp_stat_create"
1602 ipp_action_id_t aid
,
1605 int (*update
)(ipp_stat_t
*, void *, int),
1611 ipp_stat_impl_t
*sip
;
1618 ASSERT(spp
!= NULL
);
1621 * Sanity check the arguments.
1624 if (name
== NULL
|| nstat
<= 0 || update
== NULL
)
1628 * Translate the action id into the action pointer.
1631 if ((ap
= hold_action(aid
)) == NULL
)
1635 * Grab relevant action and module information.
1638 LOCK_ACTION(ap
, RW_READER
);
1639 class = ap
->ippa_name
;
1640 instance
= (int)ap
->ippa_id
;
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
)
1656 * Create a set of kstats.
1659 DBG2(DBG_STATS
, "creating stat set '%s' for action '%s'\n",
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
));
1666 return (EINVAL
); /* Assume EINVAL was the cause */
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
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
);
1716 #define __FN__ "ipp_stat_install"
1721 ipp_stat_impl_t
*sip
= (ipp_stat_impl_t
*)sp
;
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
);
1734 #define __FN__ "ipp_stat_destroy"
1739 ipp_stat_impl_t
*sip
= (ipp_stat_impl_t
*)sp
;
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
));
1759 #define __FN__ "ipp_stat_named_init"
1761 ipp_stat_named_init(
1767 ipp_stat_impl_t
*sip
= (ipp_stat_impl_t
*)sp
;
1776 if ((type
& IPP_STAT_TAG
) == 0)
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
);
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
);
1809 #define __FN__ "ipp_stat_named_op"
1821 ASSERT(valp
!= NULL
);
1824 type
= knp
->data_type
| IPP_STAT_TAG
;
1827 * Copy data to or from the named kstat, depending on the specified
1832 case IPP_STAT_WRITE
:
1834 case IPP_STAT_INT32
:
1835 *(int32_t *)valp
= knp
->value
.i32
;
1837 case IPP_STAT_UINT32
:
1838 *(uint32_t *)valp
= knp
->value
.ui32
;
1840 case IPP_STAT_INT64
:
1841 *(int64_t *)valp
= knp
->value
.i64
;
1843 case IPP_STAT_UINT64
:
1844 *(uint64_t *)valp
= knp
->value
.ui64
;
1846 case IPP_STAT_STRING
:
1847 (void) strncpy(valp
, knp
->value
.c
, 16);
1850 ASSERT(0); /* should not reach here */
1857 case IPP_STAT_INT32
:
1858 knp
->value
.i32
= *(int32_t *)valp
;
1860 case IPP_STAT_UINT32
:
1861 knp
->value
.ui32
= *(uint32_t *)valp
;
1863 case IPP_STAT_INT64
:
1864 knp
->value
.i64
= *(int64_t *)valp
;
1866 case IPP_STAT_UINT64
:
1867 knp
->value
.ui64
= *(uint64_t *)valp
;
1869 case IPP_STAT_STRING
:
1870 (void) strncpy(knp
->value
.c
, valp
, 16);
1873 ASSERT(0); /* should not reach here */
1887 * Local functions (for local people. There's nothing for you here!)
1890 #define __FN__ "ref_mod"
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
)
1920 * Set the reference to the action and link it onto the module's list.
1923 rp
->ippr_action
= ap
;
1927 * Keep a 'back pointer' from the action structure to the module
1937 #define __FN__ "unref_mod"
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
)
1957 rpp
= &(rp
->ippr_nextp
);
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
;
1976 #define __FN__ "is_mod_busy"
1982 * Return a value which is true (non-zero) iff the module refers
1986 return (imp
->ippm_action
!= NULL
);
1990 #define __FN__ "get_mod_ref"
1994 ipp_action_id_t
**bufp
,
2000 ipp_action_id_t
*buf
;
2003 ASSERT(rw_lock_held(imp
->ippm_lock
));
2006 * Count the number of actions referred to from the module structure.
2010 for (rp
= imp
->ippm_action
; rp
!= NULL
; rp
= rp
->ippr_nextp
) {
2013 DBG1(DBG_LIST
, "%d actions found\n", nelt
);
2016 * If there are no actions referred to then there's nothing to do.
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
)
2034 * Fill the buffer with an array of action ids.
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
);
2050 #define __FN__ "get_mods"
2053 ipp_mod_id_t
**bufp
,
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");
2072 rw_exit(ipp_mod_byname_lock
);
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
);
2087 rw_enter(ipp_mod_byid_lock
, RW_READER
);
2090 * Search the array of all modules.
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
)
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
) {
2118 rw_exit(ipp_mod_byid_lock
);
2119 rw_exit(ipp_mod_byname_lock
);
2121 ASSERT((uintptr_t)buf
== (uintptr_t)*bufp
+ length
);
2126 #define __FN__ "find_mod"
2129 const char *modname
)
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.
2154 rp
= ipp_mod_byname
[hb
];
2157 * Scan the bucket for a match.
2160 while (rp
!= NULL
) {
2162 if (strcmp(imp
->ippm_name
, modname
) == 0)
2164 rp
= rp
->ippr_nextp
;
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
);
2178 rw_exit(ipp_mod_byname_lock
);
2184 #define __FN__ "alloc_mod"
2187 const char *modname
,
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.
2205 rpp
= &ipp_mod_byname
[hb
];
2208 * Scan the bucket making sure the module isn't already
2212 while ((rp
= *rpp
) != NULL
) {
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
);
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
);
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
);
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
;
2253 * Set the reference and link it into the hash bucket.
2260 * Increment the module count.
2265 *midp
= imp
->ippm_id
;
2266 rw_exit(ipp_mod_byname_lock
);
2271 #define __FN__ "free_mod"
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
)
2296 rpp
= &(rp
->ippr_nextp
);
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.
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) {
2328 kmem_cache_free(ipp_mod_cache
, imp
);
2329 rw_exit(ipp_mod_byname_lock
);
2334 rw_exit(ipp_mod_byname_lock
);
2338 #define __FN__ "hold_mod"
2349 * Use the module id as an index into the array of all module
2353 rw_enter(ipp_mod_byid_lock
, RW_READER
);
2354 if ((imp
= ipp_mod_byid
[mid
]) == NULL
) {
2355 rw_exit(ipp_mod_byid_lock
);
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
) {
2370 rw_exit(ipp_mod_byid_lock
);
2376 * Increment the hold count to prevent the structure from being
2380 atomic_inc_32(&(imp
->ippm_hold_count
));
2381 rw_exit(ipp_mod_byid_lock
);
2387 #define __FN__ "rele_mod"
2393 * This call means we're done with the pointer so we can drop the
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) {
2408 kmem_cache_free(ipp_mod_cache
, imp
);
2416 #define __FN__ "get_mid"
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.
2439 while (ipp_mod_byid
[index
] != NULL
) {
2442 index
= IPP_MOD_RESERVED
+ 1;
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.
2453 if (index
> limit
) {
2454 ipp_next_mid
= IPP_MOD_RESERVED
+ 1;
2456 ipp_next_mid
= (ipp_mod_id_t
)index
;
2458 return ((ipp_mod_id_t
)(--index
));
2462 #define __FN__ "condemn_action"
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
)
2479 rpp
= &(rp
->ippr_nextp
);
2483 * Create a new entry for the action.
2487 if ((rp
= kmem_zalloc(sizeof (ipp_ref_t
), KM_NOSLEEP
)) == NULL
)
2490 rp
->ippr_action
= ap
;
2498 #define __FN__ "destroy_action"
2511 * Check that the action is available.
2514 LOCK_ACTION(ap
, RW_WRITER
);
2515 if (ap
->ippa_state
!= IPP_ASTATE_AVAILABLE
) {
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);
2539 * NOTE: We can hang onto the lock because the packet count is
2540 * decremented without needing to take the lock.
2547 * The packet count did not fall to zero.
2549 if (ap
->ippa_packets
> 0) {
2550 ap
->ippa_state
= IPP_ASTATE_AVAILABLE
;
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
;
2568 ASSERT(imp
!= NULL
);
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
;
2585 CONFIG_WRITE_END(ap
);
2590 CONFIG_WRITE_END(ap
);
2592 LOCK_ACTION(ap
, RW_WRITER
);
2593 LOCK_MOD(imp
, RW_WRITER
);
2596 ap
->ippa_state
= IPP_ASTATE_PROTO
;
2600 * Free the action structure.
2603 ASSERT(ap
->ippa_ref
== NULL
);
2611 #define __FN__ "ref_action"
2614 ipp_action_t
*refby_ap
,
2615 ipp_action_t
*ref_ap
)
2618 ipp_ref_t
**save_rpp
;
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
2629 rpp
= &(refby_ap
->ippa_ref
);
2630 while ((rp
= *rpp
) != NULL
) {
2631 if (rp
->ippr_action
== ref_ap
)
2633 rpp
= &(rp
->ippr_nextp
);
2636 if ((rp
= *rpp
) != NULL
) {
2639 * There is an existing reference so increment its counter.
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
)
2652 rp
= rp
->ippr_nextp
;
2660 * Allocate, fill in and link a new reference structure.
2663 if ((rp
= kmem_zalloc(sizeof (ipp_ref_t
), KM_NOSLEEP
)) == NULL
)
2666 rp
->ippr_action
= ref_ap
;
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
2688 if ((rp
= kmem_zalloc(sizeof (ipp_ref_t
),
2689 KM_NOSLEEP
)) == NULL
) {
2693 kmem_free(rp
, sizeof (ipp_ref_t
));
2699 * Fill in the reference structure with the 'back pointer' and
2700 * link it into the list.
2703 rp
->ippr_action
= refby_ap
;
2712 #define __FN__ "unref_action"
2715 ipp_action_t
*refby_ap
,
2716 ipp_action_t
*ref_ap
)
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
)
2732 rpp
= &(rp
->ippr_nextp
);
2738 if (rp
->ippr_count
> 1) {
2741 * There are currently multiple references so decrement the
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
)
2755 rp
= rp
->ippr_nextp
;
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
)
2778 rpp
= &(rp
->ippr_nextp
);
2783 * Unlink and free this reference structure too.
2786 *rpp
= rp
->ippr_nextp
;
2787 kmem_free(rp
, sizeof (ipp_ref_t
));
2794 #define __FN__ "is_action_refd"
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
);
2808 #define __FN__ "find_action"
2809 static ipp_action_id_t
2813 ipp_action_id_t aid
;
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.
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)
2846 rp
= rp
->ippr_nextp
;
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
);
2860 rw_exit(ipp_action_byname_lock
);
2866 #define __FN__ "alloc_action"
2870 ipp_action_id_t
*aidp
)
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
) {
2888 rpp
= &ipp_action_byname
[hb
];
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",
2902 rw_exit(ipp_action_byname_lock
);
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
);
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
);
2924 * Dream up a name if there isn't a real one and note that the action is
2928 if (aname
== NULL
) {
2929 (void) sprintf(ap
->ippa_name
, "$%08X", ap
->ippa_id
);
2930 ap
->ippa_nameless
= B_TRUE
;
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
;
2944 * Fill in the reference structure and lint it onto the list.
2947 rp
->ippr_action
= ap
;
2951 * Increment the action count.
2956 *aidp
= ap
->ippa_id
;
2957 rw_exit(ipp_action_byname_lock
);
2962 #define __FN__ "free_action"
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
];
2981 rpp
= &ipp_action_noname
;
2984 * Scan the bucket for a match.
2987 while ((rp
= *rpp
) != NULL
) {
2988 if (rp
->ippr_action
== ap
)
2990 rpp
= &(rp
->ippr_nextp
);
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.
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) {
3022 kmem_cache_free(ipp_action_cache
, ap
);
3023 rw_exit(ipp_action_byname_lock
);
3028 rw_exit(ipp_action_byname_lock
);
3032 #define __FN__ "hold_action"
3033 static ipp_action_t
*
3035 ipp_action_id_t aid
)
3043 * Use the action id as an index into the array of all action
3047 rw_enter(ipp_action_byid_lock
, RW_READER
);
3048 if ((ap
= ipp_action_byid
[aid
]) == NULL
) {
3049 rw_exit(ipp_action_byid_lock
);
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
) {
3062 rw_exit(ipp_action_byid_lock
);
3068 * Increment the hold count to prevent the structure from being
3072 atomic_inc_32(&(ap
->ippa_hold_count
));
3073 rw_exit(ipp_action_byid_lock
);
3079 #define __FN__ "rele_action"
3085 * This call means we're done with the pointer so we can drop the
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) {
3100 kmem_cache_free(ipp_action_cache
, ap
);
3107 #define __FN__ "get_aid"
3108 static ipp_action_id_t
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.
3130 while (ipp_action_byid
[index
] != NULL
) {
3133 index
= IPP_ACTION_RESERVED
+ 1;
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.
3145 ipp_next_aid
= IPP_ACTION_RESERVED
+ 1;
3147 ipp_next_aid
= (ipp_action_id_t
)index
;
3149 return ((ipp_action_id_t
)(--index
));
3153 #define __FN__ "alloc_packet"
3157 ipp_action_id_t aid
,
3163 if ((pp
= kmem_cache_alloc(ipp_packet_cache
, KM_NOSLEEP
)) == NULL
)
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
);
3181 #define __FN__ "realloc_packet"
3189 length
= (pp
->ippp_class_limit
+ 1) << 1;
3190 if ((array
= kmem_alloc(length
* sizeof (ipp_class_t
),
3191 KM_NOSLEEP
)) == NULL
)
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;
3207 #define __FN__ "free_packet"
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
);
3222 #define __FN__ "hash"
3231 * Make a hash value by XORing all the ascii codes in the text string.
3234 for (ptr
= (char *)name
; *ptr
!= '\0'; ptr
++) {
3239 * Return the value modulo the number of hash buckets we allow.
3242 return (val
% IPP_NBUCKET
);
3246 #define __FN__ "update_stats"
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
3262 return (sip
->ippsi_update((ipp_stat_t
*)sip
, sip
->ippsi_arg
, rw
));
3266 #define __FN__ "init_mods"
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),
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
*));
3297 #define __FN__ "init_actions"
3303 * Initialise the array of all action structures and the action
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
;
3331 #define __FN__ "init_packets"
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
);
3348 * Kmem cache constructor/destructor functions.
3351 #define __FN__ "mod_constructor"
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
);
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.
3391 ipp_mod_byid
[mid
] = imp
;
3393 rw_exit(ipp_mod_byid_lock
);
3399 #define __FN__ "mod_destructor"
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
);
3435 #define __FN__ "action_constructor"
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
);
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.
3476 ipp_action_byid
[aid
] = ap
;
3478 rw_exit(ipp_action_byid_lock
);
3483 #define __FN__ "action_destructor"
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
);
3523 #define __FN__ "packet_constructor"
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
)
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;
3551 #define __FN__ "packet_destructor"
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
));
3580 * Debug message printout code.
3594 if ((type
& ipp_debug_flags
) == 0)
3597 mutex_enter(debug_mutex
);
3599 (void) vsnprintf(buf
, 255, fmt
, adx
);
3602 printf("(%llx) %s: %s", (unsigned long long)curthread
->t_did
, fn
,
3604 mutex_exit(debug_mutex
);
3606 #endif /* IPP_DBG */