dman.c revision 5c066ec28ea93f3a7c93082611a61747f255290a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Common Development and Distribution License (the "License").
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
193974072f41a843678abf5f61979c748687e66bSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Starcat Management Network Driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ****** NOTICE **** This file also resides in the SSC gate as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ****** NOTICE **** usr/src/uts/sun4u/scman/scman.c. Any changes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ****** NOTICE **** made here must be propogated there as well.
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set manstr_t dlpistate (upper half of multiplexor)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set man_dest_t dlpistate (lower half of multiplexor)
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic const char *lss[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *_mw_type[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define man_kzalloc(a, b) man_dbg_kzalloc(__LINE__, a, b)
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid *man_dbg_kzalloc(int line, size_t size, int kmflags);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set manstr_t dlpistate (upper half of multiplexor)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SETSTATE(msp, state) msp->ms_dlpistate = (state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set man_dest_t dlpistate (lower half of multiplexor)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define D_SETSTATE(mdp, state) mdp->md_dlpistate = (state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DL_PRIM(mp) (((union DL_primitives *)(mp)->b_rptr)->dl_primitive)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (((union DL_primitives *)(mp)->b_rptr)->promiscon_req.dl_level)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define IOC_CMD(mp) (((struct iocblk *)(mp)->b_rptr)->ioc_cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start of kstat-related declarations
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_NOT_PHYSICAL (1<<3) /* no matching physical stat */
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct man_kstat_info_s {
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *mk_physname; /* e.g. framing (NULL for same) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *mk_physalias; /* e.g. framing (NULL for same) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Master declaration macro, note that it uses token pasting
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_DECLARE(name, pname, palias, bits, flags) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel { name, pname, palias, KSTAT_DATA_UINT ## bits, flags }
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Obsolete forms don't have the _sinceswitch forms, they are all errors
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_OBSOLETE32(name, alias) MK_DECLARE(alias, name, alias, 32, MK_ERROR)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_OBSOLETE64(name, alias) MK_DECLARE(alias, name, alias, 64, MK_ERROR)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The only non-counters don't have any other aliases
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_NOTCOUNTER32(name) MK_DECLARE(name, name, NULL, 32, MK_NOT_COUNTER)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_NOTCOUNTER64(name) MK_DECLARE(name, name, NULL, 64, MK_NOT_COUNTER)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Normal counter forms
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Error counters need special MK_ERROR flag only for the non-AP form
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These AP-specific stats are not backed by physical statistics
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_NOTPHYS32(name) MK_DECLARE(name, NULL, NULL, 32, MK_NOT_PHYSICAL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_NOTPHYS64(name) MK_DECLARE(name, NULL, NULL, 64, MK_NOT_PHYSICAL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * START of the actual man_kstat_info declaration using above macros
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Link Input/Output stats
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These are new MIB-II stats, per PSARC 1997/198
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Error values
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These are the 64-bit values, they fallback to 32-bit values
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* New AP switching statistics */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MAN_NUMSTATS (sizeof (man_kstat_info) / sizeof (man_kstat_info_t))
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Miscellaneous ethernet stuff.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MANs DL_INFO_ACK template.
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_min_sdu */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_reserved */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_current_state */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_qos_length */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_qos_offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_range_length */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_range_offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (dl_info_ack_t) + MAN_ADDRL, /* dl_brdcst_addr_offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0 /* dl_growth */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Ethernet broadcast address definition.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set via MAN_SET_SC_IPADDRS ioctl.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_sc_ipaddrs_t man_sc_ipaddrs = { 0xffffffffU, 0xffffffffU };
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set via MAN_SET_SC_IP6ADDRS ioctl.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_sc_ip6addrs_t man_sc_ip6addrs = { 0, 0, 0, 0, 0, 0, 0, 0 };
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IP & ICMP constants
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Function prototypes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Upper multiplexor functions.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_attach(dev_info_t *, ddi_attach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_detach(dev_info_t *, ddi_detach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_open(register queue_t *, dev_t *, int, int, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_deconfigure(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_start_dest(man_dest_t *, manstr_t *, man_pg_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_set_linkcheck_time(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_close_ctl();
03831d35f7499c87d51205817c93e9a8d42c4baestevel * upper/lower multiplexor functions.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_start_lower(man_dest_t *, mblk_t *, queue_t *, int caller);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Lower multiplexor functions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Link failover routines.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_linkcheck_timer(void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_autoswitch(man_pg_t *, man_dev_t *, man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_prep_dests_for_switch(man_pg_t *, man_dest_t **, int *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_do_icmp_bcast(man_dest_t *, t_uscalar_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions normally executing outside of the STREAMs perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions supporting/processing work requests.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_bwork(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions implementing/supporting failover.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Executed inside perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_dest_t *man_switch_match(man_dest_t *, int, void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_reset_dlpi(void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Executed outside perimeter (us man_lock for synchronization).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions supporting pathgroups
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_pg_assign(man_pg_t **, mi_path_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_pg_create(man_pg_t **, man_pg_t **, mi_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_pg_activate(man_t *, mi_path_t *, man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_pg_t *man_find_path_by_dev(man_pg_t *, man_dev_t *, man_path_t **);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_path_t *man_find_path_by_ppa(man_path_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_path_t *man_find_active_path(man_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_path_t *man_find_alternate_path(man_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_path_remove(man_path_t **, man_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_path_insert(man_path_t **, man_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_path_merge(man_path_t **, man_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions supporting kstat reporting.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_update_dev_kstats(kstat_named_t *, man_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_sum_dests_kstats(kstat_named_t *, man_pg_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_kstat_named_init(kstat_named_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_kstat_byname(kstat_t *, char *, kstat_named_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_sum_kstats(kstat_named_t *, kstat_t *, kstat_named_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions supporting ndd.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_pathgroups_report(queue_t *, mblk_t *, caddr_t, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_set_active_path(queue_t *, mblk_t *, char *, caddr_t,
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_get_hostinfo(queue_t *, mblk_t *, caddr_t, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_param_get(queue_t *, mblk_t *, caddr_t, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_param_set(queue_t *, mblk_t *, char *, caddr_t, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_param_cleanup(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN SSC/Domain specific externs.
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int man_domain_configure(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int man_domain_deconfigure(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Driver Globals protected by inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic manstr_t *man_strup = NULL; /* list of MAN STREAMS */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic caddr_t man_ndlist = NULL; /* head of ndd var list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Driver globals protected by man_lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kthread_id_t man_bwork_id = NULL; /* background thread ID */
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_workq_t *man_iwork_q; /* inner perim (uwsrv) work q */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_linkrec_t *man_linkrec_head = NULL; /* list of linkblks */
03831d35f7499c87d51205817c93e9a8d42c4baestevelldi_handle_t man_ctl_lh = NULL; /* MAN control handle */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These parameters are accessed via ndd to report the link configuration
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for the MAN driver. They can also be used to force configuration changes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ------------------------------------------------------------------------- */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* min max value name */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* DISPLAY */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * STREAMs information.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Upper read queue does not do anything.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Module linkage information for the kernel.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Locking Theory:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * D_MTPERMOD - Only an inner perimeter: All routines single
03831d35f7499c87d51205817c93e9a8d42c4baestevel * threaded (except put, see below).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * D_MTPUTSHARED - Put routines enter inner perimeter shared (not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exclusive) for concurrency/performance reasons.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Anyone who needs exclusive outer perimeter permission (changing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * global data structures) does so via qwriter() calls. The
03831d35f7499c87d51205817c93e9a8d42c4baestevel * background thread does all his work outside of perimeter and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * submits work via qtimeout() when data structures need to be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * modified.
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MAN_MDEV_FLAGS (D_MP|D_MTPERMOD|D_MTPUTSHARED)
03831d35f7499c87d51205817c93e9a8d42c4baestevelDDI_DEFINE_STREAM_OPS(man_ops, nulldev, nulldev, man_attach,
193974072f41a843678abf5f61979c748687e66bSherry Moore man_detach, nodev, man_info, MAN_MDEV_FLAGS, &man_maninfo,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_driverops, /* Module type. This one is a pseudo driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "MAN MetaDriver",
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* Virtual Driver loader entry points */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ddi_soft_state_init(&man_softstate, sizeof (man_t), 4);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_init: ddi_soft_state_init failed"
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_bwork_q = man_kzalloc(sizeof (man_workq_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_iwork_q = man_kzalloc(sizeof (man_workq_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * _info is called by modinfo().
03831d35f7499c87d51205817c93e9a8d42c4baestevel * _fini called by modunload() just before driver is unloaded from memory.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The only upper stream left should be man_ctl_lh. Note that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_close (upper stream) is synchronous (i.e. it waits for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * all STREAMS framework associated with the upper stream to be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * torn down). This guarantees that man_ctl_lh will never become
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NULL until noone is around to notice. This assumption is made
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in a few places like man_plumb, man_unplumb, etc.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Deconfigure the driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * need to detach every instance of the driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free up locks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Deconfigure the MAN driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * I may have to handle straggling work requests. Just qwait?
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or cvwait? Called from _fini - TBD
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_deconfigure: submitting CLOSE_CTL\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_deconfigure: submitting STOP\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_deconfigure: returns %d\n", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_attach - allocate resources and attach an instance of the MAN driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The <man>.conf file controls how many instances of the MAN driver are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * available.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dip - devinfo of node
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cmd - one of DDI_ATTACH | DDI_RESUME
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - DDI_SUCCESS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - DDI_FAILURE
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t flag = KSTAT_FLAG_WRITABLE; /* support netstat -kc */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_attach: bad command %d\n", cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we assume that instance is always equal to zero.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and there will always only be one instance.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this is done because when dman opens itself via DMAN_INT_PATH,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the path assumes that the instance number is zero.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if we ever need to support multiple instances of the dman
03831d35f7499c87d51205817c93e9a8d42c4baestevel * driver or non-zero instances, this will have to change.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate per device info pointer and link in to global list of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN devices.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((ddi_soft_state_zalloc(man_softstate, instance) != DDI_SUCCESS) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((manp = ddi_get_soft_state(man_softstate, instance)) == NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_attach: cannot zalloc soft state!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set ethernet address. Note that this address is duplicated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * at md_src_eaddr.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize failover-related fields (timers and such),
03831d35f7499c87d51205817c93e9a8d42c4baestevel * taking values from properties if present.
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_init_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_linkcheck_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_linkstale_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_linkstale_retries = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_dr_delay = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_dr_retries = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_kstat_waittime = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_dlpireset_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_create_internal_pathname(dip, MAN_IDNAME, S_IFCHR,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_attach: failed for instance %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(dip), DDI_NT_NET, CLONE_DEV) == DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_attach: failed for instance %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate meta kstat_t for this instance of the driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that each of man_path_t keeps track of the kstats
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for the real devices via mp_last_knp.
03831d35f7499c87d51205817c93e9a8d42c4baestevel ksp = kstat_create(MAN_IDNAME, ddi_get_instance(dip), NULL, "net",
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_attach(%d): kstat_create failed"
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_attach(%d) returns DDI_SUCCESS",
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_attach(%d) eaddr returns DDI_FAILIRE",
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) localetheraddr((struct ether_addr *)NULL, eap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_detach - detach an instance of a driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dip - devinfo of node
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cmd - one of DDI_DETACH | DDI_SUSPEND
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - DDI_SUCCESS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - DDI_FAILURE
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_detach(%d):\n", ddi_get_instance(dip)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_detach: bad command %d\n", cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = (man_t *)ddi_get_soft_state(man_softstate, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_detach: unable to get softstate"
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_detach: %s%d refcnt %d", MAN_IDNAME,
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_detach returns DDI_SUCCESS"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_info:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * As a standard DLPI style-2, man_info() should always return
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DDI_FAILURE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * However, man_open() has special treatment for a direct open
03831d35f7499c87d51205817c93e9a8d42c4baestevel * via kstr_open() without going through the CLONE driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To make this special kstr_open() work, we need to map
03831d35f7499c87d51205817c93e9a8d42c4baestevel * minor of 0 to instance 0.
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (minor == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* Standard Device Driver entry points */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_open - open the device
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rq - upper read queue of the stream
03831d35f7499c87d51205817c93e9a8d42c4baestevel * devp - pointer to a device number
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flag - information passed from the user program open(2) system call
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sflag - stream flags
03831d35f7499c87d51205817c93e9a8d42c4baestevel * credp - pointer to the cred(9S) user credential structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - errno value for failure
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *credp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_OCLOSE, ("man_open: rq(0x%p) sflag(0x%x)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reopen; q_ptr set to msp at open completion.
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate and initialize manstr_t for this device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the MAN driver configured on 1st open. Note that the only way
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we get sflag != CLONEOPEN is via the call in man_plumbctl(). All
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CLONEOPEN calls to man_open will be via the file system
03831d35f7499c87d51205817c93e9a8d42c4baestevel * device node /dev/man, a pseudo clone device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sflag == CLONEOPEN && man_config_state != MAN_CONFIGURED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * First open calls man_configure. Everyone qwaits until
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we get it open. See man_open_ctl() comments for mutex
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Determine minor device number. man_open serialized by
03831d35f7499c87d51205817c93e9a8d42c4baestevel * D_MTPERMOD.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; (tsp = *prevmsp) != NULL; prevmsp = &tsp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Should only get here from man_plumbctl().
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*LINTED E_ASSIGN_UINT_TO_SIGNED_INT*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel * No need to protect this here as all opens are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * qwaiting, and the bgthread (who is doing this open)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is the only one who mucks with this variable.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Link new entry into global list of active entries.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disable automatic enabling of our write service procedure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We control this explicitly.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_OCLOSE, ("man_open: exit rq(0x%p) minor %d errno %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clean up on error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the driver configured. Called from first man_open with exclusive
03831d35f7499c87d51205817c93e9a8d42c4baestevel * inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize NDD parameters.
03831d35f7499c87d51205817c93e9a8d42c4baestevel !man_param_register(man_param_arr, A_CNT(man_param_arr))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_configure: man_param_register failed!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start up background thread.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Submit work to get control stream opened. Qwait until its
03831d35f7499c87d51205817c93e9a8d42c4baestevel * done. See man_open_ctl for mutex lock/synchronization info.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Submit work and wait. When man_open_ctl exits
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_open, it will cause qwait below to return.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If on domain, setup IOSRAM and build the pathgroups
03831d35f7499c87d51205817c93e9a8d42c4baestevel * automatically.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_configure: returns %d\n", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_close - close the device
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rq - upper read queue of the stream
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - errno value for failure
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_OCLOSE, ("man_close: rq(0x%p)\n", (void *)rq));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unlink the per-Stream entry from the active list and free it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp && msp->ms_next != close_msp; )
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Still DL_ATTACHED
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_work_alloc(MAN_WORK_CLOSE_STREAM, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Driver about to unload.
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Ask bgthread to tear down lower stream and qwait
03831d35f7499c87d51205817c93e9a8d42c4baestevel * until its done.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Excise lower dests array, set it closing and hand it to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * background thread to dispose of.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) quntimeout(man_ctl_wq, mdp[i].md_lc_timer_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Dump any DL type messages previously caught.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We need to clear fast path flag when dlioc messages are cleaned.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN_WORK_CLOSE_STREAM work request preallocated by caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_uwput - handle DLPI messages issued from upstream, the write
03831d35f7499c87d51205817c93e9a8d42c4baestevel * side of the upper half of multiplexor. Called with shared access to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wq - upper write queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - mblk ptr to DLPI request
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_UWPUT, ("man_uwput: wq(0x%p) mp(0x%p) db_type(0x%x)"
193974072f41a843678abf5f61979c748687e66bSherry Moore " msp(0x%p)\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)wq, (void *)mp, DB_TYPE(mp), (void *)msp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("man_uwput: M_IOCTL ioc_cmd(0x%x)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("man_uwput: M_CTL ioc_cmd(0x%x)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (((msp->ms_flags & (MAN_SFLAG_FAST | MAN_SFLAG_RAW)) == 0) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((DL_PRIM(mp) == DL_UNITDATA_IND) && !wq->q_first) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("man_uwput: illegal mblk(0x%p) type(0x%x)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel } /* End switch */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_UWPUT, ("man_uwput: exit wq(0x%p) mp(0x%p)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_start - handle data messages issued from upstream. Send down
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to particular man_dest based on ether_addr, otherwise send out to all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * valid man_dests.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wq - upper write queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - mblk ptr to DLPI request
03831d35f7499c87d51205817c93e9a8d42c4baestevel * caller - Caller ID for decision making on canput failure
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 - Data xmitted or No flow control situation detected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 - Flow control situation detected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * STREAMS Flow Control: can be used if there is only one destination
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for a stream (1 to 1 multiplexor). In this case, we will use the upper
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write queue to store mblks when in flow control. If there are multiple
03831d35f7499c87d51205817c93e9a8d42c4baestevel * destinations, we cannot use the STREAMs based flow control (1 to many
03831d35f7499c87d51205817c93e9a8d42c4baestevel * multiplexor). In this case, we will use the lower write queue to store
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mblks when in flow control. Since destinations come and go, we may
03831d35f7499c87d51205817c93e9a8d42c4baestevel * transition between 1-to-1 and 1-to-m. So it may be the case that we have
03831d35f7499c87d51205817c93e9a8d42c4baestevel * some mblks stored on the upper queue, and some on the lower queue. However,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we will never send mblks out of order. See man_uwput and man_start_lower().
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A simple flow control mechanism is implemented for the deferred mblk list,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as this list is expected to be used temporarily for a very short
03831d35f7499c87d51205817c93e9a8d42c4baestevel * period required for switching paths. This flow control mechanism is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * used only as a defensive approach to avoid infinite growth of this list.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_start(register queue_t *wq, register mblk_t *mp, eaddr_t *eap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DATA, ("man_start: msp(0x%p) ether_addr(%s)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Optimization if only one valid destination.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TDB - This needs to be optimized (some bits in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ehp->dhost will act as an index.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 to 1 multiplexing, use upper wq for flow control.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Its going somewhere specific
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_start_lower(mdp, mp, flow_wq, MAN_UPPER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Broadcast or multicast - send everone a copy.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
193974072f41a843678abf5f61979c748687e66bSherry Moore " failed!"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send a DL_UNITDATA or M_DATA fastpath data mblk to a particular
03831d35f7499c87d51205817c93e9a8d42c4baestevel * destination. Others mblk types sent down via * man_dlpi_senddown().
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 - Data xmitted
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 - Data not xmitted due to flow control.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_start_lower(man_dest_t *mdp, mblk_t *mp, queue_t *flow_wq, int caller)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Lower stream ready for data transmit.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for flow control conditions for lower
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A simple flow control mechanism.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add 'mp' to the deferred
03831d35f7499c87d51205817c93e9a8d42c4baestevel * msg list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Inform flow control situation
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If 1 to 1 mux, use upper write queue for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flow control.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * putbq() message and indicate
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flow control situation to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 to many mux, use lower write queue for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flow control. Be mindful not to overflow
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the lower MAN STREAM q.
193974072f41a843678abf5f61979c748687e66bSherry Moore " lower q flow controlled -"
193974072f41a843678abf5f61979c748687e66bSherry Moore " discarding packet"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_lwsrv is draining flow controlled mblks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Lower stream in transition, do flow control.
193974072f41a843678abf5f61979c748687e66bSherry Moore "man_start_lower: no dest for mdp(0x%p), caller(%d)!",
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DATA, ("man_start_lower: mdp(0x%p) closing",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Defer until PLUMBED and DL_IDLE. See man_lwsrv().
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Upper stream sending data down, add to defered mblk
03831d35f7499c87d51205817c93e9a8d42c4baestevel * list for stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_ioctl - handle ioctl requests for this driver (I_PLINK/I_PUNLINK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or pass thru to the physical driver below. Note that most M_IOCTLs we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * care about come down the control msp, but the IOC ones come down the IP.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called with exclusive inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wq - upper write queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - mblk ptr to DLPI ioctl request
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(ioc_cmd, "not handled IOCTL 0x%x", iocp->ioc_cmd);
193974072f41a843678abf5f61979c748687e66bSherry Moore ("man_ioctl: wq(0x%p) mp(0x%p) cmd(%s)\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (iocp->ioc_cmd == MAN_SETPATH) ? "MAN_SETPATH" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (iocp->ioc_cmd == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (iocp->ioc_cmd == DLIOCRAW) ? "DLIOCRAW" : ioc_cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Handle the requests...
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG((MAN_SWITCH | MAN_PATH | MAN_DLPI), ("man_ioctl: exit\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_plink: handle I_PLINK requests on the control stream
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create a record to hold lower stream info. man_plumb will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * retrieve it after calling ldi_ioctl(I_PLINK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel lrp = man_kzalloc(sizeof (man_linkrec_t), KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_unplink - handle I_PUNLINK requests on the control stream
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set instance linkcheck timer value.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_set_linkcheck_time: enter"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, mtp->mtp_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Man path ioctl processing. Should only happen on the SSC. Called
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with exclusive inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the local ethernet address of this machine.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set my SC and other SC IPv4 addresses for use in man_pinger routine.
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_sc_ipaddrs = *(man_sc_ipaddrs_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("ip_other_sc_ipaddr = %s", buf));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set my SC and other SC IPv6 addresses for use in man_pinger routine.
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_sc_ip6addrs = *(man_sc_ip6addrs_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("ip6_other_sc_ipaddr = %s", buf));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * M_DATA fastpath info request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = miocpullup(mp, sizeof (dl_unitdata_req_t) + MAN_ADDRL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sanity check the DL_UNITDATA_REQ destination address
03831d35f7499c87d51205817c93e9a8d42c4baestevel * offset and length values.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate a new mblk to hold the ether header.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((nmp = allocb(ETHERHEADER_SIZE, BPRI_MED)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* We only need one dl_ioc_hdr mblk for replay */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Forward the packet to all lower destinations. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((status != 0) || ((status = man_dlpi_senddown(msp, mp)) != 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Fill in the ether header.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Link new mblk in after the "request" mblks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_dl_ioc_hdr_info: returns, status = %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_uwsrv - Upper write queue service routine to handle deferred
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DLPI messages issued from upstream, the write side of the upper half
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of multiplexor. It is also used by man_bwork to switch the lower
03831d35f7499c87d51205817c93e9a8d42c4baestevel * multiplexor.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wq - upper write queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_UWSRV, ("man_uwsrv: wq(0x%p) msp", (void *)wq));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Can probably remove this as I never put data messages
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_start() indicated flow control
03831d35f7499c87d51205817c93e9a8d42c4baestevel * situation, stop processing now.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_proto() indicated flow control
03831d35f7499c87d51205817c93e9a8d42c4baestevel * situation detected by man_start(),
03831d35f7499c87d51205817c93e9a8d42c4baestevel * stop processing now.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_UWSRV, ("man_uwsrv: discarding mp(0x%p)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check to see if bgthread wants us to do something inside the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_proto - handle DLPI protocol requests issued from upstream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called by man_uwsrv(). We disassociate upper and lower multiplexor
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DLPI state transitions. The upper stream here (manstr_t) transitions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * appropriately, saves the DLPI requests via man_dlpi(), and then
03831d35f7499c87d51205817c93e9a8d42c4baestevel * arranges for the DLPI request to be sent down via man_dlpi_senddown() if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * appropriate.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wq - upper write queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - mbl ptr to protocol request
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG((MAN_UWSRV | MAN_DLPI), ("man_proto: prim(%d)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, dlp->dl_primitive, DL_UNSUPPORTED, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } /* End switch */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG((MAN_UWSRV | MAN_DLPI), ("man_proto: exit\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Validate destination address format.
03831d35f7499c87d51205817c93e9a8d42c4baestevel dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADADDR, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Error if no M_DATA follows.
03831d35f7499c87d51205817c93e9a8d42c4baestevel dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADDATA, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Handle DL_ATTACH_REQ.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attach us to MAN PPA (device instance).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create a DL replay list for the lower stream. These wont
03831d35f7499c87d51205817c93e9a8d42c4baestevel * actually be sent down until the lower streams are made active
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (sometime after the call to man_init_dests below).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make copy for dlpi resync of upper and lower streams.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* TBD - need to clean off ATTACH req on failure here. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_init_dests/man_start_dest needs these set before call.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate and init lower destination structures.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we cant get the lower streams ready, then
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remove the messages from the DL replay list and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fail attach.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_areq: ppa 0x%x man_refcnt: %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called at DL_ATTACH time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Man_lock is held to protect pathgroup list(man_pg).
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get a destination ready for use.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_start_dest(man_dest_t *mdp, manstr_t *msp, man_pg_t *mpg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&msp->ms_manp->man_eaddr, &mdp->md_src_eaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set up linktimers so that first time through, we will do
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a failover.
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_linkcheck_timer,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp, man_gettimer(MAN_TIMER_INIT, mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * As an optimization, if there is only one destination,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remember the destination pointer. Used by man_start().
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Catch dlpi message for replaying, and arrange to send it down
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to any destinations not PLUMBING. See man_dlpi_replay().
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Catch IOCTL type DL_ messages.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We catch all DLPI messages that we have to resend to a new AP'ed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * device to put him in the right state. We link these messages together
03831d35f7499c87d51205817c93e9a8d42c4baestevel * w/ their b_next fields and hang it off of msp->ms_dl_mp. We
03831d35f7499c87d51205817c93e9a8d42c4baestevel * must be careful to restore b_next fields before doing dupmsg/freemsg!
03831d35f7499c87d51205817c93e9a8d42c4baestevel * msp - pointer of stream struct to process
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mblk - pointer to DLPI request to catch
193974072f41a843678abf5f61979c748687e66bSherry Moore ("man_dl_catch: adding %s\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (prim == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (prim == DL_PROMISCON_REQ) ? promisc[DL_PROMISCON_TYPE(mp)] :
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send down a single DLPI M_[PC]PROTO to all currently valid dests.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * msp - ptr to NDM stream structure DL_ messages was received on.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - ptr to mblk containing DL_ request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Build replay and duplicate list for all possible destinations.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i >= 0; i--)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_dlpi_replay - traverse the list of DLPI requests and reapply them to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the upper and lower streams into the same state. Called holding inner
03831d35f7499c87d51205817c93e9a8d42c4baestevel * perimeter lock exclusive. Note thet we defer M_IOCTL type dlpi messages
03831d35f7499c87d51205817c93e9a8d42c4baestevel * until we get an OK_ACK to our ATTACH (see man_lrsrv and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_dlioc_replay).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mdp - pointer to lower queue (destination)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rmp - list of mblks to send down stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_dlpi_replay: mdp(0x%p)", (void *)mdp));
193974072f41a843678abf5f61979c748687e66bSherry Moore ("man_dlpi_replay: mdp(0x%p) sending %s\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore "DL_IOC_HDR_INFO" : (dlp->dl_primitive == DLIOCRAW) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore "DLIOCRAW" : dps[(unsigned)(dlp->dl_primitive)]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * insert the lower devices ppa.
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_work_alloc(MAN_WORK_CLOSE_STREAM, KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_DETACH_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Toss everything.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_dl_release - Remove the corresponding DLPI request from the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * catch list. Walk thru the catch list looking for the other half of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the pair and delete it. If we are detaching, delete the entire list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * msp - pointer of stream struct to process
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - pointer to mblk to first half of pair. We will delete other
03831d35f7499c87d51205817c93e9a8d42c4baestevel * half of pair based on this.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Currently we only clean DL_ PROTO type messages. There is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * no way to turn off M_CTL or DL_IOC stuff other than sending
03831d35f7499c87d51205817c93e9a8d42c4baestevel * down a DL_DETACH, which resets everything.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (match_dbtype != M_PROTO && match_dbtype != M_PCPROTO) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Selectively find a caught mblk that matches this one and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remove it from the list
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (tmp = tmp->b_next; tmp != NULL; tmp = tmp->b_next) {
193974072f41a843678abf5f61979c748687e66bSherry Moore (DL_PRIM(mp) == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Compare two DL_ messages. If they are complimentary (e.g. DL_UNBIND
03831d35f7499c87d51205817c93e9a8d42c4baestevel * compliments DL_BIND), return true.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Primitive to clean off list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_match_proto returns %d", matched));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Bind upper stream to a particular SAP. Called with exclusive innerperim
03831d35f7499c87d51205817c93e9a8d42c4baestevel * QPAIR, shared outerperim.
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&msp->ms_manp->man_eaddr, &man_addr.dl_phys);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlbindack(wq, mp, msp->ms_sap, &man_addr, MAN_ADDRL, 0, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_UNBIND_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Exchange current msg for a DL_INFO_ACK. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel size = sizeof (dl_info_ack_t) + MAN_ADDRL + ETHERADDRL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mexchange(wq, mp, size, M_PCPROTO, DL_INFO_ACK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_ireq: man_ireq: mp == NULL."));
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Fill in the DL_INFO_ACK fields and reply. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlap = (man_dladdr_t *)(mp->b_rptr + dlip->dl_addr_offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If attached, return physical address.
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&msp->ms_manp->man_eaddr, &dlap->dl_phys);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ep = (struct ether_addr *)(mp->b_rptr + dlip->dl_brdcst_addr_offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (((dl_promiscon_req_t *)mp->b_rptr)->dl_level) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Catch request for replay, and forward down to any lower
03831d35f7499c87d51205817c93e9a8d42c4baestevel * lower stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCON_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (((dl_promiscoff_req_t *)mp->b_rptr)->dl_level) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Enable multicast requests. We might need to track addresses instead of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * just passing things through (see eri_dmreq) - TBD.
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Catch request for replay, and forward down to any lower
03831d35f7499c87d51205817c93e9a8d42c4baestevel * lower stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_DISABMULTI_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) localetheraddr((struct ether_addr *)NULL, &addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_NOTSUPPORTED, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TBD - this routine probably should be protected w/ an ndd
03831d35f7499c87d51205817c93e9a8d42c4baestevel * tuneable, or a man.conf parameter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Error if length of address isn't right or the address
03831d35f7499c87d51205817c93e9a8d42c4baestevel * specified is a multicast or broadcast address.
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Error if this stream is not attached to a device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We will also resend DL_SET_PHYS_ADDR_REQ for each dest
03831d35f7499c87d51205817c93e9a8d42c4baestevel * when it is linked under us.
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(addrp, msp->ms_manp->man_eaddr.ether_addr_octet);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These routines make up the lower part of the MAN streams framework.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_lwsrv - Deferred mblks for down stream. We end up here when
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the destination is not DL_IDLE when traffic comes downstream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wq - lower write queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Arrange to send deferred mp's first, then mblks on the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * service queue. Since we are exclusive in the inner perimeter,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we dont have to worry about md_lock, like the put procedures,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * which are MTPUTSHARED.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Put it back on queue, making sure to avoid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * infinite loop mentioned in putbq(9F)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_lrput - handle DLPI messages issued from downstream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rq - lower read queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - mblk ptr to DLPI request
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
193974072f41a843678abf5f61979c748687e66bSherry Moore (prim == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRPUT, ("man_lrput: rq(0x%p) mp(0x%p) mdp(0x%p)"
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mp, (void *)mdp, DB_TYPE(mp), prim_str));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Turn around */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp == NULL || mdp->md_state != MAN_DSTATE_READY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRPUT, ("man_lrput: not ready mdp(0x%p),"
193974072f41a843678abf5f61979c748687e66bSherry Moore " state(%d)", (void *)mdp, mdp ? mdp->md_state : -1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we have a destination in the right state, forward on datagrams.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_dlpistate == DL_IDLE && canputnext(mdp->md_rq)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * go put mblk_t directly up to next queue.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRPUT, ("man_lrput: putnext to rq(0x%p)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Handle in man_lrsrv with exclusive inner perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Either this is a response from our attempt to sync the upper and lower
03831d35f7499c87d51205817c93e9a8d42c4baestevel * stream states, or its data. If its not data. Do DL_* response processing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and transition md_dlpistate accordingly. If its data, toss it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRSRV, ("man_lrsrv: rq(0x%p)", (void *)rq));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mdp == NULL) || (mdp->md_state & MAN_DSTATE_CLOSING)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we're not connected, or its a datagram, toss it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MAN_IS_DATA(mp) || mdp->md_state != MAN_DSTATE_READY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRSRV, ("man_lrsrv: dropping mblk mdp(0x%p)"
193974072f41a843678abf5f61979c748687e66bSherry Moore " is_data(%d)", (void *)mdp, MAN_IS_DATA(mp)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Should be response to man_dlpi_replay. Discard unless there
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is a failure we care about.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Do proto processing below. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DL_IOC* failed for some reason.
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRSRV, ("man_lrsrv: M_IOCNAK err %d for cmd(%s)\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (iocp->ioc_cmd == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (iocp->ioc_cmd == DLIOCRAW) ? "DLIOCRAW" : ioc_cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* FALLTHRU */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OK response from DL_IOC*, ignore.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRSRV, ("man_lrsrv: prim %s", dps[(int)prim]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DLPI state processing big theory: We do not rigorously check
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DLPI states (e.g. PENDING stuff). Simple rules:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1) If we see an OK_ACK to an ATTACH_REQ, dlpistate = DL_UNBOUND.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 2) If we see an BIND_ACK to a BIND_REQ, dlpistate = DL_IDLE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3) If we see a OK_ACK response to an UNBIND_REQ
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dlpistate = DL_UNBOUND.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 4) If we see a OK_ACK response to a DETACH_REQ,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dlpistate = DL_UNATTACHED.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Everything that isn't handle by 1-4 above is handled by 5)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 5) A NAK to any DL_* messages we care about causes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dlpistate = DL_UNATTACHED and man_reset_dlpi to run
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TBD - need a reset counter so we can try a switch if it gets
03831d35f7499c87d51205817c93e9a8d42c4baestevel * too high.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Cancel timer and set md_dlpistate.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We're ready for data. Get man_lwsrv to run to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * process any defered data and start linkcheck timer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ignore error TBD (better comment)
193974072f41a843678abf5f61979c748687e66bSherry Moore ("\tdl_errno %d dl_unix_errno %d cprim %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore dlp->error_ack.dl_errno, dlp->error_ack.dl_unix_errno,
193974072f41a843678abf5f61979c748687e66bSherry Moore ("\tdl_errno %d unix_errno %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We should not get here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_lrsrv: unexpected DL prim 0x%lx!",
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(mdp->md_msp->ms_manp->man_pg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Autoswitching is disabled for instance 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on the SC as we expect the domain to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initiate the path switching.
03831d35f7499c87d51205817c93e9a8d42c4baestevel } /* End while (getq()) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Not ready for linkcheck.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_msp == NULL || mdp->md_msp->ms_manp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Linkchecking needs to be done on IP streams. For domain, all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * driver instances need checking, for SC only instance 1 needs it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((man_is_on_domain || mdp->md_msp->ms_manp->man_meta_ppa == 1) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Linkcheck not need on this link.
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The following routines process work requests posted to man_iwork_q
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from the non-STREAMS half of the driver (see man_bwork.c). The work
03831d35f7499c87d51205817c93e9a8d42c4baestevel * requires access to the inner perimeter lock of the driver. This
03831d35f7499c87d51205817c93e9a8d42c4baestevel * lock is acquired by man_uwsrv, who calls man_iwork to process the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_iwork_q->
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The man_bwork has posted some work for us to do inside the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * perimeter. This mainly involves updating lower multiplexor data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * structures (non-blocking type stuff). So, we can hold the man_lock
03831d35f7499c87d51205817c93e9a8d42c4baestevel * until we are done processing all work items. Note that some of these
03831d35f7499c87d51205817c93e9a8d42c4baestevel * routines in turn submit work back to the bgthread, which they can do
03831d35f7499c87d51205817c93e9a8d42c4baestevel * since we hold the man_lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return status to man_dr_detach immediately. If
03831d35f7499c87d51205817c93e9a8d42c4baestevel * no error submitting SWITCH request, man_iswitch
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or man_bclose will cv_signal man_dr_detach on
03831d35f7499c87d51205817c93e9a8d42c4baestevel * completion of SWITCH work request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we've completed the work request, delete, or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cv_signal waiter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_dr_detach has submitted a request to DRSWITCH a path.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * He is in cv_wait_sig(wp->mw_cv). We forward the work request on to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_bwork as a switch request. It should end up back at
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_iwork, who will cv_signal(wp->mw_cv) man_dr_detach.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called holding inner perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_lock is held to synchronize access to pathgroup list(man_pg).
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_do_dr_switch: pg_id %d work:", adp->a_pg_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check to see if detaching device is active. If so, activate
03831d35f7499c87d51205817c93e9a8d42c4baestevel * an alternate.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp && mp->mp_device.mdev_ppa == adp->a_sf_dev.mdev_ppa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DR thread is sleeping on wp->mw_cv. We change the work
03831d35f7499c87d51205817c93e9a8d42c4baestevel * request from DRSWITCH to SWITCH and submit it to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for processing by man_bwork (via man_pg_cmd). At
03831d35f7499c87d51205817c93e9a8d42c4baestevel * completion the SWITCH work request is processed by
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_iswitch() or man_bclose and the DR thread will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * be cv_signal'd.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Tell man_dr_detach that detaching device is not currently
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ENODEV is a noop, not really an error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_dr_attach has submitted a request to DRATTACH a path,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * add that path to the path list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called holding perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_do_dr_attach: pg_id %d work:", adp->a_pg_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Extract SC ethernet address from IOSRAM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_dr_attach passes the new device info in a_sf_dev.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_dr_detach has submitted a request to DRDETACH a path.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * He is in cv_wait_sig(wp->mw_cv). We remove the path and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cv_signal(wp->mw_cv) man_dr_detach.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called holding perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_do_dr_detach: pg_id %d work:", adp->a_pg_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We should have switched detaching path if it was active.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp && mp->mp_device.mdev_ppa == adp->a_sf_dev.mdev_ppa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Submit an ASSIGN command, minus the detaching device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->mp_device.mdev_ppa != adp->a_sf_dev.mdev_ppa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Need to include SCs ethernet address in command.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hand back status to man_dr_detach request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The background thread has configured new lower multiplexor streams for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the given destinations. Update the appropriate destination data structures
03831d35f7499c87d51205817c93e9a8d42c4baestevel * inside the inner perimeter. We must take care to deal with destinations
03831d35f7499c87d51205817c93e9a8d42c4baestevel * whose upper stream has closed or detached from lower streams.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 Done with work request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 Reused work request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Update destination structures as appropriate.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check to see if lower stream we just switch is still
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = man_switch_match(tdp, adp->a_pg_id, tdp->md_switch_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Switch failed for some reason. Clear
03831d35f7499c87d51205817c93e9a8d42c4baestevel * PLUMBING flag and retry switch again later.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Swap new info, for old. We return the old info to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_bwork to close things up below.
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy((char *)mdp, (char *)&tmp, sizeof (man_dest_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * save the wq from the destination passed(tdp).
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_device.mdev_major == adp->a_sf_dev.mdev_major);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(tdp->md_device.mdev_ppa == adp->a_st_dev.mdev_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(tdp->md_device.mdev_major == adp->a_st_dev.mdev_major);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Resync lower w/ upper dlpi state. This will start link
03831d35f7499c87d51205817c93e9a8d42c4baestevel * timer if/when lower stream goes to DL_IDLE (see man_lrsrv).
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy((char *)&tmp, (char *)tdp, sizeof (man_dest_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Never got switch-to destinations open, free them.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear pathgroup switching flag and update path flags.
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Switch succeeded, mark path we switched from as failed, and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * device we switch to as active and clear its failed flag (if set).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sync up kstats.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_iswitch: switch from dev:"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_SWITCH, man_print_dev(&adp->a_sf_dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_iswitch: switch to dev:"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_SWITCH, man_print_dev(&adp->a_st_dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Decrement manp reference count and hand back work request if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find the destination in the upper stream that we just switched.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_switch_match(man_dest_t *sdp, int pg_id, void *sid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check if upper stream closed, or detached.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Upper stream detached and reattached while we were
03831d35f7499c87d51205817c93e9a8d42c4baestevel * switching.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bg_thread cant complete the switch for some reason. (Re)start the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * linkcheck timer again.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we have not yet initialized link, or the upper stream is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DL_IDLE, restart the linktimer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_linkcheck_timer,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp, man_gettimer(MAN_TIMER_LINKCHECK, mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Arrange to replay all of ms_dl_mp on the new lower stream to get it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in sync with the upper stream. Note that this includes setting the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * physical address.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called from qtimeout with inner perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send down an unbind and detach request, just to clean things
03831d35f7499c87d51205817c93e9a8d42c4baestevel * out, we ignore ERROR_ACKs for unbind and detach in man_lrsrv.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If low on memory, try again later. I Could use qbufcall, but that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * could fail and I would have to try and recover from that w/
03831d35f7499c87d51205817c93e9a8d42c4baestevel * qtimeout anyway.
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_reset_dlpi,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp, man_gettimer(MAN_TIMER_LINKCHECK, mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Once we receive acknowledgement that DL_ATTACH_REQ was successful,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we can send down the DL_* related IOCTLs (e.g. DL_IOC_HDR). If we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * try and send them downsteam w/o waiting, the ioctl's get processed before
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the ATTACH_REQ and they are rejected. TBD - could just do the lower
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dlpi state change in lock step. TBD
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = allocb(DL_SET_PHYS_ADDR_REQ_SIZE + ETHERADDRL, BPRI_MED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp->set_physaddr_req.dl_primitive = DL_SET_PHYS_ADDR_REQ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_wptr += DL_SET_PHYS_ADDR_REQ_SIZE + ETHERADDRL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_alloc_physreq: physaddr %s\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A new path in a pathgroup has become active for the first time. Setup
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the lower destinations in prepartion for man_pg_activate to call
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_autoswitch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TBD - Take out
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ASSERT(mdp->md_device.mdev_state == MDEV_UNASSIGNED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ASSERT(mdp->md_state == MAN_DSTATE_NOTPRESENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Count up number of destinations we need to close.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cdp = man_kzalloc(sizeof (man_dest_t) * close_cnt, KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clean up optimized destination pointer if we are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * closing it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns TRUE if stream uses pathgroup, FALSE otherwise.
193974072f41a843678abf5f61979c748687e66bSherry Moore (msp->ms_manp->man_meta_ppa != mpg->mpg_man_ppa));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp == NULL || mdp->md_msp == NULL || mdp->md_msp->ms_manp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_gettimer: unknown timer %d", timer));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check the links for each active destination. Called inside inner
03831d35f7499c87d51205817c93e9a8d42c4baestevel * perimeter via qtimeout. This timer only runs on the domain side of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * driver. It should never run on the SC side.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * On a MAN_LINKGOOD link, we check/probe the link health every
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN_LINKCHECK_TIME seconds. If the link goes MAN_LINKSTALE, the we probe
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the link every MAN_LINKSTALE_TIME seconds, and fail the link after probing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the link MAN_LINKSTALE_RETRIES times.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The man_lock is held to synchronize access pathgroup list(man_pg).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear timeout id and check if someones waiting on us to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * complete a close.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_linkcheck_timer: not ready mdp"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the lower stream needs initializing, just go straight to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * switch code. As the linkcheck timer is started for all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SAPs, do not send ping packets during the initialization.
193974072f41a843678abf5f61979c748687e66bSherry Moore "man_linkcheck_timer: unneeded linkcheck on mdp(0x%p)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The above call to man_needs_linkcheck() validates
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mdp->md_msp and mdp->md_msp->ms_manp pointers.
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(mdp->md_msp->ms_manp->man_pg, mdp->md_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = man_find_path_by_ppa(mpg->mpg_pathp, mdp->md_device.mdev_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This is the most common case, when traffic is flowing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear the FAILED flag and update lru.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we're here, it means we have not seen any traffic
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Mark the destination as FAILED and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * update lru.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do any work required from state transitions above.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Stop linkcheck timer until switch completes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_linkcheck_timer,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp, man_gettimer(MAN_TIMER_LINKCHECK, mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Handle linkcheck initiated autoswitching.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called with man_lock held.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set flags and refcnt. Cleared in man_iswitch when SWITCH completes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(mdp->md_msp->ms_manp->man_pg, mdp->md_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We're initializing, ask for a switch to our currently
03831d35f7499c87d51205817c93e9a8d42c4baestevel * active device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_msp != NULL && mdp->md_msp->ms_manp != NULL &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_linkcheck_timer: link failure on %s%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_iswitch not going to run, clean up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Gather up all lower multiplexor streams that have this link open and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * try to switch them. Called from inner perimeter and holding man_lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * pg_id - Pathgroup to do switch for.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * st_devp - New device to switch to.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wait_for_switch - whether or not to qwait for completion.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_autoswitch(man_pg_t *mpg, man_dev_t *st_devp, man_work_t *waiter_wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set dests as PLUMBING, cancel timers and return array of dests
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that need a switch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_prep_dests_for_switch(mpg, &sdp, &sdp_cnt);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If no streams are active, there are no streams to switch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return ENODEV (see man_pg_activate).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Ask the bgthread to switch. See man_bwork.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If an alternate path exists for pathgroup, arrange for switch to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * happen. Note that we need to switch each of msp->dests[pg_id], for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * all on man_strup. We must:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Cancel any timers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Mark dests as PLUMBING
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Submit switch request to man_bwork_q->
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_prep_dests_for_switch(man_pg_t *mpg, man_dest_t **mdpp, int *cntp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_prep_dests_for_switch: pg_id %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Count up number of streams, there is one destination that needs
03831d35f7499c87d51205817c93e9a8d42c4baestevel * switching per stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sdp = man_kzalloc(sizeof (man_dest_t) * sdp_cnt, KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Mark each destination as unusable.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Mark destination as plumbing and store the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * address of sdp as a way to identify the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SWITCH request when it comes back (see man_iswitch).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copy destination info.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Cancel timers.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_prep_dests_for_switch: returns %d"
193974072f41a843678abf5f61979c748687e66bSherry Moore " sdp(0x%p) sdp_cnt(%d)", status, (void *)sdp, sdp_cnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The code below generates an ICMP echo packet and sends it to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * broadcast address in the hopes that the other end will respond
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and the man_linkcheck_timer logic will see the traffic.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This assumes ethernet-like media.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Generate an ICMP packet. Called exclusive inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mdp - destination to send packet to.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sap - either ETHERTYPE_ARP or ETHERTYPE_IPV6
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* TBD - merge pinger and this routine. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(sap == ETHERTYPE_IPV6 || sap == ETHERTYPE_IP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send the ICMP message
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_do_icmp_bcast: sap=0x%x mp=0x%p",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send it out.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_do_icmp_broadcast: xmit failed"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(ðerbroadcast, &dlsap.dl_phys, sizeof (dlsap.dl_phys));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fill out the ICMP echo packet headers
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_version_and_hdr_length = (IP_VERSION << 4)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Domain generates ping packets for domain to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SC network (dman0 <--> scman0).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that ping packets are only generated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by the SC across scman1 (SC to SC network).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IP version = 6, priority = 0, flow = 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Domain generates ping packets for domain to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SC network (dman0 <--> scman0).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that ping packets are only generated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by the SC across scman1 (SC to SC network).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IPv6 and IP are the same for ICMP as far as I'm concerned.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < datalen; i++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmph->icmph_checksum = IP_CSUM(mp->b_cont, iph_hdr_len, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmph->icmph_checksum = IP_CSUM(mp->b_cont, iph_hdr_len - 32,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * icp->icmp_time = ???;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = allocb(sizeof (dl_unitdata_req_t) + sizeof (*dlsap), BPRI_MED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * phys addr first - TBD
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The routines in this file are executed by the MAN background thread,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * which executes outside of the STREAMS framework (see man_str.c). It is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * allowed to do the things required to modify the STREAMS driver (things
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that are normally done from a user process). These routines do things like
03831d35f7499c87d51205817c93e9a8d42c4baestevel * open and close drivers, PLINK and PUNLINK streams to/from the multiplexor,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The mechanism of communication between the STREAMS portion of the driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and the background thread portion are two work queues, man_bwork_q
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and man_iwork_q (background work q and streams work q). Work
03831d35f7499c87d51205817c93e9a8d42c4baestevel * requests are placed on those queues when one half of the driver wants
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the other half to do some work for it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The MAN background thread executes the man_bwork routine. Its sole
03831d35f7499c87d51205817c93e9a8d42c4baestevel * job is to process work requests placed on this work q. The MAN upper
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write service routine is responsible for processing work requests posted
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the man_iwork_q->
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Both work queues are protected by the global mutex man_lock. The
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_bwork is signalged via the condvarman_bwork_q->q_cv. The man_uwsrv
03831d35f7499c87d51205817c93e9a8d42c4baestevel * routine is signaled by calling qenable (forcing man_uwsrv to run).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_bwork - Work thread for this device. It is responsible for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * performing operations which can't occur within the STREAMS framework.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - Called holding no locks
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - Obtains the global mutex man_lock to remove work from
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_bwork_q, and post work to man_iwork_q->
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - Note that we do not want to hold any locks when making
03831d35f7499c87d51205817c93e9a8d42c4baestevel * any ldi_ calls.
03831d35f7499c87d51205817c93e9a8d42c4baestevel CALLB_CPR_INIT(&cprinfo, &man_lock, callb_generic_cpr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mn_work_thrd");
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (done == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * While there is nothing to do, sit in cv_wait. If work
03831d35f7499c87d51205817c93e9a8d42c4baestevel * request is made, requester will signal.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_open_ctl - Open the control stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - errno code
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Mutex Locking Notes:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We need a way to keep the CLONE_OPEN qwaiters in man_open from
03831d35f7499c87d51205817c93e9a8d42c4baestevel * checking the man_config variables after the ldi_open call below
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns from man_open, leaving the inner perimeter. So, we use the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_lock to synchronize the threads in man_open_ctl and man_open. We
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hold man_lock across this call into man_open, which in general is a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * no-no. But, the STREAMs portion of the driver (other than open)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * doesn't use it. So, if ldi_open gets hijacked to run any part of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the MAN streams driver, it wont end up recursively trying to acquire
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_lock. Note that the non-CLONE_OPEN portion of man_open doesnt
03831d35f7499c87d51205817c93e9a8d42c4baestevel * acquire it either, so again no recursive mutex.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_open_ctl: plumbing control stream\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get eri driver loaded and kstats initialized. Is there a better
03831d35f7499c87d51205817c93e9a8d42c4baestevel * way to do this? - TBD.
193974072f41a843678abf5f61979c748687e66bSherry Moore "man_open_ctl: ident alloc failed, error %d", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_open_by_name(ERI_PATH, FREAD | FWRITE | FNOCTTY,
193974072f41a843678abf5f61979c748687e66bSherry Moore "man_open_ctl: eri open failed, error %d", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_open_by_name(DMAN_INT_PATH, FREAD | FWRITE | FNOCTTY,
193974072f41a843678abf5f61979c748687e66bSherry Moore "man_open_ctl: man control dev open failed, "
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Update global config state. TBD - dont need lock here, since
03831d35f7499c87d51205817c93e9a8d42c4baestevel * everyone is stuck in open until we finish. Only other modifier
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is man_deconfigure via _fini, which returns EBUSY if there is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * any open streams (other than control). Do need to signal qwaiters
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_open_ctl: man_ctl_lh(0x%p) errno = %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_close_ctl - Close control stream, we are about to unload driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - Called holding no locks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_close_ctl: unplumbing control stream\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Close the lower streams. Get all the timers canceled, close the lower
03831d35f7499c87d51205817c93e9a8d42c4baestevel * stream and delete the dest array.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 Closed all streams.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 Couldn't close one or more streams, timers still running.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - Called holding no locks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(adp->a_mdp, sizeof (man_dest_t) * adp->a_ndests);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We want to close down all lower streams. Need to wait until all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * timers and work related to these lower streams is quiesced.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns 1 if lower streams are quiesced, 0 if we need to wait
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a bit longer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_cancel_timers: mdp(0x%p) cnt %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < cnt; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) quntimeout(man_ctl_wq, mdp[i].md_lc_timer_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A failover is started at start of day, when the driver detects a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * link failure (see man_linkcheck_timer), or when DR detaches
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the IO board containing the current active link between SC and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * domain (see man_dr_detach, man_iwork, and man_do_dr_detach). A
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN_WORK_SWITCH work request containing all the lower streams that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * should be switched is posted on the man_bwork_q-> This work request is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processed here. Once all lower streams have been switched to an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * alternate path, the MAN_WORK_SWITCH work request is passed back to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_iwork_q where it is processed within the inner perimeter of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * STREAMS framework (see man_iswitch).
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that when the switch fails for whatever reason, we just hand
03831d35f7499c87d51205817c93e9a8d42c4baestevel * back the lower streams untouched and let another failover happen.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hopefully we will sooner or later succeed at the failover.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make a temporary copy of dest array, updating device to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * alternate and try to open all lower streams. bgthread can sleep.
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp = man_kzalloc(sizeof (man_dest_t) * adp->a_ndests,
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(adp->a_mdp, tdp, sizeof (man_dest_t) * adp->a_ndests);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Before we switch to the new path, lets sync the kstats.
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Didn't plumb everyone, unplumb new lower stuff and return.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j <= i; j++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_is_on_domain && man_dossc_switch(adp->a_st_dev.mdev_exp_id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we cant set new path on the SSC, then fail the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * failover.
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(adp->a_mdp, sizeof (man_dest_t) * adp->a_ndests);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_bswitch: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hand processed switch request back to man_iwork for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processing in man_iswitch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_plumb - Configure a lower stream for this destination.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - Called holding no locks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - success - 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - error code of failure
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_plumb: mdp(0x%p) %s%d exp(%d)",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp, ddi_major_to_name(mdp->md_device.mdev_major),
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_device.mdev_ppa, mdp->md_device.mdev_exp_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Control stream should already be open.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * previously opens were done by a dev_t of makedev(clone_major,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mdev_major) which should always map to /devices/pseudo/clone@0:eri
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_major_to_name(mdp->md_device.mdev_major)) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_open_by_name(ERI_PATH, FREAD | FWRITE | FNOCTTY,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Link netdev under MAN.
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_ioctl(man_ctl_lh, I_PLINK, (intptr_t)lh,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "man_plumb: ldi_ioctl(I_PLINK) failed, error %d", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we can't find the linkrec then return an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * error. It will be automatically unplumbed on failure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_unplumb - tear down the STREAMs framework for the lower multiplexor.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mdp - destination struct of interest
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - return error from ldi_ioctl
03831d35f7499c87d51205817c93e9a8d42c4baestevel * I_PUNLINK causes the multiplexor resources to be freed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_ioctl(man_ctl_lh, I_PUNLINK, (intptr_t)mdp->md_muxid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_unplumb: ldi_ioctl(I_PUNLINK) failed"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Delete linkrec if it exists.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The routines below deal with paths and pathgroups. These data structures
03831d35f7499c87d51205817c93e9a8d42c4baestevel * are used to track the physical devices connecting the domain and SSC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These devices make up the lower streams of the MAN multiplexor. The
03831d35f7499c87d51205817c93e9a8d42c4baestevel * routines all expect the man_lock to be held.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A pathgroup consists of all paths that connect a particular domain and the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SSC. The concept of a pathgroup id (pg_id) is used to uniquely identify
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a pathgroup. For Domains, there is just one pathgroup, that connecting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the domain to the SSC (pg_id == 0). On the SSC, there is one pathgroup per
03831d35f7499c87d51205817c93e9a8d42c4baestevel * domain. The pg_id field corresponds to the domain tags A-R. A pg_id of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 means domain tag A, a pg_id of 1 means domain B, etc.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The path data structure identifies one path between the SSC and a domain.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It describes the information for the path: the major and minor number of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the physical device; kstat pointers; and ethernet address of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * other end of the path.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The pathgroups are anchored at man_pg_head and are protected by the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by the inner perimeter. The routines are only called by the STREAMs
03831d35f7499c87d51205817c93e9a8d42c4baestevel * portion of the driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Update man instance pathgroup info. Exclusive inner perimeter assures
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this code is single threaded. man_refcnt assures man_t wont detach
03831d35f7499c87d51205817c93e9a8d42c4baestevel * while we are playing with man_pg stuff.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns 0 on success, errno on failure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, mip->mip_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pg_cmd: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Assign paths to a pathgroup. If pathgroup doesnt exists, create it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If path doesnt exist, create it. If ethernet address of existing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * pathgroup different, change it. If an existing path is not in the new
03831d35f7499c87d51205817c93e9a8d42c4baestevel * list, remove it. If anything changed, send PATH_UPDATE request to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_iwork to update all man_dest_t's.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mplpp - man pathgroup list point to point.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mip - new/updated pathgroup info to assign.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pg_assign(man_pg_t **mplpp, mi_path_t *mip, int add_only)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cnt == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Assure the devices to be assigned are not assigned to some other
03831d35f7499c87d51205817c93e9a8d42c4baestevel * pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < cnt; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_path_by_dev(*mplpp, &mip->mip_devs[i], NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Already assigned to some other man instance
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find pathgroup, or allocate new one if it doesnt exist and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * add it to list at mplpp. Result is that mpg points to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * pathgroup to modify.
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (ether_cmp(&mip->mip_eaddr, &mpg->mpg_dst_eaddr) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_pg_assign: ethernet address mismatch");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create list of new paths to add to pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < cnt; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_find_path_by_dev(*mplpp, &mip->mip_devs[i], NULL))
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue; /* Already exists in this pathgroup */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_PATH, man_print_dev(&mp->mp_device));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_dr_attach passes only the path which is being DRd in.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * So just add the path and don't worry about removing paths.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check if any paths we want to remove are ACTIVE. If not,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * do a second pass and remove them.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < cnt; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove all paths from a pathgroup (domain shutdown). If there is an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * active path in the group, shut down all destinations referencing it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for existence of pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mpg = man_find_pg_by_id(*plpp, mip->mip_pg_id)) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free all the paths for this pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove this pathgroup from the list, and free it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (tpg = tpg->mpg_next; tpg != NULL; tpg = tpg->mpg_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set a new active path. This is done via man_ioctl so we are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exclusive in the inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pg_activate(man_t *manp, mi_path_t *mip, man_work_t *waiter_wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg2 = man_find_path_by_dev(plp, mip->mip_devs, &mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mp->mp_device.mdev_ppa == mip->mip_devs->mdev_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This is the first time a path has been activated for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this pathgroup. Initialize all upper streams dest
03831d35f7499c87d51205817c93e9a8d42c4baestevel * structure for this pathgroup so autoswitch will find
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Path already active, nothing to do.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Try to autoswitch to requested device. Set flags and refcnt.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Cleared in man_iswitch when SWITCH completes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Switch to path specified.
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_autoswitch(mpg1, mip->mip_devs, waiter_wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_iswitch not going to run, clean up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Device not plumbed isn't really an error. Change
03831d35f7499c87d51205817c93e9a8d42c4baestevel * active device setting here, since man_iswitch isn't
03831d35f7499c87d51205817c93e9a8d42c4baestevel * going to be run to do it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pg_activate: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mpg = man_find_pg_by_id(plp, mip->mip_pg_id)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mp = mpg->mpg_pathp; mp != NULL; mp = mp->mp_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(&mp->mp_device, &mip->mip_devs[cnt], sizeof (man_dev_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pg_read: pg(0x%p) id(%d) found %d paths",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TBD - What should errno be if user buffer too small ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return existing pathgroup, or create it. TBD - Need to update
03831d35f7499c87d51205817c93e9a8d42c4baestevel * all of destinations if we added a pathgroup. Also, need to update
03831d35f7499c87d51205817c93e9a8d42c4baestevel * all of man_strup if we add a path.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mplpp - man pathgroup list point to pointer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mpgp - returns newly created man pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mip - info to fill in mpgp.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pg_create(man_pg_t **mplpp, man_pg_t **mpgp, mi_path_t *mip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ether_cmp(&mip->mip_eaddr, &zero_ether_addr) == 0) {
193974072f41a843678abf5f61979c748687e66bSherry Moore " addresss not set!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return pointer to pathgroup containing mdevp, null otherwise. Also,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if a path pointer is passed in, set it to matching path in pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called holding man_lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_find_path_by_dev(man_pg_t *plp, man_dev_t *mdevp, man_path_t **mpp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mp = mpg->mpg_pathp; mp != NULL; mp = mp->mp_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return pointer to pathgroup assigned to destination, null if not found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called holding man_lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Try and find an alternate path.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find a non-failed path, or the lru failed path and switch to it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Nowhere to switch to.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Assumes caller has verified existence.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_path_remove: removing path"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (tp = tp->mp_next; tp != NULL; tp = tp->mp_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Insert path into list, ascending order by ppa.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tp->mp_device.mdev_ppa > mp->mp_device.mdev_ppa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (tp = tp->mp_next; tp != NULL; tp = tp->mp_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Merge npp into lpp, ascending order by ppa. Assumes no
03831d35f7499c87d51205817c93e9a8d42c4baestevel * duplicates in either list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_path_kstat_init: mpp(0x%p)\n", (void *)mpp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create named kstats for accounting purposes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_knp = man_kzalloc(MAN_NUMSTATS * sizeof (kstat_named_t),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_path_kstat_init: returns %d\n", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(mp->mp_last_knp, MAN_NUMSTATS * sizeof (kstat_named_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_work_alloc - allocate and initiate a work request structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel * type - type of request to allocate
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - ptr to an initialized work structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_work_free - deallocate a work request structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wp - ptr to work structure to be freed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Post work to a work queue. The man_bwork sleeps on
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_bwork_q->q_cv, and work requesters may sleep on mw_cv.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The man_lock is used to protect both cv's.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cv_signal for man_bwork_q, qenable for man_iwork_q
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else { /* q == man_iwork_q */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* <<<<<<<<<<<<<<<<<<<<<<< NDD SUPPORT FUNCTIONS >>>>>>>>>>>>>>>>>>> */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ndd support functions to get/set parameters
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Register each element of the parameter array with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * named dispatch handler. Each element is loaded using
03831d35f7499c87d51205817c93e9a8d42c4baestevel * nd_load()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cnt - the number of elements present in the parameter array
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_param_register: manpa(0x%p) cnt %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_param_register: returns %d\n", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pathgroups_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pathgroups_report: wq(0x%p) mp(0x%p)"
193974072f41a843678abf5f61979c748687e66bSherry Moore " caddr 0x%p", (void *)wq, (void *)mp, (void *)cp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf(mp, "MAN Pathgroup report: (* == failed)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf(mp, "====================================="
193974072f41a843678abf5f61979c748687e66bSherry Moore "==========================================");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < 2; i++) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "Interface\tDestination\t\tActive Path\tAlternate Paths");
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf(mp, "---------------------------------------"
193974072f41a843678abf5f61979c748687e66bSherry Moore "----------------------------------------");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mpg = manp->man_pg; mpg != NULL; mpg = mpg->mpg_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i == 0) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "Other SSC\t");
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pathgroups_report: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Active path
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Alternate Paths.
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_major_to_name(plist->mp_device.mdev_major),
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NDD request to set active path. Calling context is man_ioctl, so we are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exclusive in the inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Syntax is "ndd -set /dev/dman <man ppa> <pg_id> <phys ppa>"
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED3 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_set_active_path(queue_t *wq, mblk_t *mp, char *value, caddr_t cp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_set_active_path: wq(0x%p) mp(0x%p)"
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_set_active_path: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Dump out the contents of the IOSRAM handoff structure. Note that if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * anything changes here, you must make sure that the sysinit script
03831d35f7499c87d51205817c93e9a8d42c4baestevel * stays in sync with this output.
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_get_hostinfo(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_magic = 0x%x", manc.manc_magic);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_version = 0%d", manc.manc_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel netnum = manc.manc_dom_ipaddr & manc.manc_dom_ip_netmask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) inet_ntop(AF_INET6, (void *)&manc.manc_dom_ipv6addr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) inet_ntop(AF_INET6, (void *)&manc.manc_sc_ipv6addr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_iob_bitmap = 0x%x\tio boards = ",
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_EXPANDERS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_golden_iob = %d", manc.manc_golden_iob);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *
03831d35f7499c87d51205817c93e9a8d42c4baestevel static char b[18];
03831d35f7499c87d51205817c93e9a8d42c4baestevel unsigned char *p;
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = (unsigned char *)∈
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(b, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (b);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * parameter value. cp points to the required parameter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sets the man parameter to the value in the param_register using
03831d35f7499c87d51205817c93e9a8d42c4baestevel * nd_load().
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free the Named Dispatch Table by calling man_nd_free
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free the table pointed to by 'ndp'
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_kstat_update - update the statistics for a meta-interface.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ksp - kstats struct
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rw - flag indicating whether stats are to be read or written.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The destination specific kstat information is protected by the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * perimeter lock, so we submit a work request to get the stats
03831d35f7499c87d51205817c93e9a8d42c4baestevel * updated (see man_do_kstats()), and then collect the results
03831d35f7499c87d51205817c93e9a8d42c4baestevel * when cv_signal'd. Note that we are doing cv_timedwait_sig()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as a precautionary measure only.
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_kstat_update: %s\n", rw ? "KSTAT_WRITE" :
193974072f41a843678abf5f61979c748687e66bSherry Moore "KSTAT_READ"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the driver has been configured, get kstats updated by inner
03831d35f7499c87d51205817c93e9a8d42c4baestevel * perimeter prior to retrieving.
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_work_alloc(MAN_WORK_KSTAT_UPDATE, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel wait_status = cv_timedwait_sig(&wp->mw_cv, &man_lock,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_get_lbolt() + drv_usectohz(manp->man_kstat_waittime));
193974072f41a843678abf5f61979c748687e66bSherry Moore "timedout, returning stale stats."));
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_NUMSTATS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_NUMSTATS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_kstat_update: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sum destination kstats for all active paths for a given instance of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN driver. Called with perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sync mp_last_knp for each path associated with the MAN instance.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mpg = manp->man_pg; mpg != NULL; mpg = mpg->mpg_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mp = man_find_active_path(mpg->mpg_pathp)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We just to update the destination statistics here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sum device kstats for all active paths for a given instance of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN driver. Called with man_lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mpg = manp->man_pg; mpg != NULL; mpg = mpg->mpg_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mp = man_find_active_path(mpg->mpg_pathp)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_update_path_kstats: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Update the device kstats.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * As man_kstat_update() is called with kstat_chain_lock held,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we can safely update the statistics from the underlying driver here.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_update_dev_kstats(kstat_named_t *man_knp, man_path_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(buf, "%s%d", ddi_major_to_name(major), instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_ksp = kstat_hold_byname(ddi_major_to_name(major), instance, buf,
193974072f41a843678abf5f61979c748687e66bSherry Moore ("man_update_dev_kstats: no kstat data found for %s(%d,%d)",
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_sum_dests_kstats(kstat_named_t *knp, man_pg_t *mpg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_sum_dests_kstats: mpg 0x%p", (void *)mpg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_NUMSTATS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_link_fails") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_link_stales") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_icmpv4_probes") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_icmpv6_probes") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_sum_dests_kstats: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize MAN named kstats in the space provided.
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_kstat_named_init(kstat_named_t *knp, int num_stats)
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_kstat_named_init: knp(0x%p) num_stats = %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < num_stats; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_kstat_named_init: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_kstat_byname - get a kernel stat value from its structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ksp - kstat_t structure to play with
03831d35f7499c87d51205817c93e9a8d42c4baestevel * s - string to match names with
03831d35f7499c87d51205817c93e9a8d42c4baestevel * res - in/out result data pointer
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - 1 (found)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - 0 (not found)
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_kstat_byname(kstat_t *ksp, char *s, kstat_named_t *res)
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT2, ("man_kstat_byname: GETTING %s\n", s));
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)knp < ((caddr_t)ksp->ks_data+ksp->ks_data_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT2, ("\tbad kstats type %d\n", ksp->ks_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if getting a value but couldn't find the namestring, result = 0.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a reasonable default
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT2, ("\tcouldn't find, using defaults\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT2, ("man_kstat_byname: returns\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Accumulate MAN driver kstats from the incremental values of the underlying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * physical interfaces.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Parameters:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sum_knp - The named kstat area to put cumulative value,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NULL if we just want to sync next two params.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * phys_ksp - Physical interface kstat_t pointer. Contains
03831d35f7499c87d51205817c93e9a8d42c4baestevel * more current counts.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * phys_last_knp - counts from the last time we were called for this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * physical interface. Note that the name kstats
03831d35f7499c87d51205817c93e9a8d42c4baestevel * pointed to are actually in MAN format, but they
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hold the mirrored physical devices last read
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Basic algorithm is:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for each named kstat variable {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sum_knp[i] += (phys_ksp->ksp_data[i] - phys_last_knp[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * phys_last_knp[i] = phys_ksp->ksp_data[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_sum_kstats(kstat_named_t *sum_knp, kstat_t *phys_ksp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_sum_kstats: sum_knp(0x%p) phys_ksp(0x%p)"
193974072f41a843678abf5f61979c748687e66bSherry Moore " phys_last_knp(0x%p)\n", (void *)sum_knp, (void *)phys_ksp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now for each entry in man_kstat_info, sum the named kstat.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Not that all MAN specific kstats will end up !found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_NUMSTATS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Update MAN private kstats.
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_link_fails") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_link_stales") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_icmpv4_probes") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_icmpv6_probes") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue; /* phys_ksp doesnt have this stat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * first try it by the "official" name
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((physalias) && (man_kstat_byname(phys_ksp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * clear up the "last" value, no change to the sum
03831d35f7499c87d51205817c93e9a8d42c4baestevel * at this point, we should have the good underlying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kstat value stored in phys_kn_entry
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it isn't a counter, so store the value and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * move on (e.g. ifspeed)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this handles 32-bit wrapping
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we've wrapped!
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_last_knp[i].value.ui32 = phys_kn_entry.value.ui32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * must be a 64-bit value, we ignore 64-bit
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wraps, since they shouldn't ever happen
03831d35f7499c87d51205817c93e9a8d42c4baestevel * within the life of a machine (if we assume
03831d35f7499c87d51205817c93e9a8d42c4baestevel * machines don't stay up for more than a few
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hundred years without a reboot...)
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_last_knp[i].value.ui64 = phys_kn_entry.value.ui64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * now we need to save the value
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* trunk down to 32 bits, possibly lossy */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *_ms_flags[] = {
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_major_to_name(msp->ms_meta_maj), msp->ms_meta_ppa,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tms_dlpistate: %s\n", dss[msp->ms_dlpistate]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tms_dl_mp: 0x%p\n", (void *)msp->ms_dl_mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tms_manp: 0x%p\n", (void *)msp->ms_manp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tms_dests: 0x%p\n", (void *)msp->ms_dests);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *_md_state[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmd_dlpistate: %s", dss[mdp->md_dlpistate]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmd_rcvcnt %lu md_lastrcvcnt %lu", mdp->md_rcvcnt,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Print out state as text.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (state == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *_mdev_state[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "UNASSIGNED ",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "ASSIGNED",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(buf, "\t mdev_major: %d\n", mdevp->mdev_major);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\t mdev_exp_id: %d\n", mdevp->mdev_exp_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (state == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *_mip_cmd[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "MI_PATH_READ",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "MI_PATH_ASSIGN",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "MI_PATH_ACTIVATE",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "MI_PATH_DEACTIVATE",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "MI_PATH_UNASSIGN"
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmtp_instance: %d\n", mtp->mtp_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmip_pg_id: %d\n", mip->mip_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmip_cmd: %s\n", _mip_cmd[mip->mip_cmd]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmip_eaddr: %s\n", ether_sprintf(&mip->mip_eaddr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmip_devs: 0x%p\n", (void *)mip->mip_devs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmip_ndevs: %d\n", mip->mip_ndevs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmpg_next: 0x%p\n", (void *)mpg->mpg_next);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmpg_pg_id: %d\n", mpg->mpg_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmpg_man_ppa: %d\n", mpg->mpg_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmpg_pathp: 0x%p\n", (void *)mpg->mpg_pathp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *_mw_flags[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmw_type: %s\n", _mw_type[wp->mw_type]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\twp_status: %d\n", wp->mw_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\twp_arg: 0x%p\n", (void *)&wp->mw_arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmw_next: 0x%p\n", (void *)wp->mw_next);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmp_next: 0x%p\n", (void *)mp->mp_next);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmp_last_knp: 0x%p\n", (void *)mp->mp_last_knp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KMEM, ("0x%p %lu\tzalloc'd @ %d\n", (void *)tmp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KMEM, ("0x%p %lu\tfree'd @ %d\n", (void *)buf, size, line));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */