17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5d624471bSelowe * Common Development and Distribution License (the "License").
6d624471bSelowe * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22d624471bSelowe * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/param.h>
287c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
297c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
307c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
317c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
327c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
337c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
347c478bd9Sstevel@tonic-gate #include <sys/spl.h>
357c478bd9Sstevel@tonic-gate #include <sys/time.h>
367c478bd9Sstevel@tonic-gate #include <sys/varargs.h>
377c478bd9Sstevel@tonic-gate #include <ipp/ipp.h>
387c478bd9Sstevel@tonic-gate #include <ipp/ipp_impl.h>
397c478bd9Sstevel@tonic-gate #include <ipp/ipgpc/ipgpc.h>
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate * Debug switch.
437c478bd9Sstevel@tonic-gate */
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate #if defined(DEBUG)
467c478bd9Sstevel@tonic-gate #define IPP_DBG
477c478bd9Sstevel@tonic-gate #endif
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate * Globals
517c478bd9Sstevel@tonic-gate */
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate /*
547c478bd9Sstevel@tonic-gate * ipp_action_count is not static because it is imported by inet/ipp_common.h
557c478bd9Sstevel@tonic-gate */
567c478bd9Sstevel@tonic-gate uint32_t ipp_action_count = 0;
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate static kmem_cache_t *ipp_mod_cache = NULL;
597c478bd9Sstevel@tonic-gate static uint32_t ipp_mod_count = 0;
607c478bd9Sstevel@tonic-gate static uint32_t ipp_max_mod = IPP_NMOD;
617c478bd9Sstevel@tonic-gate static ipp_mod_t **ipp_mod_byid;
627c478bd9Sstevel@tonic-gate static krwlock_t ipp_mod_byid_lock[1];
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate static ipp_mod_id_t ipp_next_mid = IPP_MOD_RESERVED + 1;
657c478bd9Sstevel@tonic-gate static ipp_mod_id_t ipp_mid_limit;
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate static ipp_ref_t *ipp_mod_byname[IPP_NBUCKET];
687c478bd9Sstevel@tonic-gate static krwlock_t ipp_mod_byname_lock[1];
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate static kmem_cache_t *ipp_action_cache = NULL;
717c478bd9Sstevel@tonic-gate static uint32_t ipp_max_action = IPP_NACTION;
727c478bd9Sstevel@tonic-gate static ipp_action_t **ipp_action_byid;
737c478bd9Sstevel@tonic-gate static krwlock_t ipp_action_byid_lock[1];
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate static ipp_action_id_t ipp_next_aid = IPP_ACTION_RESERVED + 1;
767c478bd9Sstevel@tonic-gate static ipp_action_id_t ipp_aid_limit;
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate static ipp_ref_t *ipp_action_byname[IPP_NBUCKET];
797c478bd9Sstevel@tonic-gate static krwlock_t ipp_action_byname_lock[1];
807c478bd9Sstevel@tonic-gate static ipp_ref_t *ipp_action_noname;
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate static kmem_cache_t *ipp_packet_cache = NULL;
837c478bd9Sstevel@tonic-gate static uint_t ipp_packet_classes = IPP_NCLASS;
847c478bd9Sstevel@tonic-gate static uint_t ipp_packet_logging = 0;
857c478bd9Sstevel@tonic-gate static uint_t ipp_packet_log_entries = IPP_NLOG;
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate /*
887c478bd9Sstevel@tonic-gate * Prototypes
897c478bd9Sstevel@tonic-gate */
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate void ipp_init(void);
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate int ipp_list_mods(ipp_mod_id_t **, int *);
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate ipp_mod_id_t ipp_mod_lookup(const char *);
967c478bd9Sstevel@tonic-gate int ipp_mod_name(ipp_mod_id_t, char **);
977c478bd9Sstevel@tonic-gate int ipp_mod_register(const char *, ipp_ops_t *);
987c478bd9Sstevel@tonic-gate int ipp_mod_unregister(ipp_mod_id_t);
997c478bd9Sstevel@tonic-gate int ipp_mod_list_actions(ipp_mod_id_t, ipp_action_id_t **,
1007c478bd9Sstevel@tonic-gate int *);
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate ipp_action_id_t ipp_action_lookup(const char *);
1037c478bd9Sstevel@tonic-gate int ipp_action_name(ipp_action_id_t, char **);
1047c478bd9Sstevel@tonic-gate int ipp_action_mod(ipp_action_id_t, ipp_mod_id_t *);
1057c478bd9Sstevel@tonic-gate int ipp_action_create(ipp_mod_id_t, const char *,
1067c478bd9Sstevel@tonic-gate nvlist_t **, ipp_flags_t, ipp_action_id_t *);
1077c478bd9Sstevel@tonic-gate int ipp_action_modify(ipp_action_id_t, nvlist_t **,
1087c478bd9Sstevel@tonic-gate ipp_flags_t);
1097c478bd9Sstevel@tonic-gate int ipp_action_destroy(ipp_action_id_t, ipp_flags_t);
1107c478bd9Sstevel@tonic-gate int ipp_action_info(ipp_action_id_t, int (*)(nvlist_t *,
1117c478bd9Sstevel@tonic-gate void *), void *, ipp_flags_t);
1127c478bd9Sstevel@tonic-gate void ipp_action_set_ptr(ipp_action_id_t, void *);
1137c478bd9Sstevel@tonic-gate void *ipp_action_get_ptr(ipp_action_id_t);
1147c478bd9Sstevel@tonic-gate int ipp_action_ref(ipp_action_id_t, ipp_action_id_t,
1157c478bd9Sstevel@tonic-gate ipp_flags_t);
1167c478bd9Sstevel@tonic-gate int ipp_action_unref(ipp_action_id_t, ipp_action_id_t,
1177c478bd9Sstevel@tonic-gate ipp_flags_t);
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate int ipp_packet_alloc(ipp_packet_t **, const char *,
1207c478bd9Sstevel@tonic-gate ipp_action_id_t);
1217c478bd9Sstevel@tonic-gate void ipp_packet_free(ipp_packet_t *);
1227c478bd9Sstevel@tonic-gate int ipp_packet_add_class(ipp_packet_t *, const char *,
1237c478bd9Sstevel@tonic-gate ipp_action_id_t);
1247c478bd9Sstevel@tonic-gate int ipp_packet_process(ipp_packet_t **);
1257c478bd9Sstevel@tonic-gate int ipp_packet_next(ipp_packet_t *, ipp_action_id_t);
1267c478bd9Sstevel@tonic-gate void ipp_packet_set_data(ipp_packet_t *, mblk_t *);
1277c478bd9Sstevel@tonic-gate mblk_t *ipp_packet_get_data(ipp_packet_t *);
1287c478bd9Sstevel@tonic-gate void ipp_packet_set_private(ipp_packet_t *, void *,
1297c478bd9Sstevel@tonic-gate void (*)(void *));
1307c478bd9Sstevel@tonic-gate void *ipp_packet_get_private(ipp_packet_t *);
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate int ipp_stat_create(ipp_action_id_t, const char *, int,
1337c478bd9Sstevel@tonic-gate int (*)(ipp_stat_t *, void *, int), void *, ipp_stat_t **);
1347c478bd9Sstevel@tonic-gate void ipp_stat_install(ipp_stat_t *);
1357c478bd9Sstevel@tonic-gate void ipp_stat_destroy(ipp_stat_t *);
1367c478bd9Sstevel@tonic-gate int ipp_stat_named_init(ipp_stat_t *, const char *, uchar_t,
1377c478bd9Sstevel@tonic-gate ipp_named_t *);
1387c478bd9Sstevel@tonic-gate int ipp_stat_named_op(ipp_named_t *, void *, int);
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate static int ref_mod(ipp_action_t *, ipp_mod_t *);
1417c478bd9Sstevel@tonic-gate static void unref_mod(ipp_action_t *, ipp_mod_t *);
1427c478bd9Sstevel@tonic-gate static int is_mod_busy(ipp_mod_t *);
1437c478bd9Sstevel@tonic-gate static int get_mod_ref(ipp_mod_t *, ipp_action_id_t **, int *);
1447c478bd9Sstevel@tonic-gate static int get_mods(ipp_mod_id_t **bufp, int *);
1457c478bd9Sstevel@tonic-gate static ipp_mod_id_t find_mod(const char *);
1467c478bd9Sstevel@tonic-gate static int alloc_mod(const char *, ipp_mod_id_t *);
1477c478bd9Sstevel@tonic-gate static void free_mod(ipp_mod_t *);
1487c478bd9Sstevel@tonic-gate static ipp_mod_t *hold_mod(ipp_mod_id_t);
1497c478bd9Sstevel@tonic-gate static void rele_mod(ipp_mod_t *);
1507c478bd9Sstevel@tonic-gate static ipp_mod_id_t get_mid(void);
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate static int condemn_action(ipp_ref_t **, ipp_action_t *);
1537c478bd9Sstevel@tonic-gate static int destroy_action(ipp_action_t *, ipp_flags_t);
1547c478bd9Sstevel@tonic-gate static int ref_action(ipp_action_t *, ipp_action_t *);
1557c478bd9Sstevel@tonic-gate static int unref_action(ipp_action_t *, ipp_action_t *);
1567c478bd9Sstevel@tonic-gate static int is_action_refd(ipp_action_t *);
1577c478bd9Sstevel@tonic-gate static ipp_action_id_t find_action(const char *);
1587c478bd9Sstevel@tonic-gate static int alloc_action(const char *, ipp_action_id_t *);
1597c478bd9Sstevel@tonic-gate static void free_action(ipp_action_t *);
1607c478bd9Sstevel@tonic-gate static ipp_action_t *hold_action(ipp_action_id_t);
1617c478bd9Sstevel@tonic-gate static void rele_action(ipp_action_t *);
1627c478bd9Sstevel@tonic-gate static ipp_action_id_t get_aid(void);
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate static int alloc_packet(const char *, ipp_action_id_t,
1657c478bd9Sstevel@tonic-gate ipp_packet_t **);
1667c478bd9Sstevel@tonic-gate static int realloc_packet(ipp_packet_t *);
1677c478bd9Sstevel@tonic-gate static void free_packet(ipp_packet_t *);
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate static int hash(const char *);
1707c478bd9Sstevel@tonic-gate static int update_stats(kstat_t *, int);
1717c478bd9Sstevel@tonic-gate static void init_mods(void);
1727c478bd9Sstevel@tonic-gate static void init_actions(void);
1737c478bd9Sstevel@tonic-gate static void init_packets(void);
1747c478bd9Sstevel@tonic-gate static int mod_constructor(void *, void *, int);
1757c478bd9Sstevel@tonic-gate static void mod_destructor(void *, void *);
1767c478bd9Sstevel@tonic-gate static int action_constructor(void *, void *, int);
1777c478bd9Sstevel@tonic-gate static void action_destructor(void *, void *);
1787c478bd9Sstevel@tonic-gate static int packet_constructor(void *, void *, int);
1797c478bd9Sstevel@tonic-gate static void packet_destructor(void *, void *);
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate /*
1827c478bd9Sstevel@tonic-gate * Debug message macros
1837c478bd9Sstevel@tonic-gate */
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate #ifdef IPP_DBG
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate #define DBG_MOD 0x00000001ull
1887c478bd9Sstevel@tonic-gate #define DBG_ACTION 0x00000002ull
1897c478bd9Sstevel@tonic-gate #define DBG_PACKET 0x00000004ull
1907c478bd9Sstevel@tonic-gate #define DBG_STATS 0x00000008ull
1917c478bd9Sstevel@tonic-gate #define DBG_LIST 0x00000010ull
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate static uint64_t ipp_debug_flags =
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate * DBG_PACKET |
1967c478bd9Sstevel@tonic-gate * DBG_STATS |
1977c478bd9Sstevel@tonic-gate * DBG_LIST |
1987c478bd9Sstevel@tonic-gate * DBG_MOD |
1997c478bd9Sstevel@tonic-gate * DBG_ACTION |
2007c478bd9Sstevel@tonic-gate */
2017c478bd9Sstevel@tonic-gate 0;
2027c478bd9Sstevel@tonic-gate
2037c478bd9Sstevel@tonic-gate static kmutex_t debug_mutex[1];
2047c478bd9Sstevel@tonic-gate
2057c478bd9Sstevel@tonic-gate /*PRINTFLIKE3*/
2067c478bd9Sstevel@tonic-gate static void ipp_debug(uint64_t, const char *, char *, ...)
2077c478bd9Sstevel@tonic-gate __KPRINTFLIKE(3);
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate #define DBG0(_type, _fmt) \
2107c478bd9Sstevel@tonic-gate ipp_debug((_type), __FN__, (_fmt));
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate #define DBG1(_type, _fmt, _a1) \
2137c478bd9Sstevel@tonic-gate ipp_debug((_type), __FN__, (_fmt), (_a1));
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate #define DBG2(_type, _fmt, _a1, _a2) \
2167c478bd9Sstevel@tonic-gate ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2));
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate #define DBG3(_type, _fmt, _a1, _a2, _a3) \
2197c478bd9Sstevel@tonic-gate ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
2207c478bd9Sstevel@tonic-gate (_a3));
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4) \
2237c478bd9Sstevel@tonic-gate ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
2247c478bd9Sstevel@tonic-gate (_a3), (_a4));
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5) \
2277c478bd9Sstevel@tonic-gate ipp_debug((_type), __FN__, (_fmt), (_a1), (_a2), \
2287c478bd9Sstevel@tonic-gate (_a3), (_a4), (_a5));
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate #else /* IPP_DBG */
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate #define DBG0(_type, _fmt)
2337c478bd9Sstevel@tonic-gate #define DBG1(_type, _fmt, _a1)
2347c478bd9Sstevel@tonic-gate #define DBG2(_type, _fmt, _a1, _a2)
2357c478bd9Sstevel@tonic-gate #define DBG3(_type, _fmt, _a1, _a2, _a3)
2367c478bd9Sstevel@tonic-gate #define DBG4(_type, _fmt, _a1, _a2, _a3, _a4)
2377c478bd9Sstevel@tonic-gate #define DBG5(_type, _fmt, _a1, _a2, _a3, _a4, _a5)
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate #endif /* IPP_DBG */
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate /*
2427c478bd9Sstevel@tonic-gate * Lock macros
2437c478bd9Sstevel@tonic-gate */
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate #define LOCK_MOD(_imp, _rw) \
2467c478bd9Sstevel@tonic-gate rw_enter((_imp)->ippm_lock, (_rw))
2477c478bd9Sstevel@tonic-gate #define UNLOCK_MOD(_imp) \
2487c478bd9Sstevel@tonic-gate rw_exit((_imp)->ippm_lock)
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate #define LOCK_ACTION(_ap, _rw) \
2517c478bd9Sstevel@tonic-gate rw_enter((_ap)->ippa_lock, (_rw))
2527c478bd9Sstevel@tonic-gate #define UNLOCK_ACTION(_imp) \
2537c478bd9Sstevel@tonic-gate rw_exit((_imp)->ippa_lock)
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate #define CONFIG_WRITE_START(_ap) \
2567c478bd9Sstevel@tonic-gate CONFIG_LOCK_ENTER((_ap)->ippa_config_lock, CL_WRITE)
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate #define CONFIG_WRITE_END(_ap) \
2597c478bd9Sstevel@tonic-gate CONFIG_LOCK_EXIT((_ap)->ippa_config_lock)
2607c478bd9Sstevel@tonic-gate
2617c478bd9Sstevel@tonic-gate #define CONFIG_READ_START(_ap) \
2627c478bd9Sstevel@tonic-gate CONFIG_LOCK_ENTER((_ap)->ippa_config_lock, CL_READ)
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate #define CONFIG_READ_END(_ap) \
2657c478bd9Sstevel@tonic-gate CONFIG_LOCK_EXIT((_ap)->ippa_config_lock)
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate /*
2687c478bd9Sstevel@tonic-gate * Exported functions
2697c478bd9Sstevel@tonic-gate */
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate #define __FN__ "ipp_init"
2727c478bd9Sstevel@tonic-gate void
ipp_init(void)2737c478bd9Sstevel@tonic-gate ipp_init(
2747c478bd9Sstevel@tonic-gate void)
2757c478bd9Sstevel@tonic-gate {
2767c478bd9Sstevel@tonic-gate #ifdef IPP_DBG
2777c478bd9Sstevel@tonic-gate mutex_init(debug_mutex, NULL, MUTEX_ADAPTIVE,
2787c478bd9Sstevel@tonic-gate (void *)ipltospl(LOCK_LEVEL));
2797c478bd9Sstevel@tonic-gate #endif /* IPP_DBG */
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate * Initialize module and action structure caches and associated locks.
2837c478bd9Sstevel@tonic-gate */
2847c478bd9Sstevel@tonic-gate
2857c478bd9Sstevel@tonic-gate init_mods();
2867c478bd9Sstevel@tonic-gate init_actions();
2877c478bd9Sstevel@tonic-gate init_packets();
2887c478bd9Sstevel@tonic-gate }
2897c478bd9Sstevel@tonic-gate #undef __FN__
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate #define __FN__ "ipp_list_mods"
2927c478bd9Sstevel@tonic-gate int
ipp_list_mods(ipp_mod_id_t ** bufp,int * neltp)2937c478bd9Sstevel@tonic-gate ipp_list_mods(
2947c478bd9Sstevel@tonic-gate ipp_mod_id_t **bufp,
2957c478bd9Sstevel@tonic-gate int *neltp)
2967c478bd9Sstevel@tonic-gate {
2977c478bd9Sstevel@tonic-gate ASSERT(bufp != NULL);
2987c478bd9Sstevel@tonic-gate ASSERT(neltp != NULL);
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate return (get_mods(bufp, neltp));
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate #undef __FN__
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate /*
3057c478bd9Sstevel@tonic-gate * Module manipulation interface.
3067c478bd9Sstevel@tonic-gate */
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate #define __FN__ "ipp_mod_lookup"
3097c478bd9Sstevel@tonic-gate ipp_mod_id_t
ipp_mod_lookup(const char * modname)3107c478bd9Sstevel@tonic-gate ipp_mod_lookup(
3117c478bd9Sstevel@tonic-gate const char *modname)
3127c478bd9Sstevel@tonic-gate {
3137c478bd9Sstevel@tonic-gate ipp_mod_id_t mid;
3147c478bd9Sstevel@tonic-gate #define FIRST_TIME 0
3157c478bd9Sstevel@tonic-gate int try = FIRST_TIME;
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate /*
3187c478bd9Sstevel@tonic-gate * Sanity check the module name.
3197c478bd9Sstevel@tonic-gate */
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate if (modname == NULL || strlen(modname) > MAXNAMELEN - 1)
3227c478bd9Sstevel@tonic-gate return (IPP_MOD_INVAL);
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate try_again:
3257c478bd9Sstevel@tonic-gate if ((mid = find_mod(modname)) == IPP_MOD_INVAL) {
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate /*
3287c478bd9Sstevel@tonic-gate * Module not installed.
3297c478bd9Sstevel@tonic-gate */
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate if (try++ == FIRST_TIME) {
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate /*
3347c478bd9Sstevel@tonic-gate * This is the first attempt to find the module so
3357c478bd9Sstevel@tonic-gate * try to 'demand load' it.
3367c478bd9Sstevel@tonic-gate */
3377c478bd9Sstevel@tonic-gate
3387c478bd9Sstevel@tonic-gate DBG1(DBG_MOD, "loading module '%s'\n", modname);
3397c478bd9Sstevel@tonic-gate (void) modload("ipp", (char *)modname);
3407c478bd9Sstevel@tonic-gate goto try_again;
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate return (mid);
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate #undef FIRST_TIME
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate #undef __FN__
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate #define __FN__ "ipp_mod_name"
3517c478bd9Sstevel@tonic-gate int
ipp_mod_name(ipp_mod_id_t mid,char ** modnamep)3527c478bd9Sstevel@tonic-gate ipp_mod_name(
3537c478bd9Sstevel@tonic-gate ipp_mod_id_t mid,
3547c478bd9Sstevel@tonic-gate char **modnamep)
3557c478bd9Sstevel@tonic-gate {
3567c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
3577c478bd9Sstevel@tonic-gate char *modname;
3587c478bd9Sstevel@tonic-gate char *buf;
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate ASSERT(modnamep != NULL);
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate /*
3637c478bd9Sstevel@tonic-gate * Translate the module id into the module pointer.
3647c478bd9Sstevel@tonic-gate */
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate if ((imp = hold_mod(mid)) == NULL)
3677c478bd9Sstevel@tonic-gate return (ENOENT);
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_READER);
3707c478bd9Sstevel@tonic-gate modname = imp->ippm_name;
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate /*
3737c478bd9Sstevel@tonic-gate * Allocate a buffer to pass back to the caller.
3747c478bd9Sstevel@tonic-gate */
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate if ((buf = kmem_zalloc(strlen(modname) + 1, KM_NOSLEEP)) == NULL) {
3777c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
3787c478bd9Sstevel@tonic-gate rele_mod(imp);
3797c478bd9Sstevel@tonic-gate return (ENOMEM);
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate /*
3837c478bd9Sstevel@tonic-gate * Copy the module name into the buffer.
3847c478bd9Sstevel@tonic-gate */
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate (void) strcpy(buf, modname);
3877c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate *modnamep = buf;
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate rele_mod(imp);
3927c478bd9Sstevel@tonic-gate return (0);
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate #undef __FN__
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate #define __FN__ "ipp_mod_register"
3977c478bd9Sstevel@tonic-gate int
ipp_mod_register(const char * modname,ipp_ops_t * ipp_ops)3987c478bd9Sstevel@tonic-gate ipp_mod_register(
3997c478bd9Sstevel@tonic-gate const char *modname,
4007c478bd9Sstevel@tonic-gate ipp_ops_t *ipp_ops)
4017c478bd9Sstevel@tonic-gate {
4027c478bd9Sstevel@tonic-gate ipp_mod_id_t mid;
4037c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
4047c478bd9Sstevel@tonic-gate int rc;
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate ASSERT(ipp_ops != NULL);
4077c478bd9Sstevel@tonic-gate
4087c478bd9Sstevel@tonic-gate /*
4097c478bd9Sstevel@tonic-gate * Sanity check the module name.
4107c478bd9Sstevel@tonic-gate */
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate if (modname == NULL || strlen(modname) > MAXNAMELEN - 1)
4137c478bd9Sstevel@tonic-gate return (EINVAL);
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate /*
4167c478bd9Sstevel@tonic-gate * Allocate a module structure.
4177c478bd9Sstevel@tonic-gate */
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate if ((rc = alloc_mod(modname, &mid)) != 0)
4207c478bd9Sstevel@tonic-gate return (rc);
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate imp = hold_mod(mid);
4237c478bd9Sstevel@tonic-gate ASSERT(imp != NULL);
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate /*
4267c478bd9Sstevel@tonic-gate * Make module available for use.
4277c478bd9Sstevel@tonic-gate */
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_WRITER);
4307c478bd9Sstevel@tonic-gate DBG1(DBG_MOD, "registering module '%s'\n", imp->ippm_name);
4317c478bd9Sstevel@tonic-gate imp->ippm_ops = ipp_ops;
4327c478bd9Sstevel@tonic-gate imp->ippm_state = IPP_MODSTATE_AVAILABLE;
4337c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate rele_mod(imp);
4367c478bd9Sstevel@tonic-gate return (0);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate #undef __FN__
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate #define __FN__ "ipp_mod_unregister"
4417c478bd9Sstevel@tonic-gate int
ipp_mod_unregister(ipp_mod_id_t mid)4427c478bd9Sstevel@tonic-gate ipp_mod_unregister(
4437c478bd9Sstevel@tonic-gate ipp_mod_id_t mid)
4447c478bd9Sstevel@tonic-gate {
4457c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
4467c478bd9Sstevel@tonic-gate
4477c478bd9Sstevel@tonic-gate /*
4487c478bd9Sstevel@tonic-gate * Translate the module id into the module pointer.
4497c478bd9Sstevel@tonic-gate */
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate if ((imp = hold_mod(mid)) == NULL)
4527c478bd9Sstevel@tonic-gate return (ENOENT);
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_WRITER);
4557c478bd9Sstevel@tonic-gate ASSERT(imp->ippm_state == IPP_MODSTATE_AVAILABLE);
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate /*
4587c478bd9Sstevel@tonic-gate * Check to see if there are any actions that reference the module.
4597c478bd9Sstevel@tonic-gate */
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate if (is_mod_busy(imp)) {
4627c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
4637c478bd9Sstevel@tonic-gate rele_mod(imp);
4647c478bd9Sstevel@tonic-gate return (EBUSY);
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate /*
4687c478bd9Sstevel@tonic-gate * Prevent further use of the module.
4697c478bd9Sstevel@tonic-gate */
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate DBG1(DBG_MOD, "unregistering module '%s'\n", imp->ippm_name);
4727c478bd9Sstevel@tonic-gate imp->ippm_state = IPP_MODSTATE_PROTO;
4737c478bd9Sstevel@tonic-gate imp->ippm_ops = NULL;
4747c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate /*
4777c478bd9Sstevel@tonic-gate * Free the module structure.
4787c478bd9Sstevel@tonic-gate */
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate free_mod(imp);
4817c478bd9Sstevel@tonic-gate rele_mod(imp);
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate return (0);
4847c478bd9Sstevel@tonic-gate }
4857c478bd9Sstevel@tonic-gate #undef __FN__
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate #define __FN__ "ipp_mod_list_actions"
4887c478bd9Sstevel@tonic-gate int
ipp_mod_list_actions(ipp_mod_id_t mid,ipp_action_id_t ** bufp,int * neltp)4897c478bd9Sstevel@tonic-gate ipp_mod_list_actions(
4907c478bd9Sstevel@tonic-gate ipp_mod_id_t mid,
4917c478bd9Sstevel@tonic-gate ipp_action_id_t **bufp,
4927c478bd9Sstevel@tonic-gate int *neltp)
4937c478bd9Sstevel@tonic-gate {
4947c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
4957c478bd9Sstevel@tonic-gate int rc;
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate ASSERT(bufp != NULL);
4987c478bd9Sstevel@tonic-gate ASSERT(neltp != NULL);
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate /*
5017c478bd9Sstevel@tonic-gate * Translate the module id into the module pointer.
5027c478bd9Sstevel@tonic-gate */
5037c478bd9Sstevel@tonic-gate
5047c478bd9Sstevel@tonic-gate if ((imp = hold_mod(mid)) == NULL)
5057c478bd9Sstevel@tonic-gate return (ENOENT);
5067c478bd9Sstevel@tonic-gate
5077c478bd9Sstevel@tonic-gate /*
5087c478bd9Sstevel@tonic-gate * Get the list of actions referencing the module.
5097c478bd9Sstevel@tonic-gate */
5107c478bd9Sstevel@tonic-gate
5117c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_READER);
5127c478bd9Sstevel@tonic-gate rc = get_mod_ref(imp, bufp, neltp);
5137c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate rele_mod(imp);
5167c478bd9Sstevel@tonic-gate return (rc);
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate #undef __FN__
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate /*
5217c478bd9Sstevel@tonic-gate * Action manipulation interface.
5227c478bd9Sstevel@tonic-gate */
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_lookup"
5257c478bd9Sstevel@tonic-gate ipp_action_id_t
ipp_action_lookup(const char * aname)5267c478bd9Sstevel@tonic-gate ipp_action_lookup(
5277c478bd9Sstevel@tonic-gate const char *aname)
5287c478bd9Sstevel@tonic-gate {
5297c478bd9Sstevel@tonic-gate if (aname == NULL)
5307c478bd9Sstevel@tonic-gate return (IPP_ACTION_INVAL);
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate /*
5337c478bd9Sstevel@tonic-gate * Check for special case 'virtual action' names.
5347c478bd9Sstevel@tonic-gate */
5357c478bd9Sstevel@tonic-gate
5367c478bd9Sstevel@tonic-gate if (strcmp(aname, IPP_ANAME_CONT) == 0)
5377c478bd9Sstevel@tonic-gate return (IPP_ACTION_CONT);
5387c478bd9Sstevel@tonic-gate else if (strcmp(aname, IPP_ANAME_DEFER) == 0)
5397c478bd9Sstevel@tonic-gate return (IPP_ACTION_DEFER);
5407c478bd9Sstevel@tonic-gate else if (strcmp(aname, IPP_ANAME_DROP) == 0)
5417c478bd9Sstevel@tonic-gate return (IPP_ACTION_DROP);
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate /*
5447c478bd9Sstevel@tonic-gate * Now check real actions.
5457c478bd9Sstevel@tonic-gate */
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate return (find_action(aname));
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate #undef __FN__
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_name"
5527c478bd9Sstevel@tonic-gate int
ipp_action_name(ipp_action_id_t aid,char ** anamep)5537c478bd9Sstevel@tonic-gate ipp_action_name(
5547c478bd9Sstevel@tonic-gate ipp_action_id_t aid,
5557c478bd9Sstevel@tonic-gate char **anamep)
5567c478bd9Sstevel@tonic-gate {
5577c478bd9Sstevel@tonic-gate ipp_action_t *ap;
5587c478bd9Sstevel@tonic-gate char *aname;
5597c478bd9Sstevel@tonic-gate char *buf;
5607c478bd9Sstevel@tonic-gate int rc;
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate ASSERT(anamep != NULL);
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate /*
5657c478bd9Sstevel@tonic-gate * Check for special case 'virtual action' ids.
5667c478bd9Sstevel@tonic-gate */
5677c478bd9Sstevel@tonic-gate
5687c478bd9Sstevel@tonic-gate switch (aid) {
5697c478bd9Sstevel@tonic-gate case IPP_ACTION_CONT:
5707c478bd9Sstevel@tonic-gate ap = NULL;
5717c478bd9Sstevel@tonic-gate aname = IPP_ANAME_CONT;
5727c478bd9Sstevel@tonic-gate break;
5737c478bd9Sstevel@tonic-gate case IPP_ACTION_DEFER:
5747c478bd9Sstevel@tonic-gate ap = NULL;
5757c478bd9Sstevel@tonic-gate aname = IPP_ANAME_DEFER;
5767c478bd9Sstevel@tonic-gate break;
5777c478bd9Sstevel@tonic-gate case IPP_ACTION_DROP:
5787c478bd9Sstevel@tonic-gate ap = NULL;
5797c478bd9Sstevel@tonic-gate aname = IPP_ANAME_DROP;
5807c478bd9Sstevel@tonic-gate break;
5817c478bd9Sstevel@tonic-gate default:
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate /*
5847c478bd9Sstevel@tonic-gate * Not a special case. Check for a real action.
5857c478bd9Sstevel@tonic-gate */
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate if ((ap = hold_action(aid)) == NULL)
5887c478bd9Sstevel@tonic-gate return (ENOENT);
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_READER);
5917c478bd9Sstevel@tonic-gate aname = ap->ippa_name;
5927c478bd9Sstevel@tonic-gate break;
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate
5957c478bd9Sstevel@tonic-gate /*
5967c478bd9Sstevel@tonic-gate * Allocate a buffer to pass back to the caller.
5977c478bd9Sstevel@tonic-gate */
5987c478bd9Sstevel@tonic-gate
5997c478bd9Sstevel@tonic-gate if ((buf = kmem_zalloc(strlen(aname) + 1, KM_NOSLEEP)) == NULL) {
6007c478bd9Sstevel@tonic-gate rc = ENOMEM;
6017c478bd9Sstevel@tonic-gate goto done;
6027c478bd9Sstevel@tonic-gate }
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate /*
6057c478bd9Sstevel@tonic-gate * Copy the action name into the buffer.
6067c478bd9Sstevel@tonic-gate */
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate (void) strcpy(buf, aname);
6097c478bd9Sstevel@tonic-gate *anamep = buf;
6107c478bd9Sstevel@tonic-gate rc = 0;
6117c478bd9Sstevel@tonic-gate done:
6127c478bd9Sstevel@tonic-gate /*
6137c478bd9Sstevel@tonic-gate * Unlock the action if necessary (i.e. it wasn't a virtual action).
6147c478bd9Sstevel@tonic-gate */
6157c478bd9Sstevel@tonic-gate
6167c478bd9Sstevel@tonic-gate if (ap != NULL) {
6177c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
6187c478bd9Sstevel@tonic-gate rele_action(ap);
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate return (rc);
6227c478bd9Sstevel@tonic-gate }
6237c478bd9Sstevel@tonic-gate #undef __FN__
6247c478bd9Sstevel@tonic-gate
6257c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_mod"
6267c478bd9Sstevel@tonic-gate int
ipp_action_mod(ipp_action_id_t aid,ipp_mod_id_t * midp)6277c478bd9Sstevel@tonic-gate ipp_action_mod(
6287c478bd9Sstevel@tonic-gate ipp_action_id_t aid,
6297c478bd9Sstevel@tonic-gate ipp_mod_id_t *midp)
6307c478bd9Sstevel@tonic-gate {
6317c478bd9Sstevel@tonic-gate ipp_action_t *ap;
6327c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
6337c478bd9Sstevel@tonic-gate
6347c478bd9Sstevel@tonic-gate ASSERT(midp != NULL);
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate /*
6377c478bd9Sstevel@tonic-gate * Return an error for 'virtual action' ids.
6387c478bd9Sstevel@tonic-gate */
6397c478bd9Sstevel@tonic-gate
6407c478bd9Sstevel@tonic-gate switch (aid) {
6417c478bd9Sstevel@tonic-gate case IPP_ACTION_CONT:
6427c478bd9Sstevel@tonic-gate /*FALLTHRU*/
6437c478bd9Sstevel@tonic-gate case IPP_ACTION_DEFER:
6447c478bd9Sstevel@tonic-gate /*FALLTHRU*/
6457c478bd9Sstevel@tonic-gate case IPP_ACTION_DROP:
6467c478bd9Sstevel@tonic-gate return (EINVAL);
6477c478bd9Sstevel@tonic-gate default:
6487c478bd9Sstevel@tonic-gate break;
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate /*
6527c478bd9Sstevel@tonic-gate * This is a real action.
6537c478bd9Sstevel@tonic-gate */
6547c478bd9Sstevel@tonic-gate
6557c478bd9Sstevel@tonic-gate if ((ap = hold_action(aid)) == NULL)
6567c478bd9Sstevel@tonic-gate return (ENOENT);
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate /*
6597c478bd9Sstevel@tonic-gate * Check that the action is not in prototype state.
6607c478bd9Sstevel@tonic-gate */
6617c478bd9Sstevel@tonic-gate
6627c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_READER);
6637c478bd9Sstevel@tonic-gate if (ap->ippa_state == IPP_ASTATE_PROTO) {
6647c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
6657c478bd9Sstevel@tonic-gate rele_action(ap);
6667c478bd9Sstevel@tonic-gate return (ENOENT);
6677c478bd9Sstevel@tonic-gate }
6687c478bd9Sstevel@tonic-gate
6697c478bd9Sstevel@tonic-gate imp = ap->ippa_mod;
6707c478bd9Sstevel@tonic-gate ASSERT(imp != NULL);
6717c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
6727c478bd9Sstevel@tonic-gate
6737c478bd9Sstevel@tonic-gate *midp = imp->ippm_id;
6747c478bd9Sstevel@tonic-gate
6757c478bd9Sstevel@tonic-gate rele_action(ap);
6767c478bd9Sstevel@tonic-gate return (0);
6777c478bd9Sstevel@tonic-gate }
6787c478bd9Sstevel@tonic-gate #undef __FN__
6797c478bd9Sstevel@tonic-gate
6807c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_create"
6817c478bd9Sstevel@tonic-gate int
ipp_action_create(ipp_mod_id_t mid,const char * aname,nvlist_t ** nvlpp,ipp_flags_t flags,ipp_action_id_t * aidp)6827c478bd9Sstevel@tonic-gate ipp_action_create(
6837c478bd9Sstevel@tonic-gate ipp_mod_id_t mid,
6847c478bd9Sstevel@tonic-gate const char *aname,
6857c478bd9Sstevel@tonic-gate nvlist_t **nvlpp,
6867c478bd9Sstevel@tonic-gate ipp_flags_t flags,
6877c478bd9Sstevel@tonic-gate ipp_action_id_t *aidp)
6887c478bd9Sstevel@tonic-gate {
6897c478bd9Sstevel@tonic-gate ipp_ops_t *ippo;
6907c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
6917c478bd9Sstevel@tonic-gate ipp_action_id_t aid;
6927c478bd9Sstevel@tonic-gate ipp_action_t *ap;
6937c478bd9Sstevel@tonic-gate int rc;
6947c478bd9Sstevel@tonic-gate
6957c478bd9Sstevel@tonic-gate ASSERT(nvlpp != NULL);
6967c478bd9Sstevel@tonic-gate ASSERT(*nvlpp != NULL);
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate /*
6997c478bd9Sstevel@tonic-gate * Sanity check the action name (NULL means the framework chooses the
7007c478bd9Sstevel@tonic-gate * name).
7017c478bd9Sstevel@tonic-gate */
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate if (aname != NULL && strlen(aname) > MAXNAMELEN - 1)
7047c478bd9Sstevel@tonic-gate return (EINVAL);
7057c478bd9Sstevel@tonic-gate
7067c478bd9Sstevel@tonic-gate /*
7077c478bd9Sstevel@tonic-gate * Translate the module id into the module pointer.
7087c478bd9Sstevel@tonic-gate */
7097c478bd9Sstevel@tonic-gate
7107c478bd9Sstevel@tonic-gate if ((imp = hold_mod(mid)) == NULL)
7117c478bd9Sstevel@tonic-gate return (ENOENT);
7127c478bd9Sstevel@tonic-gate
7137c478bd9Sstevel@tonic-gate /*
7147c478bd9Sstevel@tonic-gate * Allocate an action.
7157c478bd9Sstevel@tonic-gate */
7167c478bd9Sstevel@tonic-gate
7177c478bd9Sstevel@tonic-gate if ((rc = alloc_action(aname, &aid)) != 0) {
7187c478bd9Sstevel@tonic-gate rele_mod(imp);
7197c478bd9Sstevel@tonic-gate return (rc);
7207c478bd9Sstevel@tonic-gate }
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate ap = hold_action(aid);
7237c478bd9Sstevel@tonic-gate ASSERT(ap != NULL);
7247c478bd9Sstevel@tonic-gate
7257c478bd9Sstevel@tonic-gate /*
7267c478bd9Sstevel@tonic-gate * Note that the action is in the process of creation/destruction.
7277c478bd9Sstevel@tonic-gate */
7287c478bd9Sstevel@tonic-gate
7297c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_WRITER);
7307c478bd9Sstevel@tonic-gate ap->ippa_state = IPP_ASTATE_CONFIG_PENDING;
7317c478bd9Sstevel@tonic-gate
7327c478bd9Sstevel@tonic-gate /*
7337c478bd9Sstevel@tonic-gate * Reference the module for which the action is being created.
7347c478bd9Sstevel@tonic-gate */
7357c478bd9Sstevel@tonic-gate
7367c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_WRITER);
7377c478bd9Sstevel@tonic-gate if ((rc = ref_mod(ap, imp)) != 0) {
7387c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
7397c478bd9Sstevel@tonic-gate ap->ippa_state = IPP_ASTATE_PROTO;
7407c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
7417c478bd9Sstevel@tonic-gate
7427c478bd9Sstevel@tonic-gate free_action(ap);
7437c478bd9Sstevel@tonic-gate rele_action(ap);
7447c478bd9Sstevel@tonic-gate rele_mod(imp);
7457c478bd9Sstevel@tonic-gate return (rc);
7467c478bd9Sstevel@tonic-gate }
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
7497c478bd9Sstevel@tonic-gate
7507c478bd9Sstevel@tonic-gate ippo = imp->ippm_ops;
7517c478bd9Sstevel@tonic-gate ASSERT(ippo != NULL);
7527c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate /*
7557c478bd9Sstevel@tonic-gate * Call into the module to create the action context.
7567c478bd9Sstevel@tonic-gate */
7577c478bd9Sstevel@tonic-gate
7587c478bd9Sstevel@tonic-gate CONFIG_WRITE_START(ap);
7597c478bd9Sstevel@tonic-gate DBG2(DBG_ACTION, "creating action '%s' in module '%s'\n",
7607c478bd9Sstevel@tonic-gate ap->ippa_name, imp->ippm_name);
7617c478bd9Sstevel@tonic-gate if ((rc = ippo->ippo_action_create(ap->ippa_id, nvlpp, flags)) != 0) {
7627c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_WRITER);
7637c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_WRITER);
7647c478bd9Sstevel@tonic-gate unref_mod(ap, imp);
7657c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
7667c478bd9Sstevel@tonic-gate ap->ippa_state = IPP_ASTATE_PROTO;
7677c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
7687c478bd9Sstevel@tonic-gate
7697c478bd9Sstevel@tonic-gate CONFIG_WRITE_END(ap);
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate free_action(ap);
7727c478bd9Sstevel@tonic-gate rele_action(ap);
7737c478bd9Sstevel@tonic-gate rele_mod(imp);
7747c478bd9Sstevel@tonic-gate return (rc);
7757c478bd9Sstevel@tonic-gate }
7767c478bd9Sstevel@tonic-gate CONFIG_WRITE_END(ap);
7777c478bd9Sstevel@tonic-gate
7787c478bd9Sstevel@tonic-gate /*
7797c478bd9Sstevel@tonic-gate * Make the action available for use.
7807c478bd9Sstevel@tonic-gate */
7817c478bd9Sstevel@tonic-gate
7827c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_WRITER);
7837c478bd9Sstevel@tonic-gate ap->ippa_state = IPP_ASTATE_AVAILABLE;
7847c478bd9Sstevel@tonic-gate if (aidp != NULL)
7857c478bd9Sstevel@tonic-gate *aidp = ap->ippa_id;
7867c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
7877c478bd9Sstevel@tonic-gate
7887c478bd9Sstevel@tonic-gate rele_action(ap);
7897c478bd9Sstevel@tonic-gate rele_mod(imp);
7907c478bd9Sstevel@tonic-gate return (0);
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate #undef __FN__
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_destroy"
7957c478bd9Sstevel@tonic-gate int
ipp_action_destroy(ipp_action_id_t aid,ipp_flags_t flags)7967c478bd9Sstevel@tonic-gate ipp_action_destroy(
7977c478bd9Sstevel@tonic-gate ipp_action_id_t aid,
7987c478bd9Sstevel@tonic-gate ipp_flags_t flags)
7997c478bd9Sstevel@tonic-gate {
8007c478bd9Sstevel@tonic-gate ipp_ref_t *rp = NULL;
8017c478bd9Sstevel@tonic-gate ipp_ref_t *tmp;
8027c478bd9Sstevel@tonic-gate ipp_action_t *ap;
8037c478bd9Sstevel@tonic-gate int rc;
8047c478bd9Sstevel@tonic-gate
8057c478bd9Sstevel@tonic-gate /*
8067c478bd9Sstevel@tonic-gate * Translate the action id into the action pointer.
8077c478bd9Sstevel@tonic-gate */
8087c478bd9Sstevel@tonic-gate
8097c478bd9Sstevel@tonic-gate if ((ap = hold_action(aid)) == NULL)
8107c478bd9Sstevel@tonic-gate return (ENOENT);
8117c478bd9Sstevel@tonic-gate
8127c478bd9Sstevel@tonic-gate /*
8137c478bd9Sstevel@tonic-gate * Set the condemned action list pointer and destroy the action.
8147c478bd9Sstevel@tonic-gate */
8157c478bd9Sstevel@tonic-gate
8167c478bd9Sstevel@tonic-gate ap->ippa_condemned = &rp;
8177c478bd9Sstevel@tonic-gate if ((rc = destroy_action(ap, flags)) == 0) {
8187c478bd9Sstevel@tonic-gate
8197c478bd9Sstevel@tonic-gate /*
8207c478bd9Sstevel@tonic-gate * Destroy any other actions condemned by the destruction of
8217c478bd9Sstevel@tonic-gate * the first action.
8227c478bd9Sstevel@tonic-gate */
8237c478bd9Sstevel@tonic-gate
8247c478bd9Sstevel@tonic-gate for (tmp = rp; tmp != NULL; tmp = tmp->ippr_nextp) {
8257c478bd9Sstevel@tonic-gate ap = tmp->ippr_action;
8267c478bd9Sstevel@tonic-gate ap->ippa_condemned = &rp;
8277c478bd9Sstevel@tonic-gate (void) destroy_action(ap, flags);
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate } else {
8307c478bd9Sstevel@tonic-gate
8317c478bd9Sstevel@tonic-gate /*
8327c478bd9Sstevel@tonic-gate * Unreference any condemned actions since the destruction of
8337c478bd9Sstevel@tonic-gate * the first action failed.
8347c478bd9Sstevel@tonic-gate */
8357c478bd9Sstevel@tonic-gate
8367c478bd9Sstevel@tonic-gate for (tmp = rp; tmp != NULL; tmp = tmp->ippr_nextp) {
8377c478bd9Sstevel@tonic-gate ap = tmp->ippr_action;
8387c478bd9Sstevel@tonic-gate rele_action(ap);
8397c478bd9Sstevel@tonic-gate }
8407c478bd9Sstevel@tonic-gate }
8417c478bd9Sstevel@tonic-gate
8427c478bd9Sstevel@tonic-gate /*
8437c478bd9Sstevel@tonic-gate * Clean up the condemned list.
8447c478bd9Sstevel@tonic-gate */
8457c478bd9Sstevel@tonic-gate
8467c478bd9Sstevel@tonic-gate while (rp != NULL) {
8477c478bd9Sstevel@tonic-gate tmp = rp;
8487c478bd9Sstevel@tonic-gate rp = rp->ippr_nextp;
8497c478bd9Sstevel@tonic-gate kmem_free(tmp, sizeof (ipp_ref_t));
8507c478bd9Sstevel@tonic-gate }
8517c478bd9Sstevel@tonic-gate
8527c478bd9Sstevel@tonic-gate return (rc);
8537c478bd9Sstevel@tonic-gate }
8547c478bd9Sstevel@tonic-gate #undef __FN__
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_modify"
8577c478bd9Sstevel@tonic-gate int
ipp_action_modify(ipp_action_id_t aid,nvlist_t ** nvlpp,ipp_flags_t flags)8587c478bd9Sstevel@tonic-gate ipp_action_modify(
8597c478bd9Sstevel@tonic-gate ipp_action_id_t aid,
8607c478bd9Sstevel@tonic-gate nvlist_t **nvlpp,
8617c478bd9Sstevel@tonic-gate ipp_flags_t flags)
8627c478bd9Sstevel@tonic-gate {
8637c478bd9Sstevel@tonic-gate ipp_action_t *ap;
8647c478bd9Sstevel@tonic-gate ipp_ops_t *ippo;
8657c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
8667c478bd9Sstevel@tonic-gate int rc;
8677c478bd9Sstevel@tonic-gate
8687c478bd9Sstevel@tonic-gate ASSERT(nvlpp != NULL);
8697c478bd9Sstevel@tonic-gate ASSERT(*nvlpp != NULL);
8707c478bd9Sstevel@tonic-gate
8717c478bd9Sstevel@tonic-gate /*
8727c478bd9Sstevel@tonic-gate * Translate the action id into the action pointer.
8737c478bd9Sstevel@tonic-gate */
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate if ((ap = hold_action(aid)) == NULL)
8767c478bd9Sstevel@tonic-gate return (ENOENT);
8777c478bd9Sstevel@tonic-gate
8787c478bd9Sstevel@tonic-gate /*
8797c478bd9Sstevel@tonic-gate * Check that the action is either available for use or is in the
8807c478bd9Sstevel@tonic-gate * process of creation/destruction.
8817c478bd9Sstevel@tonic-gate *
8827c478bd9Sstevel@tonic-gate * NOTE: It is up to the module to lock multiple configuration
8837c478bd9Sstevel@tonic-gate * operations against each other if necessary.
8847c478bd9Sstevel@tonic-gate */
8857c478bd9Sstevel@tonic-gate
8867c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_READER);
8877c478bd9Sstevel@tonic-gate if (ap->ippa_state != IPP_ASTATE_AVAILABLE &&
8887c478bd9Sstevel@tonic-gate ap->ippa_state != IPP_ASTATE_CONFIG_PENDING) {
8897c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
8907c478bd9Sstevel@tonic-gate rele_action(ap);
8917c478bd9Sstevel@tonic-gate return (EPROTO);
8927c478bd9Sstevel@tonic-gate }
8937c478bd9Sstevel@tonic-gate
8947c478bd9Sstevel@tonic-gate imp = ap->ippa_mod;
8957c478bd9Sstevel@tonic-gate ASSERT(imp != NULL);
8967c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
8977c478bd9Sstevel@tonic-gate
8987c478bd9Sstevel@tonic-gate ippo = imp->ippm_ops;
8997c478bd9Sstevel@tonic-gate ASSERT(ippo != NULL);
9007c478bd9Sstevel@tonic-gate
9017c478bd9Sstevel@tonic-gate /*
9027c478bd9Sstevel@tonic-gate * Call into the module to modify the action context.
9037c478bd9Sstevel@tonic-gate */
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate DBG1(DBG_ACTION, "modifying action '%s'\n", ap->ippa_name);
9067c478bd9Sstevel@tonic-gate CONFIG_WRITE_START(ap);
9077c478bd9Sstevel@tonic-gate rc = ippo->ippo_action_modify(aid, nvlpp, flags);
9087c478bd9Sstevel@tonic-gate CONFIG_WRITE_END(ap);
9097c478bd9Sstevel@tonic-gate
9107c478bd9Sstevel@tonic-gate rele_action(ap);
9117c478bd9Sstevel@tonic-gate return (rc);
9127c478bd9Sstevel@tonic-gate }
9137c478bd9Sstevel@tonic-gate #undef __FN__
9147c478bd9Sstevel@tonic-gate
9157c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_info"
9167c478bd9Sstevel@tonic-gate int
ipp_action_info(ipp_action_id_t aid,int (* fn)(nvlist_t *,void *),void * arg,ipp_flags_t flags)9177c478bd9Sstevel@tonic-gate ipp_action_info(
9187c478bd9Sstevel@tonic-gate ipp_action_id_t aid,
9197c478bd9Sstevel@tonic-gate int (*fn)(nvlist_t *, void *),
9207c478bd9Sstevel@tonic-gate void *arg,
9217c478bd9Sstevel@tonic-gate ipp_flags_t flags)
9227c478bd9Sstevel@tonic-gate {
9237c478bd9Sstevel@tonic-gate ipp_action_t *ap;
9247c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
9257c478bd9Sstevel@tonic-gate ipp_ops_t *ippo;
9267c478bd9Sstevel@tonic-gate int rc;
9277c478bd9Sstevel@tonic-gate
9287c478bd9Sstevel@tonic-gate /*
9297c478bd9Sstevel@tonic-gate * Translate the action id into the action pointer.
9307c478bd9Sstevel@tonic-gate */
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate if ((ap = hold_action(aid)) == NULL)
9337c478bd9Sstevel@tonic-gate return (ENOENT);
9347c478bd9Sstevel@tonic-gate
9357c478bd9Sstevel@tonic-gate /*
9367c478bd9Sstevel@tonic-gate * Check that the action is available for use. We don't want to
9377c478bd9Sstevel@tonic-gate * read back parameters while the action is in the process of
9387c478bd9Sstevel@tonic-gate * creation/destruction.
9397c478bd9Sstevel@tonic-gate */
9407c478bd9Sstevel@tonic-gate
9417c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_READER);
9427c478bd9Sstevel@tonic-gate if (ap->ippa_state != IPP_ASTATE_AVAILABLE) {
9437c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
9447c478bd9Sstevel@tonic-gate rele_action(ap);
9457c478bd9Sstevel@tonic-gate return (EPROTO);
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate imp = ap->ippa_mod;
9497c478bd9Sstevel@tonic-gate ASSERT(imp != NULL);
9507c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
9517c478bd9Sstevel@tonic-gate
9527c478bd9Sstevel@tonic-gate ippo = imp->ippm_ops;
9537c478bd9Sstevel@tonic-gate ASSERT(ippo != NULL);
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate /*
9567c478bd9Sstevel@tonic-gate * Call into the module to get the action configuration information.
9577c478bd9Sstevel@tonic-gate */
9587c478bd9Sstevel@tonic-gate
9597c478bd9Sstevel@tonic-gate DBG1(DBG_ACTION,
9607c478bd9Sstevel@tonic-gate "getting configuration information from action '%s'\n",
9617c478bd9Sstevel@tonic-gate ap->ippa_name);
9627c478bd9Sstevel@tonic-gate CONFIG_READ_START(ap);
9637c478bd9Sstevel@tonic-gate if ((rc = ippo->ippo_action_info(aid, fn, arg, flags)) != 0) {
9647c478bd9Sstevel@tonic-gate CONFIG_READ_END(ap);
9657c478bd9Sstevel@tonic-gate rele_action(ap);
9667c478bd9Sstevel@tonic-gate return (rc);
9677c478bd9Sstevel@tonic-gate }
9687c478bd9Sstevel@tonic-gate CONFIG_READ_END(ap);
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate rele_action(ap);
9717c478bd9Sstevel@tonic-gate return (0);
9727c478bd9Sstevel@tonic-gate }
9737c478bd9Sstevel@tonic-gate #undef __FN__
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_set_ptr"
9767c478bd9Sstevel@tonic-gate void
ipp_action_set_ptr(ipp_action_id_t aid,void * ptr)9777c478bd9Sstevel@tonic-gate ipp_action_set_ptr(
9787c478bd9Sstevel@tonic-gate ipp_action_id_t aid,
9797c478bd9Sstevel@tonic-gate void *ptr)
9807c478bd9Sstevel@tonic-gate {
9817c478bd9Sstevel@tonic-gate ipp_action_t *ap;
9827c478bd9Sstevel@tonic-gate
9837c478bd9Sstevel@tonic-gate /*
9847c478bd9Sstevel@tonic-gate * Translate the action id into the action pointer.
9857c478bd9Sstevel@tonic-gate */
9867c478bd9Sstevel@tonic-gate
9877c478bd9Sstevel@tonic-gate ap = hold_action(aid);
9887c478bd9Sstevel@tonic-gate ASSERT(ap != NULL);
9897c478bd9Sstevel@tonic-gate
9907c478bd9Sstevel@tonic-gate /*
9917c478bd9Sstevel@tonic-gate * Set the private data pointer.
9927c478bd9Sstevel@tonic-gate */
9937c478bd9Sstevel@tonic-gate
9947c478bd9Sstevel@tonic-gate ap->ippa_ptr = ptr;
9957c478bd9Sstevel@tonic-gate rele_action(ap);
9967c478bd9Sstevel@tonic-gate }
9977c478bd9Sstevel@tonic-gate #undef __FN__
9987c478bd9Sstevel@tonic-gate
9997c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_get_ptr"
10007c478bd9Sstevel@tonic-gate void *
ipp_action_get_ptr(ipp_action_id_t aid)10017c478bd9Sstevel@tonic-gate ipp_action_get_ptr(
10027c478bd9Sstevel@tonic-gate ipp_action_id_t aid)
10037c478bd9Sstevel@tonic-gate {
10047c478bd9Sstevel@tonic-gate ipp_action_t *ap;
10057c478bd9Sstevel@tonic-gate void *ptr;
10067c478bd9Sstevel@tonic-gate
10077c478bd9Sstevel@tonic-gate /*
10087c478bd9Sstevel@tonic-gate * Translate the action id into the action pointer.
10097c478bd9Sstevel@tonic-gate */
10107c478bd9Sstevel@tonic-gate
10117c478bd9Sstevel@tonic-gate ap = hold_action(aid);
10127c478bd9Sstevel@tonic-gate ASSERT(ap != NULL);
10137c478bd9Sstevel@tonic-gate
10147c478bd9Sstevel@tonic-gate /*
10157c478bd9Sstevel@tonic-gate * Return the private data pointer.
10167c478bd9Sstevel@tonic-gate */
10177c478bd9Sstevel@tonic-gate
10187c478bd9Sstevel@tonic-gate ptr = ap->ippa_ptr;
10197c478bd9Sstevel@tonic-gate rele_action(ap);
10207c478bd9Sstevel@tonic-gate
10217c478bd9Sstevel@tonic-gate return (ptr);
10227c478bd9Sstevel@tonic-gate }
10237c478bd9Sstevel@tonic-gate #undef __FN__
10247c478bd9Sstevel@tonic-gate
10257c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_ref"
10267c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10277c478bd9Sstevel@tonic-gate int
ipp_action_ref(ipp_action_id_t aid,ipp_action_id_t ref_aid,ipp_flags_t flags)10287c478bd9Sstevel@tonic-gate ipp_action_ref(
10297c478bd9Sstevel@tonic-gate ipp_action_id_t aid,
10307c478bd9Sstevel@tonic-gate ipp_action_id_t ref_aid,
10317c478bd9Sstevel@tonic-gate ipp_flags_t flags)
10327c478bd9Sstevel@tonic-gate {
10337c478bd9Sstevel@tonic-gate ipp_action_t *ap;
10347c478bd9Sstevel@tonic-gate ipp_action_t *ref_ap;
10357c478bd9Sstevel@tonic-gate int rc;
10367c478bd9Sstevel@tonic-gate
10377c478bd9Sstevel@tonic-gate /*
10387c478bd9Sstevel@tonic-gate * Actions are not allowed to reference themselves.
10397c478bd9Sstevel@tonic-gate */
10407c478bd9Sstevel@tonic-gate
10417c478bd9Sstevel@tonic-gate if (aid == ref_aid)
10427c478bd9Sstevel@tonic-gate return (EINVAL);
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate /*
10457c478bd9Sstevel@tonic-gate * Check for a special case 'virtual action' id.
10467c478bd9Sstevel@tonic-gate */
10477c478bd9Sstevel@tonic-gate
10487c478bd9Sstevel@tonic-gate switch (ref_aid) {
10497c478bd9Sstevel@tonic-gate case IPP_ACTION_CONT:
10507c478bd9Sstevel@tonic-gate /*FALLTHRU*/
10517c478bd9Sstevel@tonic-gate case IPP_ACTION_DEFER:
10527c478bd9Sstevel@tonic-gate /*FALLTHRU*/
10537c478bd9Sstevel@tonic-gate case IPP_ACTION_DROP:
10547c478bd9Sstevel@tonic-gate return (0);
10557c478bd9Sstevel@tonic-gate default:
10567c478bd9Sstevel@tonic-gate break;
10577c478bd9Sstevel@tonic-gate }
10587c478bd9Sstevel@tonic-gate
10597c478bd9Sstevel@tonic-gate /*
10607c478bd9Sstevel@tonic-gate * Translate the action ids into action pointers.
10617c478bd9Sstevel@tonic-gate */
10627c478bd9Sstevel@tonic-gate
10637c478bd9Sstevel@tonic-gate if ((ap = hold_action(aid)) == NULL)
10647c478bd9Sstevel@tonic-gate return (ENOENT);
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate if ((ref_ap = hold_action(ref_aid)) == NULL) {
10677c478bd9Sstevel@tonic-gate rele_action(ap);
10687c478bd9Sstevel@tonic-gate return (ENOENT);
10697c478bd9Sstevel@tonic-gate }
10707c478bd9Sstevel@tonic-gate
10717c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_WRITER);
10727c478bd9Sstevel@tonic-gate LOCK_ACTION(ref_ap, RW_WRITER);
10737c478bd9Sstevel@tonic-gate
10747c478bd9Sstevel@tonic-gate if (ref_ap->ippa_state != IPP_ASTATE_AVAILABLE) {
10757c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ref_ap);
10767c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
10777c478bd9Sstevel@tonic-gate
10787c478bd9Sstevel@tonic-gate rele_action(ref_ap);
10797c478bd9Sstevel@tonic-gate rele_action(ap);
10807c478bd9Sstevel@tonic-gate return (EPROTO);
10817c478bd9Sstevel@tonic-gate }
10827c478bd9Sstevel@tonic-gate
10837c478bd9Sstevel@tonic-gate /*
10847c478bd9Sstevel@tonic-gate * Create references between the two actions.
10857c478bd9Sstevel@tonic-gate */
10867c478bd9Sstevel@tonic-gate
10877c478bd9Sstevel@tonic-gate rc = ref_action(ap, ref_ap);
10887c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ref_ap);
10897c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
10907c478bd9Sstevel@tonic-gate
10917c478bd9Sstevel@tonic-gate rele_action(ref_ap);
10927c478bd9Sstevel@tonic-gate rele_action(ap);
10937c478bd9Sstevel@tonic-gate return (rc);
10947c478bd9Sstevel@tonic-gate }
10957c478bd9Sstevel@tonic-gate #undef __FN__
10967c478bd9Sstevel@tonic-gate
10977c478bd9Sstevel@tonic-gate #define __FN__ "ipp_action_unref"
10987c478bd9Sstevel@tonic-gate int
ipp_action_unref(ipp_action_id_t aid,ipp_action_id_t ref_aid,ipp_flags_t flags)10997c478bd9Sstevel@tonic-gate ipp_action_unref(
11007c478bd9Sstevel@tonic-gate ipp_action_id_t aid,
11017c478bd9Sstevel@tonic-gate ipp_action_id_t ref_aid,
11027c478bd9Sstevel@tonic-gate ipp_flags_t flags)
11037c478bd9Sstevel@tonic-gate {
11047c478bd9Sstevel@tonic-gate ipp_action_t *ap;
11057c478bd9Sstevel@tonic-gate ipp_action_t *ref_ap;
11067c478bd9Sstevel@tonic-gate int ref_is_busy;
11077c478bd9Sstevel@tonic-gate int rc;
11087c478bd9Sstevel@tonic-gate
11097c478bd9Sstevel@tonic-gate if (aid == ref_aid)
11107c478bd9Sstevel@tonic-gate return (EINVAL);
11117c478bd9Sstevel@tonic-gate
11127c478bd9Sstevel@tonic-gate /*
11137c478bd9Sstevel@tonic-gate * Check for a special case 'virtual action' id.
11147c478bd9Sstevel@tonic-gate */
11157c478bd9Sstevel@tonic-gate
11167c478bd9Sstevel@tonic-gate switch (ref_aid) {
11177c478bd9Sstevel@tonic-gate case IPP_ACTION_CONT:
11187c478bd9Sstevel@tonic-gate /*FALLTHRU*/
11197c478bd9Sstevel@tonic-gate case IPP_ACTION_DEFER:
11207c478bd9Sstevel@tonic-gate /*FALLTHRU*/
11217c478bd9Sstevel@tonic-gate case IPP_ACTION_DROP:
11227c478bd9Sstevel@tonic-gate return (0);
11237c478bd9Sstevel@tonic-gate default:
11247c478bd9Sstevel@tonic-gate break;
11257c478bd9Sstevel@tonic-gate }
11267c478bd9Sstevel@tonic-gate
11277c478bd9Sstevel@tonic-gate /*
11287c478bd9Sstevel@tonic-gate * Translate the action ids into action pointers.
11297c478bd9Sstevel@tonic-gate */
11307c478bd9Sstevel@tonic-gate
11317c478bd9Sstevel@tonic-gate if ((ap = hold_action(aid)) == NULL)
11327c478bd9Sstevel@tonic-gate return (ENOENT);
11337c478bd9Sstevel@tonic-gate
11347c478bd9Sstevel@tonic-gate if ((ref_ap = hold_action(ref_aid)) == NULL) {
11357c478bd9Sstevel@tonic-gate rele_action(ap);
11367c478bd9Sstevel@tonic-gate return (ENOENT);
11377c478bd9Sstevel@tonic-gate }
11387c478bd9Sstevel@tonic-gate
11397c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_WRITER);
11407c478bd9Sstevel@tonic-gate LOCK_ACTION(ref_ap, RW_WRITER);
11417c478bd9Sstevel@tonic-gate
11427c478bd9Sstevel@tonic-gate /*
11437c478bd9Sstevel@tonic-gate * Remove the reference between the actions.
11447c478bd9Sstevel@tonic-gate */
11457c478bd9Sstevel@tonic-gate
11467c478bd9Sstevel@tonic-gate if ((rc = unref_action(ap, ref_ap)) != 0) {
11477c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ref_ap);
11487c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
11497c478bd9Sstevel@tonic-gate rele_action(ref_ap);
11507c478bd9Sstevel@tonic-gate rele_action(ap);
11517c478bd9Sstevel@tonic-gate return (rc);
11527c478bd9Sstevel@tonic-gate }
11537c478bd9Sstevel@tonic-gate
11547c478bd9Sstevel@tonic-gate ref_is_busy = is_action_refd(ref_ap);
11557c478bd9Sstevel@tonic-gate
11567c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ref_ap);
11577c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
11587c478bd9Sstevel@tonic-gate
11597c478bd9Sstevel@tonic-gate if (flags & IPP_DESTROY_REF) {
11607c478bd9Sstevel@tonic-gate if (!ref_is_busy) {
11617c478bd9Sstevel@tonic-gate
11627c478bd9Sstevel@tonic-gate /*
11637c478bd9Sstevel@tonic-gate * Condemn the action so that it will be destroyed.
11647c478bd9Sstevel@tonic-gate */
11657c478bd9Sstevel@tonic-gate
11667c478bd9Sstevel@tonic-gate (void) condemn_action(ap->ippa_condemned, ref_ap);
11677c478bd9Sstevel@tonic-gate return (0);
11687c478bd9Sstevel@tonic-gate }
11697c478bd9Sstevel@tonic-gate }
11707c478bd9Sstevel@tonic-gate
11717c478bd9Sstevel@tonic-gate rele_action(ref_ap);
11727c478bd9Sstevel@tonic-gate rele_action(ap);
11737c478bd9Sstevel@tonic-gate return (0);
11747c478bd9Sstevel@tonic-gate }
11757c478bd9Sstevel@tonic-gate #undef __FN__
11767c478bd9Sstevel@tonic-gate
11777c478bd9Sstevel@tonic-gate /*
11787c478bd9Sstevel@tonic-gate * Packet manipulation interface.
11797c478bd9Sstevel@tonic-gate */
11807c478bd9Sstevel@tonic-gate
11817c478bd9Sstevel@tonic-gate #define __FN__ "ipp_packet_alloc"
11827c478bd9Sstevel@tonic-gate int
ipp_packet_alloc(ipp_packet_t ** ppp,const char * name,ipp_action_id_t aid)11837c478bd9Sstevel@tonic-gate ipp_packet_alloc(
11847c478bd9Sstevel@tonic-gate ipp_packet_t **ppp,
11857c478bd9Sstevel@tonic-gate const char *name,
11867c478bd9Sstevel@tonic-gate ipp_action_id_t aid)
11877c478bd9Sstevel@tonic-gate {
11887c478bd9Sstevel@tonic-gate ipp_packet_t *pp;
11897c478bd9Sstevel@tonic-gate int rc;
11907c478bd9Sstevel@tonic-gate
11917c478bd9Sstevel@tonic-gate ASSERT(ppp != NULL);
11927c478bd9Sstevel@tonic-gate
11937c478bd9Sstevel@tonic-gate /*
11947c478bd9Sstevel@tonic-gate * A name is required.
11957c478bd9Sstevel@tonic-gate */
11967c478bd9Sstevel@tonic-gate
11977c478bd9Sstevel@tonic-gate if (name == NULL || strlen(name) > MAXNAMELEN - 1)
11987c478bd9Sstevel@tonic-gate return (EINVAL);
11997c478bd9Sstevel@tonic-gate
12007c478bd9Sstevel@tonic-gate /*
12017c478bd9Sstevel@tonic-gate * Allocate a packet structure from the cache.
12027c478bd9Sstevel@tonic-gate */
12037c478bd9Sstevel@tonic-gate
12047c478bd9Sstevel@tonic-gate if ((rc = alloc_packet(name, aid, &pp)) != 0)
12057c478bd9Sstevel@tonic-gate return (rc);
12067c478bd9Sstevel@tonic-gate
12077c478bd9Sstevel@tonic-gate if (ipp_packet_logging != 0 && pp->ippp_log == NULL) {
12087c478bd9Sstevel@tonic-gate
12097c478bd9Sstevel@tonic-gate /*
12107c478bd9Sstevel@tonic-gate * Logging is turned on but there's no log buffer. We need
12117c478bd9Sstevel@tonic-gate * to allocate one.
12127c478bd9Sstevel@tonic-gate */
12137c478bd9Sstevel@tonic-gate if ((pp->ippp_log = kmem_alloc(
12147c478bd9Sstevel@tonic-gate ipp_packet_log_entries * sizeof (ipp_log_t),
12157c478bd9Sstevel@tonic-gate KM_NOSLEEP)) != NULL) {
12167c478bd9Sstevel@tonic-gate pp->ippp_log_limit = ipp_packet_log_entries - 1;
12177c478bd9Sstevel@tonic-gate pp->ippp_log_windex = 0;
12187c478bd9Sstevel@tonic-gate }
12197c478bd9Sstevel@tonic-gate } else if (ipp_packet_logging == 0 && pp->ippp_log != NULL) {
12207c478bd9Sstevel@tonic-gate
12217c478bd9Sstevel@tonic-gate /*
12227c478bd9Sstevel@tonic-gate * A log buffer is present but logging has been turned off.
12237c478bd9Sstevel@tonic-gate * Free the buffer now,
12247c478bd9Sstevel@tonic-gate */
12257c478bd9Sstevel@tonic-gate
12267c478bd9Sstevel@tonic-gate kmem_free(pp->ippp_log,
12277c478bd9Sstevel@tonic-gate (pp->ippp_log_limit + 1) * sizeof (ipp_log_t));
12287c478bd9Sstevel@tonic-gate pp->ippp_log = NULL;
12297c478bd9Sstevel@tonic-gate pp->ippp_log_limit = 0;
12307c478bd9Sstevel@tonic-gate pp->ippp_log_windex = 0;
12317c478bd9Sstevel@tonic-gate }
12327c478bd9Sstevel@tonic-gate
12337c478bd9Sstevel@tonic-gate *ppp = pp;
12347c478bd9Sstevel@tonic-gate return (0);
12357c478bd9Sstevel@tonic-gate }
12367c478bd9Sstevel@tonic-gate #undef __FN__
12377c478bd9Sstevel@tonic-gate
12387c478bd9Sstevel@tonic-gate #define __FN__ "ipp_packet_free"
12397c478bd9Sstevel@tonic-gate void
ipp_packet_free(ipp_packet_t * pp)12407c478bd9Sstevel@tonic-gate ipp_packet_free(
12417c478bd9Sstevel@tonic-gate ipp_packet_t *pp)
12427c478bd9Sstevel@tonic-gate {
12437c478bd9Sstevel@tonic-gate
12447c478bd9Sstevel@tonic-gate ASSERT(pp != NULL);
12457c478bd9Sstevel@tonic-gate
12467c478bd9Sstevel@tonic-gate /*
12477c478bd9Sstevel@tonic-gate * If there is a private structure pointer set, call its free
12487c478bd9Sstevel@tonic-gate * function.
12497c478bd9Sstevel@tonic-gate */
12507c478bd9Sstevel@tonic-gate
12517c478bd9Sstevel@tonic-gate if (pp->ippp_private) {
12527c478bd9Sstevel@tonic-gate pp->ippp_private_free(pp->ippp_private);
12537c478bd9Sstevel@tonic-gate pp->ippp_private = NULL;
12547c478bd9Sstevel@tonic-gate pp->ippp_private_free = NULL;
12557c478bd9Sstevel@tonic-gate }
12567c478bd9Sstevel@tonic-gate
12577c478bd9Sstevel@tonic-gate /*
12587c478bd9Sstevel@tonic-gate * Free the packet structure back to the cache.
12597c478bd9Sstevel@tonic-gate */
12607c478bd9Sstevel@tonic-gate
12617c478bd9Sstevel@tonic-gate free_packet(pp);
12627c478bd9Sstevel@tonic-gate }
12637c478bd9Sstevel@tonic-gate #undef __FN__
12647c478bd9Sstevel@tonic-gate
12657c478bd9Sstevel@tonic-gate #define __FN__ "ipp_packet_add_class"
12667c478bd9Sstevel@tonic-gate int
ipp_packet_add_class(ipp_packet_t * pp,const char * name,ipp_action_id_t aid)12677c478bd9Sstevel@tonic-gate ipp_packet_add_class(
12687c478bd9Sstevel@tonic-gate ipp_packet_t *pp,
12697c478bd9Sstevel@tonic-gate const char *name,
12707c478bd9Sstevel@tonic-gate ipp_action_id_t aid)
12717c478bd9Sstevel@tonic-gate {
12727c478bd9Sstevel@tonic-gate ipp_class_t *cp;
12737c478bd9Sstevel@tonic-gate int rc;
12747c478bd9Sstevel@tonic-gate
12757c478bd9Sstevel@tonic-gate ASSERT(pp != NULL);
12767c478bd9Sstevel@tonic-gate
12777c478bd9Sstevel@tonic-gate /*
12787c478bd9Sstevel@tonic-gate * A name is required.
12797c478bd9Sstevel@tonic-gate */
12807c478bd9Sstevel@tonic-gate
12817c478bd9Sstevel@tonic-gate if (name == NULL || strlen(name) > MAXNAMELEN - 1)
12827c478bd9Sstevel@tonic-gate return (EINVAL);
12837c478bd9Sstevel@tonic-gate
12847c478bd9Sstevel@tonic-gate /*
12857c478bd9Sstevel@tonic-gate * Check if there is an available class structure.
12867c478bd9Sstevel@tonic-gate */
12877c478bd9Sstevel@tonic-gate
12887c478bd9Sstevel@tonic-gate if (pp->ippp_class_windex == pp->ippp_class_limit) {
12897c478bd9Sstevel@tonic-gate
12907c478bd9Sstevel@tonic-gate /*
12917c478bd9Sstevel@tonic-gate * No more structures. Re-allocate the array.
12927c478bd9Sstevel@tonic-gate */
12937c478bd9Sstevel@tonic-gate
12947c478bd9Sstevel@tonic-gate if ((rc = realloc_packet(pp)) != 0)
12957c478bd9Sstevel@tonic-gate return (rc);
12967c478bd9Sstevel@tonic-gate }
12977c478bd9Sstevel@tonic-gate ASSERT(pp->ippp_class_windex < pp->ippp_class_limit);
12987c478bd9Sstevel@tonic-gate
12997c478bd9Sstevel@tonic-gate /*
13007c478bd9Sstevel@tonic-gate * Set up a new class structure.
13017c478bd9Sstevel@tonic-gate */
13027c478bd9Sstevel@tonic-gate
13037c478bd9Sstevel@tonic-gate cp = &(pp->ippp_class_array[pp->ippp_class_windex++]);
13047c478bd9Sstevel@tonic-gate (void) strcpy(cp->ippc_name, name);
13057c478bd9Sstevel@tonic-gate cp->ippc_aid = aid;
13067c478bd9Sstevel@tonic-gate
13077c478bd9Sstevel@tonic-gate return (0);
13087c478bd9Sstevel@tonic-gate }
13097c478bd9Sstevel@tonic-gate #undef __FN__
13107c478bd9Sstevel@tonic-gate
13117c478bd9Sstevel@tonic-gate #define __FN__ "ipp_packet_process"
13127c478bd9Sstevel@tonic-gate int
ipp_packet_process(ipp_packet_t ** ppp)13137c478bd9Sstevel@tonic-gate ipp_packet_process(
13147c478bd9Sstevel@tonic-gate ipp_packet_t **ppp)
13157c478bd9Sstevel@tonic-gate {
13167c478bd9Sstevel@tonic-gate ipp_packet_t *pp;
13177c478bd9Sstevel@tonic-gate ipp_action_id_t aid;
13187c478bd9Sstevel@tonic-gate ipp_class_t *cp;
13197c478bd9Sstevel@tonic-gate ipp_log_t *lp;
13207c478bd9Sstevel@tonic-gate ipp_action_t *ap;
13217c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
13227c478bd9Sstevel@tonic-gate ipp_ops_t *ippo;
13237c478bd9Sstevel@tonic-gate int rc;
13247c478bd9Sstevel@tonic-gate
13257c478bd9Sstevel@tonic-gate ASSERT(ppp != NULL);
13267c478bd9Sstevel@tonic-gate pp = *ppp;
13277c478bd9Sstevel@tonic-gate ASSERT(pp != NULL);
13287c478bd9Sstevel@tonic-gate
13297c478bd9Sstevel@tonic-gate /*
13307c478bd9Sstevel@tonic-gate * Walk the class list.
13317c478bd9Sstevel@tonic-gate */
13327c478bd9Sstevel@tonic-gate
13337c478bd9Sstevel@tonic-gate while (pp->ippp_class_rindex < pp->ippp_class_windex) {
13347c478bd9Sstevel@tonic-gate cp = &(pp->ippp_class_array[pp->ippp_class_rindex]);
13357c478bd9Sstevel@tonic-gate
13367c478bd9Sstevel@tonic-gate /*
13377c478bd9Sstevel@tonic-gate * While there is a real action to invoke...
13387c478bd9Sstevel@tonic-gate */
13397c478bd9Sstevel@tonic-gate
13407c478bd9Sstevel@tonic-gate aid = cp->ippc_aid;
13417c478bd9Sstevel@tonic-gate while (aid != IPP_ACTION_CONT &&
13427c478bd9Sstevel@tonic-gate aid != IPP_ACTION_DEFER &&
13437c478bd9Sstevel@tonic-gate aid != IPP_ACTION_DROP) {
13447c478bd9Sstevel@tonic-gate
13457c478bd9Sstevel@tonic-gate ASSERT(aid != IPP_ACTION_INVAL);
13467c478bd9Sstevel@tonic-gate
13477c478bd9Sstevel@tonic-gate /*
13487c478bd9Sstevel@tonic-gate * Translate the action id to the action pointer.
13497c478bd9Sstevel@tonic-gate */
13507c478bd9Sstevel@tonic-gate
13517c478bd9Sstevel@tonic-gate if ((ap = hold_action(aid)) == NULL) {
13527c478bd9Sstevel@tonic-gate DBG1(DBG_PACKET,
13537c478bd9Sstevel@tonic-gate "action id '%d' not found\n", aid);
13547c478bd9Sstevel@tonic-gate return (ENOENT);
13557c478bd9Sstevel@tonic-gate }
13567c478bd9Sstevel@tonic-gate
13577c478bd9Sstevel@tonic-gate /*
13587c478bd9Sstevel@tonic-gate * Check that the action is available for use...
13597c478bd9Sstevel@tonic-gate */
13607c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_READER);
13617c478bd9Sstevel@tonic-gate if (ap->ippa_state != IPP_ASTATE_AVAILABLE) {
13627c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
13637c478bd9Sstevel@tonic-gate rele_action(ap);
13647c478bd9Sstevel@tonic-gate return (EPROTO);
13657c478bd9Sstevel@tonic-gate }
13667c478bd9Sstevel@tonic-gate
13677c478bd9Sstevel@tonic-gate /*
13687c478bd9Sstevel@tonic-gate * Increment the action's packet count to note that
13697c478bd9Sstevel@tonic-gate * it's being used.
13707c478bd9Sstevel@tonic-gate *
13717c478bd9Sstevel@tonic-gate * NOTE: We only have a read lock, so we need to use
13727c478bd9Sstevel@tonic-gate * atomic_add_32(). The read lock is still
13737c478bd9Sstevel@tonic-gate * important though as it is crucial to block
13747c478bd9Sstevel@tonic-gate * out a destroy operation between the action
13757c478bd9Sstevel@tonic-gate * state being checked and the packet count
13767c478bd9Sstevel@tonic-gate * being incremented.
13777c478bd9Sstevel@tonic-gate */
13787c478bd9Sstevel@tonic-gate
13791a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&(ap->ippa_packets));
13807c478bd9Sstevel@tonic-gate
13817c478bd9Sstevel@tonic-gate imp = ap->ippa_mod;
13827c478bd9Sstevel@tonic-gate ASSERT(imp != NULL);
13837c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
13847c478bd9Sstevel@tonic-gate
13857c478bd9Sstevel@tonic-gate ippo = imp->ippm_ops;
13867c478bd9Sstevel@tonic-gate ASSERT(ippo != NULL);
13877c478bd9Sstevel@tonic-gate
13887c478bd9Sstevel@tonic-gate /*
13897c478bd9Sstevel@tonic-gate * If there's a log, grab the next entry and fill it
13907c478bd9Sstevel@tonic-gate * in.
13917c478bd9Sstevel@tonic-gate */
13927c478bd9Sstevel@tonic-gate
13937c478bd9Sstevel@tonic-gate if (pp->ippp_log != NULL &&
13947c478bd9Sstevel@tonic-gate pp->ippp_log_windex <= pp->ippp_log_limit) {
13957c478bd9Sstevel@tonic-gate lp = &(pp->ippp_log[pp->ippp_log_windex++]);
13967c478bd9Sstevel@tonic-gate lp->ippl_aid = aid;
13977c478bd9Sstevel@tonic-gate (void) strcpy(lp->ippl_name, cp->ippc_name);
13987c478bd9Sstevel@tonic-gate gethrestime(&lp->ippl_begin);
13997c478bd9Sstevel@tonic-gate } else {
14007c478bd9Sstevel@tonic-gate lp = NULL;
14017c478bd9Sstevel@tonic-gate }
14027c478bd9Sstevel@tonic-gate
14037c478bd9Sstevel@tonic-gate /*
14047c478bd9Sstevel@tonic-gate * Invoke the action.
14057c478bd9Sstevel@tonic-gate */
14067c478bd9Sstevel@tonic-gate
14077c478bd9Sstevel@tonic-gate rc = ippo->ippo_action_invoke(aid, pp);
14087c478bd9Sstevel@tonic-gate
14097c478bd9Sstevel@tonic-gate /*
14107c478bd9Sstevel@tonic-gate * Also log the time that the action finished
14117c478bd9Sstevel@tonic-gate * processing.
14127c478bd9Sstevel@tonic-gate */
14137c478bd9Sstevel@tonic-gate
14147c478bd9Sstevel@tonic-gate if (lp != NULL)
14157c478bd9Sstevel@tonic-gate gethrestime(&lp->ippl_end);
14167c478bd9Sstevel@tonic-gate
14177c478bd9Sstevel@tonic-gate /*
14187c478bd9Sstevel@tonic-gate * Decrement the packet count.
14197c478bd9Sstevel@tonic-gate */
14207c478bd9Sstevel@tonic-gate
14211a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&(ap->ippa_packets));
14227c478bd9Sstevel@tonic-gate
14237c478bd9Sstevel@tonic-gate /*
14247c478bd9Sstevel@tonic-gate * If the class' action id is the same now as it was
14257c478bd9Sstevel@tonic-gate * before then clearly no 'next action' has been set.
14267c478bd9Sstevel@tonic-gate * This is a protocol error.
14277c478bd9Sstevel@tonic-gate */
14287c478bd9Sstevel@tonic-gate
14297c478bd9Sstevel@tonic-gate if (cp->ippc_aid == aid) {
14307c478bd9Sstevel@tonic-gate DBG1(DBG_PACKET,
14317c478bd9Sstevel@tonic-gate "action '%s' did not set next action\n",
14327c478bd9Sstevel@tonic-gate ap->ippa_name);
14337c478bd9Sstevel@tonic-gate rele_action(ap);
14347c478bd9Sstevel@tonic-gate return (EPROTO);
14357c478bd9Sstevel@tonic-gate }
14367c478bd9Sstevel@tonic-gate
14377c478bd9Sstevel@tonic-gate /*
14387c478bd9Sstevel@tonic-gate * The action did not complete successfully. Terminate
14397c478bd9Sstevel@tonic-gate * packet processing.
14407c478bd9Sstevel@tonic-gate */
14417c478bd9Sstevel@tonic-gate
14427c478bd9Sstevel@tonic-gate if (rc != 0) {
14437c478bd9Sstevel@tonic-gate DBG2(DBG_PACKET,
14447c478bd9Sstevel@tonic-gate "action error '%d' from action '%s'\n",
14457c478bd9Sstevel@tonic-gate rc, ap->ippa_name);
14467c478bd9Sstevel@tonic-gate rele_action(ap);
14477c478bd9Sstevel@tonic-gate return (rc);
14487c478bd9Sstevel@tonic-gate }
14497c478bd9Sstevel@tonic-gate
14507c478bd9Sstevel@tonic-gate rele_action(ap);
14517c478bd9Sstevel@tonic-gate
14527c478bd9Sstevel@tonic-gate /*
14537c478bd9Sstevel@tonic-gate * Look at the next action.
14547c478bd9Sstevel@tonic-gate */
14557c478bd9Sstevel@tonic-gate
14567c478bd9Sstevel@tonic-gate aid = cp->ippc_aid;
14577c478bd9Sstevel@tonic-gate }
14587c478bd9Sstevel@tonic-gate
14597c478bd9Sstevel@tonic-gate /*
14607c478bd9Sstevel@tonic-gate * No more real actions to invoke, check for 'virtual' ones.
14617c478bd9Sstevel@tonic-gate */
14627c478bd9Sstevel@tonic-gate
14637c478bd9Sstevel@tonic-gate /*
14647c478bd9Sstevel@tonic-gate * Packet deferred: module has held onto packet for processing
14657c478bd9Sstevel@tonic-gate * later.
14667c478bd9Sstevel@tonic-gate */
14677c478bd9Sstevel@tonic-gate
14687c478bd9Sstevel@tonic-gate if (cp->ippc_aid == IPP_ACTION_DEFER) {
14697c478bd9Sstevel@tonic-gate *ppp = NULL;
14707c478bd9Sstevel@tonic-gate return (0);
14717c478bd9Sstevel@tonic-gate }
14727c478bd9Sstevel@tonic-gate
14737c478bd9Sstevel@tonic-gate /*
14747c478bd9Sstevel@tonic-gate * Packet dropped: free the packet and discontinue processing.
14757c478bd9Sstevel@tonic-gate */
14767c478bd9Sstevel@tonic-gate
14777c478bd9Sstevel@tonic-gate if (cp->ippc_aid == IPP_ACTION_DROP) {
14787c478bd9Sstevel@tonic-gate freemsg(pp->ippp_data);
14797c478bd9Sstevel@tonic-gate ipp_packet_free(pp);
14807c478bd9Sstevel@tonic-gate *ppp = NULL;
14817c478bd9Sstevel@tonic-gate return (0);
14827c478bd9Sstevel@tonic-gate }
14837c478bd9Sstevel@tonic-gate
14847c478bd9Sstevel@tonic-gate /*
14857c478bd9Sstevel@tonic-gate * Must be 'continue processing': move onto the next class.
14867c478bd9Sstevel@tonic-gate */
14877c478bd9Sstevel@tonic-gate
14887c478bd9Sstevel@tonic-gate ASSERT(cp->ippc_aid == IPP_ACTION_CONT);
14897c478bd9Sstevel@tonic-gate pp->ippp_class_rindex++;
14907c478bd9Sstevel@tonic-gate }
14917c478bd9Sstevel@tonic-gate
14927c478bd9Sstevel@tonic-gate return (0);
14937c478bd9Sstevel@tonic-gate }
14947c478bd9Sstevel@tonic-gate #undef __FN__
14957c478bd9Sstevel@tonic-gate
14967c478bd9Sstevel@tonic-gate #define __FN__ "ipp_packet_next"
14977c478bd9Sstevel@tonic-gate int
ipp_packet_next(ipp_packet_t * pp,ipp_action_id_t aid)14987c478bd9Sstevel@tonic-gate ipp_packet_next(
14997c478bd9Sstevel@tonic-gate ipp_packet_t *pp,
15007c478bd9Sstevel@tonic-gate ipp_action_id_t aid)
15017c478bd9Sstevel@tonic-gate {
15027c478bd9Sstevel@tonic-gate ipp_action_t *ap;
15037c478bd9Sstevel@tonic-gate ipp_class_t *cp;
15047c478bd9Sstevel@tonic-gate
15057c478bd9Sstevel@tonic-gate ASSERT(pp != NULL);
15067c478bd9Sstevel@tonic-gate
15077c478bd9Sstevel@tonic-gate cp = &(pp->ippp_class_array[pp->ippp_class_rindex]);
15087c478bd9Sstevel@tonic-gate ASSERT(cp != NULL);
15097c478bd9Sstevel@tonic-gate
15107c478bd9Sstevel@tonic-gate /*
15117c478bd9Sstevel@tonic-gate * Check for a special case 'virtual action' id.
15127c478bd9Sstevel@tonic-gate */
15137c478bd9Sstevel@tonic-gate
15147c478bd9Sstevel@tonic-gate switch (aid) {
15157c478bd9Sstevel@tonic-gate case IPP_ACTION_INVAL:
15167c478bd9Sstevel@tonic-gate return (EINVAL);
15177c478bd9Sstevel@tonic-gate case IPP_ACTION_DEFER:
15187c478bd9Sstevel@tonic-gate /*FALLTHRU*/
15197c478bd9Sstevel@tonic-gate case IPP_ACTION_CONT:
15207c478bd9Sstevel@tonic-gate /*FALLTHRU*/
15217c478bd9Sstevel@tonic-gate case IPP_ACTION_DROP:
15227c478bd9Sstevel@tonic-gate break;
15237c478bd9Sstevel@tonic-gate default:
15247c478bd9Sstevel@tonic-gate
15257c478bd9Sstevel@tonic-gate /*
15267c478bd9Sstevel@tonic-gate * Not a virtual action so try to translate the action id
15277c478bd9Sstevel@tonic-gate * into the action pointer to confirm the actions existence.
15287c478bd9Sstevel@tonic-gate */
15297c478bd9Sstevel@tonic-gate
15307c478bd9Sstevel@tonic-gate if ((ap = hold_action(aid)) == NULL) {
15317c478bd9Sstevel@tonic-gate DBG0(DBG_PACKET, "invalid action\n");
15327c478bd9Sstevel@tonic-gate return (ENOENT);
15337c478bd9Sstevel@tonic-gate }
15347c478bd9Sstevel@tonic-gate rele_action(ap);
15357c478bd9Sstevel@tonic-gate
15367c478bd9Sstevel@tonic-gate break;
15377c478bd9Sstevel@tonic-gate }
15387c478bd9Sstevel@tonic-gate
15397c478bd9Sstevel@tonic-gate /*
15407c478bd9Sstevel@tonic-gate * Set the class' new action id.
15417c478bd9Sstevel@tonic-gate */
15427c478bd9Sstevel@tonic-gate
15437c478bd9Sstevel@tonic-gate cp->ippc_aid = aid;
15447c478bd9Sstevel@tonic-gate
15457c478bd9Sstevel@tonic-gate return (0);
15467c478bd9Sstevel@tonic-gate }
15477c478bd9Sstevel@tonic-gate #undef __FN__
15487c478bd9Sstevel@tonic-gate
15497c478bd9Sstevel@tonic-gate #define __FN__ "ipp_packet_set_data"
15507c478bd9Sstevel@tonic-gate void
ipp_packet_set_data(ipp_packet_t * pp,mblk_t * data)15517c478bd9Sstevel@tonic-gate ipp_packet_set_data(
15527c478bd9Sstevel@tonic-gate ipp_packet_t *pp,
15537c478bd9Sstevel@tonic-gate mblk_t *data)
15547c478bd9Sstevel@tonic-gate {
15557c478bd9Sstevel@tonic-gate ASSERT(pp != NULL);
15567c478bd9Sstevel@tonic-gate pp->ippp_data = data;
15577c478bd9Sstevel@tonic-gate }
15587c478bd9Sstevel@tonic-gate #undef __FN__
15597c478bd9Sstevel@tonic-gate
15607c478bd9Sstevel@tonic-gate #define __FN__ "ipp_packet_get_data"
15617c478bd9Sstevel@tonic-gate mblk_t *
ipp_packet_get_data(ipp_packet_t * pp)15627c478bd9Sstevel@tonic-gate ipp_packet_get_data(
15637c478bd9Sstevel@tonic-gate ipp_packet_t *pp)
15647c478bd9Sstevel@tonic-gate {
15657c478bd9Sstevel@tonic-gate ASSERT(pp != NULL);
15667c478bd9Sstevel@tonic-gate return (pp->ippp_data);
15677c478bd9Sstevel@tonic-gate }
15687c478bd9Sstevel@tonic-gate #undef __FN__
15697c478bd9Sstevel@tonic-gate
15707c478bd9Sstevel@tonic-gate #define __FN__ "ipp_packet_set_private"
15717c478bd9Sstevel@tonic-gate void
ipp_packet_set_private(ipp_packet_t * pp,void * buf,void (* free_func)(void *))15727c478bd9Sstevel@tonic-gate ipp_packet_set_private(
15737c478bd9Sstevel@tonic-gate ipp_packet_t *pp,
15747c478bd9Sstevel@tonic-gate void *buf,
15757c478bd9Sstevel@tonic-gate void (*free_func)(void *))
15767c478bd9Sstevel@tonic-gate {
15777c478bd9Sstevel@tonic-gate ASSERT(pp != NULL);
15787c478bd9Sstevel@tonic-gate ASSERT(free_func != NULL);
15797c478bd9Sstevel@tonic-gate
15807c478bd9Sstevel@tonic-gate pp->ippp_private = buf;
15817c478bd9Sstevel@tonic-gate pp->ippp_private_free = free_func;
15827c478bd9Sstevel@tonic-gate }
15837c478bd9Sstevel@tonic-gate #undef __FN__
15847c478bd9Sstevel@tonic-gate
15857c478bd9Sstevel@tonic-gate #define __FN__ "ipp_packet_get_private"
15867c478bd9Sstevel@tonic-gate void *
ipp_packet_get_private(ipp_packet_t * pp)15877c478bd9Sstevel@tonic-gate ipp_packet_get_private(
15887c478bd9Sstevel@tonic-gate ipp_packet_t *pp)
15897c478bd9Sstevel@tonic-gate {
15907c478bd9Sstevel@tonic-gate ASSERT(pp != NULL);
15917c478bd9Sstevel@tonic-gate return (pp->ippp_private);
15927c478bd9Sstevel@tonic-gate }
15937c478bd9Sstevel@tonic-gate #undef __FN__
15947c478bd9Sstevel@tonic-gate
15957c478bd9Sstevel@tonic-gate /*
15967c478bd9Sstevel@tonic-gate * Statistics interface.
15977c478bd9Sstevel@tonic-gate */
15987c478bd9Sstevel@tonic-gate
15997c478bd9Sstevel@tonic-gate #define __FN__ "ipp_stat_create"
16007c478bd9Sstevel@tonic-gate int
ipp_stat_create(ipp_action_id_t aid,const char * name,int nstat,int (* update)(ipp_stat_t *,void *,int),void * arg,ipp_stat_t ** spp)16017c478bd9Sstevel@tonic-gate ipp_stat_create(
16027c478bd9Sstevel@tonic-gate ipp_action_id_t aid,
16037c478bd9Sstevel@tonic-gate const char *name,
16047c478bd9Sstevel@tonic-gate int nstat,
16057c478bd9Sstevel@tonic-gate int (*update)(ipp_stat_t *, void *, int),
16067c478bd9Sstevel@tonic-gate void *arg,
16077c478bd9Sstevel@tonic-gate ipp_stat_t **spp)
16087c478bd9Sstevel@tonic-gate {
16097c478bd9Sstevel@tonic-gate ipp_action_t *ap;
16107c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
16117c478bd9Sstevel@tonic-gate ipp_stat_impl_t *sip;
16127c478bd9Sstevel@tonic-gate ipp_stat_t *sp;
16137c478bd9Sstevel@tonic-gate kstat_t *ksp;
16147c478bd9Sstevel@tonic-gate char *class;
16157c478bd9Sstevel@tonic-gate char *modname;
16167c478bd9Sstevel@tonic-gate int instance;
16177c478bd9Sstevel@tonic-gate
16187c478bd9Sstevel@tonic-gate ASSERT(spp != NULL);
16197c478bd9Sstevel@tonic-gate
16207c478bd9Sstevel@tonic-gate /*
16217c478bd9Sstevel@tonic-gate * Sanity check the arguments.
16227c478bd9Sstevel@tonic-gate */
16237c478bd9Sstevel@tonic-gate
16247c478bd9Sstevel@tonic-gate if (name == NULL || nstat <= 0 || update == NULL)
16257c478bd9Sstevel@tonic-gate return (EINVAL);
16267c478bd9Sstevel@tonic-gate
16277c478bd9Sstevel@tonic-gate /*
16287c478bd9Sstevel@tonic-gate * Translate the action id into the action pointer.
16297c478bd9Sstevel@tonic-gate */
16307c478bd9Sstevel@tonic-gate
16317c478bd9Sstevel@tonic-gate if ((ap = hold_action(aid)) == NULL)
16327c478bd9Sstevel@tonic-gate return (ENOENT);
16337c478bd9Sstevel@tonic-gate
16347c478bd9Sstevel@tonic-gate /*
16357c478bd9Sstevel@tonic-gate * Grab relevant action and module information.
16367c478bd9Sstevel@tonic-gate */
16377c478bd9Sstevel@tonic-gate
16387c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_READER);
16397c478bd9Sstevel@tonic-gate class = ap->ippa_name;
16407c478bd9Sstevel@tonic-gate instance = (int)ap->ippa_id;
16417c478bd9Sstevel@tonic-gate
16427c478bd9Sstevel@tonic-gate imp = ap->ippa_mod;
16437c478bd9Sstevel@tonic-gate ASSERT(imp != NULL);
16447c478bd9Sstevel@tonic-gate
16457c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_READER);
16467c478bd9Sstevel@tonic-gate modname = imp->ippm_name;
16477c478bd9Sstevel@tonic-gate
16487c478bd9Sstevel@tonic-gate /*
16497c478bd9Sstevel@tonic-gate * Allocate a stats info structure.
16507c478bd9Sstevel@tonic-gate */
16517c478bd9Sstevel@tonic-gate
16527c478bd9Sstevel@tonic-gate if ((sip = kmem_alloc(sizeof (ipp_stat_impl_t), KM_NOSLEEP)) == NULL)
16537c478bd9Sstevel@tonic-gate return (ENOMEM);
16547c478bd9Sstevel@tonic-gate
16557c478bd9Sstevel@tonic-gate /*
16567c478bd9Sstevel@tonic-gate * Create a set of kstats.
16577c478bd9Sstevel@tonic-gate */
16587c478bd9Sstevel@tonic-gate
16597c478bd9Sstevel@tonic-gate DBG2(DBG_STATS, "creating stat set '%s' for action '%s'\n",
16607c478bd9Sstevel@tonic-gate name, class);
1661d624471bSelowe if ((ksp = kstat_create(modname, instance, name, class,
16627c478bd9Sstevel@tonic-gate KSTAT_TYPE_NAMED, nstat, KSTAT_FLAG_WRITABLE)) == NULL) {
16637c478bd9Sstevel@tonic-gate kmem_free(sip, sizeof (ipp_stat_impl_t));
16647c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
16657c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
16667c478bd9Sstevel@tonic-gate return (EINVAL); /* Assume EINVAL was the cause */
16677c478bd9Sstevel@tonic-gate }
16687c478bd9Sstevel@tonic-gate
16697c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
16707c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
16717c478bd9Sstevel@tonic-gate
16727c478bd9Sstevel@tonic-gate DBG1(DBG_STATS, "ks_data = %p\n", ksp->ks_data);
16737c478bd9Sstevel@tonic-gate
16747c478bd9Sstevel@tonic-gate /*
16757c478bd9Sstevel@tonic-gate * Set up the kstats structure with a private data pointer and an
16767c478bd9Sstevel@tonic-gate * 'update' function.
16777c478bd9Sstevel@tonic-gate */
16787c478bd9Sstevel@tonic-gate
16797c478bd9Sstevel@tonic-gate ksp->ks_update = update_stats;
16807c478bd9Sstevel@tonic-gate ksp->ks_private = (void *)sip;
16817c478bd9Sstevel@tonic-gate
16827c478bd9Sstevel@tonic-gate /*
16837c478bd9Sstevel@tonic-gate * Keep a reference to the kstats structure in our own stats info
16847c478bd9Sstevel@tonic-gate * structure.
16857c478bd9Sstevel@tonic-gate */
16867c478bd9Sstevel@tonic-gate
16877c478bd9Sstevel@tonic-gate sip->ippsi_ksp = ksp;
16887c478bd9Sstevel@tonic-gate sip->ippsi_data = ksp->ks_data;
16897c478bd9Sstevel@tonic-gate
16907c478bd9Sstevel@tonic-gate /*
16917c478bd9Sstevel@tonic-gate * Fill in the rest of the stats info structure.
16927c478bd9Sstevel@tonic-gate */
16937c478bd9Sstevel@tonic-gate
16947c478bd9Sstevel@tonic-gate (void) strcpy(sip->ippsi_name, name);
16957c478bd9Sstevel@tonic-gate sip->ippsi_arg = arg;
16967c478bd9Sstevel@tonic-gate sip->ippsi_update = update;
16977c478bd9Sstevel@tonic-gate sip->ippsi_limit = nstat;
16987c478bd9Sstevel@tonic-gate sip->ippsi_count = 0;
16997c478bd9Sstevel@tonic-gate mutex_init(sip->ippsi_lock, NULL, MUTEX_ADAPTIVE,
17007c478bd9Sstevel@tonic-gate (void *)ipltospl(LOCK_LEVEL));
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate /*
17037c478bd9Sstevel@tonic-gate * Case the stats info structure to a semi-opaque structure that
17047c478bd9Sstevel@tonic-gate * we pass back to the caller.
17057c478bd9Sstevel@tonic-gate */
17067c478bd9Sstevel@tonic-gate
17077c478bd9Sstevel@tonic-gate sp = (ipp_stat_t *)sip;
17087c478bd9Sstevel@tonic-gate ASSERT(sp->ipps_data == sip->ippsi_data);
17097c478bd9Sstevel@tonic-gate *spp = sp;
17107c478bd9Sstevel@tonic-gate
17117c478bd9Sstevel@tonic-gate rele_action(ap);
17127c478bd9Sstevel@tonic-gate return (0);
17137c478bd9Sstevel@tonic-gate }
17147c478bd9Sstevel@tonic-gate #undef __FN__
17157c478bd9Sstevel@tonic-gate
17167c478bd9Sstevel@tonic-gate #define __FN__ "ipp_stat_install"
17177c478bd9Sstevel@tonic-gate void
ipp_stat_install(ipp_stat_t * sp)17187c478bd9Sstevel@tonic-gate ipp_stat_install(
17197c478bd9Sstevel@tonic-gate ipp_stat_t *sp)
17207c478bd9Sstevel@tonic-gate {
17217c478bd9Sstevel@tonic-gate ipp_stat_impl_t *sip = (ipp_stat_impl_t *)sp;
17227c478bd9Sstevel@tonic-gate
17237c478bd9Sstevel@tonic-gate ASSERT(sp != NULL);
17247c478bd9Sstevel@tonic-gate
17257c478bd9Sstevel@tonic-gate /*
17267c478bd9Sstevel@tonic-gate * Install the set of kstats referenced by the stats info structure.
17277c478bd9Sstevel@tonic-gate */
17287c478bd9Sstevel@tonic-gate
17297c478bd9Sstevel@tonic-gate DBG1(DBG_STATS, "installing stat set '%s'\n", sip->ippsi_name);
17307c478bd9Sstevel@tonic-gate kstat_install(sip->ippsi_ksp);
17317c478bd9Sstevel@tonic-gate }
17327c478bd9Sstevel@tonic-gate #undef __FN__
17337c478bd9Sstevel@tonic-gate
17347c478bd9Sstevel@tonic-gate #define __FN__ "ipp_stat_destroy"
17357c478bd9Sstevel@tonic-gate void
ipp_stat_destroy(ipp_stat_t * sp)17367c478bd9Sstevel@tonic-gate ipp_stat_destroy(
17377c478bd9Sstevel@tonic-gate ipp_stat_t *sp)
17387c478bd9Sstevel@tonic-gate {
17397c478bd9Sstevel@tonic-gate ipp_stat_impl_t *sip = (ipp_stat_impl_t *)sp;
17407c478bd9Sstevel@tonic-gate
17417c478bd9Sstevel@tonic-gate ASSERT(sp != NULL);
17427c478bd9Sstevel@tonic-gate
17437c478bd9Sstevel@tonic-gate /*
17447c478bd9Sstevel@tonic-gate * Destroy the set of kstats referenced by the stats info structure.
17457c478bd9Sstevel@tonic-gate */
17467c478bd9Sstevel@tonic-gate
17477c478bd9Sstevel@tonic-gate DBG1(DBG_STATS, "destroying stat set '%s'\n", sip->ippsi_name);
17487c478bd9Sstevel@tonic-gate kstat_delete(sip->ippsi_ksp);
17497c478bd9Sstevel@tonic-gate
17507c478bd9Sstevel@tonic-gate /*
17517c478bd9Sstevel@tonic-gate * Destroy the stats info structure itself.
17527c478bd9Sstevel@tonic-gate */
17537c478bd9Sstevel@tonic-gate
17547c478bd9Sstevel@tonic-gate mutex_destroy(sip->ippsi_lock);
17557c478bd9Sstevel@tonic-gate kmem_free(sip, sizeof (ipp_stat_impl_t));
17567c478bd9Sstevel@tonic-gate }
17577c478bd9Sstevel@tonic-gate #undef __FN__
17587c478bd9Sstevel@tonic-gate
17597c478bd9Sstevel@tonic-gate #define __FN__ "ipp_stat_named_init"
17607c478bd9Sstevel@tonic-gate int
ipp_stat_named_init(ipp_stat_t * sp,const char * name,uchar_t type,ipp_named_t * np)17617c478bd9Sstevel@tonic-gate ipp_stat_named_init(
17627c478bd9Sstevel@tonic-gate ipp_stat_t *sp,
17637c478bd9Sstevel@tonic-gate const char *name,
17647c478bd9Sstevel@tonic-gate uchar_t type,
17657c478bd9Sstevel@tonic-gate ipp_named_t *np)
17667c478bd9Sstevel@tonic-gate {
17677c478bd9Sstevel@tonic-gate ipp_stat_impl_t *sip = (ipp_stat_impl_t *)sp;
17687c478bd9Sstevel@tonic-gate uchar_t ktype;
17697c478bd9Sstevel@tonic-gate
17707c478bd9Sstevel@tonic-gate ASSERT(sp != NULL);
17717c478bd9Sstevel@tonic-gate ASSERT(np != NULL);
17727c478bd9Sstevel@tonic-gate
17737c478bd9Sstevel@tonic-gate if (name == NULL)
17747c478bd9Sstevel@tonic-gate return (EINVAL);
17757c478bd9Sstevel@tonic-gate
17767c478bd9Sstevel@tonic-gate if ((type & IPP_STAT_TAG) == 0)
17777c478bd9Sstevel@tonic-gate return (EINVAL);
17787c478bd9Sstevel@tonic-gate ktype = type & ~IPP_STAT_TAG;
17797c478bd9Sstevel@tonic-gate
17807c478bd9Sstevel@tonic-gate /*
17817c478bd9Sstevel@tonic-gate * Check we will not exceed the maximum number of a stats that was
17827c478bd9Sstevel@tonic-gate * indicated during set creation.
17837c478bd9Sstevel@tonic-gate */
17847c478bd9Sstevel@tonic-gate
17857c478bd9Sstevel@tonic-gate mutex_enter(sip->ippsi_lock);
17867c478bd9Sstevel@tonic-gate if (sip->ippsi_count >= sip->ippsi_limit) {
17877c478bd9Sstevel@tonic-gate mutex_exit(sip->ippsi_lock);
17887c478bd9Sstevel@tonic-gate return (ENOSPC);
17897c478bd9Sstevel@tonic-gate }
17907c478bd9Sstevel@tonic-gate
17917c478bd9Sstevel@tonic-gate /*
17927c478bd9Sstevel@tonic-gate * Bump the count.
17937c478bd9Sstevel@tonic-gate */
17947c478bd9Sstevel@tonic-gate
17957c478bd9Sstevel@tonic-gate sip->ippsi_count++;
17967c478bd9Sstevel@tonic-gate
17977c478bd9Sstevel@tonic-gate /*
17987c478bd9Sstevel@tonic-gate * Create a new named kstat.
17997c478bd9Sstevel@tonic-gate */
18007c478bd9Sstevel@tonic-gate
18017c478bd9Sstevel@tonic-gate DBG3(DBG_STATS, "%s.%s: knp = %p\n", sip->ippsi_name, name, np);
1802d624471bSelowe kstat_named_init(np, name, ktype);
18037c478bd9Sstevel@tonic-gate mutex_exit(sip->ippsi_lock);
18047c478bd9Sstevel@tonic-gate
18057c478bd9Sstevel@tonic-gate return (0);
18067c478bd9Sstevel@tonic-gate }
18077c478bd9Sstevel@tonic-gate #undef __FN__
18087c478bd9Sstevel@tonic-gate
18097c478bd9Sstevel@tonic-gate #define __FN__ "ipp_stat_named_op"
18107c478bd9Sstevel@tonic-gate int
ipp_stat_named_op(ipp_named_t * np,void * valp,int rw)18117c478bd9Sstevel@tonic-gate ipp_stat_named_op(
18127c478bd9Sstevel@tonic-gate ipp_named_t *np,
18137c478bd9Sstevel@tonic-gate void *valp,
18147c478bd9Sstevel@tonic-gate int rw)
18157c478bd9Sstevel@tonic-gate {
18167c478bd9Sstevel@tonic-gate kstat_named_t *knp;
18177c478bd9Sstevel@tonic-gate uchar_t type;
18187c478bd9Sstevel@tonic-gate int rc = 0;
18197c478bd9Sstevel@tonic-gate
18207c478bd9Sstevel@tonic-gate ASSERT(np != NULL);
18217c478bd9Sstevel@tonic-gate ASSERT(valp != NULL);
18227c478bd9Sstevel@tonic-gate
18237c478bd9Sstevel@tonic-gate knp = np;
18247c478bd9Sstevel@tonic-gate type = knp->data_type | IPP_STAT_TAG;
18257c478bd9Sstevel@tonic-gate
18267c478bd9Sstevel@tonic-gate /*
18277c478bd9Sstevel@tonic-gate * Copy data to or from the named kstat, depending on the specified
18287c478bd9Sstevel@tonic-gate * opcode.
18297c478bd9Sstevel@tonic-gate */
18307c478bd9Sstevel@tonic-gate
18317c478bd9Sstevel@tonic-gate switch (rw) {
18327c478bd9Sstevel@tonic-gate case IPP_STAT_WRITE:
18337c478bd9Sstevel@tonic-gate switch (type) {
18347c478bd9Sstevel@tonic-gate case IPP_STAT_INT32:
18357c478bd9Sstevel@tonic-gate *(int32_t *)valp = knp->value.i32;
18367c478bd9Sstevel@tonic-gate break;
18377c478bd9Sstevel@tonic-gate case IPP_STAT_UINT32:
18387c478bd9Sstevel@tonic-gate *(uint32_t *)valp = knp->value.ui32;
18397c478bd9Sstevel@tonic-gate break;
18407c478bd9Sstevel@tonic-gate case IPP_STAT_INT64:
18417c478bd9Sstevel@tonic-gate *(int64_t *)valp = knp->value.i64;
18427c478bd9Sstevel@tonic-gate break;
18437c478bd9Sstevel@tonic-gate case IPP_STAT_UINT64:
18447c478bd9Sstevel@tonic-gate *(uint64_t *)valp = knp->value.ui64;
18457c478bd9Sstevel@tonic-gate break;
18467c478bd9Sstevel@tonic-gate case IPP_STAT_STRING:
18477c478bd9Sstevel@tonic-gate (void) strncpy(valp, knp->value.c, 16);
18487c478bd9Sstevel@tonic-gate break;
18497c478bd9Sstevel@tonic-gate default:
18507c478bd9Sstevel@tonic-gate ASSERT(0); /* should not reach here */
18517c478bd9Sstevel@tonic-gate break;
18527c478bd9Sstevel@tonic-gate }
18537c478bd9Sstevel@tonic-gate
18547c478bd9Sstevel@tonic-gate break;
18557c478bd9Sstevel@tonic-gate case IPP_STAT_READ:
18567c478bd9Sstevel@tonic-gate switch (type) {
18577c478bd9Sstevel@tonic-gate case IPP_STAT_INT32:
18587c478bd9Sstevel@tonic-gate knp->value.i32 = *(int32_t *)valp;
18597c478bd9Sstevel@tonic-gate break;
18607c478bd9Sstevel@tonic-gate case IPP_STAT_UINT32:
18617c478bd9Sstevel@tonic-gate knp->value.ui32 = *(uint32_t *)valp;
18627c478bd9Sstevel@tonic-gate break;
18637c478bd9Sstevel@tonic-gate case IPP_STAT_INT64:
18647c478bd9Sstevel@tonic-gate knp->value.i64 = *(int64_t *)valp;
18657c478bd9Sstevel@tonic-gate break;
18667c478bd9Sstevel@tonic-gate case IPP_STAT_UINT64:
18677c478bd9Sstevel@tonic-gate knp->value.ui64 = *(uint64_t *)valp;
18687c478bd9Sstevel@tonic-gate break;
18697c478bd9Sstevel@tonic-gate case IPP_STAT_STRING:
18707c478bd9Sstevel@tonic-gate (void) strncpy(knp->value.c, valp, 16);
18717c478bd9Sstevel@tonic-gate break;
18727c478bd9Sstevel@tonic-gate default:
18737c478bd9Sstevel@tonic-gate ASSERT(0); /* should not reach here */
18747c478bd9Sstevel@tonic-gate break;
18757c478bd9Sstevel@tonic-gate }
18767c478bd9Sstevel@tonic-gate
18777c478bd9Sstevel@tonic-gate break;
18787c478bd9Sstevel@tonic-gate default:
18797c478bd9Sstevel@tonic-gate rc = EINVAL;
18807c478bd9Sstevel@tonic-gate }
18817c478bd9Sstevel@tonic-gate
18827c478bd9Sstevel@tonic-gate return (rc);
18837c478bd9Sstevel@tonic-gate }
18847c478bd9Sstevel@tonic-gate #undef __FN__
18857c478bd9Sstevel@tonic-gate
18867c478bd9Sstevel@tonic-gate /*
18877c478bd9Sstevel@tonic-gate * Local functions (for local people. There's nothing for you here!)
18887c478bd9Sstevel@tonic-gate */
18897c478bd9Sstevel@tonic-gate
18907c478bd9Sstevel@tonic-gate #define __FN__ "ref_mod"
18917c478bd9Sstevel@tonic-gate static int
ref_mod(ipp_action_t * ap,ipp_mod_t * imp)18927c478bd9Sstevel@tonic-gate ref_mod(
18937c478bd9Sstevel@tonic-gate ipp_action_t *ap,
18947c478bd9Sstevel@tonic-gate ipp_mod_t *imp)
18957c478bd9Sstevel@tonic-gate {
18967c478bd9Sstevel@tonic-gate ipp_ref_t **rpp;
18977c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
18987c478bd9Sstevel@tonic-gate
18997c478bd9Sstevel@tonic-gate ASSERT(rw_write_held(ap->ippa_lock));
19007c478bd9Sstevel@tonic-gate ASSERT(rw_write_held(imp->ippm_lock));
19017c478bd9Sstevel@tonic-gate
19027c478bd9Sstevel@tonic-gate /*
19037c478bd9Sstevel@tonic-gate * Add the new reference at the end of the module's list.
19047c478bd9Sstevel@tonic-gate */
19057c478bd9Sstevel@tonic-gate
19067c478bd9Sstevel@tonic-gate rpp = &(imp->ippm_action);
19077c478bd9Sstevel@tonic-gate while ((rp = *rpp) != NULL) {
19087c478bd9Sstevel@tonic-gate ASSERT(rp->ippr_action != ap);
19097c478bd9Sstevel@tonic-gate rpp = &(rp->ippr_nextp);
19107c478bd9Sstevel@tonic-gate }
19117c478bd9Sstevel@tonic-gate
19127c478bd9Sstevel@tonic-gate /*
19137c478bd9Sstevel@tonic-gate * Allocate a reference structure.
19147c478bd9Sstevel@tonic-gate */
19157c478bd9Sstevel@tonic-gate
19167c478bd9Sstevel@tonic-gate if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL)
19177c478bd9Sstevel@tonic-gate return (ENOMEM);
19187c478bd9Sstevel@tonic-gate
19197c478bd9Sstevel@tonic-gate /*
19207c478bd9Sstevel@tonic-gate * Set the reference to the action and link it onto the module's list.
19217c478bd9Sstevel@tonic-gate */
19227c478bd9Sstevel@tonic-gate
19237c478bd9Sstevel@tonic-gate rp->ippr_action = ap;
19247c478bd9Sstevel@tonic-gate *rpp = rp;
19257c478bd9Sstevel@tonic-gate
19267c478bd9Sstevel@tonic-gate /*
19277c478bd9Sstevel@tonic-gate * Keep a 'back pointer' from the action structure to the module
19287c478bd9Sstevel@tonic-gate * structure.
19297c478bd9Sstevel@tonic-gate */
19307c478bd9Sstevel@tonic-gate
19317c478bd9Sstevel@tonic-gate ap->ippa_mod = imp;
19327c478bd9Sstevel@tonic-gate
19337c478bd9Sstevel@tonic-gate return (0);
19347c478bd9Sstevel@tonic-gate }
19357c478bd9Sstevel@tonic-gate #undef __FN__
19367c478bd9Sstevel@tonic-gate
19377c478bd9Sstevel@tonic-gate #define __FN__ "unref_mod"
19387c478bd9Sstevel@tonic-gate static void
unref_mod(ipp_action_t * ap,ipp_mod_t * imp)19397c478bd9Sstevel@tonic-gate unref_mod(
19407c478bd9Sstevel@tonic-gate ipp_action_t *ap,
19417c478bd9Sstevel@tonic-gate ipp_mod_t *imp)
19427c478bd9Sstevel@tonic-gate {
19437c478bd9Sstevel@tonic-gate ipp_ref_t **rpp;
19447c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
19457c478bd9Sstevel@tonic-gate
19467c478bd9Sstevel@tonic-gate ASSERT(rw_write_held(ap->ippa_lock));
19477c478bd9Sstevel@tonic-gate ASSERT(rw_write_held(imp->ippm_lock));
19487c478bd9Sstevel@tonic-gate
19497c478bd9Sstevel@tonic-gate /*
19507c478bd9Sstevel@tonic-gate * Scan the module's list for the reference to the action.
19517c478bd9Sstevel@tonic-gate */
19527c478bd9Sstevel@tonic-gate
19537c478bd9Sstevel@tonic-gate rpp = &(imp->ippm_action);
19547c478bd9Sstevel@tonic-gate while ((rp = *rpp) != NULL) {
19557c478bd9Sstevel@tonic-gate if (rp->ippr_action == ap)
19567c478bd9Sstevel@tonic-gate break;
19577c478bd9Sstevel@tonic-gate rpp = &(rp->ippr_nextp);
19587c478bd9Sstevel@tonic-gate }
19597c478bd9Sstevel@tonic-gate ASSERT(rp != NULL);
19607c478bd9Sstevel@tonic-gate
19617c478bd9Sstevel@tonic-gate /*
19627c478bd9Sstevel@tonic-gate * Unlink the reference structure and free it.
19637c478bd9Sstevel@tonic-gate */
19647c478bd9Sstevel@tonic-gate
19657c478bd9Sstevel@tonic-gate *rpp = rp->ippr_nextp;
19667c478bd9Sstevel@tonic-gate kmem_free(rp, sizeof (ipp_ref_t));
19677c478bd9Sstevel@tonic-gate
19687c478bd9Sstevel@tonic-gate /*
19697c478bd9Sstevel@tonic-gate * NULL the 'back pointer'.
19707c478bd9Sstevel@tonic-gate */
19717c478bd9Sstevel@tonic-gate
19727c478bd9Sstevel@tonic-gate ap->ippa_mod = NULL;
19737c478bd9Sstevel@tonic-gate }
19747c478bd9Sstevel@tonic-gate #undef __FN__
19757c478bd9Sstevel@tonic-gate
19767c478bd9Sstevel@tonic-gate #define __FN__ "is_mod_busy"
19777c478bd9Sstevel@tonic-gate static int
is_mod_busy(ipp_mod_t * imp)19787c478bd9Sstevel@tonic-gate is_mod_busy(
19797c478bd9Sstevel@tonic-gate ipp_mod_t *imp)
19807c478bd9Sstevel@tonic-gate {
19817c478bd9Sstevel@tonic-gate /*
19827c478bd9Sstevel@tonic-gate * Return a value which is true (non-zero) iff the module refers
19837c478bd9Sstevel@tonic-gate * to no actions.
19847c478bd9Sstevel@tonic-gate */
19857c478bd9Sstevel@tonic-gate
19867c478bd9Sstevel@tonic-gate return (imp->ippm_action != NULL);
19877c478bd9Sstevel@tonic-gate }
19887c478bd9Sstevel@tonic-gate #undef __FN__
19897c478bd9Sstevel@tonic-gate
19907c478bd9Sstevel@tonic-gate #define __FN__ "get_mod_ref"
19917c478bd9Sstevel@tonic-gate static int
get_mod_ref(ipp_mod_t * imp,ipp_action_id_t ** bufp,int * neltp)19927c478bd9Sstevel@tonic-gate get_mod_ref(
19937c478bd9Sstevel@tonic-gate ipp_mod_t *imp,
19947c478bd9Sstevel@tonic-gate ipp_action_id_t **bufp,
19957c478bd9Sstevel@tonic-gate int *neltp)
19967c478bd9Sstevel@tonic-gate {
19977c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
19987c478bd9Sstevel@tonic-gate int nelt;
19997c478bd9Sstevel@tonic-gate ipp_action_t *ap;
20007c478bd9Sstevel@tonic-gate ipp_action_id_t *buf;
20017c478bd9Sstevel@tonic-gate int length;
20027c478bd9Sstevel@tonic-gate
20037c478bd9Sstevel@tonic-gate ASSERT(rw_lock_held(imp->ippm_lock));
20047c478bd9Sstevel@tonic-gate
20057c478bd9Sstevel@tonic-gate /*
20067c478bd9Sstevel@tonic-gate * Count the number of actions referred to from the module structure.
20077c478bd9Sstevel@tonic-gate */
20087c478bd9Sstevel@tonic-gate
20097c478bd9Sstevel@tonic-gate nelt = 0;
20107c478bd9Sstevel@tonic-gate for (rp = imp->ippm_action; rp != NULL; rp = rp->ippr_nextp) {
20117c478bd9Sstevel@tonic-gate nelt++;
20127c478bd9Sstevel@tonic-gate }
20137c478bd9Sstevel@tonic-gate DBG1(DBG_LIST, "%d actions found\n", nelt);
20147c478bd9Sstevel@tonic-gate
20157c478bd9Sstevel@tonic-gate /*
20167c478bd9Sstevel@tonic-gate * If there are no actions referred to then there's nothing to do.
20177c478bd9Sstevel@tonic-gate */
20187c478bd9Sstevel@tonic-gate
20197c478bd9Sstevel@tonic-gate if (nelt == 0) {
20207c478bd9Sstevel@tonic-gate *bufp = NULL;
20217c478bd9Sstevel@tonic-gate *neltp = 0;
20227c478bd9Sstevel@tonic-gate return (0);
20237c478bd9Sstevel@tonic-gate }
20247c478bd9Sstevel@tonic-gate
20257c478bd9Sstevel@tonic-gate /*
20267c478bd9Sstevel@tonic-gate * Allocate a buffer to pass back to the caller.
20277c478bd9Sstevel@tonic-gate */
20287c478bd9Sstevel@tonic-gate
20297c478bd9Sstevel@tonic-gate length = nelt * sizeof (ipp_action_id_t);
20307c478bd9Sstevel@tonic-gate if ((buf = kmem_alloc(length, KM_NOSLEEP)) == NULL)
20317c478bd9Sstevel@tonic-gate return (ENOMEM);
20327c478bd9Sstevel@tonic-gate
20337c478bd9Sstevel@tonic-gate /*
20347c478bd9Sstevel@tonic-gate * Fill the buffer with an array of action ids.
20357c478bd9Sstevel@tonic-gate */
20367c478bd9Sstevel@tonic-gate
20377c478bd9Sstevel@tonic-gate *bufp = buf;
20387c478bd9Sstevel@tonic-gate *neltp = nelt;
20397c478bd9Sstevel@tonic-gate
20407c478bd9Sstevel@tonic-gate for (rp = imp->ippm_action; rp != NULL; rp = rp->ippr_nextp) {
20417c478bd9Sstevel@tonic-gate ap = rp->ippr_action;
20427c478bd9Sstevel@tonic-gate *buf++ = ap->ippa_id;
20437c478bd9Sstevel@tonic-gate }
20447c478bd9Sstevel@tonic-gate
20457c478bd9Sstevel@tonic-gate ASSERT((uintptr_t)buf == (uintptr_t)*bufp + length);
20467c478bd9Sstevel@tonic-gate return (0);
20477c478bd9Sstevel@tonic-gate }
20487c478bd9Sstevel@tonic-gate #undef __FN__
20497c478bd9Sstevel@tonic-gate
20507c478bd9Sstevel@tonic-gate #define __FN__ "get_mods"
20517c478bd9Sstevel@tonic-gate static int
get_mods(ipp_mod_id_t ** bufp,int * neltp)20527c478bd9Sstevel@tonic-gate get_mods(
20537c478bd9Sstevel@tonic-gate ipp_mod_id_t **bufp,
20547c478bd9Sstevel@tonic-gate int *neltp)
20557c478bd9Sstevel@tonic-gate {
20567c478bd9Sstevel@tonic-gate ipp_mod_id_t *buf;
20577c478bd9Sstevel@tonic-gate int length;
20587c478bd9Sstevel@tonic-gate ipp_mod_id_t mid;
20597c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
20607c478bd9Sstevel@tonic-gate
20617c478bd9Sstevel@tonic-gate
20627c478bd9Sstevel@tonic-gate rw_enter(ipp_mod_byname_lock, RW_READER);
20637c478bd9Sstevel@tonic-gate
20647c478bd9Sstevel@tonic-gate /*
20657c478bd9Sstevel@tonic-gate * If there are no modules registered then there's nothing to do.
20667c478bd9Sstevel@tonic-gate */
20677c478bd9Sstevel@tonic-gate
20687c478bd9Sstevel@tonic-gate if (ipp_mod_count == 0) {
20697c478bd9Sstevel@tonic-gate DBG0(DBG_LIST, "no modules registered\n");
20707c478bd9Sstevel@tonic-gate *bufp = NULL;
20717c478bd9Sstevel@tonic-gate *neltp = 0;
20727c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
20737c478bd9Sstevel@tonic-gate return (0);
20747c478bd9Sstevel@tonic-gate }
20757c478bd9Sstevel@tonic-gate
20767c478bd9Sstevel@tonic-gate /*
20777c478bd9Sstevel@tonic-gate * Allocate a buffer to pass back to the caller.
20787c478bd9Sstevel@tonic-gate */
20797c478bd9Sstevel@tonic-gate
20807c478bd9Sstevel@tonic-gate DBG1(DBG_LIST, "%d modules registered\n", ipp_mod_count);
20817c478bd9Sstevel@tonic-gate length = ipp_mod_count * sizeof (ipp_mod_id_t);
20827c478bd9Sstevel@tonic-gate if ((buf = kmem_alloc(length, KM_NOSLEEP)) == NULL) {
20837c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
20847c478bd9Sstevel@tonic-gate return (ENOMEM);
20857c478bd9Sstevel@tonic-gate }
20867c478bd9Sstevel@tonic-gate
20877c478bd9Sstevel@tonic-gate rw_enter(ipp_mod_byid_lock, RW_READER);
20887c478bd9Sstevel@tonic-gate
20897c478bd9Sstevel@tonic-gate /*
20907c478bd9Sstevel@tonic-gate * Search the array of all modules.
20917c478bd9Sstevel@tonic-gate */
20927c478bd9Sstevel@tonic-gate
20937c478bd9Sstevel@tonic-gate *bufp = buf;
20947c478bd9Sstevel@tonic-gate *neltp = ipp_mod_count;
20957c478bd9Sstevel@tonic-gate
20967c478bd9Sstevel@tonic-gate for (mid = IPP_MOD_RESERVED + 1; mid <= ipp_mid_limit; mid++) {
20977c478bd9Sstevel@tonic-gate if ((imp = ipp_mod_byid[mid]) == NULL)
20987c478bd9Sstevel@tonic-gate continue;
20997c478bd9Sstevel@tonic-gate
21007c478bd9Sstevel@tonic-gate /*
21017c478bd9Sstevel@tonic-gate * If the module has 'destruct pending' set then it means it
21027c478bd9Sstevel@tonic-gate * is either still in the cache (i.e not allocated) or in the
21037c478bd9Sstevel@tonic-gate * process of being set up by alloc_mod().
21047c478bd9Sstevel@tonic-gate */
21057c478bd9Sstevel@tonic-gate
21067c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_READER);
21077c478bd9Sstevel@tonic-gate ASSERT(imp->ippm_id == mid);
21087c478bd9Sstevel@tonic-gate
21097c478bd9Sstevel@tonic-gate if (imp->ippm_destruct_pending) {
21107c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
21117c478bd9Sstevel@tonic-gate continue;
21127c478bd9Sstevel@tonic-gate }
21137c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
21147c478bd9Sstevel@tonic-gate
21157c478bd9Sstevel@tonic-gate *buf++ = mid;
21167c478bd9Sstevel@tonic-gate }
21177c478bd9Sstevel@tonic-gate
21187c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byid_lock);
21197c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
21207c478bd9Sstevel@tonic-gate
21217c478bd9Sstevel@tonic-gate ASSERT((uintptr_t)buf == (uintptr_t)*bufp + length);
21227c478bd9Sstevel@tonic-gate return (0);
21237c478bd9Sstevel@tonic-gate }
21247c478bd9Sstevel@tonic-gate #undef __FN__
21257c478bd9Sstevel@tonic-gate
21267c478bd9Sstevel@tonic-gate #define __FN__ "find_mod"
21277c478bd9Sstevel@tonic-gate static ipp_mod_id_t
find_mod(const char * modname)21287c478bd9Sstevel@tonic-gate find_mod(
21297c478bd9Sstevel@tonic-gate const char *modname)
21307c478bd9Sstevel@tonic-gate {
21317c478bd9Sstevel@tonic-gate ipp_mod_id_t mid;
21327c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
21337c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
21347c478bd9Sstevel@tonic-gate int hb;
21357c478bd9Sstevel@tonic-gate
21367c478bd9Sstevel@tonic-gate ASSERT(modname != NULL);
21377c478bd9Sstevel@tonic-gate
21387c478bd9Sstevel@tonic-gate rw_enter(ipp_mod_byname_lock, RW_READER);
21397c478bd9Sstevel@tonic-gate
21407c478bd9Sstevel@tonic-gate /*
21417c478bd9Sstevel@tonic-gate * Quick return if no modules are registered.
21427c478bd9Sstevel@tonic-gate */
21437c478bd9Sstevel@tonic-gate
21447c478bd9Sstevel@tonic-gate if (ipp_mod_count == 0) {
21457c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
21467c478bd9Sstevel@tonic-gate return (IPP_MOD_INVAL);
21477c478bd9Sstevel@tonic-gate }
21487c478bd9Sstevel@tonic-gate
21497c478bd9Sstevel@tonic-gate /*
21507c478bd9Sstevel@tonic-gate * Find the hash bucket where the module structure should be.
21517c478bd9Sstevel@tonic-gate */
21527c478bd9Sstevel@tonic-gate
21537c478bd9Sstevel@tonic-gate hb = hash(modname);
21547c478bd9Sstevel@tonic-gate rp = ipp_mod_byname[hb];
21557c478bd9Sstevel@tonic-gate
21567c478bd9Sstevel@tonic-gate /*
21577c478bd9Sstevel@tonic-gate * Scan the bucket for a match.
21587c478bd9Sstevel@tonic-gate */
21597c478bd9Sstevel@tonic-gate
21607c478bd9Sstevel@tonic-gate while (rp != NULL) {
21617c478bd9Sstevel@tonic-gate imp = rp->ippr_mod;
21627c478bd9Sstevel@tonic-gate if (strcmp(imp->ippm_name, modname) == 0)
21637c478bd9Sstevel@tonic-gate break;
21647c478bd9Sstevel@tonic-gate rp = rp->ippr_nextp;
21657c478bd9Sstevel@tonic-gate }
21667c478bd9Sstevel@tonic-gate
21677c478bd9Sstevel@tonic-gate if (rp == NULL) {
21687c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
21697c478bd9Sstevel@tonic-gate return (IPP_MOD_INVAL);
21707c478bd9Sstevel@tonic-gate }
21717c478bd9Sstevel@tonic-gate
21727c478bd9Sstevel@tonic-gate if (imp->ippm_state == IPP_MODSTATE_PROTO) {
21737c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
21747c478bd9Sstevel@tonic-gate return (IPP_MOD_INVAL);
21757c478bd9Sstevel@tonic-gate }
21767c478bd9Sstevel@tonic-gate
21777c478bd9Sstevel@tonic-gate mid = imp->ippm_id;
21787c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
21797c478bd9Sstevel@tonic-gate
21807c478bd9Sstevel@tonic-gate return (mid);
21817c478bd9Sstevel@tonic-gate }
21827c478bd9Sstevel@tonic-gate #undef __FN__
21837c478bd9Sstevel@tonic-gate
21847c478bd9Sstevel@tonic-gate #define __FN__ "alloc_mod"
21857c478bd9Sstevel@tonic-gate static int
alloc_mod(const char * modname,ipp_mod_id_t * midp)21867c478bd9Sstevel@tonic-gate alloc_mod(
21877c478bd9Sstevel@tonic-gate const char *modname,
21887c478bd9Sstevel@tonic-gate ipp_mod_id_t *midp)
21897c478bd9Sstevel@tonic-gate {
21907c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
21917c478bd9Sstevel@tonic-gate ipp_ref_t **rpp;
21927c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
21937c478bd9Sstevel@tonic-gate int hb;
21947c478bd9Sstevel@tonic-gate
21957c478bd9Sstevel@tonic-gate ASSERT(modname != NULL);
21967c478bd9Sstevel@tonic-gate ASSERT(midp != NULL);
21977c478bd9Sstevel@tonic-gate
21987c478bd9Sstevel@tonic-gate rw_enter(ipp_mod_byname_lock, RW_WRITER);
21997c478bd9Sstevel@tonic-gate
22007c478bd9Sstevel@tonic-gate /*
22017c478bd9Sstevel@tonic-gate * Find the right hash bucket for a module of the given name.
22027c478bd9Sstevel@tonic-gate */
22037c478bd9Sstevel@tonic-gate
22047c478bd9Sstevel@tonic-gate hb = hash(modname);
22057c478bd9Sstevel@tonic-gate rpp = &ipp_mod_byname[hb];
22067c478bd9Sstevel@tonic-gate
22077c478bd9Sstevel@tonic-gate /*
22087c478bd9Sstevel@tonic-gate * Scan the bucket making sure the module isn't already
22097c478bd9Sstevel@tonic-gate * registered.
22107c478bd9Sstevel@tonic-gate */
22117c478bd9Sstevel@tonic-gate
22127c478bd9Sstevel@tonic-gate while ((rp = *rpp) != NULL) {
22137c478bd9Sstevel@tonic-gate imp = rp->ippr_mod;
22147c478bd9Sstevel@tonic-gate if (strcmp(imp->ippm_name, modname) == 0) {
22157c478bd9Sstevel@tonic-gate DBG1(DBG_MOD, "module '%s' already exists\n", modname);
22167c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
22177c478bd9Sstevel@tonic-gate return (EEXIST);
22187c478bd9Sstevel@tonic-gate }
22197c478bd9Sstevel@tonic-gate rpp = &(rp->ippr_nextp);
22207c478bd9Sstevel@tonic-gate }
22217c478bd9Sstevel@tonic-gate
22227c478bd9Sstevel@tonic-gate /*
22237c478bd9Sstevel@tonic-gate * Allocate a new reference structure and a new module structure.
22247c478bd9Sstevel@tonic-gate */
22257c478bd9Sstevel@tonic-gate
22267c478bd9Sstevel@tonic-gate if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL) {
22277c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
22287c478bd9Sstevel@tonic-gate return (ENOMEM);
22297c478bd9Sstevel@tonic-gate }
22307c478bd9Sstevel@tonic-gate
22317c478bd9Sstevel@tonic-gate if ((imp = kmem_cache_alloc(ipp_mod_cache, KM_NOSLEEP)) == NULL) {
22327c478bd9Sstevel@tonic-gate kmem_free(rp, sizeof (ipp_ref_t));
22337c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
22347c478bd9Sstevel@tonic-gate return (ENOMEM);
22357c478bd9Sstevel@tonic-gate }
22367c478bd9Sstevel@tonic-gate
22377c478bd9Sstevel@tonic-gate /*
22387c478bd9Sstevel@tonic-gate * Set up the name of the new structure.
22397c478bd9Sstevel@tonic-gate */
22407c478bd9Sstevel@tonic-gate
22417c478bd9Sstevel@tonic-gate (void) strcpy(imp->ippm_name, modname);
22427c478bd9Sstevel@tonic-gate
22437c478bd9Sstevel@tonic-gate /*
22447c478bd9Sstevel@tonic-gate * Make sure the 'destruct pending' flag is clear. This indicates
22457c478bd9Sstevel@tonic-gate * that the structure is no longer part of the cache.
22467c478bd9Sstevel@tonic-gate */
22477c478bd9Sstevel@tonic-gate
22487c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_WRITER);
22497c478bd9Sstevel@tonic-gate imp->ippm_destruct_pending = B_FALSE;
22507c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
22517c478bd9Sstevel@tonic-gate
22527c478bd9Sstevel@tonic-gate /*
22537c478bd9Sstevel@tonic-gate * Set the reference and link it into the hash bucket.
22547c478bd9Sstevel@tonic-gate */
22557c478bd9Sstevel@tonic-gate
22567c478bd9Sstevel@tonic-gate rp->ippr_mod = imp;
22577c478bd9Sstevel@tonic-gate *rpp = rp;
22587c478bd9Sstevel@tonic-gate
22597c478bd9Sstevel@tonic-gate /*
22607c478bd9Sstevel@tonic-gate * Increment the module count.
22617c478bd9Sstevel@tonic-gate */
22627c478bd9Sstevel@tonic-gate
22637c478bd9Sstevel@tonic-gate ipp_mod_count++;
22647c478bd9Sstevel@tonic-gate
22657c478bd9Sstevel@tonic-gate *midp = imp->ippm_id;
22667c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
22677c478bd9Sstevel@tonic-gate return (0);
22687c478bd9Sstevel@tonic-gate }
22697c478bd9Sstevel@tonic-gate #undef __FN__
22707c478bd9Sstevel@tonic-gate
22717c478bd9Sstevel@tonic-gate #define __FN__ "free_mod"
22727c478bd9Sstevel@tonic-gate static void
free_mod(ipp_mod_t * imp)22737c478bd9Sstevel@tonic-gate free_mod(
22747c478bd9Sstevel@tonic-gate ipp_mod_t *imp)
22757c478bd9Sstevel@tonic-gate {
22767c478bd9Sstevel@tonic-gate ipp_ref_t **rpp;
22777c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
22787c478bd9Sstevel@tonic-gate int hb;
22797c478bd9Sstevel@tonic-gate
22807c478bd9Sstevel@tonic-gate rw_enter(ipp_mod_byname_lock, RW_WRITER);
22817c478bd9Sstevel@tonic-gate
22827c478bd9Sstevel@tonic-gate /*
22837c478bd9Sstevel@tonic-gate * Find the hash bucket where the module structure should be.
22847c478bd9Sstevel@tonic-gate */
22857c478bd9Sstevel@tonic-gate
22867c478bd9Sstevel@tonic-gate hb = hash(imp->ippm_name);
22877c478bd9Sstevel@tonic-gate rpp = &ipp_mod_byname[hb];
22887c478bd9Sstevel@tonic-gate
22897c478bd9Sstevel@tonic-gate /*
22907c478bd9Sstevel@tonic-gate * Scan the bucket for a match.
22917c478bd9Sstevel@tonic-gate */
22927c478bd9Sstevel@tonic-gate
22937c478bd9Sstevel@tonic-gate while ((rp = *rpp) != NULL) {
22947c478bd9Sstevel@tonic-gate if (rp->ippr_mod == imp)
22957c478bd9Sstevel@tonic-gate break;
22967c478bd9Sstevel@tonic-gate rpp = &(rp->ippr_nextp);
22977c478bd9Sstevel@tonic-gate }
22987c478bd9Sstevel@tonic-gate ASSERT(rp != NULL);
22997c478bd9Sstevel@tonic-gate
23007c478bd9Sstevel@tonic-gate /*
23017c478bd9Sstevel@tonic-gate * Unlink the reference structure and free it.
23027c478bd9Sstevel@tonic-gate */
23037c478bd9Sstevel@tonic-gate
23047c478bd9Sstevel@tonic-gate *rpp = rp->ippr_nextp;
23057c478bd9Sstevel@tonic-gate kmem_free(rp, sizeof (ipp_ref_t));
23067c478bd9Sstevel@tonic-gate
23077c478bd9Sstevel@tonic-gate /*
23087c478bd9Sstevel@tonic-gate * Decrement the module count.
23097c478bd9Sstevel@tonic-gate */
23107c478bd9Sstevel@tonic-gate
23117c478bd9Sstevel@tonic-gate ipp_mod_count--;
23127c478bd9Sstevel@tonic-gate
23137c478bd9Sstevel@tonic-gate /*
23147c478bd9Sstevel@tonic-gate * Empty the name.
23157c478bd9Sstevel@tonic-gate */
23167c478bd9Sstevel@tonic-gate
23177c478bd9Sstevel@tonic-gate *imp->ippm_name = '\0';
23187c478bd9Sstevel@tonic-gate
23197c478bd9Sstevel@tonic-gate /*
23207c478bd9Sstevel@tonic-gate * If the hold count is zero then we can free the structure
23217c478bd9Sstevel@tonic-gate * immediately, otherwise we defer to rele_mod().
23227c478bd9Sstevel@tonic-gate */
23237c478bd9Sstevel@tonic-gate
23247c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_WRITER);
23257c478bd9Sstevel@tonic-gate imp->ippm_destruct_pending = B_TRUE;
23267c478bd9Sstevel@tonic-gate if (imp->ippm_hold_count == 0) {
23277c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
23287c478bd9Sstevel@tonic-gate kmem_cache_free(ipp_mod_cache, imp);
23297c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
23307c478bd9Sstevel@tonic-gate return;
23317c478bd9Sstevel@tonic-gate }
23327c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
23337c478bd9Sstevel@tonic-gate
23347c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byname_lock);
23357c478bd9Sstevel@tonic-gate }
23367c478bd9Sstevel@tonic-gate #undef __FN__
23377c478bd9Sstevel@tonic-gate
23387c478bd9Sstevel@tonic-gate #define __FN__ "hold_mod"
23397c478bd9Sstevel@tonic-gate static ipp_mod_t *
hold_mod(ipp_mod_id_t mid)23407c478bd9Sstevel@tonic-gate hold_mod(
23417c478bd9Sstevel@tonic-gate ipp_mod_id_t mid)
23427c478bd9Sstevel@tonic-gate {
23437c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
23447c478bd9Sstevel@tonic-gate
23457c478bd9Sstevel@tonic-gate if (mid < 0)
23467c478bd9Sstevel@tonic-gate return (NULL);
23477c478bd9Sstevel@tonic-gate
23487c478bd9Sstevel@tonic-gate /*
23497c478bd9Sstevel@tonic-gate * Use the module id as an index into the array of all module
23507c478bd9Sstevel@tonic-gate * structures.
23517c478bd9Sstevel@tonic-gate */
23527c478bd9Sstevel@tonic-gate
23537c478bd9Sstevel@tonic-gate rw_enter(ipp_mod_byid_lock, RW_READER);
23547c478bd9Sstevel@tonic-gate if ((imp = ipp_mod_byid[mid]) == NULL) {
23557c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byid_lock);
23567c478bd9Sstevel@tonic-gate return (NULL);
23577c478bd9Sstevel@tonic-gate }
23587c478bd9Sstevel@tonic-gate
23597c478bd9Sstevel@tonic-gate ASSERT(imp->ippm_id == mid);
23607c478bd9Sstevel@tonic-gate
23617c478bd9Sstevel@tonic-gate /*
23627c478bd9Sstevel@tonic-gate * If the modul has 'destruct pending' set then it means it is either
23637c478bd9Sstevel@tonic-gate * still in the cache (i.e not allocated) or in the process of
23647c478bd9Sstevel@tonic-gate * being set up by alloc_mod().
23657c478bd9Sstevel@tonic-gate */
23667c478bd9Sstevel@tonic-gate
23677c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_READER);
23687c478bd9Sstevel@tonic-gate if (imp->ippm_destruct_pending) {
23697c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
23707c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byid_lock);
23717c478bd9Sstevel@tonic-gate return (NULL);
23727c478bd9Sstevel@tonic-gate }
23737c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
23747c478bd9Sstevel@tonic-gate
23757c478bd9Sstevel@tonic-gate /*
23767c478bd9Sstevel@tonic-gate * Increment the hold count to prevent the structure from being
23777c478bd9Sstevel@tonic-gate * freed.
23787c478bd9Sstevel@tonic-gate */
23797c478bd9Sstevel@tonic-gate
23801a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&(imp->ippm_hold_count));
23817c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byid_lock);
23827c478bd9Sstevel@tonic-gate
23837c478bd9Sstevel@tonic-gate return (imp);
23847c478bd9Sstevel@tonic-gate }
23857c478bd9Sstevel@tonic-gate #undef __FN__
23867c478bd9Sstevel@tonic-gate
23877c478bd9Sstevel@tonic-gate #define __FN__ "rele_mod"
23887c478bd9Sstevel@tonic-gate static void
rele_mod(ipp_mod_t * imp)23897c478bd9Sstevel@tonic-gate rele_mod(
23907c478bd9Sstevel@tonic-gate ipp_mod_t *imp)
23917c478bd9Sstevel@tonic-gate {
23927c478bd9Sstevel@tonic-gate /*
23937c478bd9Sstevel@tonic-gate * This call means we're done with the pointer so we can drop the
23947c478bd9Sstevel@tonic-gate * hold count.
23957c478bd9Sstevel@tonic-gate */
23967c478bd9Sstevel@tonic-gate
23977c478bd9Sstevel@tonic-gate ASSERT(imp->ippm_hold_count != 0);
23981a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&(imp->ippm_hold_count));
23997c478bd9Sstevel@tonic-gate
24007c478bd9Sstevel@tonic-gate /*
24017c478bd9Sstevel@tonic-gate * If the structure has 'destruct pending' set then we tried to free
24027c478bd9Sstevel@tonic-gate * it but couldn't, so do it now.
24037c478bd9Sstevel@tonic-gate */
24047c478bd9Sstevel@tonic-gate
24057c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_READER);
24067c478bd9Sstevel@tonic-gate if (imp->ippm_destruct_pending && imp->ippm_hold_count == 0) {
24077c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
24087c478bd9Sstevel@tonic-gate kmem_cache_free(ipp_mod_cache, imp);
24097c478bd9Sstevel@tonic-gate return;
24107c478bd9Sstevel@tonic-gate }
24117c478bd9Sstevel@tonic-gate
24127c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
24137c478bd9Sstevel@tonic-gate }
24147c478bd9Sstevel@tonic-gate #undef __FN__
24157c478bd9Sstevel@tonic-gate
24167c478bd9Sstevel@tonic-gate #define __FN__ "get_mid"
24177c478bd9Sstevel@tonic-gate static ipp_mod_id_t
get_mid(void)24187c478bd9Sstevel@tonic-gate get_mid(
24197c478bd9Sstevel@tonic-gate void)
24207c478bd9Sstevel@tonic-gate {
24217c478bd9Sstevel@tonic-gate int index;
24227c478bd9Sstevel@tonic-gate int start;
24237c478bd9Sstevel@tonic-gate int limit;
24247c478bd9Sstevel@tonic-gate
24257c478bd9Sstevel@tonic-gate ASSERT(rw_write_held(ipp_mod_byid_lock));
24267c478bd9Sstevel@tonic-gate
24277c478bd9Sstevel@tonic-gate /*
24287c478bd9Sstevel@tonic-gate * Start searching after the last module id we allocated.
24297c478bd9Sstevel@tonic-gate */
24307c478bd9Sstevel@tonic-gate
24317c478bd9Sstevel@tonic-gate start = (int)ipp_next_mid;
24327c478bd9Sstevel@tonic-gate limit = (int)ipp_mid_limit;
24337c478bd9Sstevel@tonic-gate
24347c478bd9Sstevel@tonic-gate /*
24357c478bd9Sstevel@tonic-gate * Look for a spare slot in the array.
24367c478bd9Sstevel@tonic-gate */
24377c478bd9Sstevel@tonic-gate
24387c478bd9Sstevel@tonic-gate index = start;
24397c478bd9Sstevel@tonic-gate while (ipp_mod_byid[index] != NULL) {
24407c478bd9Sstevel@tonic-gate index++;
24417c478bd9Sstevel@tonic-gate if (index > limit)
24427c478bd9Sstevel@tonic-gate index = IPP_MOD_RESERVED + 1;
24437c478bd9Sstevel@tonic-gate if (index == start)
24447c478bd9Sstevel@tonic-gate return (IPP_MOD_INVAL);
24457c478bd9Sstevel@tonic-gate }
24467c478bd9Sstevel@tonic-gate
24477c478bd9Sstevel@tonic-gate /*
24487c478bd9Sstevel@tonic-gate * Note that we've just allocated a new module id so that we can
24497c478bd9Sstevel@tonic-gate * start our search there next time.
24507c478bd9Sstevel@tonic-gate */
24517c478bd9Sstevel@tonic-gate
24527c478bd9Sstevel@tonic-gate index++;
24537c478bd9Sstevel@tonic-gate if (index > limit) {
24547c478bd9Sstevel@tonic-gate ipp_next_mid = IPP_MOD_RESERVED + 1;
24557c478bd9Sstevel@tonic-gate } else
24567c478bd9Sstevel@tonic-gate ipp_next_mid = (ipp_mod_id_t)index;
24577c478bd9Sstevel@tonic-gate
24587c478bd9Sstevel@tonic-gate return ((ipp_mod_id_t)(--index));
24597c478bd9Sstevel@tonic-gate }
24607c478bd9Sstevel@tonic-gate #undef __FN__
24617c478bd9Sstevel@tonic-gate
24627c478bd9Sstevel@tonic-gate #define __FN__ "condemn_action"
24637c478bd9Sstevel@tonic-gate static int
condemn_action(ipp_ref_t ** rpp,ipp_action_t * ap)24647c478bd9Sstevel@tonic-gate condemn_action(
24657c478bd9Sstevel@tonic-gate ipp_ref_t **rpp,
24667c478bd9Sstevel@tonic-gate ipp_action_t *ap)
24677c478bd9Sstevel@tonic-gate {
24687c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
24697c478bd9Sstevel@tonic-gate
24707c478bd9Sstevel@tonic-gate DBG1(DBG_ACTION, "condemning action '%s'\n", ap->ippa_name);
24717c478bd9Sstevel@tonic-gate
24727c478bd9Sstevel@tonic-gate /*
24737c478bd9Sstevel@tonic-gate * Check to see if the action is already condemned.
24747c478bd9Sstevel@tonic-gate */
24757c478bd9Sstevel@tonic-gate
24767c478bd9Sstevel@tonic-gate while ((rp = *rpp) != NULL) {
24777c478bd9Sstevel@tonic-gate if (rp->ippr_action == ap)
24787c478bd9Sstevel@tonic-gate break;
24797c478bd9Sstevel@tonic-gate rpp = &(rp->ippr_nextp);
24807c478bd9Sstevel@tonic-gate }
24817c478bd9Sstevel@tonic-gate
24827c478bd9Sstevel@tonic-gate /*
24837c478bd9Sstevel@tonic-gate * Create a new entry for the action.
24847c478bd9Sstevel@tonic-gate */
24857c478bd9Sstevel@tonic-gate
24867c478bd9Sstevel@tonic-gate if (rp == NULL) {
24877c478bd9Sstevel@tonic-gate if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL)
24887c478bd9Sstevel@tonic-gate return (ENOMEM);
24897c478bd9Sstevel@tonic-gate
24907c478bd9Sstevel@tonic-gate rp->ippr_action = ap;
24917c478bd9Sstevel@tonic-gate *rpp = rp;
24927c478bd9Sstevel@tonic-gate }
24937c478bd9Sstevel@tonic-gate
24947c478bd9Sstevel@tonic-gate return (0);
24957c478bd9Sstevel@tonic-gate }
24967c478bd9Sstevel@tonic-gate #undef __FN__
24977c478bd9Sstevel@tonic-gate
24987c478bd9Sstevel@tonic-gate #define __FN__ "destroy_action"
24997c478bd9Sstevel@tonic-gate static int
destroy_action(ipp_action_t * ap,ipp_flags_t flags)25007c478bd9Sstevel@tonic-gate destroy_action(
25017c478bd9Sstevel@tonic-gate ipp_action_t *ap,
25027c478bd9Sstevel@tonic-gate ipp_flags_t flags)
25037c478bd9Sstevel@tonic-gate {
25047c478bd9Sstevel@tonic-gate ipp_ops_t *ippo;
25057c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
25067c478bd9Sstevel@tonic-gate #define MAXWAIT 10
25077c478bd9Sstevel@tonic-gate uint32_t wait;
25087c478bd9Sstevel@tonic-gate int rc;
25097c478bd9Sstevel@tonic-gate
25107c478bd9Sstevel@tonic-gate /*
25117c478bd9Sstevel@tonic-gate * Check that the action is available.
25127c478bd9Sstevel@tonic-gate */
25137c478bd9Sstevel@tonic-gate
25147c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_WRITER);
25157c478bd9Sstevel@tonic-gate if (ap->ippa_state != IPP_ASTATE_AVAILABLE) {
25167c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
25177c478bd9Sstevel@tonic-gate rele_action(ap);
25187c478bd9Sstevel@tonic-gate return (EPROTO);
25197c478bd9Sstevel@tonic-gate }
25207c478bd9Sstevel@tonic-gate
25217c478bd9Sstevel@tonic-gate /*
25227c478bd9Sstevel@tonic-gate * Note that the action is in the process of creation/destruction.
25237c478bd9Sstevel@tonic-gate */
25247c478bd9Sstevel@tonic-gate
25257c478bd9Sstevel@tonic-gate ap->ippa_state = IPP_ASTATE_CONFIG_PENDING;
25267c478bd9Sstevel@tonic-gate
25277c478bd9Sstevel@tonic-gate /*
25287c478bd9Sstevel@tonic-gate * Wait for the in-transit packet count for this action to fall to
25297c478bd9Sstevel@tonic-gate * zero (checking at millisecond intervals).
25307c478bd9Sstevel@tonic-gate *
25317c478bd9Sstevel@tonic-gate * NOTE: no new packets will enter the action now that the
25327c478bd9Sstevel@tonic-gate * state has been changed.
25337c478bd9Sstevel@tonic-gate */
25347c478bd9Sstevel@tonic-gate
25357c478bd9Sstevel@tonic-gate for (wait = 0; ap->ippa_packets > 0 && wait < (MAXWAIT * 1000000);
25367c478bd9Sstevel@tonic-gate wait += 1000) {
25377c478bd9Sstevel@tonic-gate
25387c478bd9Sstevel@tonic-gate /*
25397c478bd9Sstevel@tonic-gate * NOTE: We can hang onto the lock because the packet count is
25407c478bd9Sstevel@tonic-gate * decremented without needing to take the lock.
25417c478bd9Sstevel@tonic-gate */
25427c478bd9Sstevel@tonic-gate
25437c478bd9Sstevel@tonic-gate drv_usecwait(1000);
25447c478bd9Sstevel@tonic-gate }
25457c478bd9Sstevel@tonic-gate
25467c478bd9Sstevel@tonic-gate /*
25477c478bd9Sstevel@tonic-gate * The packet count did not fall to zero.
25487c478bd9Sstevel@tonic-gate */
25497c478bd9Sstevel@tonic-gate if (ap->ippa_packets > 0) {
25507c478bd9Sstevel@tonic-gate ap->ippa_state = IPP_ASTATE_AVAILABLE;
25517c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
25527c478bd9Sstevel@tonic-gate rele_action(ap);
25537c478bd9Sstevel@tonic-gate return (EAGAIN);
25547c478bd9Sstevel@tonic-gate }
25557c478bd9Sstevel@tonic-gate
25567c478bd9Sstevel@tonic-gate /*
25577c478bd9Sstevel@tonic-gate * Check to see if any other action has a dependency on this one.
25587c478bd9Sstevel@tonic-gate */
25597c478bd9Sstevel@tonic-gate
25607c478bd9Sstevel@tonic-gate if (is_action_refd(ap)) {
25617c478bd9Sstevel@tonic-gate ap->ippa_state = IPP_ASTATE_AVAILABLE;
25627c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
25637c478bd9Sstevel@tonic-gate rele_action(ap);
25647c478bd9Sstevel@tonic-gate return (EBUSY);
25657c478bd9Sstevel@tonic-gate }
25667c478bd9Sstevel@tonic-gate
25677c478bd9Sstevel@tonic-gate imp = ap->ippa_mod;
25687c478bd9Sstevel@tonic-gate ASSERT(imp != NULL);
25697c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
25707c478bd9Sstevel@tonic-gate
25717c478bd9Sstevel@tonic-gate ippo = imp->ippm_ops;
25727c478bd9Sstevel@tonic-gate ASSERT(ippo != NULL);
25737c478bd9Sstevel@tonic-gate
25747c478bd9Sstevel@tonic-gate /*
25757c478bd9Sstevel@tonic-gate * Call into the module to destroy the action context.
25767c478bd9Sstevel@tonic-gate */
25777c478bd9Sstevel@tonic-gate
25787c478bd9Sstevel@tonic-gate CONFIG_WRITE_START(ap);
25797c478bd9Sstevel@tonic-gate DBG1(DBG_ACTION, "destroying action '%s'\n", ap->ippa_name);
25807c478bd9Sstevel@tonic-gate if ((rc = ippo->ippo_action_destroy(ap->ippa_id, flags)) != 0) {
25817c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_WRITER);
25827c478bd9Sstevel@tonic-gate ap->ippa_state = IPP_ASTATE_AVAILABLE;
25837c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
25847c478bd9Sstevel@tonic-gate
25857c478bd9Sstevel@tonic-gate CONFIG_WRITE_END(ap);
25867c478bd9Sstevel@tonic-gate
25877c478bd9Sstevel@tonic-gate rele_action(ap);
25887c478bd9Sstevel@tonic-gate return (rc);
25897c478bd9Sstevel@tonic-gate }
25907c478bd9Sstevel@tonic-gate CONFIG_WRITE_END(ap);
25917c478bd9Sstevel@tonic-gate
25927c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_WRITER);
25937c478bd9Sstevel@tonic-gate LOCK_MOD(imp, RW_WRITER);
25947c478bd9Sstevel@tonic-gate unref_mod(ap, imp);
25957c478bd9Sstevel@tonic-gate UNLOCK_MOD(imp);
25967c478bd9Sstevel@tonic-gate ap->ippa_state = IPP_ASTATE_PROTO;
25977c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
25987c478bd9Sstevel@tonic-gate
25997c478bd9Sstevel@tonic-gate /*
26007c478bd9Sstevel@tonic-gate * Free the action structure.
26017c478bd9Sstevel@tonic-gate */
26027c478bd9Sstevel@tonic-gate
26037c478bd9Sstevel@tonic-gate ASSERT(ap->ippa_ref == NULL);
26047c478bd9Sstevel@tonic-gate free_action(ap);
26057c478bd9Sstevel@tonic-gate rele_action(ap);
26067c478bd9Sstevel@tonic-gate return (0);
26077c478bd9Sstevel@tonic-gate #undef MAXWAIT
26087c478bd9Sstevel@tonic-gate }
26097c478bd9Sstevel@tonic-gate #undef __FN__
26107c478bd9Sstevel@tonic-gate
26117c478bd9Sstevel@tonic-gate #define __FN__ "ref_action"
26127c478bd9Sstevel@tonic-gate static int
ref_action(ipp_action_t * refby_ap,ipp_action_t * ref_ap)26137c478bd9Sstevel@tonic-gate ref_action(
26147c478bd9Sstevel@tonic-gate ipp_action_t *refby_ap,
26157c478bd9Sstevel@tonic-gate ipp_action_t *ref_ap)
26167c478bd9Sstevel@tonic-gate {
26177c478bd9Sstevel@tonic-gate ipp_ref_t **rpp;
26187c478bd9Sstevel@tonic-gate ipp_ref_t **save_rpp;
26197c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
26207c478bd9Sstevel@tonic-gate
26217c478bd9Sstevel@tonic-gate ASSERT(rw_write_held(refby_ap->ippa_lock));
26227c478bd9Sstevel@tonic-gate ASSERT(rw_write_held(ref_ap->ippa_lock));
26237c478bd9Sstevel@tonic-gate
26247c478bd9Sstevel@tonic-gate /*
26257c478bd9Sstevel@tonic-gate * We want to add the new reference at the end of the refering
26267c478bd9Sstevel@tonic-gate * action's list.
26277c478bd9Sstevel@tonic-gate */
26287c478bd9Sstevel@tonic-gate
26297c478bd9Sstevel@tonic-gate rpp = &(refby_ap->ippa_ref);
26307c478bd9Sstevel@tonic-gate while ((rp = *rpp) != NULL) {
26317c478bd9Sstevel@tonic-gate if (rp->ippr_action == ref_ap)
26327c478bd9Sstevel@tonic-gate break;
26337c478bd9Sstevel@tonic-gate rpp = &(rp->ippr_nextp);
26347c478bd9Sstevel@tonic-gate }
26357c478bd9Sstevel@tonic-gate
26367c478bd9Sstevel@tonic-gate if ((rp = *rpp) != NULL) {
26377c478bd9Sstevel@tonic-gate
26387c478bd9Sstevel@tonic-gate /*
26397c478bd9Sstevel@tonic-gate * There is an existing reference so increment its counter.
26407c478bd9Sstevel@tonic-gate */
26417c478bd9Sstevel@tonic-gate
26427c478bd9Sstevel@tonic-gate rp->ippr_count++;
26437c478bd9Sstevel@tonic-gate
26447c478bd9Sstevel@tonic-gate /*
26457c478bd9Sstevel@tonic-gate * Find the 'back pointer' and increment its counter too.
26467c478bd9Sstevel@tonic-gate */
26477c478bd9Sstevel@tonic-gate
26487c478bd9Sstevel@tonic-gate rp = ref_ap->ippa_refby;
26497c478bd9Sstevel@tonic-gate while (rp != NULL) {
26507c478bd9Sstevel@tonic-gate if (rp->ippr_action == refby_ap)
26517c478bd9Sstevel@tonic-gate break;
26527c478bd9Sstevel@tonic-gate rp = rp->ippr_nextp;
26537c478bd9Sstevel@tonic-gate }
26547c478bd9Sstevel@tonic-gate ASSERT(rp != NULL);
26557c478bd9Sstevel@tonic-gate
26567c478bd9Sstevel@tonic-gate rp->ippr_count++;
26577c478bd9Sstevel@tonic-gate } else {
26587c478bd9Sstevel@tonic-gate
26597c478bd9Sstevel@tonic-gate /*
26607c478bd9Sstevel@tonic-gate * Allocate, fill in and link a new reference structure.
26617c478bd9Sstevel@tonic-gate */
26627c478bd9Sstevel@tonic-gate
26637c478bd9Sstevel@tonic-gate if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL)
26647c478bd9Sstevel@tonic-gate return (ENOMEM);
26657c478bd9Sstevel@tonic-gate
26667c478bd9Sstevel@tonic-gate rp->ippr_action = ref_ap;
26677c478bd9Sstevel@tonic-gate rp->ippr_count = 1;
26687c478bd9Sstevel@tonic-gate *rpp = rp;
26697c478bd9Sstevel@tonic-gate save_rpp = rpp;
26707c478bd9Sstevel@tonic-gate
26717c478bd9Sstevel@tonic-gate /*
26727c478bd9Sstevel@tonic-gate * We keep a 'back pointer' which we want to add at the end of
26737c478bd9Sstevel@tonic-gate * a list in the referred action's structure.
26747c478bd9Sstevel@tonic-gate */
26757c478bd9Sstevel@tonic-gate
26767c478bd9Sstevel@tonic-gate rpp = &(ref_ap->ippa_refby);
26777c478bd9Sstevel@tonic-gate while ((rp = *rpp) != NULL) {
26787c478bd9Sstevel@tonic-gate ASSERT(rp->ippr_action != refby_ap);
26797c478bd9Sstevel@tonic-gate rpp = &(rp->ippr_nextp);
26807c478bd9Sstevel@tonic-gate }
26817c478bd9Sstevel@tonic-gate
26827c478bd9Sstevel@tonic-gate /*
26837c478bd9Sstevel@tonic-gate * Allocate another reference structure and, if this fails,
26847c478bd9Sstevel@tonic-gate * remember to clean up the first reference structure we
26857c478bd9Sstevel@tonic-gate * allocated.
26867c478bd9Sstevel@tonic-gate */
26877c478bd9Sstevel@tonic-gate
26887c478bd9Sstevel@tonic-gate if ((rp = kmem_zalloc(sizeof (ipp_ref_t),
26897c478bd9Sstevel@tonic-gate KM_NOSLEEP)) == NULL) {
26907c478bd9Sstevel@tonic-gate rpp = save_rpp;
26917c478bd9Sstevel@tonic-gate rp = *rpp;
26927c478bd9Sstevel@tonic-gate *rpp = NULL;
26937c478bd9Sstevel@tonic-gate kmem_free(rp, sizeof (ipp_ref_t));
26947c478bd9Sstevel@tonic-gate
26957c478bd9Sstevel@tonic-gate return (ENOMEM);
26967c478bd9Sstevel@tonic-gate }
26977c478bd9Sstevel@tonic-gate
26987c478bd9Sstevel@tonic-gate /*
26997c478bd9Sstevel@tonic-gate * Fill in the reference structure with the 'back pointer' and
27007c478bd9Sstevel@tonic-gate * link it into the list.
27017c478bd9Sstevel@tonic-gate */
27027c478bd9Sstevel@tonic-gate
27037c478bd9Sstevel@tonic-gate rp->ippr_action = refby_ap;
27047c478bd9Sstevel@tonic-gate rp->ippr_count = 1;
27057c478bd9Sstevel@tonic-gate *rpp = rp;
27067c478bd9Sstevel@tonic-gate }
27077c478bd9Sstevel@tonic-gate
27087c478bd9Sstevel@tonic-gate return (0);
27097c478bd9Sstevel@tonic-gate }
27107c478bd9Sstevel@tonic-gate #undef __FN__
27117c478bd9Sstevel@tonic-gate
27127c478bd9Sstevel@tonic-gate #define __FN__ "unref_action"
27137c478bd9Sstevel@tonic-gate static int
unref_action(ipp_action_t * refby_ap,ipp_action_t * ref_ap)27147c478bd9Sstevel@tonic-gate unref_action(
27157c478bd9Sstevel@tonic-gate ipp_action_t *refby_ap,
27167c478bd9Sstevel@tonic-gate ipp_action_t *ref_ap)
27177c478bd9Sstevel@tonic-gate {
27187c478bd9Sstevel@tonic-gate ipp_ref_t **rpp;
27197c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
27207c478bd9Sstevel@tonic-gate
27217c478bd9Sstevel@tonic-gate ASSERT(rw_write_held(refby_ap->ippa_lock));
27227c478bd9Sstevel@tonic-gate ASSERT(rw_write_held(ref_ap->ippa_lock));
27237c478bd9Sstevel@tonic-gate
27247c478bd9Sstevel@tonic-gate /*
27257c478bd9Sstevel@tonic-gate * Scan for the reference in the referring action's list.
27267c478bd9Sstevel@tonic-gate */
27277c478bd9Sstevel@tonic-gate
27287c478bd9Sstevel@tonic-gate rpp = &(refby_ap->ippa_ref);
27297c478bd9Sstevel@tonic-gate while ((rp = *rpp) != NULL) {
27307c478bd9Sstevel@tonic-gate if (rp->ippr_action == ref_ap)
27317c478bd9Sstevel@tonic-gate break;
27327c478bd9Sstevel@tonic-gate rpp = &(rp->ippr_nextp);
27337c478bd9Sstevel@tonic-gate }
27347c478bd9Sstevel@tonic-gate
27357c478bd9Sstevel@tonic-gate if (rp == NULL)
27367c478bd9Sstevel@tonic-gate return (ENOENT);
27377c478bd9Sstevel@tonic-gate
27387c478bd9Sstevel@tonic-gate if (rp->ippr_count > 1) {
27397c478bd9Sstevel@tonic-gate
27407c478bd9Sstevel@tonic-gate /*
27417c478bd9Sstevel@tonic-gate * There are currently multiple references so decrement the
27427c478bd9Sstevel@tonic-gate * count.
27437c478bd9Sstevel@tonic-gate */
27447c478bd9Sstevel@tonic-gate
27457c478bd9Sstevel@tonic-gate rp->ippr_count--;
27467c478bd9Sstevel@tonic-gate
27477c478bd9Sstevel@tonic-gate /*
27487c478bd9Sstevel@tonic-gate * Find the 'back pointer' and decrement its counter too.
27497c478bd9Sstevel@tonic-gate */
27507c478bd9Sstevel@tonic-gate
27517c478bd9Sstevel@tonic-gate rp = ref_ap->ippa_refby;
27527c478bd9Sstevel@tonic-gate while (rp != NULL) {
27537c478bd9Sstevel@tonic-gate if (rp->ippr_action == refby_ap)
27547c478bd9Sstevel@tonic-gate break;
27557c478bd9Sstevel@tonic-gate rp = rp->ippr_nextp;
27567c478bd9Sstevel@tonic-gate }
27577c478bd9Sstevel@tonic-gate ASSERT(rp != NULL);
27587c478bd9Sstevel@tonic-gate
27597c478bd9Sstevel@tonic-gate rp->ippr_count--;
27607c478bd9Sstevel@tonic-gate } else {
27617c478bd9Sstevel@tonic-gate
27627c478bd9Sstevel@tonic-gate /*
27637c478bd9Sstevel@tonic-gate * There is currently only a single reference, so unlink and
27647c478bd9Sstevel@tonic-gate * free the reference structure.
27657c478bd9Sstevel@tonic-gate */
27667c478bd9Sstevel@tonic-gate
27677c478bd9Sstevel@tonic-gate *rpp = rp->ippr_nextp;
27687c478bd9Sstevel@tonic-gate kmem_free(rp, sizeof (ipp_ref_t));
27697c478bd9Sstevel@tonic-gate
27707c478bd9Sstevel@tonic-gate /*
27717c478bd9Sstevel@tonic-gate * Scan for the 'back pointer' in the referred action's list.
27727c478bd9Sstevel@tonic-gate */
27737c478bd9Sstevel@tonic-gate
27747c478bd9Sstevel@tonic-gate rpp = &(ref_ap->ippa_refby);
27757c478bd9Sstevel@tonic-gate while ((rp = *rpp) != NULL) {
27767c478bd9Sstevel@tonic-gate if (rp->ippr_action == refby_ap)
27777c478bd9Sstevel@tonic-gate break;
27787c478bd9Sstevel@tonic-gate rpp = &(rp->ippr_nextp);
27797c478bd9Sstevel@tonic-gate }
27807c478bd9Sstevel@tonic-gate ASSERT(rp != NULL);
27817c478bd9Sstevel@tonic-gate
27827c478bd9Sstevel@tonic-gate /*
27837c478bd9Sstevel@tonic-gate * Unlink and free this reference structure too.
27847c478bd9Sstevel@tonic-gate */
27857c478bd9Sstevel@tonic-gate
27867c478bd9Sstevel@tonic-gate *rpp = rp->ippr_nextp;
27877c478bd9Sstevel@tonic-gate kmem_free(rp, sizeof (ipp_ref_t));
27887c478bd9Sstevel@tonic-gate }
27897c478bd9Sstevel@tonic-gate
27907c478bd9Sstevel@tonic-gate return (0);
27917c478bd9Sstevel@tonic-gate }
27927c478bd9Sstevel@tonic-gate #undef __FN__
27937c478bd9Sstevel@tonic-gate
27947c478bd9Sstevel@tonic-gate #define __FN__ "is_action_refd"
27957c478bd9Sstevel@tonic-gate static int
is_action_refd(ipp_action_t * ap)27967c478bd9Sstevel@tonic-gate is_action_refd(
27977c478bd9Sstevel@tonic-gate ipp_action_t *ap)
27987c478bd9Sstevel@tonic-gate {
27997c478bd9Sstevel@tonic-gate /*
28007c478bd9Sstevel@tonic-gate * Return a value which is true (non-zero) iff the action is not
28017c478bd9Sstevel@tonic-gate * referred to by any other actions.
28027c478bd9Sstevel@tonic-gate */
28037c478bd9Sstevel@tonic-gate
28047c478bd9Sstevel@tonic-gate return (ap->ippa_refby != NULL);
28057c478bd9Sstevel@tonic-gate }
28067c478bd9Sstevel@tonic-gate #undef __FN__
28077c478bd9Sstevel@tonic-gate
28087c478bd9Sstevel@tonic-gate #define __FN__ "find_action"
28097c478bd9Sstevel@tonic-gate static ipp_action_id_t
find_action(const char * aname)28107c478bd9Sstevel@tonic-gate find_action(
28117c478bd9Sstevel@tonic-gate const char *aname)
28127c478bd9Sstevel@tonic-gate {
28137c478bd9Sstevel@tonic-gate ipp_action_id_t aid;
28147c478bd9Sstevel@tonic-gate ipp_action_t *ap;
28157c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
28167c478bd9Sstevel@tonic-gate int hb;
28177c478bd9Sstevel@tonic-gate
28187c478bd9Sstevel@tonic-gate ASSERT(aname != NULL);
28197c478bd9Sstevel@tonic-gate
28207c478bd9Sstevel@tonic-gate rw_enter(ipp_action_byname_lock, RW_READER);
28217c478bd9Sstevel@tonic-gate
28227c478bd9Sstevel@tonic-gate /*
28237c478bd9Sstevel@tonic-gate * Quick return if there are no actions defined at all.
28247c478bd9Sstevel@tonic-gate */
28257c478bd9Sstevel@tonic-gate
28267c478bd9Sstevel@tonic-gate if (ipp_action_count == 0) {
28277c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byname_lock);
28287c478bd9Sstevel@tonic-gate return (IPP_ACTION_INVAL);
28297c478bd9Sstevel@tonic-gate }
28307c478bd9Sstevel@tonic-gate
28317c478bd9Sstevel@tonic-gate /*
28327c478bd9Sstevel@tonic-gate * Find the hash bucket where the action structure should be.
28337c478bd9Sstevel@tonic-gate */
28347c478bd9Sstevel@tonic-gate
28357c478bd9Sstevel@tonic-gate hb = hash(aname);
28367c478bd9Sstevel@tonic-gate rp = ipp_action_byname[hb];
28377c478bd9Sstevel@tonic-gate
28387c478bd9Sstevel@tonic-gate /*
28397c478bd9Sstevel@tonic-gate * Scan the bucket looking for a match.
28407c478bd9Sstevel@tonic-gate */
28417c478bd9Sstevel@tonic-gate
28427c478bd9Sstevel@tonic-gate while (rp != NULL) {
28437c478bd9Sstevel@tonic-gate ap = rp->ippr_action;
28447c478bd9Sstevel@tonic-gate if (strcmp(ap->ippa_name, aname) == 0)
28457c478bd9Sstevel@tonic-gate break;
28467c478bd9Sstevel@tonic-gate rp = rp->ippr_nextp;
28477c478bd9Sstevel@tonic-gate }
28487c478bd9Sstevel@tonic-gate
28497c478bd9Sstevel@tonic-gate if (rp == NULL) {
28507c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byname_lock);
28517c478bd9Sstevel@tonic-gate return (IPP_ACTION_INVAL);
28527c478bd9Sstevel@tonic-gate }
28537c478bd9Sstevel@tonic-gate
28547c478bd9Sstevel@tonic-gate if (ap->ippa_state == IPP_ASTATE_PROTO) {
28557c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byname_lock);
28567c478bd9Sstevel@tonic-gate return (IPP_ACTION_INVAL);
28577c478bd9Sstevel@tonic-gate }
28587c478bd9Sstevel@tonic-gate
28597c478bd9Sstevel@tonic-gate aid = ap->ippa_id;
28607c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byname_lock);
28617c478bd9Sstevel@tonic-gate
28627c478bd9Sstevel@tonic-gate return (aid);
28637c478bd9Sstevel@tonic-gate }
28647c478bd9Sstevel@tonic-gate #undef __FN__
28657c478bd9Sstevel@tonic-gate
28667c478bd9Sstevel@tonic-gate #define __FN__ "alloc_action"
28677c478bd9Sstevel@tonic-gate static int
alloc_action(const char * aname,ipp_action_id_t * aidp)28687c478bd9Sstevel@tonic-gate alloc_action(
28697c478bd9Sstevel@tonic-gate const char *aname,
28707c478bd9Sstevel@tonic-gate ipp_action_id_t *aidp)
28717c478bd9Sstevel@tonic-gate {
28727c478bd9Sstevel@tonic-gate ipp_action_t *ap;
28737c478bd9Sstevel@tonic-gate ipp_ref_t **rpp;
28747c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
28757c478bd9Sstevel@tonic-gate int hb;
28767c478bd9Sstevel@tonic-gate
28777c478bd9Sstevel@tonic-gate ASSERT(aidp != NULL);
28787c478bd9Sstevel@tonic-gate
28797c478bd9Sstevel@tonic-gate rw_enter(ipp_action_byname_lock, RW_WRITER);
28807c478bd9Sstevel@tonic-gate
28817c478bd9Sstevel@tonic-gate /*
28827c478bd9Sstevel@tonic-gate * Find the right hash bucket for an action of the given name.
28837c478bd9Sstevel@tonic-gate * (Nameless actions always go in a special bucket).
28847c478bd9Sstevel@tonic-gate */
28857c478bd9Sstevel@tonic-gate
28867c478bd9Sstevel@tonic-gate if (aname != NULL) {
28877c478bd9Sstevel@tonic-gate hb = hash(aname);
28887c478bd9Sstevel@tonic-gate rpp = &ipp_action_byname[hb];
28897c478bd9Sstevel@tonic-gate } else
28907c478bd9Sstevel@tonic-gate rpp = &ipp_action_noname;
28917c478bd9Sstevel@tonic-gate
28927c478bd9Sstevel@tonic-gate /*
28937c478bd9Sstevel@tonic-gate * Scan the bucket to make sure that an action with the given name
28947c478bd9Sstevel@tonic-gate * does not already exist.
28957c478bd9Sstevel@tonic-gate */
28967c478bd9Sstevel@tonic-gate
28977c478bd9Sstevel@tonic-gate while ((rp = *rpp) != NULL) {
28987c478bd9Sstevel@tonic-gate ap = rp->ippr_action;
28997c478bd9Sstevel@tonic-gate if (aname != NULL && strcmp(ap->ippa_name, aname) == 0) {
29007c478bd9Sstevel@tonic-gate DBG1(DBG_ACTION, "action '%s' already exists\n",
29017c478bd9Sstevel@tonic-gate aname);
29027c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byname_lock);
29037c478bd9Sstevel@tonic-gate return (EEXIST);
29047c478bd9Sstevel@tonic-gate }
29057c478bd9Sstevel@tonic-gate rpp = &(rp->ippr_nextp);
29067c478bd9Sstevel@tonic-gate }
29077c478bd9Sstevel@tonic-gate
29087c478bd9Sstevel@tonic-gate /*
29097c478bd9Sstevel@tonic-gate * Allocate a new reference structure and a new action structure.
29107c478bd9Sstevel@tonic-gate */
29117c478bd9Sstevel@tonic-gate
29127c478bd9Sstevel@tonic-gate if ((rp = kmem_zalloc(sizeof (ipp_ref_t), KM_NOSLEEP)) == NULL) {
29137c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byname_lock);
29147c478bd9Sstevel@tonic-gate return (ENOMEM);
29157c478bd9Sstevel@tonic-gate }
29167c478bd9Sstevel@tonic-gate
29177c478bd9Sstevel@tonic-gate if ((ap = kmem_cache_alloc(ipp_action_cache, KM_NOSLEEP)) == NULL) {
29187c478bd9Sstevel@tonic-gate kmem_free(rp, sizeof (ipp_ref_t));
29197c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byname_lock);
29207c478bd9Sstevel@tonic-gate return (ENOMEM);
29217c478bd9Sstevel@tonic-gate }
29227c478bd9Sstevel@tonic-gate
29237c478bd9Sstevel@tonic-gate /*
29247c478bd9Sstevel@tonic-gate * Dream up a name if there isn't a real one and note that the action is
29257c478bd9Sstevel@tonic-gate * really nameless.
29267c478bd9Sstevel@tonic-gate */
29277c478bd9Sstevel@tonic-gate
29287c478bd9Sstevel@tonic-gate if (aname == NULL) {
29297c478bd9Sstevel@tonic-gate (void) sprintf(ap->ippa_name, "$%08X", ap->ippa_id);
29307c478bd9Sstevel@tonic-gate ap->ippa_nameless = B_TRUE;
29317c478bd9Sstevel@tonic-gate } else
29327c478bd9Sstevel@tonic-gate (void) strcpy(ap->ippa_name, aname);
29337c478bd9Sstevel@tonic-gate
29347c478bd9Sstevel@tonic-gate /*
29357c478bd9Sstevel@tonic-gate * Make sure the 'destruct pending' flag is clear. This indicates that
29367c478bd9Sstevel@tonic-gate * the structure is no longer part of the cache.
29377c478bd9Sstevel@tonic-gate */
29387c478bd9Sstevel@tonic-gate
29397c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_WRITER);
29407c478bd9Sstevel@tonic-gate ap->ippa_destruct_pending = B_FALSE;
29417c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
29427c478bd9Sstevel@tonic-gate
29437c478bd9Sstevel@tonic-gate /*
29447c478bd9Sstevel@tonic-gate * Fill in the reference structure and lint it onto the list.
29457c478bd9Sstevel@tonic-gate */
29467c478bd9Sstevel@tonic-gate
29477c478bd9Sstevel@tonic-gate rp->ippr_action = ap;
29487c478bd9Sstevel@tonic-gate *rpp = rp;
29497c478bd9Sstevel@tonic-gate
29507c478bd9Sstevel@tonic-gate /*
29517c478bd9Sstevel@tonic-gate * Increment the action count.
29527c478bd9Sstevel@tonic-gate */
29537c478bd9Sstevel@tonic-gate
29547c478bd9Sstevel@tonic-gate ipp_action_count++;
29557c478bd9Sstevel@tonic-gate
29567c478bd9Sstevel@tonic-gate *aidp = ap->ippa_id;
29577c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byname_lock);
29587c478bd9Sstevel@tonic-gate return (0);
29597c478bd9Sstevel@tonic-gate }
29607c478bd9Sstevel@tonic-gate #undef __FN__
29617c478bd9Sstevel@tonic-gate
29627c478bd9Sstevel@tonic-gate #define __FN__ "free_action"
29637c478bd9Sstevel@tonic-gate static void
free_action(ipp_action_t * ap)29647c478bd9Sstevel@tonic-gate free_action(
29657c478bd9Sstevel@tonic-gate ipp_action_t *ap)
29667c478bd9Sstevel@tonic-gate {
29677c478bd9Sstevel@tonic-gate ipp_ref_t **rpp;
29687c478bd9Sstevel@tonic-gate ipp_ref_t *rp;
29697c478bd9Sstevel@tonic-gate int hb;
29707c478bd9Sstevel@tonic-gate
29717c478bd9Sstevel@tonic-gate rw_enter(ipp_action_byname_lock, RW_WRITER);
29727c478bd9Sstevel@tonic-gate
29737c478bd9Sstevel@tonic-gate /*
29747c478bd9Sstevel@tonic-gate * Find the hash bucket where the action structure should be.
29757c478bd9Sstevel@tonic-gate */
29767c478bd9Sstevel@tonic-gate
29777c478bd9Sstevel@tonic-gate if (!ap->ippa_nameless) {
29787c478bd9Sstevel@tonic-gate hb = hash(ap->ippa_name);
29797c478bd9Sstevel@tonic-gate rpp = &ipp_action_byname[hb];
29807c478bd9Sstevel@tonic-gate } else
29817c478bd9Sstevel@tonic-gate rpp = &ipp_action_noname;
29827c478bd9Sstevel@tonic-gate
29837c478bd9Sstevel@tonic-gate /*
29847c478bd9Sstevel@tonic-gate * Scan the bucket for a match.
29857c478bd9Sstevel@tonic-gate */
29867c478bd9Sstevel@tonic-gate
29877c478bd9Sstevel@tonic-gate while ((rp = *rpp) != NULL) {
29887c478bd9Sstevel@tonic-gate if (rp->ippr_action == ap)
29897c478bd9Sstevel@tonic-gate break;
29907c478bd9Sstevel@tonic-gate rpp = &(rp->ippr_nextp);
29917c478bd9Sstevel@tonic-gate }
29927c478bd9Sstevel@tonic-gate ASSERT(rp != NULL);
29937c478bd9Sstevel@tonic-gate
29947c478bd9Sstevel@tonic-gate /*
29957c478bd9Sstevel@tonic-gate * Unlink and free the reference structure.
29967c478bd9Sstevel@tonic-gate */
29977c478bd9Sstevel@tonic-gate
29987c478bd9Sstevel@tonic-gate *rpp = rp->ippr_nextp;
29997c478bd9Sstevel@tonic-gate kmem_free(rp, sizeof (ipp_ref_t));
30007c478bd9Sstevel@tonic-gate
30017c478bd9Sstevel@tonic-gate /*
30027c478bd9Sstevel@tonic-gate * Decrement the action count.
30037c478bd9Sstevel@tonic-gate */
30047c478bd9Sstevel@tonic-gate
30057c478bd9Sstevel@tonic-gate ipp_action_count--;
30067c478bd9Sstevel@tonic-gate
30077c478bd9Sstevel@tonic-gate /*
30087c478bd9Sstevel@tonic-gate * Empty the name.
30097c478bd9Sstevel@tonic-gate */
30107c478bd9Sstevel@tonic-gate
30117c478bd9Sstevel@tonic-gate *ap->ippa_name = '\0';
30127c478bd9Sstevel@tonic-gate
30137c478bd9Sstevel@tonic-gate /*
30147c478bd9Sstevel@tonic-gate * If the hold count is zero then we can free the structure
30157c478bd9Sstevel@tonic-gate * immediately, otherwise we defer to rele_action().
30167c478bd9Sstevel@tonic-gate */
30177c478bd9Sstevel@tonic-gate
30187c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_WRITER);
30197c478bd9Sstevel@tonic-gate ap->ippa_destruct_pending = B_TRUE;
30207c478bd9Sstevel@tonic-gate if (ap->ippa_hold_count == 0) {
30217c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
30227c478bd9Sstevel@tonic-gate kmem_cache_free(ipp_action_cache, ap);
30237c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byname_lock);
30247c478bd9Sstevel@tonic-gate return;
30257c478bd9Sstevel@tonic-gate }
30267c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
30277c478bd9Sstevel@tonic-gate
30287c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byname_lock);
30297c478bd9Sstevel@tonic-gate }
30307c478bd9Sstevel@tonic-gate #undef __FN__
30317c478bd9Sstevel@tonic-gate
30327c478bd9Sstevel@tonic-gate #define __FN__ "hold_action"
30337c478bd9Sstevel@tonic-gate static ipp_action_t *
hold_action(ipp_action_id_t aid)30347c478bd9Sstevel@tonic-gate hold_action(
30357c478bd9Sstevel@tonic-gate ipp_action_id_t aid)
30367c478bd9Sstevel@tonic-gate {
30377c478bd9Sstevel@tonic-gate ipp_action_t *ap;
30387c478bd9Sstevel@tonic-gate
30397c478bd9Sstevel@tonic-gate if (aid < 0)
30407c478bd9Sstevel@tonic-gate return (NULL);
30417c478bd9Sstevel@tonic-gate
30427c478bd9Sstevel@tonic-gate /*
30437c478bd9Sstevel@tonic-gate * Use the action id as an index into the array of all action
30447c478bd9Sstevel@tonic-gate * structures.
30457c478bd9Sstevel@tonic-gate */
30467c478bd9Sstevel@tonic-gate
30477c478bd9Sstevel@tonic-gate rw_enter(ipp_action_byid_lock, RW_READER);
30487c478bd9Sstevel@tonic-gate if ((ap = ipp_action_byid[aid]) == NULL) {
30497c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byid_lock);
30507c478bd9Sstevel@tonic-gate return (NULL);
30517c478bd9Sstevel@tonic-gate }
30527c478bd9Sstevel@tonic-gate
30537c478bd9Sstevel@tonic-gate /*
30547c478bd9Sstevel@tonic-gate * If the action has 'destruct pending' set then it means it is either
30557c478bd9Sstevel@tonic-gate * still in the cache (i.e not allocated) or in the process of
30567c478bd9Sstevel@tonic-gate * being set up by alloc_action().
30577c478bd9Sstevel@tonic-gate */
30587c478bd9Sstevel@tonic-gate
30597c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_READER);
30607c478bd9Sstevel@tonic-gate if (ap->ippa_destruct_pending) {
30617c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
30627c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byid_lock);
30637c478bd9Sstevel@tonic-gate return (NULL);
30647c478bd9Sstevel@tonic-gate }
30657c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
30667c478bd9Sstevel@tonic-gate
30677c478bd9Sstevel@tonic-gate /*
30687c478bd9Sstevel@tonic-gate * Increment the hold count to prevent the structure from being
30697c478bd9Sstevel@tonic-gate * freed.
30707c478bd9Sstevel@tonic-gate */
30717c478bd9Sstevel@tonic-gate
30721a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&(ap->ippa_hold_count));
30737c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byid_lock);
30747c478bd9Sstevel@tonic-gate
30757c478bd9Sstevel@tonic-gate return (ap);
30767c478bd9Sstevel@tonic-gate }
30777c478bd9Sstevel@tonic-gate #undef __FN__
30787c478bd9Sstevel@tonic-gate
30797c478bd9Sstevel@tonic-gate #define __FN__ "rele_action"
30807c478bd9Sstevel@tonic-gate static void
rele_action(ipp_action_t * ap)30817c478bd9Sstevel@tonic-gate rele_action(
30827c478bd9Sstevel@tonic-gate ipp_action_t *ap)
30837c478bd9Sstevel@tonic-gate {
30847c478bd9Sstevel@tonic-gate /*
30857c478bd9Sstevel@tonic-gate * This call means we're done with the pointer so we can drop the
30867c478bd9Sstevel@tonic-gate * hold count.
30877c478bd9Sstevel@tonic-gate */
30887c478bd9Sstevel@tonic-gate
30897c478bd9Sstevel@tonic-gate ASSERT(ap->ippa_hold_count != 0);
30901a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&(ap->ippa_hold_count));
30917c478bd9Sstevel@tonic-gate
30927c478bd9Sstevel@tonic-gate /*
30937c478bd9Sstevel@tonic-gate * If the structure has 'destruct pending' set then we tried to free
30947c478bd9Sstevel@tonic-gate * it but couldn't, so do it now.
30957c478bd9Sstevel@tonic-gate */
30967c478bd9Sstevel@tonic-gate
30977c478bd9Sstevel@tonic-gate LOCK_ACTION(ap, RW_READER);
30987c478bd9Sstevel@tonic-gate if (ap->ippa_destruct_pending && ap->ippa_hold_count == 0) {
30997c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
31007c478bd9Sstevel@tonic-gate kmem_cache_free(ipp_action_cache, ap);
31017c478bd9Sstevel@tonic-gate return;
31027c478bd9Sstevel@tonic-gate }
31037c478bd9Sstevel@tonic-gate UNLOCK_ACTION(ap);
31047c478bd9Sstevel@tonic-gate }
31057c478bd9Sstevel@tonic-gate #undef __FN__
31067c478bd9Sstevel@tonic-gate
31077c478bd9Sstevel@tonic-gate #define __FN__ "get_aid"
31087c478bd9Sstevel@tonic-gate static ipp_action_id_t
get_aid(void)31097c478bd9Sstevel@tonic-gate get_aid(
31107c478bd9Sstevel@tonic-gate void)
31117c478bd9Sstevel@tonic-gate {
31127c478bd9Sstevel@tonic-gate int index;
31137c478bd9Sstevel@tonic-gate int start;
31147c478bd9Sstevel@tonic-gate int limit;
31157c478bd9Sstevel@tonic-gate
31167c478bd9Sstevel@tonic-gate ASSERT(rw_write_held(ipp_action_byid_lock));
31177c478bd9Sstevel@tonic-gate
31187c478bd9Sstevel@tonic-gate /*
31197c478bd9Sstevel@tonic-gate * Start searching after the last action id that we allocated.
31207c478bd9Sstevel@tonic-gate */
31217c478bd9Sstevel@tonic-gate
31227c478bd9Sstevel@tonic-gate start = (int)ipp_next_aid;
31237c478bd9Sstevel@tonic-gate limit = (int)ipp_aid_limit;
31247c478bd9Sstevel@tonic-gate
31257c478bd9Sstevel@tonic-gate /*
31267c478bd9Sstevel@tonic-gate * Look for a spare slot in the array.
31277c478bd9Sstevel@tonic-gate */
31287c478bd9Sstevel@tonic-gate
31297c478bd9Sstevel@tonic-gate index = start;
31307c478bd9Sstevel@tonic-gate while (ipp_action_byid[index] != NULL) {
31317c478bd9Sstevel@tonic-gate index++;
31327c478bd9Sstevel@tonic-gate if (index > limit)
31337c478bd9Sstevel@tonic-gate index = IPP_ACTION_RESERVED + 1;
31347c478bd9Sstevel@tonic-gate if (index == start)
31357c478bd9Sstevel@tonic-gate return (IPP_ACTION_INVAL);
31367c478bd9Sstevel@tonic-gate }
31377c478bd9Sstevel@tonic-gate
31387c478bd9Sstevel@tonic-gate /*
31397c478bd9Sstevel@tonic-gate * Note that we've just allocated a new action id so that we can
31407c478bd9Sstevel@tonic-gate * start our search there next time.
31417c478bd9Sstevel@tonic-gate */
31427c478bd9Sstevel@tonic-gate
31437c478bd9Sstevel@tonic-gate index++;
31447c478bd9Sstevel@tonic-gate if (index > limit)
31457c478bd9Sstevel@tonic-gate ipp_next_aid = IPP_ACTION_RESERVED + 1;
31467c478bd9Sstevel@tonic-gate else
31477c478bd9Sstevel@tonic-gate ipp_next_aid = (ipp_action_id_t)index;
31487c478bd9Sstevel@tonic-gate
31497c478bd9Sstevel@tonic-gate return ((ipp_action_id_t)(--index));
31507c478bd9Sstevel@tonic-gate }
31517c478bd9Sstevel@tonic-gate #undef __FN__
31527c478bd9Sstevel@tonic-gate
31537c478bd9Sstevel@tonic-gate #define __FN__ "alloc_packet"
31547c478bd9Sstevel@tonic-gate static int
alloc_packet(const char * name,ipp_action_id_t aid,ipp_packet_t ** ppp)31557c478bd9Sstevel@tonic-gate alloc_packet(
31567c478bd9Sstevel@tonic-gate const char *name,
31577c478bd9Sstevel@tonic-gate ipp_action_id_t aid,
31587c478bd9Sstevel@tonic-gate ipp_packet_t **ppp)
31597c478bd9Sstevel@tonic-gate {
31607c478bd9Sstevel@tonic-gate ipp_packet_t *pp;
31617c478bd9Sstevel@tonic-gate ipp_class_t *cp;
31627c478bd9Sstevel@tonic-gate
31637c478bd9Sstevel@tonic-gate if ((pp = kmem_cache_alloc(ipp_packet_cache, KM_NOSLEEP)) == NULL)
31647c478bd9Sstevel@tonic-gate return (ENOMEM);
31657c478bd9Sstevel@tonic-gate
31667c478bd9Sstevel@tonic-gate /*
31677c478bd9Sstevel@tonic-gate * Set the packet up with a single class.
31687c478bd9Sstevel@tonic-gate */
31697c478bd9Sstevel@tonic-gate
31707c478bd9Sstevel@tonic-gate cp = &(pp->ippp_class_array[0]);
31717c478bd9Sstevel@tonic-gate pp->ippp_class_windex = 1;
31727c478bd9Sstevel@tonic-gate
31737c478bd9Sstevel@tonic-gate (void) strcpy(cp->ippc_name, name);
31747c478bd9Sstevel@tonic-gate cp->ippc_aid = aid;
31757c478bd9Sstevel@tonic-gate
31767c478bd9Sstevel@tonic-gate *ppp = pp;
31777c478bd9Sstevel@tonic-gate return (0);
31787c478bd9Sstevel@tonic-gate }
31797c478bd9Sstevel@tonic-gate #undef __FN__
31807c478bd9Sstevel@tonic-gate
31817c478bd9Sstevel@tonic-gate #define __FN__ "realloc_packet"
31827c478bd9Sstevel@tonic-gate static int
realloc_packet(ipp_packet_t * pp)31837c478bd9Sstevel@tonic-gate realloc_packet(
31847c478bd9Sstevel@tonic-gate ipp_packet_t *pp)
31857c478bd9Sstevel@tonic-gate {
31867c478bd9Sstevel@tonic-gate uint_t length;
31877c478bd9Sstevel@tonic-gate ipp_class_t *array;
31887c478bd9Sstevel@tonic-gate
31897c478bd9Sstevel@tonic-gate length = (pp->ippp_class_limit + 1) << 1;
31907c478bd9Sstevel@tonic-gate if ((array = kmem_alloc(length * sizeof (ipp_class_t),
31917c478bd9Sstevel@tonic-gate KM_NOSLEEP)) == NULL)
31927c478bd9Sstevel@tonic-gate return (ENOMEM);
31937c478bd9Sstevel@tonic-gate
31947c478bd9Sstevel@tonic-gate bcopy(pp->ippp_class_array, array,
31957c478bd9Sstevel@tonic-gate (length >> 1) * sizeof (ipp_class_t));
31967c478bd9Sstevel@tonic-gate
31977c478bd9Sstevel@tonic-gate kmem_free(pp->ippp_class_array,
31987c478bd9Sstevel@tonic-gate (length >> 1) * sizeof (ipp_class_t));
31997c478bd9Sstevel@tonic-gate
32007c478bd9Sstevel@tonic-gate pp->ippp_class_array = array;
32017c478bd9Sstevel@tonic-gate pp->ippp_class_limit = length - 1;
32027c478bd9Sstevel@tonic-gate
32037c478bd9Sstevel@tonic-gate return (0);
32047c478bd9Sstevel@tonic-gate }
32057c478bd9Sstevel@tonic-gate #undef __FN__
32067c478bd9Sstevel@tonic-gate
32077c478bd9Sstevel@tonic-gate #define __FN__ "free_packet"
32087c478bd9Sstevel@tonic-gate static void
free_packet(ipp_packet_t * pp)32097c478bd9Sstevel@tonic-gate free_packet(
32107c478bd9Sstevel@tonic-gate ipp_packet_t *pp)
32117c478bd9Sstevel@tonic-gate {
32127c478bd9Sstevel@tonic-gate pp->ippp_class_windex = 0;
32137c478bd9Sstevel@tonic-gate pp->ippp_class_rindex = 0;
32147c478bd9Sstevel@tonic-gate
32157c478bd9Sstevel@tonic-gate pp->ippp_data = NULL;
32167c478bd9Sstevel@tonic-gate pp->ippp_private = NULL;
32177c478bd9Sstevel@tonic-gate
32187c478bd9Sstevel@tonic-gate kmem_cache_free(ipp_packet_cache, pp);
32197c478bd9Sstevel@tonic-gate }
32207c478bd9Sstevel@tonic-gate #undef __FN__
32217c478bd9Sstevel@tonic-gate
32227c478bd9Sstevel@tonic-gate #define __FN__ "hash"
32237c478bd9Sstevel@tonic-gate static int
hash(const char * name)32247c478bd9Sstevel@tonic-gate hash(
32257c478bd9Sstevel@tonic-gate const char *name)
32267c478bd9Sstevel@tonic-gate {
32277c478bd9Sstevel@tonic-gate int val = 0;
32287c478bd9Sstevel@tonic-gate char *ptr;
32297c478bd9Sstevel@tonic-gate
32307c478bd9Sstevel@tonic-gate /*
32317c478bd9Sstevel@tonic-gate * Make a hash value by XORing all the ascii codes in the text string.
32327c478bd9Sstevel@tonic-gate */
32337c478bd9Sstevel@tonic-gate
3234*7e12ceb3SToomas Soome for (ptr = (char *)name; *ptr != '\0'; ptr++) {
32357c478bd9Sstevel@tonic-gate val ^= *ptr;
32367c478bd9Sstevel@tonic-gate }
32377c478bd9Sstevel@tonic-gate
32387c478bd9Sstevel@tonic-gate /*
32397c478bd9Sstevel@tonic-gate * Return the value modulo the number of hash buckets we allow.
32407c478bd9Sstevel@tonic-gate */
32417c478bd9Sstevel@tonic-gate
32427c478bd9Sstevel@tonic-gate return (val % IPP_NBUCKET);
32437c478bd9Sstevel@tonic-gate }
32447c478bd9Sstevel@tonic-gate #undef __FN__
32457c478bd9Sstevel@tonic-gate
32467c478bd9Sstevel@tonic-gate #define __FN__ "update_stats"
32477c478bd9Sstevel@tonic-gate static int
update_stats(kstat_t * ksp,int rw)32487c478bd9Sstevel@tonic-gate update_stats(
32497c478bd9Sstevel@tonic-gate kstat_t *ksp,
32507c478bd9Sstevel@tonic-gate int rw)
32517c478bd9Sstevel@tonic-gate {
32527c478bd9Sstevel@tonic-gate ipp_stat_impl_t *sip;
32537c478bd9Sstevel@tonic-gate
32547c478bd9Sstevel@tonic-gate ASSERT(ksp->ks_private != NULL);
32557c478bd9Sstevel@tonic-gate sip = (ipp_stat_impl_t *)ksp->ks_private;
32567c478bd9Sstevel@tonic-gate
32577c478bd9Sstevel@tonic-gate /*
32587c478bd9Sstevel@tonic-gate * Call the update function passed to ipp_stat_create() for the given
32597c478bd9Sstevel@tonic-gate * set of kstats.
32607c478bd9Sstevel@tonic-gate */
32617c478bd9Sstevel@tonic-gate
32627c478bd9Sstevel@tonic-gate return (sip->ippsi_update((ipp_stat_t *)sip, sip->ippsi_arg, rw));
32637c478bd9Sstevel@tonic-gate }
32647c478bd9Sstevel@tonic-gate #undef __FN__
32657c478bd9Sstevel@tonic-gate
32667c478bd9Sstevel@tonic-gate #define __FN__ "init_mods"
32677c478bd9Sstevel@tonic-gate static void
init_mods(void)32687c478bd9Sstevel@tonic-gate init_mods(
32697c478bd9Sstevel@tonic-gate void)
32707c478bd9Sstevel@tonic-gate {
32717c478bd9Sstevel@tonic-gate /*
32727c478bd9Sstevel@tonic-gate * Initialise the array of all module structures and the module
32737c478bd9Sstevel@tonic-gate * structure kmem cache.
32747c478bd9Sstevel@tonic-gate */
32757c478bd9Sstevel@tonic-gate
32767c478bd9Sstevel@tonic-gate rw_init(ipp_mod_byid_lock, NULL, RW_DEFAULT,
32777c478bd9Sstevel@tonic-gate (void *)ipltospl(LOCK_LEVEL));
32787c478bd9Sstevel@tonic-gate ipp_mod_byid = kmem_zalloc(sizeof (ipp_mod_t *) * (ipp_max_mod + 1),
32797c478bd9Sstevel@tonic-gate KM_SLEEP);
32807c478bd9Sstevel@tonic-gate ipp_mod_byid[ipp_max_mod] = (ipp_mod_t *)-1;
32817c478bd9Sstevel@tonic-gate ipp_mid_limit = (ipp_mod_id_t)(ipp_max_mod - 1);
32827c478bd9Sstevel@tonic-gate
32837c478bd9Sstevel@tonic-gate ipp_mod_cache = kmem_cache_create("ipp_mod", sizeof (ipp_mod_t),
32847c478bd9Sstevel@tonic-gate IPP_ALIGN, mod_constructor, mod_destructor, NULL, NULL, NULL, 0);
32857c478bd9Sstevel@tonic-gate ASSERT(ipp_mod_cache != NULL);
32867c478bd9Sstevel@tonic-gate
32877c478bd9Sstevel@tonic-gate /*
32887c478bd9Sstevel@tonic-gate * Initialize the 'module by name' hash bucket array.
32897c478bd9Sstevel@tonic-gate */
32907c478bd9Sstevel@tonic-gate
32917c478bd9Sstevel@tonic-gate rw_init(ipp_mod_byname_lock, NULL, RW_DEFAULT,
32927c478bd9Sstevel@tonic-gate (void *)ipltospl(LOCK_LEVEL));
32937c478bd9Sstevel@tonic-gate bzero(ipp_mod_byname, IPP_NBUCKET * sizeof (ipp_ref_t *));
32947c478bd9Sstevel@tonic-gate }
32957c478bd9Sstevel@tonic-gate #undef __FN__
32967c478bd9Sstevel@tonic-gate
32977c478bd9Sstevel@tonic-gate #define __FN__ "init_actions"
32987c478bd9Sstevel@tonic-gate static void
init_actions(void)32997c478bd9Sstevel@tonic-gate init_actions(
33007c478bd9Sstevel@tonic-gate void)
33017c478bd9Sstevel@tonic-gate {
33027c478bd9Sstevel@tonic-gate /*
33037c478bd9Sstevel@tonic-gate * Initialise the array of all action structures and the action
33047c478bd9Sstevel@tonic-gate * structure cache.
33057c478bd9Sstevel@tonic-gate */
33067c478bd9Sstevel@tonic-gate
33077c478bd9Sstevel@tonic-gate rw_init(ipp_action_byid_lock, NULL, RW_DEFAULT,
33087c478bd9Sstevel@tonic-gate (void *)ipltospl(LOCK_LEVEL));
33097c478bd9Sstevel@tonic-gate ipp_action_byid = kmem_zalloc(sizeof (ipp_action_t *) *
33107c478bd9Sstevel@tonic-gate (ipp_max_action + 1), KM_SLEEP);
33117c478bd9Sstevel@tonic-gate ipp_action_byid[ipp_max_action] = (ipp_action_t *)-1;
33127c478bd9Sstevel@tonic-gate ipp_aid_limit = (ipp_action_id_t)(ipp_max_action - 1);
33137c478bd9Sstevel@tonic-gate
33147c478bd9Sstevel@tonic-gate ipp_action_cache = kmem_cache_create("ipp_action",
33157c478bd9Sstevel@tonic-gate sizeof (ipp_action_t), IPP_ALIGN, action_constructor,
33167c478bd9Sstevel@tonic-gate action_destructor, NULL, NULL, NULL, 0);
33177c478bd9Sstevel@tonic-gate ASSERT(ipp_action_cache != NULL);
33187c478bd9Sstevel@tonic-gate
33197c478bd9Sstevel@tonic-gate /*
33207c478bd9Sstevel@tonic-gate * Initialize the 'action by name' hash bucket array (and the special
33217c478bd9Sstevel@tonic-gate * 'hash' bucket for nameless actions).
33227c478bd9Sstevel@tonic-gate */
33237c478bd9Sstevel@tonic-gate
33247c478bd9Sstevel@tonic-gate rw_init(ipp_action_byname_lock, NULL, RW_DEFAULT,
33257c478bd9Sstevel@tonic-gate (void *)ipltospl(LOCK_LEVEL));
33267c478bd9Sstevel@tonic-gate bzero(ipp_action_byname, IPP_NBUCKET * sizeof (ipp_ref_t *));
33277c478bd9Sstevel@tonic-gate ipp_action_noname = NULL;
33287c478bd9Sstevel@tonic-gate }
33297c478bd9Sstevel@tonic-gate #undef __FN__
33307c478bd9Sstevel@tonic-gate
33317c478bd9Sstevel@tonic-gate #define __FN__ "init_packets"
33327c478bd9Sstevel@tonic-gate static void
init_packets(void)33337c478bd9Sstevel@tonic-gate init_packets(
33347c478bd9Sstevel@tonic-gate void)
33357c478bd9Sstevel@tonic-gate {
33367c478bd9Sstevel@tonic-gate /*
33377c478bd9Sstevel@tonic-gate * Initialise the packet structure cache.
33387c478bd9Sstevel@tonic-gate */
33397c478bd9Sstevel@tonic-gate
33407c478bd9Sstevel@tonic-gate ipp_packet_cache = kmem_cache_create("ipp_packet",
33417c478bd9Sstevel@tonic-gate sizeof (ipp_packet_t), IPP_ALIGN, packet_constructor,
33427c478bd9Sstevel@tonic-gate packet_destructor, NULL, NULL, NULL, 0);
33437c478bd9Sstevel@tonic-gate ASSERT(ipp_packet_cache != NULL);
33447c478bd9Sstevel@tonic-gate }
33457c478bd9Sstevel@tonic-gate #undef __FN__
33467c478bd9Sstevel@tonic-gate
33477c478bd9Sstevel@tonic-gate /*
33487c478bd9Sstevel@tonic-gate * Kmem cache constructor/destructor functions.
33497c478bd9Sstevel@tonic-gate */
33507c478bd9Sstevel@tonic-gate
33517c478bd9Sstevel@tonic-gate #define __FN__ "mod_constructor"
33527c478bd9Sstevel@tonic-gate /*ARGSUSED*/
33537c478bd9Sstevel@tonic-gate static int
mod_constructor(void * buf,void * cdrarg,int kmflags)33547c478bd9Sstevel@tonic-gate mod_constructor(
33557c478bd9Sstevel@tonic-gate void *buf,
33567c478bd9Sstevel@tonic-gate void *cdrarg,
33577c478bd9Sstevel@tonic-gate int kmflags)
33587c478bd9Sstevel@tonic-gate {
33597c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
33607c478bd9Sstevel@tonic-gate ipp_mod_id_t mid;
33617c478bd9Sstevel@tonic-gate
33627c478bd9Sstevel@tonic-gate ASSERT(buf != NULL);
33637c478bd9Sstevel@tonic-gate bzero(buf, sizeof (ipp_mod_t));
33647c478bd9Sstevel@tonic-gate imp = (ipp_mod_t *)buf;
33657c478bd9Sstevel@tonic-gate
33667c478bd9Sstevel@tonic-gate rw_enter(ipp_mod_byid_lock, RW_WRITER);
33677c478bd9Sstevel@tonic-gate
33687c478bd9Sstevel@tonic-gate /*
33697c478bd9Sstevel@tonic-gate * Get a new module id.
33707c478bd9Sstevel@tonic-gate */
33717c478bd9Sstevel@tonic-gate
33727c478bd9Sstevel@tonic-gate if ((mid = get_mid()) <= IPP_MOD_RESERVED) {
33737c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byid_lock);
33747c478bd9Sstevel@tonic-gate return (-1);
33757c478bd9Sstevel@tonic-gate }
33767c478bd9Sstevel@tonic-gate
33777c478bd9Sstevel@tonic-gate /*
33787c478bd9Sstevel@tonic-gate * Initialize the buffer as a module structure in PROTO form.
33797c478bd9Sstevel@tonic-gate */
33807c478bd9Sstevel@tonic-gate
33817c478bd9Sstevel@tonic-gate imp->ippm_destruct_pending = B_TRUE;
33827c478bd9Sstevel@tonic-gate imp->ippm_state = IPP_MODSTATE_PROTO;
33837c478bd9Sstevel@tonic-gate rw_init(imp->ippm_lock, NULL, RW_DEFAULT,
33847c478bd9Sstevel@tonic-gate (void *)ipltospl(LOCK_LEVEL));
33857c478bd9Sstevel@tonic-gate
33867c478bd9Sstevel@tonic-gate /*
33877c478bd9Sstevel@tonic-gate * Insert it into the array of all module structures.
33887c478bd9Sstevel@tonic-gate */
33897c478bd9Sstevel@tonic-gate
33907c478bd9Sstevel@tonic-gate imp->ippm_id = mid;
33917c478bd9Sstevel@tonic-gate ipp_mod_byid[mid] = imp;
33927c478bd9Sstevel@tonic-gate
33937c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byid_lock);
33947c478bd9Sstevel@tonic-gate
33957c478bd9Sstevel@tonic-gate return (0);
33967c478bd9Sstevel@tonic-gate }
33977c478bd9Sstevel@tonic-gate #undef __FN__
33987c478bd9Sstevel@tonic-gate
33997c478bd9Sstevel@tonic-gate #define __FN__ "mod_destructor"
34007c478bd9Sstevel@tonic-gate /*ARGSUSED*/
34017c478bd9Sstevel@tonic-gate static void
mod_destructor(void * buf,void * cdrarg)34027c478bd9Sstevel@tonic-gate mod_destructor(
34037c478bd9Sstevel@tonic-gate void *buf,
34047c478bd9Sstevel@tonic-gate void *cdrarg)
34057c478bd9Sstevel@tonic-gate {
34067c478bd9Sstevel@tonic-gate ipp_mod_t *imp;
34077c478bd9Sstevel@tonic-gate
34087c478bd9Sstevel@tonic-gate ASSERT(buf != NULL);
34097c478bd9Sstevel@tonic-gate imp = (ipp_mod_t *)buf;
34107c478bd9Sstevel@tonic-gate
34117c478bd9Sstevel@tonic-gate ASSERT(imp->ippm_state == IPP_MODSTATE_PROTO);
34127c478bd9Sstevel@tonic-gate ASSERT(imp->ippm_action == NULL);
34137c478bd9Sstevel@tonic-gate ASSERT(*imp->ippm_name == '\0');
34147c478bd9Sstevel@tonic-gate ASSERT(imp->ippm_destruct_pending);
34157c478bd9Sstevel@tonic-gate
34167c478bd9Sstevel@tonic-gate rw_enter(ipp_mod_byid_lock, RW_WRITER);
34177c478bd9Sstevel@tonic-gate ASSERT(imp->ippm_hold_count == 0);
34187c478bd9Sstevel@tonic-gate
34197c478bd9Sstevel@tonic-gate /*
34207c478bd9Sstevel@tonic-gate * NULL the entry in the array of all module structures.
34217c478bd9Sstevel@tonic-gate */
34227c478bd9Sstevel@tonic-gate
34237c478bd9Sstevel@tonic-gate ipp_mod_byid[imp->ippm_id] = NULL;
34247c478bd9Sstevel@tonic-gate
34257c478bd9Sstevel@tonic-gate /*
34267c478bd9Sstevel@tonic-gate * Clean up any remnants of the module structure as the buffer is
34277c478bd9Sstevel@tonic-gate * about to disappear.
34287c478bd9Sstevel@tonic-gate */
34297c478bd9Sstevel@tonic-gate
34307c478bd9Sstevel@tonic-gate rw_destroy(imp->ippm_lock);
34317c478bd9Sstevel@tonic-gate rw_exit(ipp_mod_byid_lock);
34327c478bd9Sstevel@tonic-gate }
34337c478bd9Sstevel@tonic-gate #undef __FN__
34347c478bd9Sstevel@tonic-gate
34357c478bd9Sstevel@tonic-gate #define __FN__ "action_constructor"
34367c478bd9Sstevel@tonic-gate /*ARGSUSED*/
34377c478bd9Sstevel@tonic-gate static int
action_constructor(void * buf,void * cdrarg,int kmflags)34387c478bd9Sstevel@tonic-gate action_constructor(
34397c478bd9Sstevel@tonic-gate void *buf,
34407c478bd9Sstevel@tonic-gate void *cdrarg,
34417c478bd9Sstevel@tonic-gate int kmflags)
34427c478bd9Sstevel@tonic-gate {
34437c478bd9Sstevel@tonic-gate ipp_action_t *ap;
34447c478bd9Sstevel@tonic-gate ipp_action_id_t aid;
34457c478bd9Sstevel@tonic-gate
34467c478bd9Sstevel@tonic-gate ASSERT(buf != NULL);
34477c478bd9Sstevel@tonic-gate bzero(buf, sizeof (ipp_action_t));
34487c478bd9Sstevel@tonic-gate ap = (ipp_action_t *)buf;
34497c478bd9Sstevel@tonic-gate
34507c478bd9Sstevel@tonic-gate rw_enter(ipp_action_byid_lock, RW_WRITER);
34517c478bd9Sstevel@tonic-gate
34527c478bd9Sstevel@tonic-gate /*
34537c478bd9Sstevel@tonic-gate * Get a new action id.
34547c478bd9Sstevel@tonic-gate */
34557c478bd9Sstevel@tonic-gate
34567c478bd9Sstevel@tonic-gate if ((aid = get_aid()) <= IPP_ACTION_RESERVED) {
34577c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byid_lock);
34587c478bd9Sstevel@tonic-gate return (-1);
34597c478bd9Sstevel@tonic-gate }
34607c478bd9Sstevel@tonic-gate
34617c478bd9Sstevel@tonic-gate /*
34627c478bd9Sstevel@tonic-gate * Initialize the buffer as an action structure in PROTO form.
34637c478bd9Sstevel@tonic-gate */
34647c478bd9Sstevel@tonic-gate
34657c478bd9Sstevel@tonic-gate ap->ippa_state = IPP_ASTATE_PROTO;
34667c478bd9Sstevel@tonic-gate ap->ippa_destruct_pending = B_TRUE;
34677c478bd9Sstevel@tonic-gate rw_init(ap->ippa_lock, NULL, RW_DEFAULT,
34687c478bd9Sstevel@tonic-gate (void *)ipltospl(LOCK_LEVEL));
34697c478bd9Sstevel@tonic-gate CONFIG_LOCK_INIT(ap->ippa_config_lock);
34707c478bd9Sstevel@tonic-gate
34717c478bd9Sstevel@tonic-gate /*
34727c478bd9Sstevel@tonic-gate * Insert it into the array of all action structures.
34737c478bd9Sstevel@tonic-gate */
34747c478bd9Sstevel@tonic-gate
34757c478bd9Sstevel@tonic-gate ap->ippa_id = aid;
34767c478bd9Sstevel@tonic-gate ipp_action_byid[aid] = ap;
34777c478bd9Sstevel@tonic-gate
34787c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byid_lock);
34797c478bd9Sstevel@tonic-gate return (0);
34807c478bd9Sstevel@tonic-gate }
34817c478bd9Sstevel@tonic-gate #undef __FN__
34827c478bd9Sstevel@tonic-gate
34837c478bd9Sstevel@tonic-gate #define __FN__ "action_destructor"
34847c478bd9Sstevel@tonic-gate /*ARGSUSED*/
34857c478bd9Sstevel@tonic-gate static void
action_destructor(void * buf,void * cdrarg)34867c478bd9Sstevel@tonic-gate action_destructor(
34877c478bd9Sstevel@tonic-gate void *buf,
34887c478bd9Sstevel@tonic-gate void *cdrarg)
34897c478bd9Sstevel@tonic-gate {
34907c478bd9Sstevel@tonic-gate ipp_action_t *ap;
34917c478bd9Sstevel@tonic-gate
34927c478bd9Sstevel@tonic-gate ASSERT(buf != NULL);
34937c478bd9Sstevel@tonic-gate ap = (ipp_action_t *)buf;
34947c478bd9Sstevel@tonic-gate
34957c478bd9Sstevel@tonic-gate ASSERT(ap->ippa_state == IPP_ASTATE_PROTO);
34967c478bd9Sstevel@tonic-gate ASSERT(ap->ippa_ref == NULL);
34977c478bd9Sstevel@tonic-gate ASSERT(ap->ippa_refby == NULL);
34987c478bd9Sstevel@tonic-gate ASSERT(ap->ippa_packets == 0);
34997c478bd9Sstevel@tonic-gate ASSERT(*ap->ippa_name == '\0');
35007c478bd9Sstevel@tonic-gate ASSERT(ap->ippa_destruct_pending);
35017c478bd9Sstevel@tonic-gate
35027c478bd9Sstevel@tonic-gate rw_enter(ipp_action_byid_lock, RW_WRITER);
35037c478bd9Sstevel@tonic-gate ASSERT(ap->ippa_hold_count == 0);
35047c478bd9Sstevel@tonic-gate
35057c478bd9Sstevel@tonic-gate /*
35067c478bd9Sstevel@tonic-gate * NULL the entry in the array of all action structures.
35077c478bd9Sstevel@tonic-gate */
35087c478bd9Sstevel@tonic-gate
35097c478bd9Sstevel@tonic-gate ipp_action_byid[ap->ippa_id] = NULL;
35107c478bd9Sstevel@tonic-gate
35117c478bd9Sstevel@tonic-gate /*
35127c478bd9Sstevel@tonic-gate * Clean up any remnants of the action structure as the buffer is
35137c478bd9Sstevel@tonic-gate * about to disappear.
35147c478bd9Sstevel@tonic-gate */
35157c478bd9Sstevel@tonic-gate
35167c478bd9Sstevel@tonic-gate CONFIG_LOCK_FINI(ap->ippa_config_lock);
35177c478bd9Sstevel@tonic-gate rw_destroy(ap->ippa_lock);
35187c478bd9Sstevel@tonic-gate
35197c478bd9Sstevel@tonic-gate rw_exit(ipp_action_byid_lock);
35207c478bd9Sstevel@tonic-gate }
35217c478bd9Sstevel@tonic-gate #undef __FN__
35227c478bd9Sstevel@tonic-gate
35237c478bd9Sstevel@tonic-gate #define __FN__ "packet_constructor"
35247c478bd9Sstevel@tonic-gate /*ARGSUSED*/
35257c478bd9Sstevel@tonic-gate static int
packet_constructor(void * buf,void * cdrarg,int kmflags)35267c478bd9Sstevel@tonic-gate packet_constructor(
35277c478bd9Sstevel@tonic-gate void *buf,
35287c478bd9Sstevel@tonic-gate void *cdrarg,
35297c478bd9Sstevel@tonic-gate int kmflags)
35307c478bd9Sstevel@tonic-gate {
35317c478bd9Sstevel@tonic-gate ipp_packet_t *pp;
35327c478bd9Sstevel@tonic-gate ipp_class_t *cp;
35337c478bd9Sstevel@tonic-gate
35347c478bd9Sstevel@tonic-gate ASSERT(buf != NULL);
35357c478bd9Sstevel@tonic-gate bzero(buf, sizeof (ipp_packet_t));
35367c478bd9Sstevel@tonic-gate pp = (ipp_packet_t *)buf;
35377c478bd9Sstevel@tonic-gate
35387c478bd9Sstevel@tonic-gate if ((cp = kmem_alloc(ipp_packet_classes * sizeof (ipp_class_t),
35397c478bd9Sstevel@tonic-gate KM_NOSLEEP)) == NULL)
35407c478bd9Sstevel@tonic-gate return (ENOMEM);
35417c478bd9Sstevel@tonic-gate
35427c478bd9Sstevel@tonic-gate pp->ippp_class_array = cp;
35437c478bd9Sstevel@tonic-gate pp->ippp_class_windex = 0;
35447c478bd9Sstevel@tonic-gate pp->ippp_class_rindex = 0;
35457c478bd9Sstevel@tonic-gate pp->ippp_class_limit = ipp_packet_classes - 1;
35467c478bd9Sstevel@tonic-gate
35477c478bd9Sstevel@tonic-gate return (0);
35487c478bd9Sstevel@tonic-gate }
35497c478bd9Sstevel@tonic-gate #undef __FN__
35507c478bd9Sstevel@tonic-gate
35517c478bd9Sstevel@tonic-gate #define __FN__ "packet_destructor"
35527c478bd9Sstevel@tonic-gate /*ARGSUSED*/
35537c478bd9Sstevel@tonic-gate static void
packet_destructor(void * buf,void * cdrarg)35547c478bd9Sstevel@tonic-gate packet_destructor(
35557c478bd9Sstevel@tonic-gate void *buf,
35567c478bd9Sstevel@tonic-gate void *cdrarg)
35577c478bd9Sstevel@tonic-gate {
35587c478bd9Sstevel@tonic-gate ipp_packet_t *pp;
35597c478bd9Sstevel@tonic-gate
35607c478bd9Sstevel@tonic-gate ASSERT(buf != NULL);
35617c478bd9Sstevel@tonic-gate pp = (ipp_packet_t *)buf;
35627c478bd9Sstevel@tonic-gate
35637c478bd9Sstevel@tonic-gate ASSERT(pp->ippp_data == NULL);
35647c478bd9Sstevel@tonic-gate ASSERT(pp->ippp_class_windex == 0);
35657c478bd9Sstevel@tonic-gate ASSERT(pp->ippp_class_rindex == 0);
35667c478bd9Sstevel@tonic-gate ASSERT(pp->ippp_private == NULL);
35677c478bd9Sstevel@tonic-gate ASSERT(pp->ippp_private_free == NULL);
35687c478bd9Sstevel@tonic-gate
35697c478bd9Sstevel@tonic-gate kmem_free(pp->ippp_class_array,
35707c478bd9Sstevel@tonic-gate (pp->ippp_class_limit + 1) * sizeof (ipp_class_t));
35717c478bd9Sstevel@tonic-gate
35727c478bd9Sstevel@tonic-gate if (pp->ippp_log != NULL) {
35737c478bd9Sstevel@tonic-gate kmem_free(pp->ippp_log,
35747c478bd9Sstevel@tonic-gate (pp->ippp_log_limit + 1) * sizeof (ipp_log_t));
35757c478bd9Sstevel@tonic-gate }
35767c478bd9Sstevel@tonic-gate }
35777c478bd9Sstevel@tonic-gate #undef __FN__
35787c478bd9Sstevel@tonic-gate
35797c478bd9Sstevel@tonic-gate /*
35807c478bd9Sstevel@tonic-gate * Debug message printout code.
35817c478bd9Sstevel@tonic-gate */
35827c478bd9Sstevel@tonic-gate
35837c478bd9Sstevel@tonic-gate #ifdef IPP_DBG
35847c478bd9Sstevel@tonic-gate static void
ipp_debug(uint64_t type,const char * fn,char * fmt,...)35857c478bd9Sstevel@tonic-gate ipp_debug(
35867c478bd9Sstevel@tonic-gate uint64_t type,
35877c478bd9Sstevel@tonic-gate const char *fn,
35887c478bd9Sstevel@tonic-gate char *fmt,
35897c478bd9Sstevel@tonic-gate ...)
35907c478bd9Sstevel@tonic-gate {
35917c478bd9Sstevel@tonic-gate char buf[255];
35927c478bd9Sstevel@tonic-gate va_list adx;
35937c478bd9Sstevel@tonic-gate
35947c478bd9Sstevel@tonic-gate if ((type & ipp_debug_flags) == 0)
35957c478bd9Sstevel@tonic-gate return;
35967c478bd9Sstevel@tonic-gate
35977c478bd9Sstevel@tonic-gate mutex_enter(debug_mutex);
35987c478bd9Sstevel@tonic-gate va_start(adx, fmt);
35997c478bd9Sstevel@tonic-gate (void) vsnprintf(buf, 255, fmt, adx);
36007c478bd9Sstevel@tonic-gate va_end(adx);
36017c478bd9Sstevel@tonic-gate
36027c478bd9Sstevel@tonic-gate printf("(%llx) %s: %s", (unsigned long long)curthread->t_did, fn,
36037c478bd9Sstevel@tonic-gate buf);
36047c478bd9Sstevel@tonic-gate mutex_exit(debug_mutex);
36057c478bd9Sstevel@tonic-gate }
36067c478bd9Sstevel@tonic-gate #endif /* IPP_DBG */
3607