Home | History | Annotate | Download | only in usb_ia
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 
     27 /*
     28  * usb interface association driver
     29  *
     30  *	this driver attempts to the interface association node and
     31  *	creates/manages child nodes for the included interfaces.
     32  */
     33 
     34 #if defined(lint) && !defined(DEBUG)
     35 #define	DEBUG	1
     36 #endif
     37 #include <sys/usb/usba/usbai_version.h>
     38 #include <sys/usb/usba.h>
     39 #include <sys/usb/usba/usba_types.h>
     40 #include <sys/usb/usba/usba_impl.h>
     41 #include <sys/usb/usb_ia/usb_iavar.h>
     42 
     43 /* Debugging support */
     44 uint_t usb_ia_errlevel = USB_LOG_L4;
     45 uint_t usb_ia_errmask = (uint_t)DPRINT_MASK_ALL;
     46 uint_t usb_ia_instance_debug = (uint_t)-1;
     47 uint_t usb_ia_bus_config_debug = 0;
     48 
     49 _NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ia_errlevel))
     50 _NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ia_errmask))
     51 _NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ia_instance_debug))
     52 
     53 _NOTE(SCHEME_PROTECTS_DATA("unique", msgb))
     54 _NOTE(SCHEME_PROTECTS_DATA("unique", dev_info))
     55 _NOTE(SCHEME_PROTECTS_DATA("unique", usb_pipe_policy))
     56 
     57 static struct cb_ops usb_ia_cb_ops = {
     58 	nodev,		/* open */
     59 	nodev,		/* close */
     60 	nodev,		/* strategy */
     61 	nodev,		/* print */
     62 	nodev,		/* dump */
     63 	nodev,		/* read */
     64 	nodev,		/* write */
     65 	nodev,		/* ioctl */
     66 	nodev,		/* devmap */
     67 	nodev,		/* mmap */
     68 	nodev,		/* segmap */
     69 	nochpoll,	/* poll */
     70 	ddi_prop_op,	/* prop_op */
     71 	NULL,		/* aread */
     72 	D_MP
     73 };
     74 
     75 static int usb_ia_busop_get_eventcookie(dev_info_t *dip,
     76 			dev_info_t *rdip,
     77 			char *eventname,
     78 			ddi_eventcookie_t *cookie);
     79 static int usb_ia_busop_add_eventcall(dev_info_t *dip,
     80 			dev_info_t *rdip,
     81 			ddi_eventcookie_t cookie,
     82 			void (*callback)(dev_info_t *dip,
     83 				ddi_eventcookie_t cookie, void *arg,
     84 				void *bus_impldata),
     85 			void *arg, ddi_callback_id_t *cb_id);
     86 static int usb_ia_busop_remove_eventcall(dev_info_t *dip,
     87 			ddi_callback_id_t cb_id);
     88 static int usb_ia_busop_post_event(dev_info_t *dip,
     89 			dev_info_t *rdip,
     90 			ddi_eventcookie_t cookie,
     91 			void *bus_impldata);
     92 static int usb_ia_bus_config(dev_info_t *dip,
     93 			uint_t flag,
     94 			ddi_bus_config_op_t op,
     95 			void *arg,
     96 			dev_info_t **child);
     97 static int usb_ia_bus_unconfig(dev_info_t *dip,
     98 			uint_t flag,
     99 			ddi_bus_config_op_t op,
    100 			void *arg);
    101 
    102 /*
    103  * autoconfiguration data and routines.
    104  */
    105 static int	usb_ia_info(dev_info_t *, ddi_info_cmd_t,
    106 				void *, void **);
    107 static int	usb_ia_attach(dev_info_t *, ddi_attach_cmd_t);
    108 static int	usb_ia_detach(dev_info_t *, ddi_detach_cmd_t);
    109 
    110 /* other routines */
    111 static void usb_ia_create_pm_components(dev_info_t *, usb_ia_t *);
    112 static int usb_ia_bus_ctl(dev_info_t *, dev_info_t	*,
    113 				ddi_ctl_enum_t, void *, void *);
    114 static int usb_ia_power(dev_info_t *, int, int);
    115 static int usb_ia_restore_device_state(dev_info_t *, usb_ia_t *);
    116 static usb_ia_t  *usb_ia_obtain_state(dev_info_t *);
    117 static void usb_ia_event_cb(dev_info_t *, ddi_eventcookie_t, void *, void *);
    118 
    119 /* prototypes */
    120 static void usb_ia_create_children(usb_ia_t *);
    121 static int usb_ia_cleanup(usb_ia_t *);
    122 
    123 /*
    124  * Busops vector
    125  */
    126 static struct bus_ops usb_ia_busops = {
    127 	BUSO_REV,
    128 	nullbusmap,			/* bus_map */
    129 	NULL,				/* bus_get_intrspec */
    130 	NULL,				/* bus_add_intrspec */
    131 	NULL,				/* bus_remove_intrspec */
    132 	NULL,				/* XXXX bus_map_fault */
    133 	ddi_dma_map,			/* bus_dma_map */
    134 	ddi_dma_allochdl,
    135 	ddi_dma_freehdl,
    136 	ddi_dma_bindhdl,
    137 	ddi_dma_unbindhdl,
    138 	ddi_dma_flush,
    139 	ddi_dma_win,
    140 	ddi_dma_mctl,			/* bus_dma_ctl */
    141 	usb_ia_bus_ctl,		/* bus_ctl */
    142 	ddi_bus_prop_op,		/* bus_prop_op */
    143 	usb_ia_busop_get_eventcookie,
    144 	usb_ia_busop_add_eventcall,
    145 	usb_ia_busop_remove_eventcall,
    146 	usb_ia_busop_post_event,	/* bus_post_event */
    147 	NULL,				/* bus_intr_ctl */
    148 	usb_ia_bus_config,		/* bus_config */
    149 	usb_ia_bus_unconfig,		/* bus_unconfig */
    150 	NULL,				/* bus_fm_init */
    151 	NULL,				/* bus_fm_fini */
    152 	NULL,				/* bus_fm_access_enter */
    153 	NULL,				/* bus_fm_access_exit */
    154 	NULL				/* bus_power */
    155 };
    156 
    157 
    158 static struct dev_ops usb_ia_ops = {
    159 	DEVO_REV,		/* devo_rev, */
    160 	0,			/* refcnt  */
    161 	usb_ia_info,		/* info */
    162 	nulldev,		/* identify */
    163 	nulldev,		/* probe */
    164 	usb_ia_attach,		/* attach */
    165 	usb_ia_detach,		/* detach */
    166 	nodev,			/* reset */
    167 	&usb_ia_cb_ops,	/* driver operations */
    168 	&usb_ia_busops,	/* bus operations */
    169 	usb_ia_power,		/* power */
    170 	ddi_quiesce_not_needed,	/* devo_quiesce */
    171 };
    172 
    173 static struct modldrv modldrv = {
    174 	&mod_driverops, /* Type of module. This one is a driver */
    175 	"USB Interface Association Driver", /* Name of the module. */
    176 	&usb_ia_ops,	/* driver ops */
    177 };
    178 
    179 static struct modlinkage modlinkage = {
    180 	MODREV_1, (void *)&modldrv, NULL
    181 };
    182 
    183 #define	USB_IA_INITIAL_SOFT_SPACE 4
    184 static	void	*usb_ia_statep;
    185 
    186 /*
    187  * event definition
    188  */
    189 static ndi_event_definition_t usb_ia_ndi_event_defs[] = {
    190 	{USBA_EVENT_TAG_HOT_REMOVAL, DDI_DEVI_REMOVE_EVENT, EPL_KERNEL,
    191 						NDI_EVENT_POST_TO_ALL},
    192 	{USBA_EVENT_TAG_HOT_INSERTION, DDI_DEVI_INSERT_EVENT, EPL_KERNEL,
    193 						NDI_EVENT_POST_TO_ALL},
    194 	{USBA_EVENT_TAG_POST_RESUME, USBA_POST_RESUME_EVENT, EPL_KERNEL,
    195 						NDI_EVENT_POST_TO_ALL},
    196 	{USBA_EVENT_TAG_PRE_SUSPEND, USBA_PRE_SUSPEND_EVENT, EPL_KERNEL,
    197 						NDI_EVENT_POST_TO_ALL}
    198 };
    199 
    200 #define	USB_IA_N_NDI_EVENTS \
    201 	(sizeof (usb_ia_ndi_event_defs) / sizeof (ndi_event_definition_t))
    202 
    203 static	ndi_event_set_t usb_ia_ndi_events = {
    204 	NDI_EVENTS_REV1, USB_IA_N_NDI_EVENTS, usb_ia_ndi_event_defs};
    205 
    206 
    207 /*
    208  * standard driver entry points
    209  */
    210 int
    211 _init(void)
    212 {
    213 	int rval;
    214 
    215 	rval = ddi_soft_state_init(&usb_ia_statep, sizeof (struct usb_ia),
    216 	    USB_IA_INITIAL_SOFT_SPACE);
    217 	if (rval != 0) {
    218 		return (rval);
    219 	}
    220 
    221 	if ((rval = mod_install(&modlinkage)) != 0) {
    222 		ddi_soft_state_fini(&usb_ia_statep);
    223 		return (rval);
    224 	}
    225 
    226 	return (rval);
    227 }
    228 
    229 
    230 int
    231 _fini(void)
    232 {
    233 	int	rval;
    234 
    235 	rval = mod_remove(&modlinkage);
    236 
    237 	if (rval) {
    238 		return (rval);
    239 	}
    240 
    241 	ddi_soft_state_fini(&usb_ia_statep);
    242 
    243 	return (rval);
    244 }
    245 
    246 
    247 int
    248 _info(struct modinfo *modinfop)
    249 {
    250 	return (mod_info(&modlinkage, modinfop));
    251 }
    252 
    253 
    254 /*ARGSUSED*/
    255 static int
    256 usb_ia_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
    257 {
    258 	usb_ia_t	*usb_ia;
    259 	int		instance = getminor((dev_t)arg);
    260 	int		error = DDI_FAILURE;
    261 
    262 	switch (infocmd) {
    263 	case DDI_INFO_DEVT2DEVINFO:
    264 		if ((usb_ia = ddi_get_soft_state(usb_ia_statep,
    265 		    instance)) != NULL) {
    266 			*result = (void *)usb_ia->ia_dip;
    267 			if (*result != NULL) {
    268 				error = DDI_SUCCESS;
    269 			}
    270 		} else {
    271 			*result = NULL;
    272 		}
    273 		break;
    274 
    275 	case DDI_INFO_DEVT2INSTANCE:
    276 		*result = (void *)(intptr_t)instance;
    277 		error = DDI_SUCCESS;
    278 		break;
    279 	default:
    280 		break;
    281 	}
    282 
    283 	return (error);
    284 }
    285 
    286 
    287 /*
    288  * child  post attach/detach notification
    289  */
    290 static void
    291 usb_ia_post_attach(usb_ia_t *usb_ia, uint8_t ifno, struct attachspec *as)
    292 {
    293 	USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
    294 	    "usb_ia_post_attach: ifno = %d result = %d", ifno, as->result);
    295 
    296 }
    297 
    298 
    299 static void
    300 usb_ia_post_detach(usb_ia_t *usb_ia, uint8_t ifno, struct detachspec *ds)
    301 {
    302 	USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
    303 	    "usb_ia_post_detach: ifno = %d result = %d", ifno, ds->result);
    304 
    305 }
    306 
    307 
    308 /*
    309  * bus ctl support. we handle notifications here and the
    310  * rest goes up to root hub/hcd
    311  */
    312 /*ARGSUSED*/
    313 static int
    314 usb_ia_bus_ctl(dev_info_t *dip,
    315 	dev_info_t	*rdip,
    316 	ddi_ctl_enum_t	op,
    317 	void		*arg,
    318 	void		*result)
    319 {
    320 	usba_device_t *hub_usba_device = usba_get_usba_device(rdip);
    321 	dev_info_t *root_hub_dip = hub_usba_device->usb_root_hub_dip;
    322 	usb_ia_t  *usb_ia;
    323 	struct attachspec *as;
    324 	struct detachspec *ds;
    325 
    326 	usb_ia = usb_ia_obtain_state(dip);
    327 
    328 	USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
    329 	    "usb_ia_bus_ctl:\n\t"
    330 	    "dip = 0x%p, rdip = 0x%p, op = 0x%x, arg = 0x%p",
    331 	    (void *)dip, (void *)rdip, op, arg);
    332 
    333 	switch (op) {
    334 	case DDI_CTLOPS_ATTACH:
    335 		as = (struct attachspec *)arg;
    336 
    337 		switch (as->when) {
    338 		case DDI_PRE :
    339 			/* nothing to do basically */
    340 			USB_DPRINTF_L2(DPRINT_MASK_PM, usb_ia->ia_log_handle,
    341 			    "DDI_PRE DDI_CTLOPS_ATTACH");
    342 			break;
    343 		case DDI_POST :
    344 			usb_ia_post_attach(usb_ia, usba_get_ifno(rdip),
    345 			    (struct attachspec *)arg);
    346 			break;
    347 		}
    348 
    349 		break;
    350 	case DDI_CTLOPS_DETACH:
    351 		ds = (struct detachspec *)arg;
    352 
    353 		switch (ds->when) {
    354 		case DDI_PRE :
    355 			/* nothing to do basically */
    356 			USB_DPRINTF_L2(DPRINT_MASK_PM, usb_ia->ia_log_handle,
    357 			    "DDI_PRE DDI_CTLOPS_DETACH");
    358 			break;
    359 		case DDI_POST :
    360 			usb_ia_post_detach(usb_ia, usba_get_ifno(rdip),
    361 			    (struct detachspec *)arg);
    362 			break;
    363 		}
    364 
    365 		break;
    366 	default:
    367 		/* pass to root hub to handle */
    368 		return (usba_bus_ctl(root_hub_dip, rdip, op, arg, result));
    369 	}
    370 
    371 	return (DDI_SUCCESS);
    372 }
    373 
    374 
    375 /*
    376  * bus enumeration entry points
    377  */
    378 static int
    379 usb_ia_bus_config(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
    380     void *arg, dev_info_t **child)
    381 {
    382 	int		rval, circ;
    383 	usb_ia_t	*usb_ia = usb_ia_obtain_state(dip);
    384 
    385 	USB_DPRINTF_L4(DPRINT_MASK_ALL, usb_ia->ia_log_handle,
    386 	    "usb_ia_bus_config: op=%d", op);
    387 
    388 	if (usb_ia_bus_config_debug) {
    389 		flag |= NDI_DEVI_DEBUG;
    390 	}
    391 
    392 	ndi_devi_enter(dip, &circ);
    393 
    394 	/* enumerate each interface below us */
    395 	mutex_enter(&usb_ia->ia_mutex);
    396 	usb_ia_create_children(usb_ia);
    397 	mutex_exit(&usb_ia->ia_mutex);
    398 
    399 	rval = ndi_busop_bus_config(dip, flag, op, arg, child, 0);
    400 	ndi_devi_exit(dip, circ);
    401 
    402 	return (rval);
    403 }
    404 
    405 
    406 static int
    407 usb_ia_bus_unconfig(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
    408     void *arg)
    409 {
    410 	usb_ia_t  *usb_ia = usb_ia_obtain_state(dip);
    411 
    412 	dev_info_t	*cdip, *mdip;
    413 	int		interface, circular_count;
    414 	int		rval = NDI_SUCCESS;
    415 
    416 	USB_DPRINTF_L4(DPRINT_MASK_ALL, usb_ia->ia_log_handle,
    417 	    "usb_ia_bus_unconfig: op=%d", op);
    418 
    419 	if (usb_ia_bus_config_debug) {
    420 		flag |= NDI_DEVI_DEBUG;
    421 	}
    422 
    423 	/*
    424 	 * first offline and if offlining successful, then
    425 	 * remove children
    426 	 */
    427 	if (op == BUS_UNCONFIG_ALL) {
    428 		flag &= ~(NDI_DEVI_REMOVE | NDI_UNCONFIG);
    429 	}
    430 
    431 	ndi_devi_enter(dip, &circular_count);
    432 	rval = ndi_busop_bus_unconfig(dip, flag, op, arg);
    433 
    434 	if (op == BUS_UNCONFIG_ALL && rval == NDI_SUCCESS &&
    435 	    (flag & NDI_AUTODETACH) == 0) {
    436 		flag |= NDI_DEVI_REMOVE;
    437 		rval = ndi_busop_bus_unconfig(dip, flag, op, arg);
    438 	}
    439 
    440 	/* update children's list */
    441 	mutex_enter(&usb_ia->ia_mutex);
    442 	for (interface = 0; usb_ia->ia_children_dips &&
    443 	    (interface < usb_ia->ia_n_ifs); interface++) {
    444 		mdip = usb_ia->ia_children_dips[interface];
    445 
    446 		/* now search if this dip still exists */
    447 		for (cdip = ddi_get_child(dip); cdip && (cdip != mdip); )
    448 			cdip = ddi_get_next_sibling(cdip);
    449 
    450 		if (cdip != mdip) {
    451 			/* we lost the dip on this interface */
    452 			usb_ia->ia_children_dips[interface] = NULL;
    453 		} else if (cdip) {
    454 			/*
    455 			 * keep in DS_INITALIZED to prevent parent
    456 			 * from detaching
    457 			 */
    458 			(void) ddi_initchild(ddi_get_parent(cdip), cdip);
    459 		}
    460 	}
    461 	mutex_exit(&usb_ia->ia_mutex);
    462 
    463 	ndi_devi_exit(dip, circular_count);
    464 
    465 	USB_DPRINTF_L4(DPRINT_MASK_ALL, usb_ia->ia_log_handle,
    466 	    "usb_ia_bus_config: rval=%d", rval);
    467 
    468 	return (rval);
    469 }
    470 
    471 
    472 /* power entry point */
    473 /* ARGSUSED */
    474 static int
    475 usb_ia_power(dev_info_t *dip, int comp, int level)
    476 {
    477 	usb_ia_t		*usb_ia;
    478 	usb_common_power_t	*pm;
    479 	int			rval = DDI_FAILURE;
    480 
    481 	usb_ia = usb_ia_obtain_state(dip);
    482 
    483 	USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
    484 	    "usb_ia_power: Begin: usb_ia = %p, level = %d",
    485 	    (void *)usb_ia, level);
    486 
    487 	mutex_enter(&usb_ia->ia_mutex);
    488 	pm = usb_ia->ia_pm;
    489 
    490 	/* check if we are transitioning to a legal power level */
    491 	if (USB_DEV_PWRSTATE_OK(pm->uc_pwr_states, level)) {
    492 		USB_DPRINTF_L2(DPRINT_MASK_PM, usb_ia->ia_log_handle,
    493 		    "usb_ia_power: illegal power level = %d "
    494 		    "uc_pwr_states = %x", level, pm->uc_pwr_states);
    495 
    496 		mutex_exit(&usb_ia->ia_mutex);
    497 
    498 		return (rval);
    499 	}
    500 
    501 	rval = usba_common_power(dip, &(pm->uc_current_power),
    502 	    &(usb_ia->ia_dev_state), level);
    503 
    504 	mutex_exit(&usb_ia->ia_mutex);
    505 
    506 	return (rval);
    507 }
    508 
    509 /*
    510  * attach/resume entry point
    511  */
    512 static int
    513 usb_ia_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
    514 {
    515 	int		instance = ddi_get_instance(dip);
    516 	usb_ia_t	*usb_ia = NULL;
    517 	uint_t		n_ifs;
    518 	size_t		size;
    519 
    520 	switch (cmd) {
    521 	case DDI_ATTACH:
    522 
    523 		break;
    524 	case DDI_RESUME:
    525 		usb_ia = ddi_get_soft_state(usb_ia_statep, instance);
    526 		(void) usb_ia_restore_device_state(dip, usb_ia);
    527 
    528 		return (DDI_SUCCESS);
    529 	default:
    530 
    531 		return (DDI_FAILURE);
    532 	}
    533 
    534 	/*
    535 	 * Attach:
    536 	 *
    537 	 * Allocate soft state and initialize
    538 	 */
    539 	if (ddi_soft_state_zalloc(usb_ia_statep, instance) != DDI_SUCCESS) {
    540 		goto fail;
    541 	}
    542 
    543 	usb_ia = ddi_get_soft_state(usb_ia_statep, instance);
    544 	if (usb_ia == NULL) {
    545 
    546 		goto fail;
    547 	}
    548 
    549 	/* allocate handle for logging of messages */
    550 	usb_ia->ia_log_handle = usb_alloc_log_hdl(dip, "ia",
    551 	    &usb_ia_errlevel,
    552 	    &usb_ia_errmask, &usb_ia_instance_debug,
    553 	    0);
    554 
    555 	usb_ia->ia_dip	= dip;
    556 	usb_ia->ia_instance = instance;
    557 	usb_ia->ia_first_if = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
    558 	    DDI_PROP_DONTPASS, "interface", -1);
    559 	usb_ia->ia_n_ifs = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
    560 	    DDI_PROP_DONTPASS, "interface-count", -1);
    561 
    562 	if (usb_ia->ia_first_if < 0 || usb_ia->ia_n_ifs < 0) {
    563 		USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
    564 		    "interface-association property failed");
    565 
    566 		goto fail;
    567 	}
    568 
    569 	/* attach client driver to USBA */
    570 	if (usb_client_attach(dip, USBDRV_VERSION, 0) != USB_SUCCESS) {
    571 		USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
    572 		    "usb_client_attach failed");
    573 		goto fail;
    574 	}
    575 	if (usb_get_dev_data(dip, &usb_ia->ia_dev_data, USB_PARSE_LVL_NONE,
    576 	    0) != USB_SUCCESS) {
    577 		USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
    578 		    "usb_get_dev_data failed");
    579 		goto fail;
    580 	}
    581 
    582 	mutex_init(&usb_ia->ia_mutex, NULL, MUTEX_DRIVER,
    583 	    usb_ia->ia_dev_data->dev_iblock_cookie);
    584 
    585 	usb_free_dev_data(dip, usb_ia->ia_dev_data);
    586 	usb_ia->ia_dev_data = NULL;
    587 
    588 	usb_ia->ia_init_state |= USB_IA_LOCK_INIT;
    589 
    590 	if (ddi_create_minor_node(dip, "usb_ia", S_IFCHR, instance,
    591 	    DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
    592 		USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
    593 		    "cannot create devctl minor node");
    594 		goto fail;
    595 	}
    596 
    597 	usb_ia->ia_init_state |= USB_IA_MINOR_NODE_CREATED;
    598 
    599 	/*
    600 	 * allocate array for keeping track of child dips
    601 	 */
    602 	n_ifs = usb_ia->ia_n_ifs;
    603 	usb_ia->ia_cd_list_length = size = (sizeof (dev_info_t *)) * n_ifs;
    604 
    605 	usb_ia->ia_children_dips = kmem_zalloc(size, KM_SLEEP);
    606 	usb_ia->ia_child_events = kmem_zalloc(sizeof (uint8_t) * n_ifs,
    607 	    KM_SLEEP);
    608 	/*
    609 	 * Event handling: definition and registration
    610 	 * get event handle for events that we have defined
    611 	 */
    612 	(void) ndi_event_alloc_hdl(dip, 0, &usb_ia->ia_ndi_event_hdl,
    613 	    NDI_SLEEP);
    614 
    615 	/* bind event set to the handle */
    616 	if (ndi_event_bind_set(usb_ia->ia_ndi_event_hdl, &usb_ia_ndi_events,
    617 	    NDI_SLEEP)) {
    618 		USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
    619 		    "usb_ia_attach: binding event set failed");
    620 
    621 		goto fail;
    622 	}
    623 
    624 	usb_ia->ia_dev_state = USB_DEV_ONLINE;
    625 
    626 	/*
    627 	 * now create components to power manage this device
    628 	 * before attaching children
    629 	 */
    630 	usb_ia_create_pm_components(dip, usb_ia);
    631 
    632 	/* event registration for events from our parent */
    633 	usba_common_register_events(dip, n_ifs, usb_ia_event_cb);
    634 
    635 	usb_ia->ia_init_state |= USB_IA_EVENTS_REGISTERED;
    636 
    637 	ddi_report_dev(dip);
    638 
    639 	return (DDI_SUCCESS);
    640 
    641 fail:
    642 	USB_DPRINTF_L2(DPRINT_MASK_ATTA, NULL, "usb_ia%d cannot attach",
    643 	    instance);
    644 
    645 	if (usb_ia) {
    646 		(void) usb_ia_cleanup(usb_ia);
    647 	}
    648 
    649 	return (DDI_FAILURE);
    650 }
    651 
    652 
    653 /* detach or suspend this instance */
    654 static int
    655 usb_ia_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
    656 {
    657 	usb_ia_t	*usb_ia = usb_ia_obtain_state(dip);
    658 
    659 	USB_DPRINTF_L4(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
    660 	    "usb_ia_detach: cmd = 0x%x", cmd);
    661 
    662 	switch (cmd) {
    663 	case DDI_DETACH:
    664 
    665 		return (usb_ia_cleanup(usb_ia));
    666 	case DDI_SUSPEND:
    667 		/* nothing to do */
    668 		mutex_enter(&usb_ia->ia_mutex);
    669 		usb_ia->ia_dev_state = USB_DEV_SUSPENDED;
    670 		mutex_exit(&usb_ia->ia_mutex);
    671 
    672 		return (DDI_SUCCESS);
    673 	default:
    674 
    675 		return (DDI_FAILURE);
    676 	}
    677 
    678 	_NOTE(NOT_REACHED)
    679 	/* NOTREACHED */
    680 }
    681 
    682 
    683 /*
    684  * usb_ia_cleanup:
    685  *	cleanup usb_ia and deallocate. this function is called for
    686  *	handling attach failures and detaching including dynamic
    687  *	reconfiguration
    688  */
    689 /*ARGSUSED*/
    690 static int
    691 usb_ia_cleanup(usb_ia_t *usb_ia)
    692 {
    693 	usb_common_power_t	*iapm;
    694 	int			rval;
    695 	dev_info_t	*dip = usb_ia->ia_dip;
    696 
    697 	USB_DPRINTF_L4(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
    698 	    "usb_ia_cleanup:");
    699 
    700 	if ((usb_ia->ia_init_state & USB_IA_LOCK_INIT) == 0) {
    701 
    702 		goto done;
    703 	}
    704 
    705 	/*
    706 	 * deallocate events, if events are still registered
    707 	 * (ie. children still attached) then we have to fail the detach
    708 	 */
    709 	if (usb_ia->ia_ndi_event_hdl &&
    710 	    (ndi_event_free_hdl(usb_ia->ia_ndi_event_hdl) != NDI_SUCCESS)) {
    711 
    712 		USB_DPRINTF_L2(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
    713 		    "usb_ia_cleanup: ndi_event_free_hdl failed");
    714 
    715 		return (DDI_FAILURE);
    716 	}
    717 
    718 	/*
    719 	 * Disable the event callbacks, after this point, event
    720 	 * callbacks will never get called. Note we shouldn't hold
    721 	 * mutex while unregistering events because there may be a
    722 	 * competing event callback thread. Event callbacks are done
    723 	 * with ndi mutex held and this can cause a potential deadlock.
    724 	 * Note that cleanup can't fail after deregistration of events.
    725 	 */
    726 	if (usb_ia->ia_init_state & USB_IA_EVENTS_REGISTERED) {
    727 
    728 		usba_common_unregister_events(usb_ia->ia_dip, usb_ia->ia_n_ifs);
    729 	}
    730 
    731 	iapm = usb_ia->ia_pm;
    732 
    733 	mutex_enter(&usb_ia->ia_mutex);
    734 
    735 	if ((iapm) && (usb_ia->ia_dev_state != USB_DEV_DISCONNECTED)) {
    736 
    737 		mutex_exit(&usb_ia->ia_mutex);
    738 
    739 		(void) pm_busy_component(dip, 0);
    740 		if (iapm->uc_wakeup_enabled) {
    741 
    742 			/* First bring the device to full power */
    743 			(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
    744 
    745 			rval = usb_handle_remote_wakeup(dip,
    746 			    USB_REMOTE_WAKEUP_DISABLE);
    747 
    748 			if (rval != DDI_SUCCESS) {
    749 				USB_DPRINTF_L2(DPRINT_MASK_EVENTS,
    750 				    usb_ia->ia_log_handle,
    751 				    "usb_cleanup: disable remote "
    752 				    "wakeup failed, rval=%d", rval);
    753 			}
    754 		}
    755 
    756 		(void) pm_lower_power(usb_ia->ia_dip, 0, USB_DEV_OS_PWR_OFF);
    757 		(void) pm_idle_component(dip, 0);
    758 	} else {
    759 		mutex_exit(&usb_ia->ia_mutex);
    760 	}
    761 
    762 	if (iapm) {
    763 		kmem_free(iapm, sizeof (usb_common_power_t));
    764 	}
    765 
    766 	/* free children list */
    767 	if (usb_ia->ia_children_dips) {
    768 		kmem_free(usb_ia->ia_children_dips,
    769 		    usb_ia->ia_cd_list_length);
    770 	}
    771 
    772 	if (usb_ia->ia_child_events) {
    773 		kmem_free(usb_ia->ia_child_events, sizeof (uint8_t) *
    774 		    usb_ia->ia_n_ifs);
    775 	}
    776 
    777 	if (usb_ia->ia_init_state & USB_IA_MINOR_NODE_CREATED) {
    778 		ddi_remove_minor_node(dip, NULL);
    779 	}
    780 
    781 	mutex_destroy(&usb_ia->ia_mutex);
    782 
    783 done:
    784 	usb_client_detach(dip, usb_ia->ia_dev_data);
    785 
    786 	usb_free_log_hdl(usb_ia->ia_log_handle);
    787 	ddi_soft_state_free(usb_ia_statep, ddi_get_instance(dip));
    788 
    789 	ddi_prop_remove_all(dip);
    790 
    791 	return (DDI_SUCCESS);
    792 }
    793 
    794 /*
    795  * usb_ia_create_children:
    796  */
    797 static void
    798 usb_ia_create_children(usb_ia_t *usb_ia)
    799 {
    800 	usba_device_t		*usba_device;
    801 	uint_t			n_ifs, first_if;
    802 	uint_t			i;
    803 	dev_info_t		*cdip;
    804 
    805 	usba_device = usba_get_usba_device(usb_ia->ia_dip);
    806 
    807 	USB_DPRINTF_L4(DPRINT_MASK_ATTA, usb_ia->ia_log_handle,
    808 	    "usb_ia_attach_child_drivers: port = %d, address = %d",
    809 	    usba_device->usb_port, usba_device->usb_addr);
    810 
    811 	n_ifs = usb_ia->ia_n_ifs;
    812 	first_if = usb_ia->ia_first_if;
    813 
    814 	/*
    815 	 * create all children if not already present
    816 	 */
    817 	for (i = 0; i < n_ifs; i++) {
    818 		if (usb_ia->ia_children_dips[i] != NULL) {
    819 
    820 			continue;
    821 		}
    822 
    823 		mutex_exit(&usb_ia->ia_mutex);
    824 		cdip = usba_ready_interface_node(usb_ia->ia_dip, first_if + i);
    825 		mutex_enter(&usb_ia->ia_mutex);
    826 
    827 		if (cdip != NULL) {
    828 			(void) usba_bind_driver(cdip);
    829 			usb_ia->ia_children_dips[i] = cdip;
    830 		}
    831 	}
    832 
    833 }
    834 
    835 
    836 /*
    837  * event support
    838  */
    839 static int
    840 usb_ia_busop_get_eventcookie(dev_info_t *dip,
    841 	dev_info_t *rdip, char *eventname, ddi_eventcookie_t *cookie)
    842 {
    843 	usb_ia_t  *usb_ia = usb_ia_obtain_state(dip);
    844 
    845 	USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
    846 	    "usb_ia_busop_get_eventcookie: dip=0x%p, rdip=0x%p, "
    847 	    "event=%s", (void *)dip, (void *)rdip, eventname);
    848 	USB_DPRINTF_L3(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
    849 	    "(dip=%s%d rdip=%s%d)",
    850 	    ddi_driver_name(dip), ddi_get_instance(dip),
    851 	    ddi_driver_name(rdip), ddi_get_instance(rdip));
    852 
    853 	/* return event cookie, iblock cookie, and level */
    854 	return (ndi_event_retrieve_cookie(usb_ia->ia_ndi_event_hdl,
    855 	    rdip, eventname, cookie, NDI_EVENT_NOPASS));
    856 }
    857 
    858 
    859 static int
    860 usb_ia_busop_add_eventcall(dev_info_t *dip,
    861 	dev_info_t *rdip,
    862 	ddi_eventcookie_t cookie,
    863 	void (*callback)(dev_info_t *dip,
    864 	    ddi_eventcookie_t cookie, void *arg,
    865 	    void *bus_impldata),
    866 	void *arg, ddi_callback_id_t *cb_id)
    867 {
    868 	int	ifno;
    869 	usb_ia_t  *usb_ia = usb_ia_obtain_state(dip);
    870 
    871 	mutex_enter(&usb_ia->ia_mutex);
    872 	ifno = usba_get_ifno(rdip)- usb_ia->ia_first_if;
    873 	mutex_exit(&usb_ia->ia_mutex);
    874 
    875 	if (ifno < 0) {
    876 		ifno = 0;
    877 	}
    878 
    879 	USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
    880 	    "usb_ia_busop_add_eventcall: dip=0x%p, rdip=0x%p "
    881 	    "cookie=0x%p, cb=0x%p, arg=0x%p",
    882 	    (void *)dip, (void *)rdip, (void *)cookie, (void *)callback, arg);
    883 	USB_DPRINTF_L3(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
    884 	    "(dip=%s%d rdip=%s%d event=%s)",
    885 	    ddi_driver_name(dip), ddi_get_instance(dip),
    886 	    ddi_driver_name(rdip), ddi_get_instance(rdip),
    887 	    ndi_event_cookie_to_name(usb_ia->ia_ndi_event_hdl, cookie));
    888 
    889 	/* Set flag on children registering events */
    890 	switch (ndi_event_cookie_to_tag(usb_ia->ia_ndi_event_hdl, cookie)) {
    891 	case USBA_EVENT_TAG_HOT_REMOVAL:
    892 		mutex_enter(&usb_ia->ia_mutex);
    893 		usb_ia->ia_child_events[ifno] |=
    894 		    USB_IA_CHILD_EVENT_DISCONNECT;
    895 		mutex_exit(&usb_ia->ia_mutex);
    896 
    897 		break;
    898 	case USBA_EVENT_TAG_PRE_SUSPEND:
    899 		mutex_enter(&usb_ia->ia_mutex);
    900 		usb_ia->ia_child_events[ifno] |=
    901 		    USB_IA_CHILD_EVENT_PRESUSPEND;
    902 		mutex_exit(&usb_ia->ia_mutex);
    903 
    904 		break;
    905 	default:
    906 
    907 		break;
    908 	}
    909 	/* add callback (perform registration) */
    910 	return (ndi_event_add_callback(usb_ia->ia_ndi_event_hdl,
    911 	    rdip, cookie, callback, arg, NDI_SLEEP, cb_id));
    912 }
    913 
    914 
    915 static int
    916 usb_ia_busop_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
    917 {
    918 	usb_ia_t  *usb_ia = usb_ia_obtain_state(dip);
    919 	ndi_event_callbacks_t *cb = (ndi_event_callbacks_t *)cb_id;
    920 
    921 	ASSERT(cb);
    922 
    923 	USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
    924 	    "usb_ia_busop_remove_eventcall: dip=0x%p, rdip=0x%p "
    925 	    "cookie=0x%p", (void *)dip, (void *)cb->ndi_evtcb_dip,
    926 	    (void *)cb->ndi_evtcb_cookie);
    927 	USB_DPRINTF_L3(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
    928 	    "(dip=%s%d rdip=%s%d event=%s)",
    929 	    ddi_driver_name(dip), ddi_get_instance(dip),
    930 	    ddi_driver_name(cb->ndi_evtcb_dip),
    931 	    ddi_get_instance(cb->ndi_evtcb_dip),
    932 	    ndi_event_cookie_to_name(usb_ia->ia_ndi_event_hdl,
    933 	    cb->ndi_evtcb_cookie));
    934 
    935 	/* remove event registration from our event set */
    936 	return (ndi_event_remove_callback(usb_ia->ia_ndi_event_hdl, cb_id));
    937 }
    938 
    939 
    940 static int
    941 usb_ia_busop_post_event(dev_info_t *dip,
    942 	dev_info_t *rdip,
    943 	ddi_eventcookie_t cookie,
    944 	void *bus_impldata)
    945 {
    946 	usb_ia_t  *usb_ia = usb_ia_obtain_state(dip);
    947 
    948 	USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
    949 	    "usb_ia_busop_post_event: dip=0x%p, rdip=0x%p "
    950 	    "cookie=0x%p, impl=0x%p",
    951 	    (void *)dip, (void *)rdip, (void *)cookie, bus_impldata);
    952 	USB_DPRINTF_L3(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
    953 	    "(dip=%s%d rdip=%s%d event=%s)",
    954 	    ddi_driver_name(dip), ddi_get_instance(dip),
    955 	    ddi_driver_name(rdip), ddi_get_instance(rdip),
    956 	    ndi_event_cookie_to_name(usb_ia->ia_ndi_event_hdl, cookie));
    957 
    958 	/* post event to all children registered for this event */
    959 	return (ndi_event_run_callbacks(usb_ia->ia_ndi_event_hdl, rdip,
    960 	    cookie, bus_impldata));
    961 }
    962 
    963 
    964 /*
    965  * usb_ia_restore_device_state
    966  *	set the original configuration of the device
    967  */
    968 static int
    969 usb_ia_restore_device_state(dev_info_t *dip, usb_ia_t *usb_ia)
    970 {
    971 	usb_common_power_t	*iapm;
    972 
    973 	USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
    974 	    "usb_ia_restore_device_state: usb_ia = %p", (void *)usb_ia);
    975 
    976 	mutex_enter(&usb_ia->ia_mutex);
    977 	iapm = usb_ia->ia_pm;
    978 	mutex_exit(&usb_ia->ia_mutex);
    979 
    980 	/* First bring the device to full power */
    981 	(void) pm_busy_component(dip, 0);
    982 	(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
    983 
    984 	if (usb_check_same_device(dip, usb_ia->ia_log_handle, USB_LOG_L0,
    985 	    DPRINT_MASK_EVENTS, USB_CHK_VIDPID, NULL) != USB_SUCCESS) {
    986 
    987 		/* change the device state from suspended to disconnected */
    988 		mutex_enter(&usb_ia->ia_mutex);
    989 		usb_ia->ia_dev_state = USB_DEV_DISCONNECTED;
    990 		mutex_exit(&usb_ia->ia_mutex);
    991 		(void) pm_idle_component(dip, 0);
    992 
    993 		return (USB_FAILURE);
    994 	}
    995 
    996 	/*
    997 	 * if the device had remote wakeup earlier,
    998 	 * enable it again
    999 	 */
   1000 	if (iapm->uc_wakeup_enabled) {
   1001 		(void) usb_handle_remote_wakeup(usb_ia->ia_dip,
   1002 		    USB_REMOTE_WAKEUP_ENABLE);
   1003 	}
   1004 
   1005 	mutex_enter(&usb_ia->ia_mutex);
   1006 	usb_ia->ia_dev_state = USB_DEV_ONLINE;
   1007 	mutex_exit(&usb_ia->ia_mutex);
   1008 
   1009 	(void) pm_idle_component(dip, 0);
   1010 
   1011 	return (USB_SUCCESS);
   1012 }
   1013 
   1014 
   1015 /*
   1016  * usb_ia_event_cb()
   1017  *	handle disconnect and connect events
   1018  */
   1019 static void
   1020 usb_ia_event_cb(dev_info_t *dip, ddi_eventcookie_t cookie,
   1021 	void *arg, void *bus_impldata)
   1022 {
   1023 	int		i, tag;
   1024 	usb_ia_t	*usb_ia = usb_ia_obtain_state(dip);
   1025 	dev_info_t	*child_dip;
   1026 	ddi_eventcookie_t rm_cookie, ins_cookie, suspend_cookie, resume_cookie;
   1027 
   1028 	USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
   1029 	    "usb_ia_event_cb: dip=0x%p, cookie=0x%p, "
   1030 	    "arg=0x%p, impl=0x%p",
   1031 	    (void *)dip, (void *)cookie, arg, bus_impldata);
   1032 	USB_DPRINTF_L4(DPRINT_MASK_EVENTS, usb_ia->ia_log_handle,
   1033 	    "(dip=%s%d event=%s)",
   1034 	    ddi_driver_name(dip), ddi_get_instance(dip),
   1035 	    ndi_event_cookie_to_name(usb_ia->ia_ndi_event_hdl, cookie));
   1036 
   1037 	tag = NDI_EVENT_TAG(cookie);
   1038 	rm_cookie = ndi_event_tag_to_cookie(
   1039 	    usb_ia->ia_ndi_event_hdl, USBA_EVENT_TAG_HOT_REMOVAL);
   1040 	suspend_cookie = ndi_event_tag_to_cookie(
   1041 	    usb_ia->ia_ndi_event_hdl, USBA_EVENT_TAG_PRE_SUSPEND);
   1042 	ins_cookie = ndi_event_tag_to_cookie(
   1043 	    usb_ia->ia_ndi_event_hdl, USBA_EVENT_TAG_HOT_INSERTION);
   1044 	resume_cookie = ndi_event_tag_to_cookie(
   1045 	    usb_ia->ia_ndi_event_hdl, USBA_EVENT_TAG_POST_RESUME);
   1046 
   1047 	mutex_enter(&usb_ia->ia_mutex);
   1048 	switch (tag) {
   1049 	case USBA_EVENT_TAG_HOT_REMOVAL:
   1050 		if (usb_ia->ia_dev_state == USB_DEV_DISCONNECTED) {
   1051 			USB_DPRINTF_L2(DPRINT_MASK_EVENTS,
   1052 			    usb_ia->ia_log_handle,
   1053 			    "usb_ia_event_cb: Device already disconnected");
   1054 		} else {
   1055 			/* we are disconnected so set our state now */
   1056 			usb_ia->ia_dev_state = USB_DEV_DISCONNECTED;
   1057 			for (i = 0; i < usb_ia->ia_n_ifs; i++) {
   1058 				usb_ia->ia_child_events[i] &= ~
   1059 				    USB_IA_CHILD_EVENT_DISCONNECT;
   1060 			}
   1061 			mutex_exit(&usb_ia->ia_mutex);
   1062 
   1063 			/* pass disconnect event to all the children */
   1064 			(void) ndi_event_run_callbacks(
   1065 			    usb_ia->ia_ndi_event_hdl, NULL,
   1066 			    rm_cookie, bus_impldata);
   1067 
   1068 			mutex_enter(&usb_ia->ia_mutex);
   1069 		}
   1070 		break;
   1071 	case USBA_EVENT_TAG_PRE_SUSPEND:
   1072 		/* set our state *after* suspending children */
   1073 		mutex_exit(&usb_ia->ia_mutex);
   1074 
   1075 		/* pass pre_suspend event to all the children */
   1076 		(void) ndi_event_run_callbacks(usb_ia->ia_ndi_event_hdl,
   1077 		    NULL, suspend_cookie, bus_impldata);
   1078 
   1079 		mutex_enter(&usb_ia->ia_mutex);
   1080 		for (i = 0; i < usb_ia->ia_n_ifs; i++) {
   1081 			usb_ia->ia_child_events[i] &= ~
   1082 			    USB_IA_CHILD_EVENT_PRESUSPEND;
   1083 		}
   1084 		break;
   1085 	case USBA_EVENT_TAG_HOT_INSERTION:
   1086 		mutex_exit(&usb_ia->ia_mutex);
   1087 		if (usb_ia_restore_device_state(dip, usb_ia) == USB_SUCCESS) {
   1088 
   1089 			/*
   1090 			 * Check to see if this child has missed the disconnect
   1091 			 * event before it registered for event cb
   1092 			 */
   1093 			mutex_enter(&usb_ia->ia_mutex);
   1094 			for (i = 0; i < usb_ia->ia_n_ifs; i++) {
   1095 				if (usb_ia->ia_child_events[i] &
   1096 				    USB_IA_CHILD_EVENT_DISCONNECT) {
   1097 					usb_ia->ia_child_events[i] &=
   1098 					    ~USB_IA_CHILD_EVENT_DISCONNECT;
   1099 					child_dip =
   1100 					    usb_ia->ia_children_dips[i];
   1101 					mutex_exit(&usb_ia->ia_mutex);
   1102 
   1103 					/* post the missed disconnect */
   1104 					(void) ndi_event_do_callback(
   1105 					    usb_ia->ia_ndi_event_hdl,
   1106 					    child_dip,
   1107 					    rm_cookie,
   1108 					    bus_impldata);
   1109 					mutex_enter(&usb_ia->ia_mutex);
   1110 				}
   1111 			}
   1112 			mutex_exit(&usb_ia->ia_mutex);
   1113 
   1114 			/* pass reconnect event to all the children */
   1115 			(void) ndi_event_run_callbacks(
   1116 			    usb_ia->ia_ndi_event_hdl, NULL,
   1117 			    ins_cookie, bus_impldata);
   1118 
   1119 		}
   1120 		mutex_enter(&usb_ia->ia_mutex);
   1121 		break;
   1122 	case USBA_EVENT_TAG_POST_RESUME:
   1123 		/*
   1124 		 * Check to see if this child has missed the pre-suspend
   1125 		 * event before it registered for event cb
   1126 		 */
   1127 		for (i = 0; i < usb_ia->ia_n_ifs; i++) {
   1128 			if (usb_ia->ia_child_events[i] &
   1129 			    USB_IA_CHILD_EVENT_PRESUSPEND) {
   1130 				usb_ia->ia_child_events[i] &=
   1131 				    ~USB_IA_CHILD_EVENT_PRESUSPEND;
   1132 				child_dip = usb_ia->ia_children_dips[i];
   1133 				mutex_exit(&usb_ia->ia_mutex);
   1134 
   1135 				/* post the missed pre-suspend event */
   1136 				(void) ndi_event_do_callback(
   1137 				    usb_ia->ia_ndi_event_hdl,
   1138 				    child_dip, suspend_cookie,
   1139 				    bus_impldata);
   1140 				mutex_enter(&usb_ia->ia_mutex);
   1141 			}
   1142 		}
   1143 		mutex_exit(&usb_ia->ia_mutex);
   1144 
   1145 		/* pass post_resume event to all the children */
   1146 		(void) ndi_event_run_callbacks(usb_ia->ia_ndi_event_hdl,
   1147 		    NULL, resume_cookie, bus_impldata);
   1148 
   1149 		mutex_enter(&usb_ia->ia_mutex);
   1150 		break;
   1151 	}
   1152 	mutex_exit(&usb_ia->ia_mutex);
   1153 
   1154 }
   1155 
   1156 /*
   1157  * create the pm components required for power management
   1158  */
   1159 static void
   1160 usb_ia_create_pm_components(dev_info_t *dip, usb_ia_t *usb_ia)
   1161 {
   1162 	usb_common_power_t	*iapm;
   1163 	uint_t			pwr_states;
   1164 
   1165 	USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
   1166 	    "usb_ia_create_pm_components: Begin");
   1167 
   1168 	/* Allocate the PM state structure */
   1169 	iapm = kmem_zalloc(sizeof (usb_common_power_t), KM_SLEEP);
   1170 
   1171 	mutex_enter(&usb_ia->ia_mutex);
   1172 	usb_ia->ia_pm = iapm;
   1173 	iapm->uc_usb_statep = usb_ia;
   1174 	iapm->uc_pm_capabilities = 0; /* XXXX should this be 0?? */
   1175 	iapm->uc_current_power = USB_DEV_OS_FULL_PWR;
   1176 	mutex_exit(&usb_ia->ia_mutex);
   1177 
   1178 	/*
   1179 	 * By not enabling parental notification, PM enforces
   1180 	 * "strict parental dependency" meaning, usb_ia won't
   1181 	 * power off until any of its children are in full power.
   1182 	 */
   1183 
   1184 	/*
   1185 	 * there are 3 scenarios:
   1186 	 * 1. a well behaved device should have remote wakeup
   1187 	 * at interface and device level. If the interface
   1188 	 * wakes up, usb_ia will wake up
   1189 	 * 2. if the device doesn't have remote wake up and
   1190 	 * the interface has, PM will still work, ie.
   1191 	 * the interfaces wakes up and usb_ia wakes up
   1192 	 * 3. if neither the interface nor device has remote
   1193 	 * wakeup, the interface will wake up when it is opened
   1194 	 * and goes to sleep after being closed for a while
   1195 	 * In this case usb_ia should also go to sleep shortly
   1196 	 * thereafter
   1197 	 * In all scenarios it doesn't really matter whether
   1198 	 * remote wakeup at the device level is enabled or not
   1199 	 * but we do it anyways
   1200 	 */
   1201 	if (usb_handle_remote_wakeup(dip, USB_REMOTE_WAKEUP_ENABLE) ==
   1202 	    USB_SUCCESS) {
   1203 		USB_DPRINTF_L3(DPRINT_MASK_PM, usb_ia->ia_log_handle,
   1204 		    "usb_ia_create_pm_components: "
   1205 		    "Remote Wakeup Enabled");
   1206 		iapm->uc_wakeup_enabled = 1;
   1207 	}
   1208 
   1209 	if (usb_create_pm_components(dip, &pwr_states) ==
   1210 	    USB_SUCCESS) {
   1211 		iapm->uc_pwr_states = (uint8_t)pwr_states;
   1212 		(void) pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
   1213 	}
   1214 
   1215 	USB_DPRINTF_L4(DPRINT_MASK_PM, usb_ia->ia_log_handle,
   1216 	    "usb_ia_create_pm_components: End");
   1217 }
   1218 
   1219 
   1220 /*
   1221  * usb_ia_obtain_state:
   1222  */
   1223 static usb_ia_t *
   1224 usb_ia_obtain_state(dev_info_t *dip)
   1225 {
   1226 	int instance = ddi_get_instance(dip);
   1227 	usb_ia_t *statep = ddi_get_soft_state(usb_ia_statep, instance);
   1228 
   1229 	ASSERT(statep != NULL);
   1230 
   1231 	return (statep);
   1232 }
   1233