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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * usb interface association driver
30  *
31  *	this driver attempts to the interface association node and
32  *	creates/manages child nodes for the included interfaces.
33  */
34 
35 #if defined(lint) && !defined(DEBUG)
36 #define	DEBUG	1
37 #endif
38 #include <sys/usb/usba/usbai_version.h>
39 #include <sys/usb/usba.h>
40 #include <sys/usb/usba/usba_types.h>
41 #include <sys/usb/usba/usba_impl.h>
42 #include <sys/usb/usb_ia/usb_iavar.h>
43 
44 /* Debugging support */
45 uint_t usb_ia_errlevel = USB_LOG_L4;
46 uint_t usb_ia_errmask = (uint_t)DPRINT_MASK_ALL;
47 uint_t usb_ia_instance_debug = (uint_t)-1;
48 uint_t usb_ia_bus_config_debug = 0;
49 
50 _NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ia_errlevel))
51 _NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ia_errmask))
52 _NOTE(DATA_READABLE_WITHOUT_LOCK(usb_ia_instance_debug))
53 
54 _NOTE(SCHEME_PROTECTS_DATA("unique", msgb))
55 _NOTE(SCHEME_PROTECTS_DATA("unique", dev_info))
56 _NOTE(SCHEME_PROTECTS_DATA("unique", usb_pipe_policy))
57 
58 static struct cb_ops usb_ia_cb_ops = {
59 	nodev,		/* open */
60 	nodev,		/* close */
61 	nodev,		/* strategy */
62 	nodev,		/* print */
63 	nodev,		/* dump */
64 	nodev,		/* read */
65 	nodev,		/* write */
66 	nodev,		/* ioctl */
67 	nodev,		/* devmap */
68 	nodev,		/* mmap */
69 	nodev,		/* segmap */
70 	nochpoll,	/* poll */
71 	ddi_prop_op,	/* prop_op */
72 	NULL,		/* aread */
73 	D_MP
74 };
75 
76 static int usb_ia_busop_get_eventcookie(dev_info_t *dip,
77 			dev_info_t *rdip,
78 			char *eventname,
79 			ddi_eventcookie_t *cookie);
80 static int usb_ia_busop_add_eventcall(dev_info_t *dip,
81 			dev_info_t *rdip,
82 			ddi_eventcookie_t cookie,
83 			void (*callback)(dev_info_t *dip,
84 				ddi_eventcookie_t cookie, void *arg,
85 				void *bus_impldata),
86 			void *arg, ddi_callback_id_t *cb_id);
87 static int usb_ia_busop_remove_eventcall(dev_info_t *dip,
88 			ddi_callback_id_t cb_id);
89 static int usb_ia_busop_post_event(dev_info_t *dip,
90 			dev_info_t *rdip,
91 			ddi_eventcookie_t cookie,
92 			void *bus_impldata);
93 static int usb_ia_bus_config(dev_info_t *dip,
94 			uint_t flag,
95 			ddi_bus_config_op_t op,
96 			void *arg,
97 			dev_info_t **child);
98 static int usb_ia_bus_unconfig(dev_info_t *dip,
99 			uint_t flag,
100 			ddi_bus_config_op_t op,
101 			void *arg);
102 
103 /*
104  * autoconfiguration data and routines.
105  */
106 static int	usb_ia_info(dev_info_t *, ddi_info_cmd_t,
107 				void *, void **);
108 static int	usb_ia_attach(dev_info_t *, ddi_attach_cmd_t);
109 static int	usb_ia_detach(dev_info_t *, ddi_detach_cmd_t);
110 
111 /* other routines */
112 static void usb_ia_create_pm_components(dev_info_t *, usb_ia_t *);
113 static int usb_ia_bus_ctl(dev_info_t *, dev_info_t	*,
114 				ddi_ctl_enum_t, void *, void *);
115 static int usb_ia_power(dev_info_t *, int, int);
116 static int usb_ia_restore_device_state(dev_info_t *, usb_ia_t *);
117 static usb_ia_t  *usb_ia_obtain_state(dev_info_t *);
118 static void usb_ia_event_cb(dev_info_t *, ddi_eventcookie_t, void *, void *);
119 
120 /* prototypes */
121 static void usb_ia_create_children(usb_ia_t *);
122 static int usb_ia_cleanup(usb_ia_t *);
123 
124 /*
125  * Busops vector
126  */
127 static struct bus_ops usb_ia_busops = {
128 	BUSO_REV,
129 	nullbusmap,			/* bus_map */
130 	NULL,				/* bus_get_intrspec */
131 	NULL,				/* bus_add_intrspec */
132 	NULL,				/* bus_remove_intrspec */
133 	NULL,				/* XXXX bus_map_fault */
134 	ddi_dma_map,			/* bus_dma_map */
135 	ddi_dma_allochdl,
136 	ddi_dma_freehdl,
137 	ddi_dma_bindhdl,
138 	ddi_dma_unbindhdl,
139 	ddi_dma_flush,
140 	ddi_dma_win,
141 	ddi_dma_mctl,			/* bus_dma_ctl */
142 	usb_ia_bus_ctl,		/* bus_ctl */
143 	ddi_bus_prop_op,		/* bus_prop_op */
144 	usb_ia_busop_get_eventcookie,
145 	usb_ia_busop_add_eventcall,
146 	usb_ia_busop_remove_eventcall,
147 	usb_ia_busop_post_event,	/* bus_post_event */
148 	NULL,				/* bus_intr_ctl */
149 	usb_ia_bus_config,		/* bus_config */
150 	usb_ia_bus_unconfig,		/* bus_unconfig */
151 	NULL,				/* bus_fm_init */
152 	NULL,				/* bus_fm_fini */
153 	NULL,				/* bus_fm_access_enter */
154 	NULL,				/* bus_fm_access_exit */
155 	NULL				/* bus_power */
156 };
157 
158 
159 static struct dev_ops usb_ia_ops = {
160 	DEVO_REV,		/* devo_rev, */
161 	0,			/* refcnt  */
162 	usb_ia_info,		/* info */
163 	nulldev,		/* identify */
164 	nulldev,		/* probe */
165 	usb_ia_attach,		/* attach */
166 	usb_ia_detach,		/* detach */
167 	nodev,			/* reset */
168 	&usb_ia_cb_ops,	/* driver operations */
169 	&usb_ia_busops,	/* bus operations */
170 	usb_ia_power		/* power */
171 };
172 
173 static struct modldrv modldrv = {
174 	&mod_driverops, /* Type of module. This one is a driver */
175 	"USB Interface Association Driver %I%", /* 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