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