dman.c revision d3d50737e566cade9a08d73d2af95105ac7cd960
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or http://www.opensolaris.org/os/licensing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Starcat Management Network Driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/proc.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/disp.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kstat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ksynch.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stream.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/dlpi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stropts.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/strsubr.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/debug.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kstr.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/errno.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ethernet.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/byteorder.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunldi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/strsun.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/callb.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/pci.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <netinet/in.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <inet/common.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <inet/mi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <inet/nd.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/socket.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <netinet/igmp_var.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <netinet/ip6.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <netinet/icmp6.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <inet/ip.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <inet/ip6.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/file.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/dman.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/autoconf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/zone.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int ddi_create_internal_pathname(dev_info_t *, char *, int, minor_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MAN_IDNAME "dman"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DMAN_INT_PATH "/devices/pseudo/dman@0:dman"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DMAN_PATH "/devices/pseudo/clone@0:dman"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define ERI_IDNAME "eri"
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define ERI_PATH "/devices/pseudo/clone@0:eri"
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_print_msp(manstr_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_print_man(man_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_print_mdp(man_dest_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_print_dev(man_dev_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_print_mip(mi_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_print_mtp(mi_time_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_print_mpg(man_pg_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_print_path(man_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_print_work(man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set manstr_t dlpistate (upper half of multiplexor)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SETSTATE(msp, state) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("msp=0x%p @ %d state %s=>%s\n", \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)msp, __LINE__, dss[msp->ms_dlpistate], \
03831d35f7499c87d51205817c93e9a8d42c4baestevel dss[(state)])); \
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_dlpistate = (state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set man_dest_t dlpistate (lower half of multiplexor)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define D_SETSTATE(mdp, state) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("dst=0x%p @ %d state %s=>%s\n", \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)mdp, __LINE__, dss[mdp->md_dlpistate], \
03831d35f7499c87d51205817c93e9a8d42c4baestevel dss[(state)])); \
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dlpistate = (state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *promisc[] = { /* DLPI promisc Strings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "not used", /* 0x00 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_PROMISC_PHYS", /* 0x01 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_PROMISC_SAP", /* 0x02 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_PROMISC_MULTI" /* 0x03 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *dps[] = { /* DLPI Primitive Strings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_INFO_REQ", /* 0x00 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_BIND_REQ", /* 0x01 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_UNBIND_REQ", /* 0x02 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_INFO_ACK", /* 0x03 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_BIND_ACK", /* 0x04 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_ERROR_ACK", /* 0x05 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_OK_ACK", /* 0x06 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_UNITDATA_REQ", /* 0x07 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_UNITDATA_IND", /* 0x08 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_UDERROR_IND", /* 0x09 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_UDQOS_REQ", /* 0x0a */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_ATTACH_REQ", /* 0x0b */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DETACH_REQ", /* 0x0c */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_CONNECT_REQ", /* 0x0d */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_CONNECT_IND", /* 0x0e */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_CONNECT_RES", /* 0x0f */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_CONNECT_CON", /* 0x10 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_TOKEN_REQ", /* 0x11 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_TOKEN_ACK", /* 0x12 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DISCONNECT_REQ", /* 0x13 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DISCONNECT_IND", /* 0x14 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_SUBS_UNBIND_REQ", /* 0x15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_LIARLIARPANTSONFIRE", /* 0x16 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_RESET_REQ", /* 0x17 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_RESET_IND", /* 0x18 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_RESET_RES", /* 0x19 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_RESET_CON", /* 0x1a */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_SUBS_BIND_REQ", /* 0x1b */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_SUBS_BIND_ACK", /* 0x1c */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_ENABMULTI_REQ", /* 0x1d */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DISABMULTI_REQ", /* 0x1e */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_PROMISCON_REQ", /* 0x1f */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_PROMISCOFF_REQ", /* 0x20 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DATA_ACK_REQ", /* 0x21 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DATA_ACK_IND", /* 0x22 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DATA_ACK_STATUS_IND", /* 0x23 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_REPLY_REQ", /* 0x24 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_REPLY_IND", /* 0x25 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_REPLY_STATUS_IND", /* 0x26 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_REPLY_UPDATE_REQ", /* 0x27 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_REPLY_UPDATE_STATUS_IND", /* 0x28 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_XID_REQ", /* 0x29 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_XID_IND", /* 0x2a */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_XID_RES", /* 0x2b */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_XID_CON", /* 0x2c */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_TEST_REQ", /* 0x2d */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_TEST_IND", /* 0x2e */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_TEST_RES", /* 0x2f */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_TEST_CON", /* 0x30 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_PHYS_ADDR_REQ", /* 0x31 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_PHYS_ADDR_ACK", /* 0x32 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_SET_PHYS_ADDR_REQ", /* 0x33 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_GET_STATISTICS_REQ", /* 0x34 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_GET_STATISTICS_ACK", /* 0x35 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MAN_DLPI_MAX_PRIM 0x35
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *dss[] = { /* DLPI State Strings */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_UNBOUND", /* 0x00 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_BIND_PENDING", /* 0x01 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_UNBIND_PENDING", /* 0x02 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_IDLE", /* 0x03 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_UNATTACHED", /* 0x04 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_ATTACH_PENDING", /* 0x05 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DETACH_PENDING", /* 0x06 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_UDQOS_PENDING", /* 0x07 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_OUTCON_PENDING", /* 0x08 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_INCON_PENDING", /* 0x09 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_CONN_RES_PENDING", /* 0x0a */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DATAXFER", /* 0x0b */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_USER_RESET_PENDING", /* 0x0c */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_PROV_RESET_PENDING", /* 0x0d */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_RESET_RES_PENDING", /* 0x0e */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DISCON8_PENDING", /* 0x0f */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DISCON9_PENDING", /* 0x10 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DISCON11_PENDING", /* 0x11 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DISCON12_PENDING", /* 0x12 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_DISCON13_PENDING", /* 0x13 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_SUBS_BIND_PND", /* 0x14 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DL_SUBS_UNBIND_PND", /* 0x15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic const char *lss[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "UNKNOWN", /* 0x0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "INIT", /* 0x1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "GOOD", /* 0x2 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "STALE", /* 0x3 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "FAIL", /* 0x4 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *_mw_type[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "OPEN_CTL", /* 0x0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "CLOSE_CTL", /* 0x1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SWITCH", /* 0x2 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "PATH_UPDATE", /* 0x3 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "CLOSE", /* 0x4 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "CLOSE_STREAM", /* 0x5 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DRATTACH", /* 0x6 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DRDETACH", /* 0x7 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "STOP", /* 0x8 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DRSWITCH", /* 0x9 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "KSTAT_UPDATE" /* 0xA */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint32_t man_debug = MAN_WARN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define man_kzalloc(a, b) man_dbg_kzalloc(__LINE__, a, b)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define man_kfree(a, b) man_dbg_kfree(__LINE__, a, b)
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid *man_dbg_kzalloc(int line, size_t size, int kmflags);
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid man_dbg_kfree(int line, void *buf, size_t size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint32_t man_debug = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set manstr_t dlpistate (upper half of multiplexor)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SETSTATE(msp, state) msp->ms_dlpistate = (state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set man_dest_t dlpistate (lower half of multiplexor)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define D_SETSTATE(mdp, state) mdp->md_dlpistate = (state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define man_kzalloc(a, b) kmem_zalloc(a, b)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define man_kfree(a, b) kmem_free(a, b)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DL_PRIM(mp) (((union DL_primitives *)(mp)->b_rptr)->dl_primitive)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DL_PROMISCON_TYPE(mp) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (((union DL_primitives *)(mp)->b_rptr)->promiscon_req.dl_level)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define IOC_CMD(mp) (((struct iocblk *)(mp)->b_rptr)->ioc_cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start of kstat-related declarations
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_NOT_COUNTER (1<<0) /* is it a counter? */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_ERROR (1<<2) /* for error statistics */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_NOT_PHYSICAL (1<<3) /* no matching physical stat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct man_kstat_info_s {
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *mk_name; /* e.g. align_errors */
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *mk_physname; /* e.g. framing (NULL for same) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *mk_physalias; /* e.g. framing (NULL for same) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t mk_type; /* e.g. KSTAT_DATA_UINT32 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int mk_flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} man_kstat_info_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Master declaration macro, note that it uses token pasting
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_DECLARE(name, pname, palias, bits, flags) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel { name, pname, palias, KSTAT_DATA_UINT ## bits, flags }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Obsolete forms don't have the _sinceswitch forms, they are all errors
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The only non-counters don't have any other aliases
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Normal counter forms
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_DECLARE32(name, alias) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE(name, name, alias, 32, 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_DECLARE64(name, alias) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE(name, name, alias, 64, 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Error counters need special MK_ERROR flag only for the non-AP form
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_ERROR32(name, alias) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE(name, name, alias, 32, MK_ERROR)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MK_ERROR64(name, alias) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE(name, name, alias, 64, MK_ERROR)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These AP-specific stats are not backed by physical statistics
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * START of the actual man_kstat_info declaration using above macros
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_kstat_info_t man_kstat_info[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Link Input/Output stats
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE32("ipackets", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("ierrors", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE32("opackets", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("oerrors", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("collisions", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_NOTCOUNTER64("ifspeed"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These are new MIB-II stats, per PSARC 1997/198
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE32("rbytes", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE32("obytes", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE32("multircv", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE32("multixmt", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE32("brdcstrcv", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE32("brdcstxmt", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Error values
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("norcvbuf", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("noxmtbuf", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("unknowns", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These are the 64-bit values, they fallback to 32-bit values
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE64("ipackets64", "ipackets"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE64("opackets64", "opackets"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE64("rbytes64", "rbytes"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_DECLARE64("obytes64", "obytes"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* New AP switching statistics */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_NOTPHYS64("man_switches"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_NOTPHYS64("man_link_fails"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_NOTPHYS64("man_link_stales"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_NOTPHYS64("man_icmpv4_probes"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_NOTPHYS64("man_icmpv6_probes"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("align_errors", "framing"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("fcs_errors", "crc"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("first_collisions", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("multi_collisions", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("sqe_errors", "sqe"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("tx_late_collisions", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("ex_collisions", "excollisions"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("macxmt_errors", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("carrier_errors", "nocarrier"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("toolong_errors", "buff"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_ERROR32("macrcv_errors", NULL),
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_OBSOLETE32("framing", "align_errors"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_OBSOLETE32("crc", "fcs_errors"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_OBSOLETE32("sqe", "sqe_errors"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_OBSOLETE32("excollisions", "ex_collisions"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_OBSOLETE32("nocarrier", "carrier_errors"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel MK_OBSOLETE32("buff", "toolong_errors"),
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MAN_NUMSTATS (sizeof (man_kstat_info) / sizeof (man_kstat_info_t))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Miscellaneous ethernet stuff.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MANs DL_INFO_ACK template.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic dl_info_ack_t man_infoack = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DL_INFO_ACK, /* dl_primitive */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ETHERMTU, /* dl_max_sdu */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_min_sdu */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_ADDRL, /* dl_addr_length */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DL_ETHER, /* dl_mac_type */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_reserved */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_current_state */
03831d35f7499c87d51205817c93e9a8d42c4baestevel -2, /* dl_sap_length */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DL_CLDLS, /* dl_service_mode */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_qos_length */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_qos_offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_range_length */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* dl_range_offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DL_STYLE2, /* dl_provider_style */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (dl_info_ack_t), /* dl_addr_offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DL_VERSION_2, /* dl_version */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ETHERADDRL, /* dl_brdcst_addr_length */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (dl_info_ack_t) + MAN_ADDRL, /* dl_brdcst_addr_offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0 /* dl_growth */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Ethernet broadcast address definition.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct ether_addr etherbroadcast = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct ether_addr zero_ether_addr = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set via MAN_SET_SC_IPADDRS ioctl.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_sc_ipaddrs_t man_sc_ipaddrs = { 0xffffffffU, 0xffffffffU };
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set via MAN_SET_SC_IP6ADDRS ioctl.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_sc_ip6addrs_t man_sc_ip6addrs = { 0, 0, 0, 0, 0, 0, 0, 0 };
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IP & ICMP constants
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef ETHERTYPE_IPV6
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define ETHERTYPE_IPV6 0x86DD
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Function prototypes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Upper multiplexor functions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
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_configure(queue_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_deconfigure(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_init_dests(man_t *, manstr_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_start_dest(man_dest_t *, manstr_t *, man_pg_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_set_optimized_dest(manstr_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_close(queue_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_cancel_timers(man_adest_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_uwput(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_start(queue_t *, mblk_t *, eaddr_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_ioctl(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_set_linkcheck_time(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_setpath(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_geteaddr(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_set_sc_ipaddrs(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_set_sc_ip6addrs(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_get_our_etheraddr(eaddr_t *eap);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_nd_getset(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_dl_ioc_hdr_info(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_uwsrv(queue_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_proto(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_udreq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_areq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mblk_t *man_alloc_physreq_mp(eaddr_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_dreq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_dodetach(manstr_t *, man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_dl_clean(mblk_t **);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_breq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_ubreq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_ireq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_ponreq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_poffreq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_emreq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_dmreq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_pareq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_spareq(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_dlpi(manstr_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_dlioc(manstr_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_dl_catch(mblk_t **, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_dl_release(mblk_t **, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_match_proto(mblk_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_open_ctl();
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_close_ctl();
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * upper/lower multiplexor functions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_dlpi_senddown(manstr_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_start_lower(man_dest_t *, mblk_t *, queue_t *, int caller);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_lrput(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Lower multiplexor functions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_lwsrv(queue_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_lrsrv(queue_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_dlpi_replay(man_dest_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_dlioc_replay(man_dest_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Link failover routines.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_gettimer(int, man_dest_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_linkcheck_timer(void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_needs_linkcheck(man_dest_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_do_autoswitch(man_dest_t *);
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 int man_str_uses_pg(manstr_t *, man_pg_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_do_icmp_bcast(man_dest_t *, t_uscalar_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mblk_t *man_alloc_udreq(int, man_dladdr_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mblk_t *man_pinger(t_uscalar_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions normally executing outside of the STREAMs perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions supporting/processing work requests.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_bwork(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_iwork(void); /* inside perimeter */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid man_work_add(man_workq_t *, man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_work_t *man_work_alloc(int, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid man_work_free(man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions implementing/supporting failover.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Executed inside perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_do_dr_attach(man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_do_dr_switch(man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_do_dr_detach(man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_iswitch(man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_ifail_dest(man_dest_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_dest_t *man_switch_match(man_dest_t *, int, void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_add_dests(man_pg_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_reset_dlpi(void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mblk_t *man_dup_mplist(mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mblk_t *man_alloc_ubreq_dreq();
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Executed outside perimeter (us man_lock for synchronization).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_bclose(man_adest_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_bswitch(man_adest_t *, man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_plumb(man_dest_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_unplumb(man_dest_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_plink(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_unplink(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_linkrec_insert(man_linkrec_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic queue_t *man_linkrec_find(int);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions supporting pathgroups
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint man_pg_cmd(mi_path_t *, man_work_t *);
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_unassign(man_pg_t **, mi_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_pg_activate(man_t *, mi_path_t *, man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_pg_read(man_pg_t *, mi_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_pg_t *man_find_path_by_dev(man_pg_t *, man_dev_t *, man_path_t **);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_pg_t *man_find_pg_by_id(man_pg_t *, int);
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 *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_path_kstat_init(man_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_path_kstat_uninit(man_path_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions supporting kstat reporting.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_kstat_update(kstat_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_do_kstats(man_work_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_update_path_kstats(man_t *);
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/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Functions supporting ndd.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_param_register(param_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_pathgroups_report(queue_t *, mblk_t *, caddr_t, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_preport(man_path_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_set_active_path(queue_t *, mblk_t *, char *, caddr_t,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_get_hostinfo(queue_t *, mblk_t *, caddr_t, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *man_inet_ntoa(in_addr_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);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void man_nd_free(caddr_t *nd_pparam);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN SSC/Domain specific externs.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int man_get_iosram(manc_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int man_domain_configure(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int man_domain_deconfigure(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int man_dossc_switch(uint32_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int man_is_on_domain;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Driver Globals protected by inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic manstr_t *man_strup = NULL; /* list of MAN STREAMS */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic caddr_t man_ndlist = NULL; /* head of ndd var list */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid *man_softstate = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Driver globals protected by man_lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelkmutex_t man_lock; /* lock protecting vars below */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kthread_id_t man_bwork_id = NULL; /* background thread ID */
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_workq_t *man_bwork_q; /* bgthread work q */
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelqueue_t *man_ctl_wq = NULL; /* MAN control rq */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_config_state = MAN_UNCONFIGURED;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int man_config_error = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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#define MAN_NOTUSR 0x0f000000
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ------------------------------------------------------------------------- */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic param_t man_param_arr[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* min max value name */
03831d35f7499c87d51205817c93e9a8d42c4baestevel { 0, 0xFFFF, 0, "man_debug_level"},
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MAN_NDD_GETABLE 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MAN_NDD_SETABLE 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t man_param_display[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* DISPLAY */
03831d35f7499c87d51205817c93e9a8d42c4baestevelMAN_NDD_SETABLE, /* man_debug_level */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * STREAMs information.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct module_info man_m_info = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_IDNUM, /* mi_idnum */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_IDNAME, /* mi_idname */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_MINPSZ, /* mi_minpsz */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_MAXPSZ, /* mi_maxpsz */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_HIWAT, /* mi_hiwat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_LOWAT /* mi_lowat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Upper read queue does not do anything.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct qinit man_urinit = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* qi_putp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* qi_srvp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_open, /* qi_qopen */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_close, /* qi_qclose */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* qi_qadmin */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &man_m_info, /* qi_minfo */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL /* qi_mstat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct qinit man_lrinit = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_lrput, /* qi_putp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_lrsrv, /* qi_srvp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_open, /* qi_qopen */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_close, /* qi_qclose */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* qi_qadmin */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &man_m_info, /* qi_minfo */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL /* qi_mstat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct qinit man_uwinit = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_uwput, /* qi_putp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_uwsrv, /* qi_srvp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_open, /* qi_qopen */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_close, /* qi_qclose */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* qi_qadmin */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &man_m_info, /* qi_minfo */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL /* qi_mstat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct qinit man_lwinit = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* qi_putp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_lwsrv, /* qi_srvp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_open, /* qi_qopen */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_close, /* qi_qclose */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* qi_qadmin */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &man_m_info, /* qi_minfo */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL /* qi_mstat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct streamtab man_maninfo = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &man_urinit, /* st_rdinit */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &man_uwinit, /* st_wrinit */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &man_lrinit, /* st_muxrinit */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &man_lwinit /* st_muxwrinit */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Module linkage information for the kernel.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MAN_MDEV_FLAGS (D_MP|D_MTPERMOD|D_MTPUTSHARED)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelDDI_DEFINE_STREAM_OPS(man_ops, nulldev, nulldev, man_attach,
193974072f41a843678abf5f61979c748687e66bSherry Moore man_detach, nodev, man_info, MAN_MDEV_FLAGS, &man_maninfo,
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_supported);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int nodev(), nulldev();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modldrv modldrv = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_driverops, /* Module type. This one is a pseudo driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "MAN MetaDriver",
03831d35f7499c87d51205817c93e9a8d42c4baestevel &man_ops, /* driver ops */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlinkage modlinkage = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MODREV_1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *) &modldrv,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* Virtual Driver loader entry points */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_init(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = DDI_FAILURE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("_init:"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = mod_install(&modlinkage);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_init: mod_install failed"
193974072f41a843678abf5f61979c748687e66bSherry Moore " error = %d", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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"
193974072f41a843678abf5f61979c748687e66bSherry Moore " error = %d", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mod_remove(&modlinkage);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&man_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&man_bwork_q->q_cv, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&man_iwork_q->q_cv, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * _info is called by modinfo().
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_info(struct modinfo *modinfop)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("_info:"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = mod_info(&modlinkage, modinfop);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("_info: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * _fini called by modunload() just before driver is unloaded from memory.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_fini(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("_fini:"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_strup && (man_strup->ms_next != NULL))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EBUSY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Deconfigure the driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_deconfigure();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * need to detach every instance of the driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = mod_remove(&modlinkage);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_fini(&man_softstate);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free up locks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&man_bwork_q->q_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&man_iwork_q->q_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(man_bwork_q, sizeof (man_workq_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(man_iwork_q, sizeof (man_workq_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("_fini: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Deconfigure the MAN driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_deconfigure()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_t *wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_deconfigure:\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_is_on_domain) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_domain_deconfigure();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_param_cleanup(); /* Free up NDD resources */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * I may have to handle straggling work requests. Just qwait?
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or cvwait? Called from _fini - TBD
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(man_bwork_q->q_work == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(man_iwork_q->q_work == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_deconfigure: submitting CLOSE_CTL\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_ctl_lh != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_work_alloc(MAN_WORK_CLOSE_CTL, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_flags = MAN_WFLAGS_CVWAITER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_add(man_bwork_q, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (!(wp->mw_flags & MAN_WFLAGS_DONE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&wp->mw_cv, &man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_free(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_deconfigure: submitting STOP\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_bwork_id != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_work_alloc(MAN_WORK_STOP, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_flags = MAN_WFLAGS_CVWAITER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_add(man_bwork_q, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (!(wp->mw_flags & MAN_WFLAGS_DONE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&wp->mw_cv, &man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_free(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_config_state = MAN_UNCONFIGURED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_deconfigure: returns %d\n", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dip - devinfo of node
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cmd - one of DDI_ATTACH | DDI_RESUME
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - DDI_SUCCESS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - DDI_FAILURE
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp; /* per instance data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t flag = KSTAT_FLAG_WRITABLE; /* support netstat -kc */
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_t *ksp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int minor_node_created = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel eaddr_t man_eaddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_attach: \n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd != DDI_ATTACH) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_attach: bad command %d\n", cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_get_our_etheraddr(&man_eaddr))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(instance == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate per device info pointer and link in to global list of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN devices.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
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 return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_set_driver_private(dip, manp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_dip = dip;
5c066ec28ea93f3a7c93082611a61747f255290aJerry Gilliam manp->man_meta_major = ddi_driver_major(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_meta_ppa = instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set ethernet address. Note that this address is duplicated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * at md_src_eaddr.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&man_eaddr, &manp->man_eaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_eaddr_v = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_attach: set ether to %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore ether_sprintf(&manp->man_eaddr)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize failover-related fields (timers and such),
03831d35f7499c87d51205817c93e9a8d42c4baestevel * taking values from properties if present.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_init_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "init_time", MAN_INIT_TIME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_linkcheck_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "linkcheck_time", MAN_LINKCHECK_TIME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_linkstale_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "man_linkstale_time", MAN_LINKSTALE_TIME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_linkstale_retries = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "man_linkstale_retries", MAN_LINKSTALE_RETRIES);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_dr_delay = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "man_dr_delay", MAN_DR_DELAY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_dr_retries = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "man_dr_retries", MAN_DR_RETRIES);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_kstat_waittime = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "man_kstat_waittime", MAN_KSTAT_WAITTIME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_dlpireset_time = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "man_dlpireset_time", MAN_DLPIRESET_TIME);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_create_internal_pathname(dip, MAN_IDNAME, S_IFCHR,
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(dip)) == DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel minor_node_created = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_attach: failed for instance %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_get_instance(dip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_create_minor_node(dip, MAN_IDNAME, S_IFCHR,
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(dip), DDI_NT_NET, CLONE_DEV) == DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel minor_node_created = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_attach: failed for instance %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_get_instance(dip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef kstat
03831d35f7499c87d51205817c93e9a8d42c4baestevel flag |= KSTAT_FLAG_PERSISTENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel ksp = kstat_create(MAN_IDNAME, ddi_get_instance(dip), NULL, "net",
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_TYPE_NAMED, MAN_NUMSTATS, flag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ksp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_attach(%d): kstat_create failed"
193974072f41a843678abf5f61979c748687e66bSherry Moore " - manp(0x%p)", manp->man_meta_ppa,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)manp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kstat_named_init(ksp->ks_data, MAN_NUMSTATS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ksp->ks_update = man_kstat_update;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ksp->ks_private = (void *) manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_ksp = ksp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_install(manp->man_ksp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_report_dev(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_attach(%d) returns DDI_SUCCESS",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(dip)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (minor_node_created)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_minor_node(dip, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_set_driver_private(dip, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(man_softstate, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_attach(%d) eaddr returns DDI_FAILIRE",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(dip)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_get_our_etheraddr(eaddr_t *eap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manc_t manc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_is_on_domain) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status = man_get_iosram(&manc))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&manc.manc_dom_eaddr, eap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) localetheraddr((struct ether_addr *)NULL, eap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_detach - detach an instance of a driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dip - devinfo of node
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cmd - one of DDI_DETACH | DDI_SUSPEND
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - DDI_SUCCESS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - DDI_FAILURE
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register man_t *manp; /* per instance data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_detach(%d):\n", ddi_get_instance(dip)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd != DDI_DETACH) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_detach: bad command %d\n", cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dip == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_detach: dip == NULL\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = (man_t *)ddi_get_soft_state(man_softstate, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_detach: unable to get softstate"
193974072f41a843678abf5f61979c748687e66bSherry Moore " for instance = %d, dip = 0x%p!\n", instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp->man_refcnt != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_detach: %s%d refcnt %d", MAN_IDNAME,
193974072f41a843678abf5f61979c748687e66bSherry Moore instance, manp->man_refcnt);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_INIT, man_print_man(manp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_minor_node(dip, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_delete(manp->man_ksp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(man_softstate, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_set_driver_private(dip, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_INIT, ("man_detach returns DDI_SUCCESS"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_info:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * As a standard DLPI style-2, man_info() should always return
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DDI_FAILURE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel minor_t minor;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (infocmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_INFO_DEVT2DEVINFO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_INFO_DEVT2INSTANCE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel minor = getminor((dev_t)arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (minor == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *result = (void *)(uintptr_t)minor;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* Standard Device Driver entry points */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_open - open the device
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - errno value for failure
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *credp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int minordev = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *tsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t **prevmsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_OCLOSE, ("man_open: rq(0x%p) sflag(0x%x)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)rq, sflag));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(sflag != MODOPEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reopen; q_ptr set to msp at open completion.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rq->q_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate and initialize manstr_t for this device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = man_kzalloc(sizeof (manstr_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SETSTATE(msp, DL_UNATTACHED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_meta_ppa = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_rq = rq;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rq->q_ptr = WR(rq)->q_ptr = msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel qprocson(rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sflag == CLONEOPEN && man_config_state != MAN_CONFIGURED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * First open calls man_configure. Everyone qwaits until
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we get it open. See man_open_ctl() comments for mutex
03831d35f7499c87d51205817c93e9a8d42c4baestevel * lock/synchronization info.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_config_state == MAN_UNCONFIGURED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_config_state = MAN_CONFIGURING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_configure(rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (man_config_state == MAN_CONFIGURING) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = qwait_sig(rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINTR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_config_error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_config_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Determine minor device number. man_open serialized by
03831d35f7499c87d51205817c93e9a8d42c4baestevel * D_MTPERMOD.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel prevmsp = &man_strup;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sflag == CLONEOPEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel minordev = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; (tsp = *prevmsp) != NULL; prevmsp = &tsp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (minordev < tsp->ms_minor)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel minordev++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel *devp = makedevice(getmajor(*devp), minordev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Should only get here from man_plumbctl().
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*LINTED E_ASSIGN_UINT_TO_SIGNED_INT*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel minordev = getminor(*devp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_ctl_wq = WR(rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(minordev == 0); /* TBD delete this */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_meta_maj = getmajor(*devp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_minor = minordev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (minordev == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_flags = MAN_SFLAG_CONTROL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Link new entry into global list of active entries.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_next = *prevmsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *prevmsp = msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disable automatic enabling of our write service procedure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We control this explicitly.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel noenable(WR(rq));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_OCLOSE, ("man_open: exit rq(0x%p) minor %d errno %d\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)rq, minordev, status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clean up on error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel qprocsoff(rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rq->q_ptr = WR(rq)->q_ptr = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree((char *)msp, sizeof (manstr_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) qassociate(rq, -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the driver configured. Called from first man_open with exclusive
03831d35f7499c87d51205817c93e9a8d42c4baestevel * inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_configure(queue_t *rq)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_t *wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_configure:"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize NDD parameters.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!man_ndlist &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel !man_param_register(man_param_arr, A_CNT(man_param_arr))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_configure: man_param_register failed!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_config_error = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start up background thread.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_bwork_id == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_bwork_id = thread_create(NULL, 2 * DEFAULTSTKSZ,
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_bwork, NULL, 0, &p0, TS_RUN, minclsyspri);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Submit work to get control stream opened. Qwait until its
03831d35f7499c87d51205817c93e9a8d42c4baestevel * done. See man_open_ctl for mutex lock/synchronization info.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_ctl_lh == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_work_alloc(MAN_WORK_OPEN_CTL, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_flags |= MAN_WFLAGS_QWAITER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_q = WR(rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Submit work and wait. When man_open_ctl exits
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_open, it will cause qwait below to return.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_add(man_bwork_q, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (!(wp->mw_flags & MAN_WFLAGS_DONE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel qwait(rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = wp->mw_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_free(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If on domain, setup IOSRAM and build the pathgroups
03831d35f7499c87d51205817c93e9a8d42c4baestevel * automatically.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((status == 0) && man_is_on_domain)
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_domain_configure();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_config_error = status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_config_state = MAN_UNCONFIGURED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_config_state = MAN_CONFIGURED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_configure: returns %d\n", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_close - close the device
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rq - upper read queue of the stream
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - errno value for failure
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_close(queue_t *rq)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *close_msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_OCLOSE, ("man_close: rq(0x%p)\n", (void *)rq));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel qprocsoff(rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel close_msp = (manstr_t *)rq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unlink the per-Stream entry from the active list and free it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (close_msp == man_strup)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_strup = close_msp->ms_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp && msp->ms_next != close_msp; )
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = msp->ms_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_close: no stream!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENODEV);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_next = close_msp->ms_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (close_msp->ms_dests != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Still DL_ATTACHED
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_t *wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_work_alloc(MAN_WORK_CLOSE_STREAM, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dodetach(close_msp, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (close_msp->ms_flags & MAN_SFLAG_CONTROL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Driver about to unload.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_ctl_wq = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rq->q_ptr = WR(rq)->q_ptr = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree((char *)close_msp, sizeof (manstr_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) qassociate(rq, -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_OCLOSE, ("man_close: exit\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Ask bgthread to tear down lower stream and qwait
03831d35f7499c87d51205817c93e9a8d42c4baestevel * until its done.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dodetach(manstr_t *msp, man_work_t *wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = msp->ms_dests;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_dests = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_destp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Excise lower dests array, set it closing and hand it to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * background thread to dispose of.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp[i].md_state |= MAN_DSTATE_CLOSING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp[i].md_msp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp[i].md_rq = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp[i].md_lc_timer_id != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) quntimeout(man_ctl_wq, mdp[i].md_lc_timer_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp[i].md_lc_timer_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp[i].md_bc_id != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel qunbufcall(man_ctl_wq, mdp[i].md_bc_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp[i].md_bc_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mdp[i].md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((mp = mdp[i].md_dmp_head) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp[i].md_dmp_head = mp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp[i].md_dmp_count = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp[i].md_dmp_tail = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mdp[i].md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Dump any DL type messages previously caught.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dl_clean(&msp->ms_dl_mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dl_clean(&msp->ms_dlioc_mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We need to clear fast path flag when dlioc messages are cleaned.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_flags &= ~MAN_SFLAG_FAST;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN_WORK_CLOSE_STREAM work request preallocated by caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(wp->mw_type == MAN_WORK_CLOSE_STREAM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_mdp = mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_ndests = MAN_MAX_DESTS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_pg_id = -1; /* Don't care */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_add(man_bwork_q, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_manp->man_refcnt--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_manp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wq - upper write queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - mblk ptr to DLPI request
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_uwput(register queue_t *wq, register mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register manstr_t *msp; /* per stream data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel register man_t *manp; /* per instance data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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#if DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_debug & MAN_UWPUT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DB_TYPE(mp) == M_IOCTL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_UWPUT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("man_uwput: M_IOCTL ioc_cmd(0x%x)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (DB_TYPE(mp) == M_CTL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_UWPUT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("man_uwput: M_CTL ioc_cmd(0x%x)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (DB_TYPE(mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_DATA:
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = msp->ms_manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (((msp->ms_flags & (MAN_SFLAG_FAST | MAN_SFLAG_RAW)) == 0) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (msp->ms_dlpistate != DL_IDLE) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (manp == NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel merror(wq, mp, EPROTO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wq->q_first) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel qenable(wq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ehdr_t *ep = (ehdr_t *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) man_start(wq, mp, &ep->ether_dhost);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_PROTO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_PCPROTO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((DL_PRIM(mp) == DL_UNITDATA_IND) && !wq->q_first) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) man_udreq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel qenable(wq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_IOCTL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_IOCDATA:
03831d35f7499c87d51205817c93e9a8d42c4baestevel qwriter(wq, mp, man_ioctl, PERIM_INNER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_CTL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_FLUSH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_UWPUT, ("man_wput: M_FLUSH\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*mp->b_rptr & FLUSHW)
03831d35f7499c87d51205817c93e9a8d42c4baestevel flushq(wq, FLUSHDATA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*mp->b_rptr & FLUSHR) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel flushq(RD(wq), FLUSHDATA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mp->b_rptr &= ~FLUSHW;
03831d35f7499c87d51205817c93e9a8d42c4baestevel qreply(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("man_uwput: illegal mblk(0x%p) type(0x%x)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)mp, DB_TYPE(mp)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } /* End switch */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_UWPUT, ("man_uwput: exit wq(0x%p) mp(0x%p)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)wq, (void *)mp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 - Data xmitted or No flow control situation detected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 - Flow control situation detected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 *
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_start(register queue_t *wq, register mblk_t *mp, eaddr_t *eap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register manstr_t *msp; /* per stream data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel register man_dest_t *mdp = NULL; /* destination */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DATA, ("man_start: msp(0x%p) ether_addr(%s)\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)msp, ether_sprintf(eap)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_dests == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_start: no destinations");
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Optimization if only one valid destination.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = msp->ms_destp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_UNICAST(eap)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel queue_t *flow_wq = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TDB - This needs to be optimized (some bits in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ehp->dhost will act as an index.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = &msp->ms_dests[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mdp->md_state == MAN_DSTATE_READY) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (ether_cmp(eap, &mdp->md_dst_eaddr) == 0))
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 to 1 multiplexing, use upper wq for flow control.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel flow_wq = wq;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Its going somewhere specific
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_start_lower(mdp, mp, flow_wq, MAN_UPPER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DATA, ("man_start: no destination"
193974072f41a843678abf5f61979c748687e66bSherry Moore " for eaddr %s\n", ether_sprintf(eap)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Broadcast or multicast - send everone a copy.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = &msp->ms_dests[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_state != MAN_DSTATE_READY)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((tmp = copymsg(mp)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) man_start_lower(mdp, tmp,
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, MAN_UPPER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DATA, ("man_start: copymsg"
193974072f41a843678abf5f61979c748687e66bSherry Moore " failed!"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_state == MAN_DSTATE_READY)
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_start_lower(mdp, mp, wq,
193974072f41a843678abf5f61979c748687e66bSherry Moore MAN_UPPER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 - Data xmitted
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 - Data not xmitted due to flow control.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_start_lower(man_dest_t *mdp, mblk_t *mp, queue_t *flow_wq, int caller)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel queue_t *wq = mdp->md_wq;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Lower stream ready for data transmit.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_state == MAN_DSTATE_READY &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dlpistate == DL_IDLE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_wq != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (caller == MAN_UPPER) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for flow control conditions for lower
03831d35f7499c87d51205817c93e9a8d42c4baestevel * stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_dmp_head == NULL &&
193974072f41a843678abf5f61979c748687e66bSherry Moore wq->q_first == NULL && canputnext(wq)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnext(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_dmp_head != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A simple flow control mechanism.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_dmp_count >= MAN_HIWAT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add 'mp' to the deferred
03831d35f7499c87d51205817c93e9a8d42c4baestevel * msg list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_tail->b_next = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_tail = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_count +=
193974072f41a843678abf5f61979c748687e66bSherry Moore msgsize(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Inform flow control situation
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel qenable(wq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If 1 to 1 mux, use upper write queue for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flow control.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (flow_wq != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * putbq() message and indicate
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flow control situation to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel putbq(flow_wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel qenable(flow_wq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 to many mux, use lower write queue for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flow control. Be mindful not to overflow
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the lower MAN STREAM q.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (canput(wq)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel qenable(wq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DATA, ("man_start_lower:"
193974072f41a843678abf5f61979c748687e66bSherry Moore " lower q flow controlled -"
193974072f41a843678abf5f61979c748687e66bSherry Moore " discarding packet"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_lwsrv is draining flow controlled mblks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (canputnext(wq))
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnext(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Lower stream in transition, do flow control.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_state == MAN_DSTATE_NOTPRESENT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevelnodest:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "man_start_lower: no dest for mdp(0x%p), caller(%d)!",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp, caller);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (caller == MAN_UPPER)
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_state & MAN_DSTATE_CLOSING) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DATA, ("man_start_lower: mdp(0x%p) closing",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (caller == MAN_UPPER)
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mdp->md_state & MAN_DSTATE_PLUMBING) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (mdp->md_state == MAN_DSTATE_INITIALIZING) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (mdp->md_dlpistate != DL_IDLE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Defer until PLUMBED and DL_IDLE. See man_lwsrv().
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (caller == MAN_UPPER) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Upper stream sending data down, add to defered mblk
03831d35f7499c87d51205817c93e9a8d42c4baestevel * list for stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_dmp_count >= MAN_HIWAT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_dmp_head == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_dmp_tail == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_head = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_tail = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_tail->b_next = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_tail = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_count += msgsize(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wq - upper write queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - mblk ptr to DLPI ioctl request
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_ioctl(register queue_t *wq, register mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iocblk *iocp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp = (struct iocblk *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel char ioc_cmd[30];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(ioc_cmd, "not handled IOCTL 0x%x", iocp->ioc_cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG((MAN_SWITCH | MAN_PATH | MAN_DLPI),
193974072f41a843678abf5f61979c748687e66bSherry Moore ("man_ioctl: wq(0x%p) mp(0x%p) cmd(%s)\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)wq, (void *)mp,
193974072f41a843678abf5f61979c748687e66bSherry Moore (iocp->ioc_cmd == I_PLINK) ? "I_PLINK" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (iocp->ioc_cmd == I_PUNLINK) ? "I_PUNLINK" :
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 }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Handle the requests...
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch ((unsigned int)iocp->ioc_cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case I_PLINK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_plink(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case I_PUNLINK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_unplink(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_SETPATH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_setpath(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_GETEADDR:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_geteaddr(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_SET_LINKCHECK_TIME:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_set_linkcheck_time(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_SET_SC_IPADDRS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_set_sc_ipaddrs(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_SET_SC_IP6ADDRS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_set_sc_ip6addrs(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DLIOCRAW:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_dlioc(msp, mp))
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(wq, mp, 0, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_flags |= MAN_SFLAG_RAW;
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocack(wq, mp, 0, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_IOC_HDR_INFO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dl_ioc_hdr_info(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_ND_GET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_ND_SET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_nd_getset(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DDI, ("man_ioctl: unknown ioc_cmd %d\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (unsigned int)iocp->ioc_cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(wq, mp, 0, EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG((MAN_SWITCH | MAN_PATH | MAN_DLPI), ("man_ioctl: exit\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_plink: handle I_PLINK requests on the control stream
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_plink(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct linkblk *linkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_linkrec_t *lrp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel linkp = (struct linkblk *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create a record to hold lower stream info. man_plumb will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * retrieve it after calling ldi_ioctl(I_PLINK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel lrp = man_kzalloc(sizeof (man_linkrec_t), KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (lrp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel lrp->l_muxid = linkp->l_index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel lrp->l_wq = linkp->l_qbot;
03831d35f7499c87d51205817c93e9a8d42c4baestevel lrp->l_rq = RD(linkp->l_qbot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_linkrec_insert(lrp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status)
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(wq, mp, 0, status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocack(wq, mp, 0, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_unplink - handle I_PUNLINK requests on the control stream
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_unplink(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct linkblk *linkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel linkp = (struct linkblk *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel RD(linkp->l_qbot)->q_ptr = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel WR(linkp->l_qbot)->q_ptr = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocack(wq, mp, 0, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_linkrec_insert(man_linkrec_t *lrp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel lrp->l_next = man_linkrec_head;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_linkrec_head = lrp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic queue_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_linkrec_find(int muxid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_linkrec_t *lpp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_linkrec_t *lp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel queue_t *wq = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_linkrec_head == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel lp = lpp = man_linkrec_head;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (lpp->l_muxid == muxid) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_linkrec_head = lpp->l_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (lp = lpp->l_next; lp; lp = lp->l_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (lp->l_muxid == muxid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel lpp = lp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (lp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wq = lp->l_wq;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(wq != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel lpp->l_next = lp->l_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(lp, sizeof (man_linkrec_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (wq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set instance linkcheck timer value.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_set_linkcheck_time(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_time_t *mtp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_set_linkcheck_time: enter"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = miocpullup(mp, sizeof (mi_time_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mtp = (mi_time_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_set_linkcheck_time: mtp"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_LINK, man_print_mtp(mtp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, mtp->mtp_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_linkcheck_time = mtp->mtp_time;
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error)
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(wq, mp, 0, error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocack(wq, mp, sizeof (mi_time_t), 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Man path ioctl processing. Should only happen on the SSC. Called
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with exclusive inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_setpath(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_path_t *mip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = miocpullup(mp, sizeof (mi_path_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mip = (mi_path_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = man_pg_cmd(mip, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error)
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(wq, mp, 0, error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocack(wq, mp, sizeof (mi_path_t), 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the local ethernet address of this machine.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_geteaddr(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel eaddr_t *eap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = miocpullup(mp, sizeof (eaddr_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(wq, mp, 0, error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel eap = (eaddr_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) localetheraddr(NULL, eap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocack(wq, mp, sizeof (eaddr_t), 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set my SC and other SC IPv4 addresses for use in man_pinger routine.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_set_sc_ipaddrs(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = miocpullup(mp, sizeof (man_sc_ipaddrs_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_sc_ipaddrs = *(man_sc_ipaddrs_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel char buf[INET_ADDRSTRLEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) inet_ntop(AF_INET,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *) &man_sc_ipaddrs.ip_other_sc_ipaddr,
193974072f41a843678abf5f61979c748687e66bSherry Moore buf, INET_ADDRSTRLEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("ip_other_sc_ipaddr = %s", buf));
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) inet_ntop(AF_INET,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *) &man_sc_ipaddrs.ip_my_sc_ipaddr,
193974072f41a843678abf5f61979c748687e66bSherry Moore buf, INET_ADDRSTRLEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("ip_my_sc_ipaddr = %s", buf));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error)
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(wq, mp, 0, error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocack(wq, mp, sizeof (man_sc_ipaddrs_t), 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set my SC and other SC IPv6 addresses for use in man_pinger routine.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_set_sc_ip6addrs(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = miocpullup(mp, sizeof (man_sc_ip6addrs_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_sc_ip6addrs = *(man_sc_ip6addrs_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel char buf[INET6_ADDRSTRLEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) inet_ntop(AF_INET6,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *) &man_sc_ip6addrs.ip6_other_sc_ipaddr,
193974072f41a843678abf5f61979c748687e66bSherry Moore buf, INET6_ADDRSTRLEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("ip6_other_sc_ipaddr = %s", buf));
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) inet_ntop(AF_INET6,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *) &man_sc_ip6addrs.ip6_my_sc_ipaddr,
193974072f41a843678abf5f61979c748687e66bSherry Moore buf, INET6_ADDRSTRLEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("ip6_my_sc_ipaddr = %s", buf));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error)
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(wq, mp, 0, error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocack(wq, mp, sizeof (man_sc_ip6addrs_t), 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * M_DATA fastpath info request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dl_ioc_hdr_info(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *nmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dladdr_t *dlap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dl_unitdata_req_t *dludp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ether_header *headerp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t off, len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_dl_ioc_hdr_info: enter"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = msp->ms_manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = miocpullup(mp, sizeof (dl_unitdata_req_t) + MAN_ADDRL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sanity check the DL_UNITDATA_REQ destination address
03831d35f7499c87d51205817c93e9a8d42c4baestevel * offset and length values.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel dludp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel off = dludp->dl_dest_addr_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = dludp->dl_dest_addr_length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dludp->dl_primitive != DL_UNITDATA_REQ ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel !MBLKIN(mp->b_cont, off, len) || len != MAN_ADDRL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlap = (man_dladdr_t *)(mp->b_cont->b_rptr + off);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate a new mblk to hold the ether header.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((nmp = allocb(ETHERHEADER_SIZE, BPRI_MED)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* We only need one dl_ioc_hdr mblk for replay */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(msp->ms_flags & MAN_SFLAG_FAST))
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_dl_catch(&msp->ms_dlioc_mp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Forward the packet to all lower destinations. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((status != 0) || ((status = man_dlpi_senddown(msp, mp)) != 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(nmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nmp->b_wptr += ETHERHEADER_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Fill in the ether header.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel headerp = (struct ether_header *)nmp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&dlap->dl_phys, &headerp->ether_dhost);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&manp->man_eaddr, &headerp->ether_shost);
03831d35f7499c87d51205817c93e9a8d42c4baestevel put_ether_type(headerp, dlap->dl_sap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Link new mblk in after the "request" mblks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel linkb(mp, nmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_dl_ioc_hdr_info: returns, status = %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(wq, mp, 0, status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_flags |= MAN_SFLAG_FAST;
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocack(wq, mp, msgsize(mp->b_cont), 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wq - upper write queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_uwsrv(queue_t *wq)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp; /* per stream data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp; /* per instance data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ehdr_t *ep;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_UWSRV, ("man_uwsrv: wq(0x%p) msp", (void *)wq));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_UWSRV, man_print_msp(msp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto done;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = msp->ms_manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mp = getq(wq)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (DB_TYPE(mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Can probably remove this as I never put data messages
03831d35f7499c87d51205817c93e9a8d42c4baestevel * here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_DATA:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ep = (ehdr_t *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_start(wq, mp, &ep->ether_dhost);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_start() indicated flow control
03831d35f7499c87d51205817c93e9a8d42c4baestevel * situation, stop processing now.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto break_loop;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_PROTO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_PCPROTO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_proto(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_proto() indicated flow control
03831d35f7499c87d51205817c93e9a8d42c4baestevel * situation detected by man_start(),
03831d35f7499c87d51205817c93e9a8d42c4baestevel * stop processing now.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto break_loop;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_UWSRV, ("man_uwsrv: discarding mp(0x%p)",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelbreak_loop:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check to see if bgthread wants us to do something inside the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((msp->ms_flags & MAN_SFLAG_CONTROL) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore man_iwork_q->q_work != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_iwork();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveldone:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_UWSRV, ("man_uwsrv: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wq - upper write queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - mbl ptr to protocol request
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_proto(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int flow_status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG((MAN_UWSRV | MAN_DLPI),
193974072f41a843678abf5f61979c748687e66bSherry Moore ("man_proto: mp(0x%p) prim(%s)\n", (void *)mp,
193974072f41a843678abf5f61979c748687e66bSherry Moore dps[dlp->dl_primitive]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (dlp->dl_primitive) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_UNITDATA_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel flow_status = man_udreq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_ATTACH_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_areq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_DETACH_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dreq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_BIND_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_breq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_UNBIND_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_ubreq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_INFO_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_ireq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PROMISCON_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_ponreq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PROMISCOFF_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_poffreq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_ENABMULTI_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_emreq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_DISABMULTI_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dmreq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PHYS_ADDR_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pareq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_SET_PHYS_ADDR_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_spareq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG((MAN_UWSRV | MAN_DLPI), ("man_proto: prim(%d)\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore dlp->dl_primitive));
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, dlp->dl_primitive, DL_UNSUPPORTED, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } /* End switch */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG((MAN_UWSRV | MAN_DLPI), ("man_proto: exit\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (flow_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_udreq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dl_unitdata_req_t *dludp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *nmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dladdr_t *dlap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t off, len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int flow_status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_dlpistate != DL_IDLE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (flow_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel dludp = (dl_unitdata_req_t *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel off = dludp->dl_dest_addr_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = dludp->dl_dest_addr_length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Validate destination address format.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!MBLKIN(mp, off, len) || (len != MAN_ADDRL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADADDR, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (flow_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Error if no M_DATA follows.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nmp = mp->b_cont;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (nmp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADDATA, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (flow_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlap = (man_dladdr_t *)(mp->b_rptr + off);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel flow_status = man_start(wq, mp, &dlap->dl_phys);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (flow_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Handle DL_ATTACH_REQ.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_areq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp; /* per instance data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp; /* per stream data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel short ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *preq = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int did_refcnt = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int dlerror = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attach us to MAN PPA (device instance).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MBLKL(mp) < DL_ATTACH_REQ_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerror = DL_BADPRIM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_dlpistate != DL_UNATTACHED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerror = DL_OUTSTATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ppa = dlp->attach_req.dl_ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ppa == -1 || qassociate(wq, ppa) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerror = DL_BADPPA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_WARN, ("man_areq: bad PPA %d", ppa));
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(manp != NULL); /* qassociate() succeeded */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_refcnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel did_refcnt = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel preq = man_alloc_physreq_mp(&manp->man_eaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (preq == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerror = DL_SYSERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make copy for dlpi resync of upper and lower streams.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_dlpi(msp, mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerror = DL_SYSERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* TBD - need to clean off ATTACH req on failure here. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_dlpi(msp, preq)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerror = DL_SYSERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_init_dests/man_start_dest needs these set before call.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_manp = manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_meta_ppa = ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate and init lower destination structures.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(msp->ms_dests == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_init_dests(manp, msp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we cant get the lower streams ready, then
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remove the messages from the DL replay list and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fail attach.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((tmp = msp->ms_dl_mp) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_dl_mp = msp->ms_dl_mp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp->b_next = tmp->b_prev = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(tmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_manp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_meta_ppa = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerror = DL_SYSERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_areq: ppa 0x%x man_refcnt: %d\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ppa, manp->man_refcnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SETSTATE(msp, DL_UNBOUND);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dlerror == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlokack(wq, mp, DL_ATTACH_REQ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (did_refcnt) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_refcnt--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ATTACH_REQ, dlerror, status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) qassociate(wq, -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (preq != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(preq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called at DL_ATTACH time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Man_lock is held to protect pathgroup list(man_pg).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_init_dests(man_t *manp, manstr_t *msp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = man_kzalloc(MAN_DEST_ARRAY_SIZE, KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_dests = mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp[i].md_muxid = -1; /* muxid 0 is valid */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&mdp->md_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(manp->man_pg, i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg && man_find_active_path(mpg->mpg_pathp))
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_start_dest(&mdp[i], msp, mpg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get a destination ready for use.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_start_dest(man_dest_t *mdp, manstr_t *msp, man_pg_t *mpg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *ap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_muxid = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dlpistate = DL_UNATTACHED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_msp = msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_rq = msp->ms_rq;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_pg_id = mpg->mpg_pg_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(msp->ms_manp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&msp->ms_manp->man_eaddr, &mdp->md_src_eaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&mpg->mpg_dst_eaddr, &mdp->md_dst_eaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ap = man_find_active_path(mpg->mpg_pathp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(ap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_device = ap->mp_device;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set up linktimers so that first time through, we will do
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a failover.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_linkstate = MAN_LINKFAIL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_state = MAN_DSTATE_INITIALIZING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_linkcheck_timer,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp, man_gettimer(MAN_TIMER_INIT, mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * As an optimization, if there is only one destination,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remember the destination pointer. Used by man_start().
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_set_optimized_dest(msp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DEST, ("man_start_dest: mdp"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_DEST, man_print_mdp(mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_set_optimized_dest(manstr_t *msp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int count = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_dests[i].md_msp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel count++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = &msp->ms_dests[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (count == 1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_destp = mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_destp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Catch dlpi message for replaying, and arrange to send it down
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to any destinations not PLUMBING. See man_dlpi_replay().
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dlpi(manstr_t *msp, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_dl_catch(&msp->ms_dl_mp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_dlpi_senddown(msp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Catch IOCTL type DL_ messages.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dlioc(manstr_t *msp, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_dl_catch(&msp->ms_dlioc_mp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_dlpi_senddown(msp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * msp - pointer of stream struct to process
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mblk - pointer to DLPI request to catch
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dl_catch(mblk_t **mplist, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *dupmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel unsigned prim;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dupmp = copymsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dupmp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*mplist == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mplist = dupmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (tmp = *mplist; tmp->b_next; )
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = tmp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp->b_next = dupmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prim = DL_PRIM(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI,
193974072f41a843678abf5f61979c748687e66bSherry Moore ("man_dl_catch: adding %s\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (prim == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (prim == DLIOCRAW) ? "DLIOCRAW" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (prim == DL_PROMISCON_REQ) ? promisc[DL_PROMISCON_TYPE(mp)] :
193974072f41a843678abf5f61979c748687e66bSherry Moore dps[prim]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send down a single DLPI M_[PC]PROTO to all currently valid dests.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * msp - ptr to NDM stream structure DL_ messages was received on.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - ptr to mblk containing DL_ request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dlpi_senddown(manstr_t *msp, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *rmp[MAN_MAX_DESTS]; /* Copy to replay */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int dstate[MAN_MAX_DESTS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int no_dests = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_dests == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = &msp->ms_dests[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_state == MAN_DSTATE_READY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dstate[i] = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel no_dests = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dstate[i] = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmp[i] = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (no_dests)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Build replay and duplicate list for all possible destinations.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dstate[i]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmp[i] = copymsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rmp[i] == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_DESTS; i++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dstate[i]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = &msp->ms_dests[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_wq != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mp->b_next == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mp->b_prev == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dlpi_replay(mdp, rmp[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i >= 0; i--)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dstate[i] && rmp[i])
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(rmp[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mdp - pointer to lower queue (destination)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rmp - list of mblks to send down stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dlpi_replay(man_dest_t *mdp, mblk_t *rmp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_dlpi_replay: mdp(0x%p)", (void *)mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rmp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = rmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmp = rmp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_prev = mp->b_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI,
193974072f41a843678abf5f61979c748687e66bSherry Moore ("man_dlpi_replay: mdp(0x%p) sending %s\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp,
193974072f41a843678abf5f61979c748687e66bSherry Moore (dlp->dl_primitive == DL_IOC_HDR_INFO) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore "DL_IOC_HDR_INFO" : (dlp->dl_primitive == DLIOCRAW) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore "DLIOCRAW" : dps[(unsigned)(dlp->dl_primitive)]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dlp->dl_primitive == DL_ATTACH_REQ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * insert the lower devices ppa.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp->attach_req.dl_ppa = mdp->md_device.mdev_ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnext(mdp->md_wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dreq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp; /* per stream data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_t *wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MBLKL(mp) < DL_DETACH_REQ_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_dlpistate != DL_UNBOUND) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_DETACH_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(msp->ms_dests != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_work_alloc(MAN_WORK_CLOSE_STREAM, KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_DETACH_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dodetach(msp, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) qassociate(wq, -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SETSTATE(msp, DL_UNATTACHED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlokack(wq, mp, DL_DETACH_REQ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dl_clean(mblk_t **mplist)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Toss everything.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((tmp = *mplist) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mplist = (*mplist)->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp->b_next = tmp->b_prev = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(tmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dl_release(mblk_t **mplist, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t match_dbtype;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *tmpp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int matched = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*mplist == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel match_dbtype = DB_TYPE(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (match_dbtype != M_PROTO && match_dbtype != M_PCPROTO) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Selectively find a caught mblk that matches this one and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remove it from the list
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = tmpp = *mplist;
03831d35f7499c87d51205817c93e9a8d42c4baestevel matched = man_match_proto(mp, tmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (matched) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mplist = tmp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp->b_next = tmp->b_prev = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (tmp = tmp->b_next; tmp != NULL; tmp = tmp->b_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (matched = man_match_proto(mp, tmp))
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmpp = tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (matched) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmpp->b_next = tmp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp->b_next = tmp->b_prev = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (matched) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_dl_release: release %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore (DL_PRIM(mp) == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (DL_PRIM(mp) == DLIOCRAW) ? "DLIOCRAW" :
193974072f41a843678abf5f61979c748687e66bSherry Moore dps[(int)DL_PRIM(mp)]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(tmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_dl_release: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Compare two DL_ messages. If they are complimentary (e.g. DL_UNBIND
03831d35f7499c87d51205817c93e9a8d42c4baestevel * compliments DL_BIND), return true.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_match_proto(mblk_t *mp1, mblk_t *mp2)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t prim1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t prim2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int matched = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Primitive to clean off list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel prim1 = DL_PRIM(mp1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel prim2 = DL_PRIM(mp2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (prim1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_UNBIND_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prim2 == DL_BIND_REQ)
03831d35f7499c87d51205817c93e9a8d42c4baestevel matched = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PROMISCOFF_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prim2 == DL_PROMISCON_REQ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dl_promiscoff_req_t *poff1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dl_promiscoff_req_t *poff2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel poff1 = (dl_promiscoff_req_t *)mp1->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel poff2 = (dl_promiscoff_req_t *)mp2->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (poff1->dl_level == poff2->dl_level)
03831d35f7499c87d51205817c93e9a8d42c4baestevel matched = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_DISABMULTI_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prim2 == DL_ENABMULTI_REQ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t off;
03831d35f7499c87d51205817c93e9a8d42c4baestevel eaddr_t *addrp1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel eaddr_t *addrp2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp1->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel off = dlp->disabmulti_req.dl_addr_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel addrp1 = (eaddr_t *)(mp1->b_rptr + off);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp2->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel off = dlp->disabmulti_req.dl_addr_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel addrp2 = (eaddr_t *)(mp2->b_rptr + off);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ether_cmp(addrp1, addrp2) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel matched = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_match_proto returns %d", matched));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (matched);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Bind upper stream to a particular SAP. Called with exclusive innerperim
03831d35f7499c87d51205817c93e9a8d42c4baestevel * QPAIR, shared outerperim.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_breq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp; /* per instance data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp; /* per stream data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dladdr_t man_addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t sap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t xidtest;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MBLKL(mp) < DL_BIND_REQ_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_BIND_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_dlpistate != DL_UNBOUND) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = msp->ms_manp; /* valid after attach */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sap = dlp->bind_req.dl_sap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel xidtest = dlp->bind_req.dl_xidtest_flg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(manp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (xidtest) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_BIND_REQ, DL_NOAUTO, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sap > ETHERTYPE_MAX) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_BIND_REQ, DL_BADSAP, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_dlpi(msp, mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_BIND_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_sap = sap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SETSTATE(msp, DL_IDLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_addr.dl_sap = msp->ms_sap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&msp->ms_manp->man_eaddr, &man_addr.dl_phys);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlbindack(wq, mp, msp->ms_sap, &man_addr, MAN_ADDRL, 0, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_ubreq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp; /* per stream data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MBLKL(mp) < DL_UNBIND_REQ_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_UNBIND_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_dlpistate != DL_IDLE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_dlpi_senddown(msp, mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_UNBIND_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dl_release(&msp->ms_dl_mp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SETSTATE(msp, DL_UNBOUND);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlokack(wq, mp, DL_UNBIND_REQ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_ireq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dl_info_ack_t *dlip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dladdr_t *dlap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel eaddr_t *ep;
03831d35f7499c87d51205817c93e9a8d42c4baestevel size_t size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MBLKL(mp) < DL_INFO_REQ_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_INFO_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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 if (mp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_ireq: man_ireq: mp == NULL."));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Fill in the DL_INFO_ACK fields and reply. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlip = (dl_info_ack_t *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *dlip = man_infoack;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlip->dl_current_state = msp->ms_dlpistate;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlap = (man_dladdr_t *)(mp->b_rptr + dlip->dl_addr_offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlap->dl_sap = msp->ms_sap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If attached, return physical address.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_manp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&msp->ms_manp->man_eaddr, &dlap->dl_phys);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero((caddr_t)&dlap->dl_phys, ETHERADDRL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ep = (struct ether_addr *)(mp->b_rptr + dlip->dl_brdcst_addr_offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&etherbroadcast, ep);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel qreply(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_ponreq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int flag;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MBLKL(mp) < DL_PROMISCON_REQ_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCON_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (((dl_promiscon_req_t *)mp->b_rptr)->dl_level) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PROMISC_PHYS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel flag = MAN_SFLAG_ALLPHYS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PROMISC_SAP:
03831d35f7499c87d51205817c93e9a8d42c4baestevel flag = MAN_SFLAG_ALLSAP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PROMISC_MULTI:
03831d35f7499c87d51205817c93e9a8d42c4baestevel flag = MAN_SFLAG_ALLMULTI;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Catch request for replay, and forward down to any lower
03831d35f7499c87d51205817c93e9a8d42c4baestevel * lower stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_dlpi(msp, mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCON_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_flags |= flag;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlokack(wq, mp, DL_PROMISCON_REQ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_poffreq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int flag;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MBLKL(mp) < DL_PROMISCOFF_REQ_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (((dl_promiscoff_req_t *)mp->b_rptr)->dl_level) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PROMISC_PHYS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel flag = MAN_SFLAG_ALLPHYS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PROMISC_SAP:
03831d35f7499c87d51205817c93e9a8d42c4baestevel flag = MAN_SFLAG_ALLSAP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PROMISC_MULTI:
03831d35f7499c87d51205817c93e9a8d42c4baestevel flag = MAN_SFLAG_ALLMULTI;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((msp->ms_flags & flag) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_dlpi_senddown(msp, mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dl_release(&msp->ms_dl_mp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp->ms_flags &= ~flag;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlokack(wq, mp, DL_PROMISCOFF_REQ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Enable multicast requests. We might need to track addresses instead of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * just passing things through (see eri_dmreq) - TBD.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_emreq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel eaddr_t *addrp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t off;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MBLKL(mp) < DL_ENABMULTI_REQ_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_dlpistate == DL_UNATTACHED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = dlp->enabmulti_req.dl_addr_length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel off = dlp->enabmulti_req.dl_addr_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel addrp = (struct ether_addr *)(mp->b_rptr + off);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((len != ETHERADDRL) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore !MBLKIN(mp, off, len) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore ((addrp->ether_addr_octet[0] & 01) == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Catch request for replay, and forward down to any lower
03831d35f7499c87d51205817c93e9a8d42c4baestevel * lower stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_dlpi(msp, mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlokack(wq, mp, DL_ENABMULTI_REQ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dmreq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel eaddr_t *addrp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t off;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MBLKL(mp) < DL_DISABMULTI_REQ_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_DISABMULTI_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_dlpistate == DL_UNATTACHED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = dlp->enabmulti_req.dl_addr_length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel off = dlp->enabmulti_req.dl_addr_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel addrp = (struct ether_addr *)(mp->b_rptr + off);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((len != ETHERADDRL) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore !MBLKIN(mp, off, len) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore ((addrp->ether_addr_octet[0] & 01) == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_dlpi_senddown(msp, mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dl_release(&msp->ms_dl_mp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlokack(wq, mp, DL_DISABMULTI_REQ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pareq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ether_addr addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MBLKL(mp) < DL_PHYS_ADDR_REQ_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel type = dlp->physaddr_req.dl_addr_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_manp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_FACT_PHYS_ADDR:
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) localetheraddr((struct ether_addr *)NULL, &addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_CURR_PHYS_ADDR:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_bcopy(&msp->ms_manp->man_eaddr, &addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_NOTSUPPORTED, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlphysaddrack(wq, mp, &addr, ETHERADDRL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TBD - this routine probably should be protected w/ an ndd
03831d35f7499c87d51205817c93e9a8d42c4baestevel * tuneable, or a man.conf parameter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_spareq(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t off;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel eaddr_t *addrp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = (manstr_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MBLKL(mp) < DL_SET_PHYS_ADDR_REQ_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = dlp->set_physaddr_req.dl_addr_length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel off = dlp->set_physaddr_req.dl_addr_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!MBLKIN(mp, off, len)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel addrp = (struct ether_addr *)(mp->b_rptr + off);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Error if length of address isn't right or the address
03831d35f7499c87d51205817c93e9a8d42c4baestevel * specified is a multicast or broadcast address.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((len != ETHERADDRL) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore ((addrp->ether_addr_octet[0] & 01) == 1) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (ether_cmp(addrp, &etherbroadcast) == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Error if this stream is not attached to a device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_manp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We will also resend DL_SET_PHYS_ADDR_REQ for each dest
03831d35f7499c87d51205817c93e9a8d42c4baestevel * when it is linked under us.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_dlpi_senddown(msp, mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_SYSERR, ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(addrp, msp->ms_manp->man_eaddr.ether_addr_octet);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_sareq: snagged %s\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ether_sprintf(&msp->ms_manp->man_eaddr)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlokack(wq, mp, DL_SET_PHYS_ADDR_REQ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These routines make up the lower part of the MAN streams framework.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wq - lower write queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_lwsrv(queue_t *wq)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mlistp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel size_t count;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = (man_dest_t *)wq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LWSRV, ("man_lwsrv: wq(0x%p) mdp(0x%p)"
193974072f41a843678abf5f61979c748687e66bSherry Moore " md_rq(0x%p)\n", (void *)wq, (void *)mdp,
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp ? (void *)mdp->md_rq : NULL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_state & MAN_DSTATE_CLOSING) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel flushq(wq, FLUSHDATA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel flushq(RD(wq), FLUSHDATA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mlistp = mdp->md_dmp_head;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_head = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel count = mdp->md_dmp_count;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_count = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mlistp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mlistp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mlistp = mp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel count -= msgsize(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_start_lower(mdp, mp, NULL, MAN_LOWER)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_count += count + msgsize(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_next = mlistp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_head = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_tail = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mp = getq(wq)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_start_lower(mdp, mp, NULL, MAN_LOWER)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Put it back on queue, making sure to avoid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * infinite loop mentioned in putbq(9F)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel noenable(wq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel putbq(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel enableok(wq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_lrput - handle DLPI messages issued from downstream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rq - lower read queue of mxx
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp - mblk ptr to DLPI request
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_lrput(queue_t *rq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t prim = MAN_DLPI_MAX_PRIM + 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *prim_str;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = (man_dest_t *)rq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DB_TYPE(mp) == M_PROTO) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel prim = dlp->dl_primitive;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prim_str = (prim > MAN_DLPI_MAX_PRIM) ? "NON DLPI" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (prim == DL_IOC_HDR_INFO) ? "DL_IOC_HDR_INFO" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (prim == DLIOCRAW) ? "DLIOCRAW" :
193974072f41a843678abf5f61979c748687e66bSherry Moore dps[(unsigned int)prim];
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRPUT, ("man_lrput: rq(0x%p) mp(0x%p) mdp(0x%p)"
193974072f41a843678abf5f61979c748687e66bSherry Moore " db_type(0x%x) dl_prim %s", (void *)rq,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mp, (void *)mdp, DB_TYPE(mp), prim_str));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_LRPUT2, man_print_mdp(mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (DB_TYPE(mp) == M_FLUSH) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Turn around */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*mp->b_rptr & FLUSHW) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mp->b_rptr &= ~FLUSHR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel qreply(rq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp == NULL || mdp->md_state != MAN_DSTATE_READY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRPUT, ("man_lrput: not ready mdp(0x%p),"
193974072f41a843678abf5f61979c748687e66bSherry Moore " state(%d)", (void *)mdp, mdp ? mdp->md_state : -1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we have a destination in the right state, forward on datagrams.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MAN_IS_DATA(mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_dlpistate == DL_IDLE && canputnext(mdp->md_rq)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = mdp->md_msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(msp->ms_flags & MAN_SFLAG_PROMISC))
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_rcvcnt++; /* Count for failover */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * go put mblk_t directly up to next queue.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRPUT, ("man_lrput: putnext to rq(0x%p)",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp->md_rq));
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnext(mdp->md_rq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Handle in man_lrsrv with exclusive inner perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel putq(rq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_lrsrv(queue_t *rq)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ulong_t prim;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ulong_t cprim;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int need_dl_reset = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iocblk *iocp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char ioc_cmd[256];
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRSRV, ("man_lrsrv: rq(0x%p)", (void *)rq));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = (man_dest_t *)rq->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mdp == NULL) || (mdp->md_state & MAN_DSTATE_CLOSING)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel flushq(rq, FLUSHDATA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel flushq(WR(rq), FLUSHDATA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mp = getq(rq)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we're not connected, or its a datagram, toss it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (MAN_IS_DATA(mp) || mdp->md_state != MAN_DSTATE_READY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRSRV, ("man_lrsrv: dropping mblk mdp(0x%p)"
193974072f41a843678abf5f61979c748687e66bSherry Moore " is_data(%d)", (void *)mdp, MAN_IS_DATA(mp)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Should be response to man_dlpi_replay. Discard unless there
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is a failure we care about.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (DB_TYPE(mp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_PROTO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_PCPROTO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Do proto processing below. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_IOCNAK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DL_IOC* failed for some reason.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel need_dl_reset = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp = (struct iocblk *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(ioc_cmd, "0x%x", iocp->ioc_cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRSRV, ("man_lrsrv: M_IOCNAK err %d for cmd(%s)\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore iocp->ioc_error,
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* FALLTHRU */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_IOCACK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_CTL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OK response from DL_IOC*, ignore.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto dl_reset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel prim = dlp->dl_primitive;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LRSRV, ("man_lrsrv: prim %s", dps[(int)prim]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DLPI state processing big theory: We do not rigorously check
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DLPI states (e.g. PENDING stuff). Simple rules:
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Everything that isn't handle by 1-4 above is handled by 5)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 5) A NAK to any DL_* messages we care about causes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * dlpistate = DL_UNATTACHED and man_reset_dlpi to run
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TBD - need a reset counter so we can try a switch if it gets
03831d35f7499c87d51205817c93e9a8d42c4baestevel * too high.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (prim) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_OK_ACK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cprim = dlp->ok_ack.dl_correct_primitive;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cprim) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_ATTACH_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_dlioc_replay(mdp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel D_SETSTATE(mdp, DL_UNBOUND);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel need_dl_reset = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_DETACH_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel D_SETSTATE(mdp, DL_UNATTACHED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_UNBIND_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Cancel timer and set md_dlpistate.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel D_SETSTATE(mdp, DL_UNBOUND);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_bc_id == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_lc_timer_id != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) quntimeout(man_ctl_wq,
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_lc_timer_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI,
193974072f41a843678abf5f61979c748687e66bSherry Moore (" cprim %s", dps[(int)cprim]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_BIND_ACK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We're ready for data. Get man_lwsrv to run to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * process any defered data and start linkcheck timer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel D_SETSTATE(mdp, DL_IDLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel qenable(mdp->md_wq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_linkstate = MAN_LINKGOOD;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_needs_linkcheck(mdp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = qtimeout(man_ctl_wq,
193974072f41a843678abf5f61979c748687e66bSherry Moore man_linkcheck_timer, (void *)mdp,
193974072f41a843678abf5f61979c748687e66bSherry Moore man_gettimer(MAN_TIMER_LINKCHECK, mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_ERROR_ACK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cprim = dlp->error_ack.dl_error_primitive;
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cprim) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_ATTACH_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_BIND_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_DISABMULTI_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_ENABMULTI_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PROMISCON_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_PROMISCOFF_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_SET_PHYS_ADDR_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel need_dl_reset = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ignore error TBD (better comment)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_UNBIND_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_DETACH_REQ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI,
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 dps[(int)cprim]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_UDERROR_IND:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI,
193974072f41a843678abf5f61979c748687e66bSherry Moore ("\tdl_errno %d unix_errno %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore dlp->uderror_ind.dl_errno,
193974072f41a843678abf5f61979c748687e66bSherry Moore dlp->uderror_ind.dl_unix_errno));
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DL_INFO_ACK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We should not get here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_lrsrv: unexpected DL prim 0x%lx!",
193974072f41a843678abf5f61979c748687e66bSherry Moore prim);
03831d35f7499c87d51205817c93e9a8d42c4baestevel need_dl_reset = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveldl_reset:
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (need_dl_reset) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (qsize(rq)) { /* Dump all messages. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel flushq(rq, FLUSHDATA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel flushq(WR(rq), FLUSHDATA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dlpierrors++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel D_SETSTATE(mdp, DL_UNATTACHED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_lc_timer_id != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) quntimeout(man_ctl_wq, mdp->md_lc_timer_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_msp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_msp->ms_manp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(mdp->md_msp->ms_manp->man_pg,
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mpg != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = man_find_path_by_ppa(mpg->mpg_pathp,
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_device.mdev_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_device.mdev_state |= MDEV_FAILED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mdp->md_dlpierrors >= MAN_MAX_DLPIERRORS) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (man_is_on_domain ||
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_msp->ms_manp->man_meta_ppa == 1)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Autoswitching is disabled for instance 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on the SC as we expect the domain to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initiate the path switching.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) man_do_autoswitch((man_dest_t *)mdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_WARN, ("man_lrsrv: dlpi failure(%d,%d),"
193974072f41a843678abf5f61979c748687e66bSherry Moore " switching path", mdp->md_device.mdev_major,
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_device.mdev_ppa));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = qtimeout(man_ctl_wq,
193974072f41a843678abf5f61979c748687e66bSherry Moore man_reset_dlpi, (void *)mdp,
193974072f41a843678abf5f61979c748687e66bSherry Moore man_gettimer(MAN_TIMER_DLPIRESET, mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } /* End while (getq()) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_lrsrv: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_needs_linkcheck(man_dest_t *mdp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Not ready for linkcheck.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_msp == NULL || mdp->md_msp->ms_manp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((man_is_on_domain || mdp->md_msp->ms_manp->man_meta_ppa == 1) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (mdp->md_msp->ms_sap == ETHERTYPE_IP ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_msp->ms_sap == ETHERTYPE_IPV6))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Linkcheck not need on this link.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_iwork()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_t *wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int wp_finished;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_iwork: q_work(0x%p)",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)man_iwork_q->q_work));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (man_iwork_q->q_work) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_iwork_q->q_work;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_iwork_q->q_work = wp->mw_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_iwork: type %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore _mw_type[wp->mw_type]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp_finished = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (wp->mw_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_WORK_DRATTACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) man_do_dr_attach(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_WORK_DRSWITCH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_do_dr_switch(wp) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp_finished = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_WORK_DRDETACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_do_dr_detach(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_WORK_SWITCH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_iswitch(wp))
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp_finished = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_WORK_KSTAT_UPDATE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_do_kstats(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_iwork: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "illegal work type(%d)", wp->mw_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we've completed the work request, delete, or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cv_signal waiter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wp_finished) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_flags |= MAN_WFLAGS_DONE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wp->mw_flags & MAN_WFLAGS_CVWAITER)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&wp->mw_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_free(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called holding inner perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_lock is held to synchronize access to pathgroup list(man_pg).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_do_dr_switch(man_work_t *wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *ap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_adest_t *adp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_path_t mpath;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel adp = &wp->mw_arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_do_dr_switch: pg_id %d work:", adp->a_pg_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_SWITCH, man_print_work(wp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp == NULL || manp->man_pg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(manp->man_pg, adp->a_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg->mpg_flags & MAN_PG_SWITCHING) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check to see if detaching device is active. If so, activate
03831d35f7499c87d51205817c93e9a8d42c4baestevel * an alternate.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = man_find_active_path(mpg->mpg_pathp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp && mp->mp_device.mdev_ppa == adp->a_sf_dev.mdev_ppa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ap = man_find_alternate_path(mpg->mpg_pathp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ap == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EBUSY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero((char *)&mpath, sizeof (mi_path_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_cmd = MI_PATH_ACTIVATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_man_ppa = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_pg_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_devs[0] = ap->mp_device;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_ndevs = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&manp->man_eaddr, &mpath.mip_eaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_type = MAN_WORK_SWITCH;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status = man_pg_cmd(&mpath, wp))
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Tell man_dr_detach that detaching device is not currently
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in use.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ENODEV is a noop, not really an error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != ENODEV)
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_status = status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_dr_attach has submitted a request to DRATTACH a path,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * add that path to the path list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called holding perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_do_dr_attach(man_work_t *wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_adest_t *adp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_path_t mpath;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manc_t manc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel adp = &wp->mw_arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_do_dr_attach: pg_id %d work:", adp->a_pg_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_SWITCH, man_print_work(wp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp == NULL || manp->man_pg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status = man_get_iosram(&manc)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Extract SC ethernet address from IOSRAM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&manc.manc_sc_eaddr, &mpath.mip_eaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_pg_id = adp->a_pg_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_man_ppa = adp->a_man_ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_dr_attach passes the new device info in a_sf_dev.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DR, ("man_do_dr_attach: "));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_DR, man_print_dev(&adp->a_sf_dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_devs[0] = adp->a_sf_dev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_ndevs = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_cmd = MI_PATH_ADD;
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_pg_cmd(&mpath, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called holding perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_do_dr_detach(man_work_t *wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_adest_t *adp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manc_t manc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_path_t mpath;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int found;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel adp = &wp->mw_arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_do_dr_detach: pg_id %d work:", adp->a_pg_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_SWITCH, man_print_work(wp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp == NULL || manp->man_pg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(manp->man_pg, adp->a_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg->mpg_flags & MAN_PG_SWITCHING) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We should have switched detaching path if it was active.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = man_find_active_path(mpg->mpg_pathp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp && mp->mp_device.mdev_ppa == adp->a_sf_dev.mdev_ppa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Submit an ASSIGN command, minus the detaching device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero((char *)&mpath, sizeof (mi_path_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status = man_get_iosram(&manc)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_cmd = MI_PATH_ASSIGN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_man_ppa = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_pg_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mpg->mpg_pathp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel found = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->mp_device.mdev_ppa != adp->a_sf_dev.mdev_ppa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_devs[i] = mp->mp_device;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel found = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mp->mp_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (found) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Need to include SCs ethernet address in command.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_ndevs = i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&manc.manc_sc_eaddr, &mpath.mip_eaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_pg_cmd(&mpath, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hand back status to man_dr_detach request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != ENODEV)
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_status = status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 Done with work request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 Reused work request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_iswitch(man_work_t *wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_adest_t *adp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *tdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int switch_ok = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel adp = &wp->mw_arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wp->mw_status != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch_ok = FALSE; /* Never got things opened */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Update destination structures as appropriate.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < adp->a_ndests; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check to see if lower stream we just switch is still
03831d35f7499c87d51205817c93e9a8d42c4baestevel * around.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp = &adp->a_mdp[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = man_switch_match(tdp, adp->a_pg_id, tdp->md_switch_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (switch_ok == FALSE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Switch failed for some reason. Clear
03831d35f7499c87d51205817c93e9a8d42c4baestevel * PLUMBING flag and retry switch again later.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_ifail_dest(mdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Swap new info, for old. We return the old info to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_bwork to close things up below.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy((char *)mdp, (char *)&tmp, sizeof (man_dest_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_state & MAN_DSTATE_PLUMBING);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_state == tdp->md_state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_state = tdp->md_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * save the wq from the destination passed(tdp).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_wq = tdp->md_wq;
03831d35f7499c87d51205817c93e9a8d42c4baestevel RD(mdp->md_wq)->q_ptr = (void *)(mdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel WR(mdp->md_wq)->q_ptr = (void *)(mdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_state &= ~MAN_DSTATE_INITIALIZING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_state |= MAN_DSTATE_READY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_device.mdev_major == adp->a_sf_dev.mdev_major);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_device = tdp->md_device;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_muxid = tdp->md_muxid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_linkstate = MAN_LINKUNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) drv_getparm(TIME, &mdp->md_lastswitch);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_state &= ~MAN_DSTATE_PLUMBING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_switch_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_switches++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dlpierrors = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel D_SETSTATE(mdp, DL_UNATTACHED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_reset_dlpi((void *)mdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy((char *)&tmp, (char *)tdp, sizeof (man_dest_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (switch_ok) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < adp->a_ndests; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp = &adp->a_mdp[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp->md_state &= ~MAN_DSTATE_PLUMBING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp->md_state &= ~MAN_DSTATE_INITIALIZING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp->md_state |= MAN_DSTATE_READY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Never got switch-to destinations open, free them.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(adp->a_mdp,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (man_dest_t) * adp->a_ndests);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear pathgroup switching flag and update path flags.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(manp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(manp->man_pg != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(manp->man_pg, adp->a_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mpg != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mpg->mpg_flags & MAN_PG_SWITCHING);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg->mpg_flags &= ~MAN_PG_SWITCHING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (switch_ok) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = man_find_active_path(mpg->mpg_pathp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(adp->a_sf_dev.mdev_major != 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_iswitch: switch from dev:"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_SWITCH, man_print_dev(&adp->a_sf_dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_device.mdev_state &= ~MDEV_ACTIVE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(adp->a_sf_dev.mdev_major == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_iswitch: switch to dev:"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_SWITCH, man_print_dev(&adp->a_st_dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(adp->a_st_dev.mdev_major != 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = man_find_path_by_ppa(mpg->mpg_pathp,
193974072f41a843678abf5f61979c748687e66bSherry Moore adp->a_st_dev.mdev_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_device.mdev_state |= MDEV_ACTIVE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Decrement manp reference count and hand back work request if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * needed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_refcnt--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (switch_ok) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_type = MAN_WORK_CLOSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_add(man_bwork_q, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (switch_ok);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find the destination in the upper stream that we just switched.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dest_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_switch_match(man_dest_t *sdp, int pg_id, void *sid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check if upper stream closed, or detached.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp != sdp->md_msp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp->ms_dests == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = &msp->ms_dests[pg_id];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Upper stream detached and reattached while we were
03831d35f7499c87d51205817c93e9a8d42c4baestevel * switching.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_switch_id != sid) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bg_thread cant complete the switch for some reason. (Re)start the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * linkcheck timer again.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_ifail_dest(man_dest_t *mdp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_lc_timer_id == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_bc_id == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_state & MAN_DSTATE_PLUMBING);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_ifail_dest"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_SWITCH, man_print_mdp(mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_state &= ~MAN_DSTATE_PLUMBING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_linkstate = MAN_LINKFAIL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we have not yet initialized link, or the upper stream is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DL_IDLE, restart the linktimer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mdp->md_state & MAN_DSTATE_INITIALIZING) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore ((mdp->md_msp->ms_sap == ETHERTYPE_IPV6 ||
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_msp->ms_sap == ETHERTYPE_IP) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_msp->ms_dlpistate == DL_IDLE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_linkcheck_timer,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp, man_gettimer(MAN_TIMER_LINKCHECK, mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called from qtimeout with inner perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_reset_dlpi(void *argp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp = (man_dest_t *)argp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *rmp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_state != MAN_DSTATE_READY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_reset_dlpi: not ready!"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msp = mdp->md_msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmp = man_dup_mplist(msp->ms_dl_mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rmp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto fail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = man_alloc_ubreq_dreq();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tmp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto fail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mp->b_next != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_next = rmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmp = tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dlpi_replay(mdp, rmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelfail:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (rmp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = rmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmp = rmp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_next = mp->b_prev = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_lc_timer_id == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_bc_id == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_reset_dlpi,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp, man_gettimer(MAN_TIMER_LINKCHECK, mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dlioc_replay(man_dest_t *mdp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *rmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_msp->ms_dlioc_mp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmp = man_dup_mplist(mdp->md_msp->ms_dlioc_mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rmp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dlpi_replay(mdp, rmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mblk_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_alloc_ubreq_dreq()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *dreq;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *ubreq = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dreq = allocb(DL_DETACH_REQ_SIZE, BPRI_MED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dreq == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dreq->b_datap->db_type = M_PROTO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)dreq->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp->dl_primitive = DL_DETACH_REQ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dreq->b_wptr += DL_DETACH_REQ_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ubreq = allocb(DL_UNBIND_REQ_SIZE, BPRI_MED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ubreq == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(dreq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ubreq->b_datap->db_type = M_PROTO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)ubreq->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp->dl_primitive = DL_UNBIND_REQ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ubreq->b_wptr += DL_UNBIND_REQ_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ubreq->b_next = dreq;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ubreq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mblk_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dup_mplist(mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *listp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *tailp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; mp != NULL; mp = mp->b_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *nmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev = mp->b_prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel next = mp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_prev = mp->b_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nmp = copymsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_prev = prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_next = next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (nmp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto nomem;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (listp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp = tailp = nmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tailp->b_next = nmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tailp = nmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (listp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelnomem:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (listp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = listp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel listp = mp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_next = mp->b_prev = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mblk_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_alloc_physreq_mp(eaddr_t *man_eap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel union DL_primitives *dlp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uscalar_t off;
03831d35f7499c87d51205817c93e9a8d42c4baestevel eaddr_t *eap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = allocb(DL_SET_PHYS_ADDR_REQ_SIZE + ETHERADDRL, BPRI_MED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_datap->db_type = M_PROTO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp = (union DL_primitives *)mp->b_wptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp->set_physaddr_req.dl_primitive = DL_SET_PHYS_ADDR_REQ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp->set_physaddr_req.dl_addr_length = ETHERADDRL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel off = DL_SET_PHYS_ADDR_REQ_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlp->set_physaddr_req.dl_addr_offset = off;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_wptr += DL_SET_PHYS_ADDR_REQ_SIZE + ETHERADDRL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel eap = (eaddr_t *)(mp->b_rptr + off);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(man_eap, eap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_DLPI, ("man_alloc_physreq: physaddr %s\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ether_sprintf(eap)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_add_dests(man_pg_t *mpg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!man_str_uses_pg(msp, mpg))
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = &msp->ms_dests[mpg->mpg_pg_id];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TBD - Take out
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ASSERT(mdp->md_device.mdev_state == MDEV_UNASSIGNED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ASSERT(mdp->md_state == MAN_DSTATE_NOTPRESENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_device.mdev_state != MDEV_UNASSIGNED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "man_add_dests mdev !unassigned");
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_PATH, man_print_mdp(mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_start_dest(mdp, msp, mpg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_remove_dests(man_pg_t *mpg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int close_cnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *cdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *tdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_t *wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_work_alloc(MAN_WORK_CLOSE, KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Count up number of destinations we need to close.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!man_str_uses_pg(msp, mpg))
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel close_cnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (close_cnt == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cdp = man_kzalloc(sizeof (man_dest_t) * close_cnt, KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cdp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_free(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp = cdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!man_str_uses_pg(msp, mpg))
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = &msp->ms_dests[mpg->mpg_pg_id];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_state |= MAN_DSTATE_CLOSING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_device.mdev_state = MDEV_UNASSIGNED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_msp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_rq = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clean up optimized destination pointer if we are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * closing it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_set_optimized_dest(msp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_lc_timer_id != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) quntimeout(man_ctl_wq, mdp->md_lc_timer_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_bc_id != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel qunbufcall(man_ctl_wq, mdp->md_bc_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_bc_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((mp = mdp->md_dmp_head) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_head = mp->b_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_count = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_dmp_tail = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *tdp++ = *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_state = MAN_DSTATE_NOTPRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_muxid = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_mdp = cdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_ndests = close_cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_add(man_bwork_q, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns TRUE if stream uses pathgroup, FALSE otherwise.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_str_uses_pg(manstr_t *msp, man_pg_t *mpg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ((msp->ms_flags & MAN_SFLAG_CONTROL) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (msp->ms_dests == NULL) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (msp->ms_manp == NULL) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (msp->ms_manp->man_meta_ppa != mpg->mpg_man_ppa));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (!status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_gettimer(int timer, man_dest_t *mdp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel int attached = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int time = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp == NULL || mdp->md_msp == NULL || mdp->md_msp->ms_manp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel attached = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (timer) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_TIMER_INIT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (attached)
03831d35f7499c87d51205817c93e9a8d42c4baestevel time = mdp->md_msp->ms_manp->man_init_time;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel time = MAN_INIT_TIME;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_TIMER_LINKCHECK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (attached) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_linkstate == MAN_LINKSTALE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel time = mdp->md_msp->ms_manp->man_linkstale_time;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel time = mdp->md_msp->ms_manp->man_linkcheck_time;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel time = MAN_LINKCHECK_TIME;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_TIMER_DLPIRESET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (attached)
03831d35f7499c87d51205817c93e9a8d42c4baestevel time = mdp->md_msp->ms_manp->man_dlpireset_time;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel time = MAN_DLPIRESET_TIME;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_gettimer: unknown timer %d", timer));
03831d35f7499c87d51205817c93e9a8d42c4baestevel time = MAN_LINKCHECK_TIME;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (drv_usectohz(time));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_linkcheck_timer(void *argp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp = (man_dest_t *)argp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int restart_timer = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int send_ping = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int newstate;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int oldstate;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_linkcheck_timer: mdp"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_LINK, man_print_mdp(mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear timeout id and check if someones waiting on us to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * complete a close.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_state == MAN_DSTATE_NOTPRESENT ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_state & MAN_DSTATE_BUSY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_linkcheck_timer: not ready mdp"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_LINK, man_print_mdp(mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_state == MAN_DSTATE_INITIALIZING) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel send_ping = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto do_switch;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel newstate = oldstate = mdp->md_linkstate;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!man_needs_linkcheck(mdp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "man_linkcheck_timer: unneeded linkcheck on mdp(0x%p)",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The above call to man_needs_linkcheck() validates
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mdp->md_msp and mdp->md_msp->ms_manp pointers.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(mdp->md_msp->ms_manp->man_pg, mdp->md_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mpg != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = man_find_path_by_ppa(mpg->mpg_pathp, mdp->md_device.mdev_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This is the most common case, when traffic is flowing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_rcvcnt != mdp->md_lastrcvcnt) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel newstate = MAN_LINKGOOD;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lastrcvcnt = mdp->md_rcvcnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel send_ping = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear the FAILED flag and update lru.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_device.mdev_state &= ~MDEV_FAILED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) drv_getparm(TIME, &mp->mp_lru);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_link_updown_msg == MAN_LINK_DOWN_MSG) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp = mdp->md_msp->ms_manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "%s%d Link up",
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_major_to_name(manp->man_meta_major),
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_meta_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_link_updown_msg = MAN_LINK_UP_MSG;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto done;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we're here, it means we have not seen any traffic
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (oldstate) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_LINKINIT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_LINKGOOD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel newstate = MAN_LINKSTALE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_linkstales++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_linkstale_retries =
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_msp->ms_manp->man_linkstale_retries;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_LINKSTALE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_LINKFAIL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_linkstales++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_linkstale_retries--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_linkstale_retries < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel newstate = MAN_LINKFAIL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_linkfails++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_linkstale_retries =
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_msp->ms_manp->man_linkstale_retries;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Mark the destination as FAILED and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * update lru.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (oldstate != MAN_LINKFAIL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_device.mdev_state |= MDEV_FAILED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) drv_getparm(TIME, &mp->mp_lru);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_linkcheck_timer: illegal link"
193974072f41a843678abf5f61979c748687e66bSherry Moore " state %d", oldstate);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baesteveldone:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (oldstate != newstate) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_linkcheck_timer"
193974072f41a843678abf5f61979c748687e66bSherry Moore " link state %s -> %s", lss[oldstate],
193974072f41a843678abf5f61979c748687e66bSherry Moore lss[newstate]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_linkstate = newstate;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do any work required from state transitions above.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (newstate == MAN_LINKFAIL) {
03831d35f7499c87d51205817c93e9a8d42c4baesteveldo_switch:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!man_do_autoswitch(mdp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Stop linkcheck timer until switch completes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel restart_timer = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel send_ping = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (send_ping)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_do_icmp_bcast(mdp, mdp->md_msp->ms_sap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (restart_timer)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = qtimeout(man_ctl_wq, man_linkcheck_timer,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp, man_gettimer(MAN_TIMER_LINKCHECK, mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_linkcheck_timer: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Handle linkcheck initiated autoswitching.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called with man_lock held.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_do_autoswitch(man_dest_t *mdp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *ap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set flags and refcnt. Cleared in man_iswitch when SWITCH completes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_msp->ms_manp->man_refcnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(mdp->md_msp->ms_manp->man_pg, mdp->md_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mpg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg->mpg_flags & MAN_PG_SWITCHING)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EBUSY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg->mpg_flags |= MAN_PG_SWITCHING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_state == MAN_DSTATE_INITIALIZING) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We're initializing, ask for a switch to our currently
03831d35f7499c87d51205817c93e9a8d42c4baestevel * active device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_autoswitch(mpg, &mdp->md_device, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_msp != NULL && mdp->md_msp->ms_manp != NULL &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_link_updown_msg == MAN_LINK_UP_MSG) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp = mdp->md_msp->ms_manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "%s%d Link down",
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_major_to_name(manp->man_meta_major),
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_meta_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_link_updown_msg = MAN_LINK_DOWN_MSG;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_linkcheck_timer: link failure on %s%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_major_to_name(mdp->md_device.mdev_major),
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_device.mdev_ppa));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ap = man_find_alternate_path(mpg->mpg_pathp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ap == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_autoswitch(mpg, &ap->mp_device, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_iswitch not going to run, clean up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg->mpg_flags &= ~MAN_PG_SWITCHING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_msp->ms_manp->man_refcnt--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_autoswitch(man_pg_t *mpg, man_dev_t *st_devp, man_work_t *waiter_wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_t *wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int sdp_cnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *sdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (waiter_wp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_work_alloc(MAN_WORK_SWITCH, KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(waiter_wp->mw_type == MAN_WORK_SWITCH);
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = waiter_wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set dests as PLUMBING, cancel timers and return array of dests
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that need a switch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_prep_dests_for_switch(mpg, &sdp, &sdp_cnt);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (waiter_wp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_free(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If no streams are active, there are no streams to switch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return ENODEV (see man_pg_activate).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sdp_cnt == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (waiter_wp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_free(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Ask the bgthread to switch. See man_bwork.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_sf_dev = sdp->md_device;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_st_dev = *st_devp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_pg_id = mpg->mpg_pg_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_man_ppa = mpg->mpg_man_ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_mdp = sdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_ndests = sdp_cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_add(man_bwork_q, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Cancel any timers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Mark dests as PLUMBING
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Submit switch request to man_bwork_q->
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_prep_dests_for_switch(man_pg_t *mpg, man_dest_t **mdpp, int *cntp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int sdp_cnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *sdp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *tdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_prep_dests_for_switch: pg_id %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore mpg->mpg_pg_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Count up number of streams, there is one destination that needs
03831d35f7499c87d51205817c93e9a8d42c4baestevel * switching per stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_str_uses_pg(msp, mpg))
03831d35f7499c87d51205817c93e9a8d42c4baestevel sdp_cnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sdp_cnt == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sdp = man_kzalloc(sizeof (man_dest_t) * sdp_cnt, KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sdp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp = sdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Mark each destination as unusable.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_str_uses_pg(msp, mpg)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = &msp->ms_dests[mpg->mpg_pg_id];
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_state |= MAN_DSTATE_PLUMBING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_switch_id = sdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copy destination info.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(mdp, tdp, sizeof (man_dest_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Cancel timers.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_lc_timer_id) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) quntimeout(man_ctl_wq,
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_lc_timer_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_lc_timer_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_bc_id) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel qunbufcall(man_ctl_wq, mdp->md_bc_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_bc_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mdpp = sdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *cntp = sdp_cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This assumes ethernet-like media.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Generate an ICMP packet. Called exclusive inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mdp - destination to send packet to.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sap - either ETHERTYPE_ARP or ETHERTYPE_IPV6
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_do_icmp_bcast(man_dest_t *mdp, t_uscalar_t sap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* TBD - merge pinger and this routine. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(sap == ETHERTYPE_IPV6 || sap == ETHERTYPE_IP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sap == ETHERTYPE_IPV6) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_icmpv6probes++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_icmpv4probes++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send the ICMP message
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = man_pinger(sap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_do_icmp_bcast: sap=0x%x mp=0x%p",
193974072f41a843678abf5f61979c748687e66bSherry Moore sap, (void *)mp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send it out.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_start_lower(mdp, mp, NULL, MAN_LOWER)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_LINK, ("man_do_icmp_broadcast: xmit failed"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mblk_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pinger(t_uscalar_t sap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dladdr_t dlsap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmph_t *icmph;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int ipver;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha_t *ipha;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip6_t *ip6h;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int iph_hdr_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int datalen = 64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t *datap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dlsap.dl_sap = htons(sap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(&etherbroadcast, &dlsap.dl_phys, sizeof (dlsap.dl_phys));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sap == ETHERTYPE_IPV6) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipver = IPV6_VERSION;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iph_hdr_len = sizeof (ip6_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel size = ICMP6_MINLEN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipver = IPV4_VERSION;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iph_hdr_len = sizeof (ipha_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel size = ICMPH_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel size += (uint16_t)iph_hdr_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel size += datalen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = man_alloc_udreq(size, &dlsap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fill out the ICMP echo packet headers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_cont->b_wptr += iph_hdr_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ipver == IPV4_VERSION) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha = (ipha_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_version_and_hdr_length = (IP_VERSION << 4)
193974072f41a843678abf5f61979c748687e66bSherry Moore | IP_SIMPLE_HDR_LENGTH_IN_WORDS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_type_of_service = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_length = size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_fragment_offset_and_flags = IPH_DF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_ttl = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_protocol = IPPROTO_ICMP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_is_on_domain) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel manc_t manc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_get_iosram(&manc)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Domain generates ping packets for domain to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SC network (dman0 <--> scman0).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_dst = manc.manc_sc_ipaddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_src = manc.manc_dom_ipaddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that ping packets are only generated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by the SC across scman1 (SC to SC network).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_dst = man_sc_ipaddrs.ip_other_sc_ipaddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_src = man_sc_ipaddrs.ip_my_sc_ipaddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_ident = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_hdr_checksum = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipha->ipha_hdr_checksum = IP_CSUM(mp->b_cont, 0, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip6h = (ip6_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IP version = 6, priority = 0, flow = 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip6h->ip6_flow = (IPV6_VERSION << 28);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip6h->ip6_plen =
193974072f41a843678abf5f61979c748687e66bSherry Moore htons((short)(size - iph_hdr_len));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip6h->ip6_nxt = IPPROTO_ICMPV6;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip6h->ip6_hlim = 1; /* stay on link */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_is_on_domain) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel manc_t manc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_get_iosram(&manc)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Domain generates ping packets for domain to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SC network (dman0 <--> scman0).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip6h->ip6_src = manc.manc_dom_ipv6addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip6h->ip6_dst = manc.manc_sc_ipv6addr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that ping packets are only generated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by the SC across scman1 (SC to SC network).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip6h->ip6_src = man_sc_ip6addrs.ip6_my_sc_ipaddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ip6h->ip6_dst = man_sc_ip6addrs.ip6_other_sc_ipaddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IPv6 and IP are the same for ICMP as far as I'm concerned.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmph = (icmph_t *)mp->b_cont->b_wptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ipver == IPV4_VERSION) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_cont->b_wptr += ICMPH_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmph->icmph_type = ICMP_ECHO_REQUEST;
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmph->icmph_code = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_cont->b_wptr += ICMP6_MINLEN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmph->icmph_type = ICMP6_ECHO_REQUEST;
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmph->icmph_code = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel datap = mp->b_cont->b_wptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_cont->b_wptr += datalen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < datalen; i++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *datap++ = i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ipver == IPV4_VERSION) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmph->icmph_checksum = IP_CSUM(mp->b_cont, iph_hdr_len, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t sum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sum = htons(IPPROTO_ICMPV6) + ip6h->ip6_plen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmph->icmph_checksum = IP_CSUM(mp->b_cont, iph_hdr_len - 32,
193974072f41a843678abf5f61979c748687e66bSherry Moore (sum & 0xffff) + (sum >> 16));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TBD
03831d35f7499c87d51205817c93e9a8d42c4baestevel * icp->icmp_time = ???;
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mblk_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_alloc_udreq(int size, man_dladdr_t *dlsap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel dl_unitdata_req_t *udreq;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = allocb(sizeof (dl_unitdata_req_t) + sizeof (*dlsap), BPRI_MED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "man_preparepkt: allocb failed");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((bp = allocb(size, BPRI_MED)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "man_preparepkts: allocb failed");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero(bp->b_rptr, size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_cont = bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_datap->db_type = M_PROTO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel udreq = (dl_unitdata_req_t *)mp->b_wptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_wptr += sizeof (dl_unitdata_req_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * phys addr first - TBD
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy((char *)dlsap, mp->b_wptr, sizeof (*dlsap));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_wptr += sizeof (*dlsap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel udreq->dl_primitive = DL_UNITDATA_REQ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel udreq->dl_dest_addr_length = sizeof (*dlsap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel udreq->dl_dest_addr_offset = sizeof (*udreq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel udreq->dl_priority.dl_min = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel udreq->dl_priority.dl_max = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 * etc.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 *
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 *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_bwork - Work thread for this device. It is responsible for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * performing operations which can't occur within the STREAMS framework.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Locking:
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_bwork()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_t *wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int done = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel callb_cpr_t cprinfo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int wp_finished;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel CALLB_CPR_INIT(&cprinfo, &man_lock, callb_generic_cpr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mn_work_thrd");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_bwork: enter"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (done == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * While there is nothing to do, sit in cv_wait. If work
03831d35f7499c87d51205817c93e9a8d42c4baestevel * request is made, requester will signal.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (man_bwork_q->q_work == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel CALLB_CPR_SAFE_BEGIN(&cprinfo);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&man_bwork_q->q_cv, &man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel CALLB_CPR_SAFE_END(&cprinfo, &man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_bwork_q->q_work;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_bwork_q->q_work = wp->mw_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp_finished = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_bwork: type %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore _mw_type[wp->mw_type]));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (wp->mw_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_WORK_OPEN_CTL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_status = man_open_ctl();
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_WORK_CLOSE_CTL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_close_ctl();
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_WORK_CLOSE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_WORK_CLOSE_STREAM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_bclose(&wp->mw_arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_WORK_SWITCH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_bswitch(&wp->mw_arg, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp_finished = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_WORK_STOP: /* man_bwork_stop() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel done = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel CALLB_CPR_EXIT(&cprinfo); /* Unlocks man_lock */
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_bwork: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "illegal work type(%d)", wp->mw_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wp_finished) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_flags |= MAN_WFLAGS_DONE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wp->mw_flags & MAN_WFLAGS_CVWAITER)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&wp->mw_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else if (wp->mw_flags & MAN_WFLAGS_QWAITER)
03831d35f7499c87d51205817c93e9a8d42c4baestevel qenable(wp->mw_q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_free(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_bwork: thread_exit"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_bwork_id = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel thread_exit();
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_open_ctl - Open the control stream.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - errno code
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_open_ctl()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ldi_handle_t ctl_lh = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ldi_ident_t li = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_open_ctl: plumbing control stream\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get eri driver loaded and kstats initialized. Is there a better
03831d35f7499c87d51205817c93e9a8d42c4baestevel * way to do this? - TBD.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_ident_from_mod(&modlinkage, &li);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "man_open_ctl: ident alloc failed, error %d", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_open_by_name(ERI_PATH, FREAD | FWRITE | FNOCTTY,
03831d35f7499c87d51205817c93e9a8d42c4baestevel kcred, &ctl_lh, li);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "man_open_ctl: eri open failed, error %d", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ctl_lh = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ldi_close(ctl_lh, NULL, kcred);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ctl_lh = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_ctl_lh != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(man_ctl_wq == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_open_by_name(DMAN_INT_PATH, FREAD | FWRITE | FNOCTTY,
03831d35f7499c87d51205817c93e9a8d42c4baestevel kcred, &ctl_lh, li);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "man_open_ctl: man control dev open failed, "
193974072f41a843678abf5f61979c748687e66bSherry Moore "error %d", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(man_config_state == MAN_CONFIGURING);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(man_ctl_lh == NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_ctl_lh = ctl_lh;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (li)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ldi_ident_release(li);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_open_ctl: man_ctl_lh(0x%p) errno = %d\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)man_ctl_lh, status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_close_ctl - Close control stream, we are about to unload driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Locking:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - Called holding no locks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_close_ctl()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel ldi_handle_t tlh;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_close_ctl: unplumbing control stream\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((tlh = man_ctl_lh) != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_ctl_lh = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tlh != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ldi_close(tlh, NULL, kcred);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Close the lower streams. Get all the timers canceled, close the lower
03831d35f7499c87d51205817c93e9a8d42c4baestevel * stream and delete the dest array.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 Closed all streams.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 Couldn't close one or more streams, timers still running.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Locking:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - Called holding no locks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_bclose(man_adest_t *adp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_cancel_timers(adp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < adp->a_ndests; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = &adp->a_mdp[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_muxid != -1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_unplumb(mdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&mdp->md_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(adp->a_mdp, sizeof (man_dest_t) * adp->a_ndests);
03831d35f7499c87d51205817c93e9a8d42c4baestevel adp->a_mdp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns 1 if lower streams are quiesced, 0 if we need to wait
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a bit longer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_cancel_timers(man_adest_t *adp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = adp->a_mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt = adp->a_ndests;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_cancel_timers: mdp(0x%p) cnt %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mdp, cnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < cnt; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp[i].md_lc_timer_id != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) quntimeout(man_ctl_wq, mdp[i].md_lc_timer_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp[i].md_lc_timer_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp[i].md_bc_id != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel qunbufcall(man_ctl_wq, mdp[i].md_bc_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp[i].md_bc_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_cancel_timers: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_bswitch(man_adest_t *adp, man_work_t *wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *tdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp = man_kzalloc(sizeof (man_dest_t) * adp->a_ndests,
193974072f41a843678abf5f61979c748687e66bSherry Moore KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(adp->a_mdp, tdp, sizeof (man_dest_t) * adp->a_ndests);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Before we switch to the new path, lets sync the kstats.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, adp->a_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_update_path_kstats(manp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < adp->a_ndests; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp[i].md_device = adp->a_st_dev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tdp[i].md_muxid = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_plumb(&tdp[i]))
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Didn't plumb everyone, unplumb new lower stuff and return.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i < adp->a_ndests) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int j;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j <= i; j++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_unplumb(&tdp[j]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_is_on_domain && man_dossc_switch(adp->a_st_dev.mdev_exp_id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we cant set new path on the SSC, then fail the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * failover.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < adp->a_ndests; i++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_unplumb(&tdp[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(adp->a_mdp, sizeof (man_dest_t) * adp->a_ndests);
03831d35f7499c87d51205817c93e9a8d42c4baestevel adp->a_mdp = tdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(tdp, sizeof (man_dest_t) * adp->a_ndests);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_bswitch: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hand processed switch request back to man_iwork for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processing in man_iswitch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_status = status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_add(man_iwork_q, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_plumb - Configure a lower stream for this destination.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Locking:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - Called holding no locks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - success - 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - error code of failure
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_plumb(man_dest_t *mdp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int muxid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ldi_handle_t lh;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ldi_ident_t li = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Control stream should already be open.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_ctl_lh == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(man_ctl_wq != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_ident_from_stream(man_ctl_wq, &li);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "man_plumb: ident alloc failed, error %d", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(strcmp(ERI_IDNAME,
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_major_to_name(mdp->md_device.mdev_major)) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_open_by_name(ERI_PATH, FREAD | FWRITE | FNOCTTY,
03831d35f7499c87d51205817c93e9a8d42c4baestevel kcred, &lh, li);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "man_plumb: eri open failed, error %d", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Link netdev under MAN.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mdp->md_muxid == -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_ioctl(man_ctl_lh, I_PLINK, (intptr_t)lh,
193974072f41a843678abf5f61979c748687e66bSherry Moore FREAD+FWRITE+FNOCTTY+FKIOCTL, kcred, &muxid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "man_plumb: ldi_ioctl(I_PLINK) failed, error %d", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ldi_close(lh, NULL, kcred);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_muxid = muxid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_wq = man_linkrec_find(muxid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we can't find the linkrec then return an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * error. It will be automatically unplumbed on failure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_wq == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ldi_close(lh, NULL, kcred);
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (li)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ldi_ident_release(li);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_plumb: exit\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_unplumb - tear down the STREAMs framework for the lower multiplexor.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mdp - destination struct of interest
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - return error from ldi_ioctl
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_unplumb(man_dest_t *mdp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status, rval;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_SWITCH, ("man_unplumb: mdp"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_SWITCH, man_print_mdp(mdp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp->md_muxid == -1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(man_ctl_lh != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * I_PUNLINK causes the multiplexor resources to be freed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ldi_ioctl(man_ctl_lh, I_PUNLINK, (intptr_t)mdp->md_muxid,
193974072f41a843678abf5f61979c748687e66bSherry Moore FREAD+FWRITE+FNOCTTY+FKIOCTL, kcred, &rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_unplumb: ldi_ioctl(I_PUNLINK) failed"
193974072f41a843678abf5f61979c748687e66bSherry Moore " errno %d\n", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Delete linkrec if it exists.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) man_linkrec_find(mdp->md_muxid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp->md_muxid = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
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 *
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 *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns 0 on success, errno on failure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pg_cmd(mi_path_t *mip, man_work_t *waiter_wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mip->mip_ndevs < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_pg_cmd: EINVAL: mip_ndevs %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore mip->mip_ndevs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, mip->mip_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pg_cmd: mip"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_PATH, man_print_mip(mip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("\tman_t"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_PATH, man_print_man(manp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (mip->mip_cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MI_PATH_ASSIGN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_pg_assign(&manp->man_pg, mip, FALSE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MI_PATH_ADD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_pg_assign(&manp->man_pg, mip, TRUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MI_PATH_UNASSIGN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_pg_unassign(&manp->man_pg, mip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MI_PATH_ACTIVATE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_pg_activate(manp, mip, waiter_wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MI_PATH_READ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_pg_read(manp->man_pg, mip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "man_pg_cmd: invalid command");
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pg_cmd: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mplpp - man pathgroup list point to point.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mip - new/updated pathgroup info to assign.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pg_assign(man_pg_t **mplpp, mi_path_t *mip, int add_only)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *add_paths = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int first_pass = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt = mip->mip_ndevs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cnt == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "man_pg_assign: mip_ndevs == 0");
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Assure the devices to be assigned are not assigned to some other
03831d35f7499c87d51205817c93e9a8d42c4baestevel * pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < cnt; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_path_by_dev(*mplpp, &mip->mip_devs[i], NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mpg->mpg_man_ppa != mip->mip_man_ppa) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (mpg->mpg_pg_id != mip->mip_pg_id)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Already assigned to some other man instance
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EEXIST;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(*mplpp, mip->mip_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_pg_create(mplpp, &mpg, mip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (ether_cmp(&mip->mip_eaddr, &mpg->mpg_dst_eaddr) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "man_pg_assign: ethernet address mismatch");
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "existing %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore ether_sprintf(&mpg->mpg_dst_eaddr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "new %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore ether_sprintf(&mip->mip_eaddr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create list of new paths to add to pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < cnt; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_find_path_by_dev(*mplpp, &mip->mip_devs[i], NULL))
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue; /* Already exists in this pathgroup */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = man_kzalloc(sizeof (man_path_t), KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_device = mip->mip_devs[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_device.mdev_state = MDEV_ASSIGNED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pg_assign: assigning mdp"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_PATH, man_print_dev(&mp->mp_device));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_path_kstat_init(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(mp, sizeof (man_path_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_insert(&add_paths, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (add_only == TRUE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check if any paths we want to remove are ACTIVE. If not,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * do a second pass and remove them.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelagain:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mpg->mpg_pathp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int in_new_list;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *rp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel in_new_list = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < cnt; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->mp_device.mdev_ppa ==
03831d35f7499c87d51205817c93e9a8d42c4baestevel mip->mip_devs[i].mdev_ppa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel in_new_list = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!in_new_list) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (first_pass) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->mp_device.mdev_state & MDEV_ACTIVE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EBUSY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rp = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mp->mp_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rp != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_remove(&mpg->mpg_pathp, rp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (first_pass == TRUE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel first_pass = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto again;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (add_paths)
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_merge(&mpg->mpg_pathp, add_paths);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (add_paths != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = add_paths;
03831d35f7499c87d51205817c93e9a8d42c4baestevel add_paths = mp->mp_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_kstat_uninit(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(mp, sizeof (man_path_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 * first.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pg_unassign(man_pg_t **plpp, mi_path_t *mip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *tpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *tppg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for existence of pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mpg = man_find_pg_by_id(*plpp, mip->mip_pg_id)) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_find_active_path(mpg->mpg_pathp) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_remove_dests(mpg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free all the paths for this pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mpg->mpg_pathp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mpg->mpg_pathp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg->mpg_pathp = mp->mp_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_kstat_uninit(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(mp, sizeof (man_path_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove this pathgroup from the list, and free it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel tpg = tppg = *plpp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tpg == mpg) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *plpp = tpg->mpg_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto free_pg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (tpg = tpg->mpg_next; tpg != NULL; tpg = tpg->mpg_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tpg == mpg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tppg = tpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(tpg != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tppg->mpg_next = tpg->mpg_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tpg->mpg_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelfree_pg:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(tpg, sizeof (man_pg_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set a new active path. This is done via man_ioctl so we are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exclusive in the inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pg_activate(man_t *manp, mi_path_t *mip, man_work_t *waiter_wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *plp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *ap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pg_activate: dev"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_PATH, man_print_dev(mip->mip_devs));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mip->mip_ndevs != 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel plp = manp->man_pg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg1 = man_find_pg_by_id(plp, mip->mip_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg1 == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg2 = man_find_path_by_dev(plp, mip->mip_devs, &mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg2 == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg1 != mpg2) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mp->mp_device.mdev_ppa == mip->mip_devs->mdev_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg1->mpg_flags & MAN_PG_SWITCHING) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ap = man_find_active_path(mpg1->mpg_pathp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ap == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 * them.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_device.mdev_state |= MDEV_ACTIVE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_add_dests(mpg1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Path already active, nothing to do.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ap == mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Try to autoswitch to requested device. Set flags and refcnt.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Cleared in man_iswitch when SWITCH completes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_refcnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg1->mpg_flags |= MAN_PG_SWITCHING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Switch to path specified.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_autoswitch(mpg1, mip->mip_devs, waiter_wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_iswitch not going to run, clean up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_refcnt--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg1->mpg_flags &= ~MAN_PG_SWITCHING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status == ENODEV) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ap->mp_device.mdev_state &= ~MDEV_ACTIVE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_device.mdev_state |= MDEV_ACTIVE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pg_activate: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pg_read(man_pg_t *plp, mi_path_t *mip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mpg = man_find_pg_by_id(plp, mip->mip_pg_id)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt = 0;
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 if (cnt == mip->mip_ndevs)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pg_read: pg(0x%p) id(%d) found %d paths",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)mpg, mpg->mpg_pg_id, cnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mip->mip_ndevs = cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TBD - What should errno be if user buffer too small ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mplpp - man pathgroup list point to pointer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mpgp - returns newly created man pathgroup.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mip - info to fill in mpgp.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pg_create(man_pg_t **mplpp, man_pg_t **mpgp, mi_path_t *mip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *tpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ether_cmp(&mip->mip_eaddr, &zero_ether_addr) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "man_ioctl: man_pg_create: ether"
193974072f41a843678abf5f61979c748687e66bSherry Moore " addresss not set!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_kzalloc(sizeof (man_pg_t), KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg->mpg_flags = MAN_PG_IDLE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg->mpg_pg_id = mip->mip_pg_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg->mpg_man_ppa = mip->mip_man_ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ether_copy(&mip->mip_eaddr, &mpg->mpg_dst_eaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pg_create: new mpg"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_PATH, man_print_mpg(mpg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tpg = *mplpp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tpg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mplpp = mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (tpg->mpg_next != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel tpg = tpg->mpg_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tpg->mpg_next = mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mpgp = mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called holding man_lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_pg_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_find_path_by_dev(man_pg_t *plp, man_dev_t *mdevp, man_path_t **mpp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mpg = plp; mpg != NULL; mpg = mpg->mpg_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mp = mpg->mpg_pathp; mp != NULL; mp = mp->mp_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->mp_device.mdev_major == mdevp->mdev_major &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_device.mdev_ppa == mdevp->mdev_ppa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpp != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mpp = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mpg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return pointer to pathgroup assigned to destination, null if not found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called holding man_lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_pg_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_find_pg_by_id(man_pg_t *mpg, int pg_id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; mpg != NULL; mpg = mpg->mpg_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg->mpg_pg_id == pg_id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mpg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_path_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_find_path_by_ppa(man_path_t *mplist, int ppa)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mp = mplist; mp != NULL; mp = mp->mp_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->mp_device.mdev_ppa == ppa)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_path_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_find_active_path(man_path_t *mplist)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mp = mplist; mp != NULL; mp = mp->mp_next)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->mp_device.mdev_state & MDEV_ACTIVE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Try and find an alternate path.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic man_path_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_find_alternate_path(man_path_t *mlp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *ap; /* Active path */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *np; /* New alternate path */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *fp = NULL; /* LRU failed path */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ap = man_find_active_path(mlp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find a non-failed path, or the lru failed path and switch to it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (np = mlp; np != NULL; np = np->mp_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np == ap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np->mp_device.mdev_state == MDEV_ASSIGNED)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np->mp_device.mdev_state & MDEV_FAILED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel fp = np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fp->mp_lru > np->mp_lru)
03831d35f7499c87d51205817c93e9a8d42c4baestevel fp = np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Nowhere to switch to.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np == NULL && (np = fp) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (np);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Assumes caller has verified existence.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_path_remove(man_path_t **lpp, man_path_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *tp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *tpp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_path_remove: removing path"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_PATH, man_print_path(mp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tp = tpp = *lpp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tp == mp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *lpp = tp->mp_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (tp = tp->mp_next; tp != NULL; tp = tp->mp_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tp == mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tpp = tp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(tp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tpp->mp_next = tp->mp_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tp->mp_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_kstat_uninit(tp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(tp, sizeof (man_path_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Insert path into list, ascending order by ppa.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_path_insert(man_path_t **lpp, man_path_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *tp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *tpp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*lpp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *lpp = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tp = tpp = *lpp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tp->mp_device.mdev_ppa > mp->mp_device.mdev_ppa) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_next = tp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *lpp = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (tp = tp->mp_next; tp != NULL; tp = tp->mp_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tp->mp_device.mdev_ppa > mp->mp_device.mdev_ppa)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tpp = tp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tpp->mp_next = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tpp->mp_next = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->mp_next = tp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Merge npp into lpp, ascending order by ppa. Assumes no
03831d35f7499c87d51205817c93e9a8d42c4baestevel * duplicates in either list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_path_merge(man_path_t **lpp, man_path_t *np)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (np != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel np = np->mp_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp->mp_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_insert(lpp, tmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_path_kstat_init(man_path_t *mpp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_t *dev_knp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_path_kstat_init: mpp(0x%p)\n", (void *)mpp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create named kstats for accounting purposes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_knp = man_kzalloc(MAN_NUMSTATS * sizeof (kstat_named_t),
193974072f41a843678abf5f61979c748687e66bSherry Moore KM_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dev_knp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kstat_named_init(dev_knp, MAN_NUMSTATS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpp->mp_last_knp = dev_knp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_path_kstat_init: returns %d\n", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_path_kstat_uninit(man_path_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree(mp->mp_last_knp, MAN_NUMSTATS * sizeof (kstat_named_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_work_alloc - allocate and initiate a work request structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * type - type of request to allocate
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - ptr to an initialized work structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_work_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_work_alloc(int type, int kmflag)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_t *wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_kzalloc(sizeof (man_work_t), kmflag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&wp->mw_cv, NULL, CV_DRIVER, NULL); \
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_type = type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_work_free - deallocate a work request structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wp - ptr to work structure to be freed
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_work_free(man_work_t *wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&wp->mw_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_kfree((void *)wp, sizeof (man_work_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_work_add(man_workq_t *q, man_work_t *wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_t *lp = q->q_work;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (lp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (lp->mw_next != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel lp = lp->mw_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel lp->mw_next = wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel q->q_work = wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cv_signal for man_bwork_q, qenable for man_iwork_q
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (q == man_bwork_q) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&q->q_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else { /* q == man_iwork_q */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_ctl_wq != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel qenable(man_ctl_wq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* <<<<<<<<<<<<<<<<<<<<<<< NDD SUPPORT FUNCTIONS >>>>>>>>>>>>>>>>>>> */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ndd support functions to get/set parameters
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Register each element of the parameter array with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * named dispatch handler. Each element is loaded using
03831d35f7499c87d51205817c93e9a8d42c4baestevel * nd_load()
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cnt - the number of elements present in the parameter array
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_param_register(param_t *manpa, int cnt)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndgetf_t getp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ndsetf_t setp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = B_TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_param_register: manpa(0x%p) cnt %d\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)manpa, cnt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel getp = man_param_get;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < cnt; i++, manpa++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (man_param_display[i]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_NDD_GETABLE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel setp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MAN_NDD_SETABLE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel setp = man_param_set;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!nd_load(&man_ndlist, manpa->param_name, getp,
193974072f41a843678abf5f61979c748687e66bSherry Moore setp, (caddr_t)manpa)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) man_nd_free(&man_ndlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = B_FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!nd_load(&man_ndlist, "man_pathgroups_report",
193974072f41a843678abf5f61979c748687e66bSherry Moore man_pathgroups_report, NULL, NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) man_nd_free(&man_ndlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = B_FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!nd_load(&man_ndlist, "man_set_active_path",
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, man_set_active_path, NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) man_nd_free(&man_ndlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = B_FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!nd_load(&man_ndlist, "man_get_hostinfo",
193974072f41a843678abf5f61979c748687e66bSherry Moore man_get_hostinfo, NULL, NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) man_nd_free(&man_ndlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = B_FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_CONFIG, ("man_param_register: returns %d\n", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_nd_getset(queue_t *wq, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!nd_getset(wq, man_ndlist, mp))
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(wq, mp, 0, ENOENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel qreply(wq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_pathgroups_report(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char pad[] = " "; /* 17 spaces */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int pad_end;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf(mp, "MAN Pathgroup report: (* == failed)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf(mp, "====================================="
193974072f41a843678abf5f61979c748687e66bSherry Moore "==========================================");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < 2; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf(mp,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Interface\tDestination\t\tActive Path\tAlternate Paths");
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf(mp, "---------------------------------------"
193974072f41a843678abf5f61979c748687e66bSherry Moore "----------------------------------------");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mpg = manp->man_pg; mpg != NULL; mpg = mpg->mpg_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf(mp, "%s%d\t\t",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_major_to_name(manp->man_meta_major),
193974072f41a843678abf5f61979c748687e66bSherry Moore manp->man_meta_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_is_on_domain) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf_nr(mp, "Master SSC\t");
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_preport(mpg->mpg_pathp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i == 0) {
193974072f41a843678abf5f61979c748687e66bSherry Moore pad_end = 17 - strlen(ether_sprintf(
193974072f41a843678abf5f61979c748687e66bSherry Moore &mpg->mpg_dst_eaddr));
193974072f41a843678abf5f61979c748687e66bSherry Moore if (pad_end < 0 || pad_end > 16)
03831d35f7499c87d51205817c93e9a8d42c4baestevel pad_end = 0;
193974072f41a843678abf5f61979c748687e66bSherry Moore pad[pad_end] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
193974072f41a843678abf5f61979c748687e66bSherry Moore (void) mi_mpprintf_nr(mp, "%c %s%s",
193974072f41a843678abf5f61979c748687e66bSherry Moore mpg->mpg_pg_id + 'A',
193974072f41a843678abf5f61979c748687e66bSherry Moore ether_sprintf(&mpg->mpg_dst_eaddr),
193974072f41a843678abf5f61979c748687e66bSherry Moore pad);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
193974072f41a843678abf5f61979c748687e66bSherry Moore pad[pad_end] = ' ';
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
193974072f41a843678abf5f61979c748687e66bSherry Moore (void) mi_mpprintf_nr(mp,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Other SSC\t");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_preport(mpg->mpg_pathp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf_nr(mp, "\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_pathgroups_report: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_preport(man_path_t *plist, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *ap;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ap = man_find_active_path(plist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Active path
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ap != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf_nr(mp, "\t%s%d\t\t",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_major_to_name(ap->mp_device.mdev_major),
193974072f41a843678abf5f61979c748687e66bSherry Moore ap->mp_device.mdev_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf_nr(mp, "None \t");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Alternate Paths.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (plist != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf_nr(mp, "%s%d exp %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_major_to_name(plist->mp_device.mdev_major),
193974072f41a843678abf5f61979c748687e66bSherry Moore plist->mp_device.mdev_ppa,
193974072f41a843678abf5f61979c748687e66bSherry Moore plist->mp_device.mdev_exp_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (plist->mp_device.mdev_state & MDEV_FAILED)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf_nr(mp, "*");
03831d35f7499c87d51205817c93e9a8d42c4baestevel plist = plist->mp_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (plist)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf_nr(mp, ", ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NDD request to set active path. Calling context is man_ioctl, so we are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exclusive in the inner perimeter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Syntax is "ndd -set /dev/dman <man ppa> <pg_id> <phys ppa>"
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED3 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_set_active_path(queue_t *wq, mblk_t *mp, char *value, caddr_t cp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cred_t *cr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *end, *meta_ppap, *phys_ppap, *pg_idp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int meta_ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int phys_ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int pg_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *np;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_path_t mpath;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_set_active_path: wq(0x%p) mp(0x%p)"
193974072f41a843678abf5f61979c748687e66bSherry Moore " args %s", (void *)wq, (void *)mp, value));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel meta_ppap = value;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((pg_idp = strchr(value, ' ')) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *pg_idp++ = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((phys_ppap = strchr(pg_idp, ' ')) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *phys_ppap++ = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel meta_ppa = (int)mi_strtol(meta_ppap, &end, 10);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pg_id = (int)mi_strtol(pg_idp, &end, 10);
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_ppa = (int)mi_strtol(phys_ppap, &end, 10);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = ddi_get_soft_state(man_softstate, meta_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp == NULL || manp->man_pg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpg = man_find_pg_by_id(manp->man_pg, pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel np = man_find_path_by_ppa(mpg->mpg_pathp, phys_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (np == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_cmd = MI_PATH_ACTIVATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_pg_id = pg_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_man_ppa = meta_ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_devs[0] = np->mp_device;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mpath.mip_ndevs = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = man_pg_cmd(&mpath, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_PATH, ("man_set_active_path: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_get_hostinfo(queue_t *wq, mblk_t *mp, caddr_t cp, cred_t *cr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel manc_t manc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *ipaddr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char ipv6addr[INET6_ADDRSTRLEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!man_is_on_domain)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status = man_get_iosram(&manc)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_magic = 0x%x", manc.manc_magic);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_version = 0%d", manc.manc_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_csum = 0x%x", manc.manc_csum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manc.manc_ip_type == AF_INET) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel in_addr_t netnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_ip_type = AF_INET");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipaddr = man_inet_ntoa(manc.manc_dom_ipaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_dom_ipaddr = %s", ipaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipaddr = man_inet_ntoa(manc.manc_dom_ip_netmask);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_dom_ip_netmask = %s", ipaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel netnum = manc.manc_dom_ipaddr & manc.manc_dom_ip_netmask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipaddr = man_inet_ntoa(netnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_dom_ip_netnum = %s", ipaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ipaddr = man_inet_ntoa(manc.manc_sc_ipaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_sc_ipaddr = %s", ipaddr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (manc.manc_ip_type == AF_INET6) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_ip_type = AF_INET6");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) inet_ntop(AF_INET6, (void *)&manc.manc_dom_ipv6addr,
193974072f41a843678abf5f61979c748687e66bSherry Moore ipv6addr, INET6_ADDRSTRLEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_dom_ipv6addr = %s", ipv6addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_dom_ipv6_netmask = %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore manc.manc_dom_ipv6_netmask.s6_addr[0]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) inet_ntop(AF_INET6, (void *)&manc.manc_sc_ipv6addr,
193974072f41a843678abf5f61979c748687e66bSherry Moore ipv6addr, INET6_ADDRSTRLEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_sc_ipv6addr = %s", ipv6addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_ip_type = NONE");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_dom_eaddr = %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore ether_sprintf(&manc.manc_dom_eaddr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_sc_eaddr = %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore ether_sprintf(&manc.manc_sc_eaddr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_iob_bitmap = 0x%x\tio boards = ",
193974072f41a843678abf5f61979c748687e66bSherry Moore manc.manc_iob_bitmap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_MAX_EXPANDERS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((manc.manc_iob_bitmap >> i) & 0x1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf_nr(mp, "%d.1, ", i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_mpprintf(mp, "manc_golden_iob = %d", manc.manc_golden_iob);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_inet_ntoa(in_addr_t in)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel static char b[18];
03831d35f7499c87d51205817c93e9a8d42c4baestevel unsigned char *p;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel p = (unsigned char *)&in;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(b, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (b);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * parameter value. cp points to the required parameter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel param_t *manpa = (param_t *)cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) mi_mpprintf(mp, "%u", manpa->param_val);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sets the man parameter to the value in the param_register using
03831d35f7499c87d51205817c93e9a8d42c4baestevel * nd_load().
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *end;
03831d35f7499c87d51205817c93e9a8d42c4baestevel size_t new_value;
03831d35f7499c87d51205817c93e9a8d42c4baestevel param_t *manpa = (param_t *)cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_value = mi_strtol(value, &end, 10);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (end == value || new_value < manpa->param_min ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_value > manpa->param_max) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel manpa->param_val = new_value;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free the Named Dispatch Table by calling man_nd_free
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_param_cleanup()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_ndlist != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel nd_free(&man_ndlist);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free the table pointed to by 'ndp'
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_nd_free(caddr_t *nd_pparam)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel ND *nd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((nd = (ND *)(*nd_pparam)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (nd->nd_tbl)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_free((char *)nd->nd_tbl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mi_free((char *)nd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *nd_pparam = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_kstat_update - update the statistics for a meta-interface.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ksp - kstats struct
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rw - flag indicating whether stats are to be read or written.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_kstat_update(kstat_t *ksp, int rw)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp; /* per instance data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_t *wp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_t *knp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_t *man_knp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_kstat_update: %s\n", rw ? "KSTAT_WRITE" :
193974072f41a843678abf5f61979c748687e66bSherry Moore "KSTAT_READ"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = (man_t *)ksp->ks_private;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_refcnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the driver has been configured, get kstats updated by inner
03831d35f7499c87d51205817c93e9a8d42c4baestevel * perimeter prior to retrieving.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_config_state == MAN_CONFIGURED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t wait_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_update_path_kstats(manp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp = man_work_alloc(MAN_WORK_KSTAT_UPDATE, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_arg.a_man_ppa = manp->man_meta_ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_flags = MAN_WFLAGS_CVWAITER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_add(man_iwork_q, wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni wait_status = cv_reltimedwait_sig(&wp->mw_cv, &man_lock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drv_usectohz(manp->man_kstat_waittime), TR_CLOCK_TICK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wp->mw_flags & MAN_WFLAGS_DONE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = wp->mw_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_work_free(wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(wait_status <= 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel wp->mw_flags &= ~MAN_WFLAGS_CVWAITER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wait_status == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = EINTR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_kstat_update: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "timedout, returning stale stats."));
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status)
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel knp = (kstat_named_t *)ksp->ks_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_knp = (kstat_named_t *)manp->man_ksp->ks_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rw == KSTAT_READ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_NUMSTATS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel knp[i].value.ui64 = man_knp[i].value.ui64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_NUMSTATS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_knp[i].value.ui64 = knp[i].value.ui64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelexit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp->man_refcnt--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_kstat_update: returns %d", status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sum destination kstats for all active paths for a given instance of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN driver. Called with perimeter lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_do_kstats(man_work_t *wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_t *manp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_do_kstats:"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sync mp_last_knp for each path associated with the MAN instance.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel manp = (man_t *)ddi_get_soft_state(man_softstate,
193974072f41a843678abf5f61979c748687e66bSherry Moore wp->mw_arg.a_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mpg = manp->man_pg; mpg != NULL; mpg = mpg->mpg_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mpg->mpg_man_ppa == manp->man_meta_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mp = man_find_active_path(mpg->mpg_pathp)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("\tkstat: path"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBGCALL(MAN_KSTAT, man_print_path(mp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We just to update the destination statistics here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_sum_dests_kstats(mp->mp_last_knp, mpg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&man_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_do_kstats: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sum device kstats for all active paths for a given instance of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAN driver. Called with man_lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_update_path_kstats(man_t *manp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_t *man_knp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_pg_t *mpg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_path_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&man_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_update_path_kstats:"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_knp = (kstat_named_t *)manp->man_ksp->ks_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mpg = manp->man_pg; mpg != NULL; mpg = mpg->mpg_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mpg->mpg_man_ppa == manp->man_meta_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mp = man_find_active_path(mpg->mpg_pathp)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_update_dev_kstats(man_knp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_update_path_kstats: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_update_dev_kstats(kstat_named_t *man_knp, man_path_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_t *dev_ksp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel major_t major;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char buf[KSTAT_STRLEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel major = mp->mp_device.mdev_major;
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = mp->mp_device.mdev_ppa;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(buf, "%s%d", ddi_major_to_name(major), instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_ksp = kstat_hold_byname(ddi_major_to_name(major), instance, buf,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ALL_ZONES);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dev_ksp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel KSTAT_ENTER(dev_ksp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel KSTAT_UPDATE(dev_ksp, KSTAT_READ);
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_sum_kstats(man_knp, dev_ksp, mp->mp_last_knp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel KSTAT_EXIT(dev_ksp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_rele(dev_ksp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT,
193974072f41a843678abf5f61979c748687e66bSherry Moore ("man_update_dev_kstats: no kstat data found for %s(%d,%d)",
193974072f41a843678abf5f61979c748687e66bSherry Moore buf, major, instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_sum_dests_kstats(kstat_named_t *knp, man_pg_t *mpg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *statname;
03831d35f7499c87d51205817c93e9a8d42c4baestevel manstr_t *msp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_dest_t *mdp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t switches = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t linkfails = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t linkstales = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t icmpv4probes = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t icmpv6probes = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_sum_dests_kstats: mpg 0x%p", (void *)mpg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (msp = man_strup; msp != NULL; msp = msp->ms_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!man_str_uses_pg(msp, mpg))
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mdp = &msp->ms_dests[mpg->mpg_pg_id];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switches += mdp->md_switches;
03831d35f7499c87d51205817c93e9a8d42c4baestevel linkfails += mdp->md_linkfails;
03831d35f7499c87d51205817c93e9a8d42c4baestevel linkstales += mdp->md_linkstales;
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmpv4probes += mdp->md_icmpv4probes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel icmpv6probes += mdp->md_icmpv6probes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_NUMSTATS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel statname = man_kstat_info[i].mk_name;
03831d35f7499c87d51205817c93e9a8d42c4baestevel flags = man_kstat_info[i].mk_flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(flags & MK_NOT_PHYSICAL))
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(statname, "man_switches") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel knp[i].value.ui64 = switches;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_link_fails") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel knp[i].value.ui64 = linkfails;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_link_stales") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel knp[i].value.ui64 = linkstales;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_icmpv4_probes") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel knp[i].value.ui64 = icmpv4probes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_icmpv6_probes") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel knp[i].value.ui64 = icmpv6probes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_sum_dests_kstats: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize MAN named kstats in the space provided.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_kstat_named_init(kstat_named_t *knp, int num_stats)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_kstat_named_init: knp(0x%p) num_stats = %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)knp, num_stats));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < num_stats; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_init(&knp[i], man_kstat_info[i].mk_name,
193974072f41a843678abf5f61979c748687e66bSherry Moore man_kstat_info[i].mk_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_kstat_named_init: returns"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * man_kstat_byname - get a kernel stat value from its structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ksp - kstat_t structure to play with
03831d35f7499c87d51205817c93e9a8d42c4baestevel * s - string to match names with
03831d35f7499c87d51205817c93e9a8d42c4baestevel * res - in/out result data pointer
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns - success - 1 (found)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * - failure - 0 (not found)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_kstat_byname(kstat_t *ksp, char *s, kstat_named_t *res)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int found = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT2, ("man_kstat_byname: GETTING %s\n", s));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ksp->ks_type == KSTAT_TYPE_NAMED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_t *knp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (knp = KSTAT_NAMED_PTR(ksp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)knp < ((caddr_t)ksp->ks_data+ksp->ks_data_size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel knp++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(s, knp->name) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel res->data_type = knp->data_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel res->value = knp->value;
03831d35f7499c87d51205817c93e9a8d42c4baestevel found++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT2, ("\t%s: %d\n", knp->name,
193974072f41a843678abf5f61979c748687e66bSherry Moore (int)knp->value.ul));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT2, ("\tbad kstats type %d\n", ksp->ks_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if getting a value but couldn't find the namestring, result = 0.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!found) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a reasonable default
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel res->data_type = KSTAT_DATA_ULONG;
03831d35f7499c87d51205817c93e9a8d42c4baestevel res->value.l = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT2, ("\tcouldn't find, using defaults\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT2, ("man_kstat_byname: returns\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (found);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Accumulate MAN driver kstats from the incremental values of the underlying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * physical interfaces.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 * kstats.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Basic algorithm is:
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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];
03831d35f7499c87d51205817c93e9a8d42c4baestevel * }
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_sum_kstats(kstat_named_t *sum_knp, kstat_t *phys_ksp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_t *phys_last_knp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *physname;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *physalias;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *statname;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_t phys_kn_entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t delta64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)phys_last_knp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MAN_NUMSTATS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int found = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int flags = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel delta64 = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel statname = man_kstat_info[i].mk_name;
03831d35f7499c87d51205817c93e9a8d42c4baestevel physname = man_kstat_info[i].mk_physname;
03831d35f7499c87d51205817c93e9a8d42c4baestevel physalias = man_kstat_info[i].mk_physalias;
03831d35f7499c87d51205817c93e9a8d42c4baestevel flags = man_kstat_info[i].mk_flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Update MAN private kstats.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (flags & MK_NOT_PHYSICAL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_t *knp = phys_last_knp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sum_knp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(statname, "man_switches") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sum_knp[i].value.ui64 = knp[i].value.ui64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_link_fails") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sum_knp[i].value.ui64 = knp[i].value.ui64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_link_stales") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sum_knp[i].value.ui64 = knp[i].value.ui64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_icmpv4_probes") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sum_knp[i].value.ui64 = knp[i].value.ui64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (strcmp(statname, "man_icmpv6_probes") == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sum_knp[i].value.ui64 = knp[i].value.ui64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue; /* phys_ksp doesnt have this stat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * first try it by the "official" name
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (phys_ksp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (man_kstat_byname(phys_ksp, physname,
193974072f41a843678abf5f61979c748687e66bSherry Moore &phys_kn_entry)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel found = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((physalias) && (man_kstat_byname(phys_ksp,
193974072f41a843678abf5f61979c748687e66bSherry Moore physalias, &phys_kn_entry))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel found = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!found) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * clear up the "last" value, no change to the sum
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_last_knp[i].value.ui64 = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * at this point, we should have the good underlying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kstat value stored in phys_kn_entry
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (flags & MK_NOT_COUNTER) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it isn't a counter, so store the value and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * move on (e.g. ifspeed)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_last_knp[i].value = phys_kn_entry.value;
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (phys_kn_entry.data_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case KSTAT_DATA_UINT32:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this handles 32-bit wrapping
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (phys_kn_entry.value.ui32 <
193974072f41a843678abf5f61979c748687e66bSherry Moore phys_last_knp[i].value.ui32) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we've wrapped!
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel delta64 += (UINT_MAX -
193974072f41a843678abf5f61979c748687e66bSherry Moore phys_last_knp[i].value.ui32);
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_last_knp[i].value.ui32 = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel delta64 += phys_kn_entry.value.ui32 -
193974072f41a843678abf5f61979c748687e66bSherry Moore phys_last_knp[i].value.ui32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_last_knp[i].value.ui32 = phys_kn_entry.value.ui32;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel delta64 = phys_kn_entry.value.ui64 -
193974072f41a843678abf5f61979c748687e66bSherry Moore phys_last_knp[i].value.ui64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel phys_last_knp[i].value.ui64 = phys_kn_entry.value.ui64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sum_knp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * now we need to save the value
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (sum_knp[i].data_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case KSTAT_DATA_UINT32:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* trunk down to 32 bits, possibly lossy */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sum_knp[i].value.ui32 += (uint32_t)delta64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel sum_knp[i].value.ui64 += delta64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KSTAT, ("man_sum_kstats: returns\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *_ms_flags[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "NONE",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "FAST", /* 0x1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "RAW", /* 0x2 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "ALLPHYS", /* 0x4 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "ALLMULTI", /* 0x8 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "ALLSAP", /* 0x10 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "CKSUM", /* 0x20 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "MULTI", /* 0x40 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SERLPBK", /* 0x80 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "MACLPBK", /* 0x100 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "CLOSING", /* 0x200 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "CLOSE_DONE", /* 0x400 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "CONTROL" /* 0x800 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_print_msp(manstr_t *msp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char buf[512];
03831d35f7499c87d51205817c93e9a8d42c4baestevel char prbuf[512];
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmsp(0x%p)\n", (void *)msp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\t%s%d SAP(0x%x):\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_major_to_name(msp->ms_meta_maj), msp->ms_meta_ppa,
193974072f41a843678abf5f61979c748687e66bSherry Moore msp->ms_sap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel prbuf[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel flags = msp->ms_flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < A_CNT(_ms_flags); i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((flags >> i) & 0x1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(buf, " %s |", _ms_flags[i+1]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel strcat(prbuf, buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel prbuf[strlen(prbuf) - 1] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tms_flags: %s\n", prbuf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tms_dlpistate: %s\n", dss[msp->ms_dlpistate]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tms_dl_mp: 0x%p\n", (void *)msp->ms_dl_mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tms_manp: 0x%p\n", (void *)msp->ms_manp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tms_dests: 0x%p\n", (void *)msp->ms_dests);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *_md_state[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "NOTPRESENT", /* 0x0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "INITIALIZING", /* 0x1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "READY", /* 0x2 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "PLUMBING", /* 0x4 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "CLOSING" /* 0x8 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_print_mdp(man_dest_t *mdp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char buf[64];
03831d35f7499c87d51205817c93e9a8d42c4baestevel char prbuf[512];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel prbuf[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmdp(0x%p)\n", (void *)mdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmd_pg_id: %d\n", mdp->md_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmd_dst_eaddr: %s\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ether_sprintf(&mdp->md_dst_eaddr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmd_src_eaddr: %s\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ether_sprintf(&mdp->md_src_eaddr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmd_dlpistate: %s", dss[mdp->md_dlpistate]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmd_muxid: 0x%u", mdp->md_muxid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmd_rcvcnt %lu md_lastrcvcnt %lu", mdp->md_rcvcnt,
193974072f41a843678abf5f61979c748687e66bSherry Moore mdp->md_lastrcvcnt);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Print out state as text.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel state = mdp->md_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (state == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel strcat(prbuf, _md_state[0]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < A_CNT(_md_state); i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((state >> i) & 0x1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(buf, " %s |", _md_state[i+1]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel strcat(prbuf, buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel prbuf[strlen(prbuf) -1] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmd_state: %s", prbuf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmd_device:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_print_dev(&mdp->md_device);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_print_man(man_t *manp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char buf[512];
03831d35f7499c87d51205817c93e9a8d42c4baestevel char prbuf[512];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel prbuf[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (manp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_major_to_name(manp->man_meta_major)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(buf, "\t man_device: %s%d\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_major_to_name(manp->man_meta_major),
193974072f41a843678abf5f61979c748687e66bSherry Moore manp->man_meta_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(buf, "\t major: %d", manp->man_meta_major);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(buf, "\t ppa: %d", manp->man_meta_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "%s", buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *_mdev_state[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "UNASSIGNED ",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "ASSIGNED",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "ACTIVE",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "FAILED"
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_print_dev(man_dev_t *mdevp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char buf[512];
03831d35f7499c87d51205817c93e9a8d42c4baestevel char prbuf[512];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel prbuf[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdevp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mdevp->mdev_major == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevelnumber:
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(buf, "\t mdev_major: %d\n", mdevp->mdev_major);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (ddi_major_to_name(mdevp->mdev_major)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(buf, "\t mdev_device: %s%d\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_major_to_name(mdevp->mdev_major),
193974072f41a843678abf5f61979c748687e66bSherry Moore mdevp->mdev_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto number;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "%s", buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\t mdev_exp_id: %d\n", mdevp->mdev_exp_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel prbuf[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel state = mdevp->mdev_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (state == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel strcat(prbuf, _mdev_state[0]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < A_CNT(_mdev_state); i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((state >> i) & 0x1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sprintf(buf, " %s |", _mdev_state[i+1]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel strcat(prbuf, buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel prbuf[strlen(prbuf) - 2] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\t mdev_state: %s\n", prbuf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_print_mtp(mi_time_t *mtp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmtp(0x%p)\n", (void *)mtp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mtp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmtp_instance: %d\n", mtp->mtp_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmtp_time: %d\n", mtp->mtp_time);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_print_mip(mi_path_t *mip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmip(0x%p)\n", (void *)mip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mip == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmip_pg_id: %d\n", mip->mip_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmip_cmd: %s\n", _mip_cmd[mip->mip_cmd]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmip_eaddr: %s\n", ether_sprintf(&mip->mip_eaddr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmip_devs: 0x%p\n", (void *)mip->mip_devs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmip_ndevs: %d\n", mip->mip_ndevs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_print_mpg(man_pg_t *mpg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmpg(0x%p)\n", (void *)mpg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mpg == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmpg_next: 0x%p\n", (void *)mpg->mpg_next);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmpg_pg_id: %d\n", mpg->mpg_pg_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmpg_man_ppa: %d\n", mpg->mpg_man_ppa);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmpg_dst_eaddr: %s\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ether_sprintf(&mpg->mpg_dst_eaddr));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmpg_pathp: 0x%p\n", (void *)mpg->mpg_pathp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *_mw_flags[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "NOWAITER", /* 0x0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "CVWAITER", /* 0x1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "QWAITER", /* 0x2 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "DONE" /* 0x3 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_print_work(man_work_t *wp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\twp(0x%p)\n\n", (void *)wp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmw_type: %s\n", _mw_type[wp->mw_type]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmw_flags: ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < A_CNT(_mw_flags); i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((wp->mw_flags >> i) & 0x1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "%s", _mw_flags[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\twp_status: %d\n", wp->mw_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\twp_arg: 0x%p\n", (void *)&wp->mw_arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmw_next: 0x%p\n", (void *)wp->mw_next);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\twp_q: 0x%p", (void *)wp->mw_q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_print_path(man_path_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmp(0x%p)\n\n", (void *)mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmp_device:");
03831d35f7499c87d51205817c93e9a8d42c4baestevel man_print_dev(&mp->mp_device);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmp_next: 0x%p\n", (void *)mp->mp_next);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmp_last_knp: 0x%p\n", (void *)mp->mp_last_knp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\tmp_lru: 0x%lx", mp->mp_lru);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid *
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dbg_kzalloc(int line, size_t size, int kmflags)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = kmem_zalloc(size, kmflags);
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KMEM, ("0x%p %lu\tzalloc'd @ %d\n", (void *)tmp,
193974072f41a843678abf5f61979c748687e66bSherry Moore size, line));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (tmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelman_dbg_kfree(int line, void *buf, size_t size)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel MAN_DBG(MAN_KMEM, ("0x%p %lu\tfree'd @ %d\n", (void *)buf, size, line));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(buf, size);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */