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