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