xref: /titanic_41/usr/src/uts/common/io/usb/usba/usbai_pipe_mgmt.c (revision aa98ce2c4ecbce8afe8b7b253a911ab24fdded32)
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  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
26  */
27 
28 
29 /*
30  * USBA: Solaris USB Architecture support
31  *
32  * all functions exposed to client drivers  have prefix usb_ while all USBA
33  * internal functions or functions exposed to HCD or hubd only have prefix
34  * usba_
35  *
36  * this file contains all USBAI pipe management
37  *	usb_pipe_open()
38  *	usb_pipe_close()
39  *	usb_pipe_set_private()
40  *	usb_pipe_get_private()
41  *	usb_pipe_abort()
42  *	usb_pipe_reset()
43  *	usb_pipe_drain_reqs()
44  */
45 #define	USBA_FRAMEWORK
46 #include <sys/usb/usba/usba_impl.h>
47 #include <sys/usb/usba/hcdi_impl.h>
48 #include <sys/atomic.h>
49 
50 extern	pri_t	maxclsyspri;
51 extern	pri_t	minclsyspri;
52 
53 /* function prototypes */
54 static	void	usba_pipe_do_async_func_thread(void *arg);
55 static	int	usba_pipe_sync_close(dev_info_t *, usba_ph_impl_t *,
56 			usba_pipe_async_req_t *, usb_flags_t);
57 static	int	usba_pipe_sync_reset(dev_info_t *, usba_ph_impl_t *,
58 			usba_pipe_async_req_t *, usb_flags_t);
59 static	int	usba_pipe_sync_drain_reqs(dev_info_t *, usba_ph_impl_t *,
60 			usba_pipe_async_req_t *, usb_flags_t);
61 
62 /* local tunables */
63 int	usba_drain_timeout = 1000;	/* in ms */
64 
65 /* return the default pipe for this device */
66 usb_pipe_handle_t
usba_get_dflt_pipe_handle(dev_info_t * dip)67 usba_get_dflt_pipe_handle(dev_info_t *dip)
68 {
69 	usba_device_t		*usba_device;
70 	usb_pipe_handle_t	pipe_handle = NULL;
71 
72 	if (dip) {
73 		usba_device = usba_get_usba_device(dip);
74 		if (usba_device) {
75 			pipe_handle =
76 			    (usb_pipe_handle_t)&usba_device->usb_ph_list[0];
77 		}
78 	}
79 
80 	return (pipe_handle);
81 }
82 
83 
84 /* return dip owner of pipe_handle */
85 dev_info_t *
usba_get_dip(usb_pipe_handle_t pipe_handle)86 usba_get_dip(usb_pipe_handle_t pipe_handle)
87 {
88 	usba_ph_impl_t		*ph_impl = (usba_ph_impl_t *)pipe_handle;
89 	dev_info_t		*dip = NULL;
90 
91 	if (ph_impl) {
92 		mutex_enter(&ph_impl->usba_ph_mutex);
93 		dip = ph_impl->usba_ph_dip;
94 		mutex_exit(&ph_impl->usba_ph_mutex);
95 	}
96 
97 	return (dip);
98 }
99 
100 
101 usb_pipe_handle_t
usba_usbdev_to_dflt_pipe_handle(usba_device_t * usba_device)102 usba_usbdev_to_dflt_pipe_handle(usba_device_t *usba_device)
103 {
104 	usb_pipe_handle_t	pipe_handle = NULL;
105 
106 	if ((usba_device) &&
107 	    (usba_device->usb_ph_list[0].usba_ph_data != NULL)) {
108 		pipe_handle = (usb_pipe_handle_t)&usba_device->usb_ph_list[0];
109 	}
110 
111 	return (pipe_handle);
112 }
113 
114 
115 usba_pipe_handle_data_t *
usba_get_ph_data(usb_pipe_handle_t pipe_handle)116 usba_get_ph_data(usb_pipe_handle_t pipe_handle)
117 {
118 	usba_ph_impl_t		*ph_impl = (usba_ph_impl_t *)pipe_handle;
119 	usba_pipe_handle_data_t *ph_data = NULL;
120 
121 	if (ph_impl) {
122 		mutex_enter(&ph_impl->usba_ph_mutex);
123 		ASSERT(ph_impl->usba_ph_ref_count >= 0);
124 		ph_data = ph_impl->usba_ph_data;
125 		mutex_exit(&ph_impl->usba_ph_mutex);
126 	}
127 
128 	return (ph_data);
129 }
130 
131 
132 usb_pipe_handle_t
usba_get_pipe_handle(usba_pipe_handle_data_t * ph_data)133 usba_get_pipe_handle(usba_pipe_handle_data_t *ph_data)
134 {
135 	usb_pipe_handle_t ph = NULL;
136 
137 	if (ph_data) {
138 		mutex_enter(&ph_data->p_mutex);
139 		ASSERT(ph_data->p_req_count >= 0);
140 		ph = (usb_pipe_handle_t)ph_data->p_ph_impl;
141 		mutex_exit(&ph_data->p_mutex);
142 	}
143 
144 	return (ph);
145 }
146 
147 
148 /*
149  * opaque to pipe handle impl translation with incr of ref count. The caller
150  * must release ph_data when done. Increment the ref count ensures that
151  * the ph_data will not be freed underneath us.
152  */
153 usba_pipe_handle_data_t *
usba_hold_ph_data(usb_pipe_handle_t pipe_handle)154 usba_hold_ph_data(usb_pipe_handle_t pipe_handle)
155 {
156 	usba_ph_impl_t		*ph_impl = (usba_ph_impl_t *)pipe_handle;
157 	usba_pipe_handle_data_t *ph_data = NULL;
158 
159 	if (ph_impl) {
160 		mutex_enter(&ph_impl->usba_ph_mutex);
161 
162 		switch (ph_impl->usba_ph_state) {
163 		case USB_PIPE_STATE_IDLE:
164 		case USB_PIPE_STATE_ACTIVE:
165 		case USB_PIPE_STATE_ERROR:
166 			ph_data = ph_impl->usba_ph_data;
167 			ph_impl->usba_ph_ref_count++;
168 			break;
169 		case USB_PIPE_STATE_CLOSED:
170 		case USB_PIPE_STATE_CLOSING:
171 		default:
172 			break;
173 		}
174 
175 		USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
176 		    "usba_hold_ph_data: ph_impl=0x%p state=%d ref=%d",
177 		    (void *)ph_impl, ph_impl->usba_ph_state,
178 		    ph_impl->usba_ph_ref_count);
179 
180 		mutex_exit(&ph_impl->usba_ph_mutex);
181 	}
182 
183 	return (ph_data);
184 }
185 
186 
187 void
usba_release_ph_data(usba_ph_impl_t * ph_impl)188 usba_release_ph_data(usba_ph_impl_t *ph_impl)
189 {
190 	if (ph_impl) {
191 		mutex_enter(&ph_impl->usba_ph_mutex);
192 
193 		USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
194 		    "usba_release_ph_data: "
195 		    "ph_impl=0x%p state=%d ref=%d",
196 		    (void *)ph_impl, ph_impl->usba_ph_state,
197 		    ph_impl->usba_ph_ref_count);
198 
199 #ifndef __lock_lint
200 		if (ph_impl->usba_ph_data) {
201 			USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
202 			    "usba_release_ph_data: req_count=%d",
203 			    ph_impl->usba_ph_data->p_req_count);
204 			ASSERT(ph_impl->usba_ph_data->p_req_count >= 0);
205 		}
206 #endif
207 		ph_impl->usba_ph_ref_count--;
208 		ASSERT(ph_impl->usba_ph_ref_count >= 0);
209 
210 		mutex_exit(&ph_impl->usba_ph_mutex);
211 	}
212 }
213 
214 
215 /*
216  * get pipe state from ph_data
217  */
218 usb_pipe_state_t
usba_get_ph_state(usba_pipe_handle_data_t * ph_data)219 usba_get_ph_state(usba_pipe_handle_data_t *ph_data)
220 {
221 	usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
222 	usb_pipe_state_t	pipe_state;
223 
224 	ASSERT(mutex_owned(&ph_data->p_mutex));
225 	mutex_enter(&ph_impl->usba_ph_mutex);
226 	pipe_state = ph_impl->usba_ph_state;
227 	mutex_exit(&ph_impl->usba_ph_mutex);
228 
229 	return (pipe_state);
230 }
231 
232 
233 /*
234  * get ref_count from ph_data
235  */
236 int
usba_get_ph_ref_count(usba_pipe_handle_data_t * ph_data)237 usba_get_ph_ref_count(usba_pipe_handle_data_t *ph_data)
238 {
239 	usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
240 	int			ref_count;
241 
242 	mutex_enter(&ph_impl->usba_ph_mutex);
243 	ref_count = ph_impl->usba_ph_ref_count;
244 	mutex_exit(&ph_impl->usba_ph_mutex);
245 
246 	return (ref_count);
247 }
248 
249 
250 /*
251  * new pipe state
252  * We need to hold both pipe mutex and ph_impl mutex
253  */
254 void
usba_pipe_new_state(usba_pipe_handle_data_t * ph_data,usb_pipe_state_t state)255 usba_pipe_new_state(usba_pipe_handle_data_t *ph_data, usb_pipe_state_t state)
256 {
257 	usba_ph_impl_t *ph_impl = ph_data->p_ph_impl;
258 
259 	ASSERT(mutex_owned(&ph_data->p_mutex));
260 
261 	mutex_enter(&ph_impl->usba_ph_mutex);
262 	ASSERT(ph_data->p_req_count >= 0);
263 	ASSERT(ph_impl->usba_ph_ref_count >= 0);
264 
265 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
266 	    "usba_pipe_new_state: "
267 	    "ph_data=0x%p old=%s new=%s ref=%d req=%d",
268 	    (void *)ph_data, usb_str_pipe_state(ph_impl->usba_ph_state),
269 	    usb_str_pipe_state(state),
270 	    ph_impl->usba_ph_ref_count, ph_data->p_req_count);
271 
272 	switch (ph_impl->usba_ph_state) {
273 	case USB_PIPE_STATE_IDLE:
274 	case USB_PIPE_STATE_ACTIVE:
275 	case USB_PIPE_STATE_ERROR:
276 	case USB_PIPE_STATE_CLOSED:
277 		ph_impl->usba_ph_state = state;
278 		break;
279 	case USB_PIPE_STATE_CLOSING:
280 	default:
281 		break;
282 	}
283 	mutex_exit(&ph_impl->usba_ph_mutex);
284 }
285 
286 
287 /*
288  * async function execution support
289  * Arguments:
290  *	dip		- devinfo pointer
291  *	sync_func	- function to be executed
292  *	ph_impl		- impl pipehandle
293  *	arg		- opaque arg
294  *	usb_flags	- none
295  *	callback	- function to be called on completion, may be NULL
296  *	callback_arg	- argument for callback function
297  *
298  * Note: The caller must do a hold on ph_data
299  *	We sleep for memory resources and taskq_dispatch which will ensure
300  *	that this function succeeds
301  */
302 int
usba_pipe_setup_func_call(dev_info_t * dip,int (* sync_func)(dev_info_t *,usba_ph_impl_t *,usba_pipe_async_req_t *,usb_flags_t),usba_ph_impl_t * ph_impl,usb_opaque_t arg,usb_flags_t usb_flags,void (* callback)(usb_pipe_handle_t,usb_opaque_t,int,usb_cb_flags_t),usb_opaque_t callback_arg)303 usba_pipe_setup_func_call(
304 	dev_info_t	*dip,
305 	int		(*sync_func)(dev_info_t *,
306 			    usba_ph_impl_t *, usba_pipe_async_req_t *,
307 			    usb_flags_t),
308 	usba_ph_impl_t *ph_impl,
309 	usb_opaque_t	arg,
310 	usb_flags_t	usb_flags,
311 	void		(*callback)(usb_pipe_handle_t,
312 			    usb_opaque_t, int, usb_cb_flags_t),
313 	usb_opaque_t	callback_arg)
314 {
315 	usba_pipe_async_req_t	*request;
316 	usb_pipe_handle_t	pipe_handle = (usb_pipe_handle_t)ph_impl;
317 	usba_pipe_handle_data_t *ph_data = ph_impl->usba_ph_data;
318 	int			rval = USB_SUCCESS;
319 	usb_cb_flags_t		callback_flags;
320 
321 	USB_DPRINTF_L3(DPRINT_MASK_USBAI, usbai_log_handle,
322 	    "usba_pipe_setup_func_call: ph_impl=0x%p, func=0x%p",
323 	    (void *)ph_impl, (void *)sync_func);
324 
325 	if (((usb_flags & USB_FLAGS_SLEEP) == 0) && (callback == NULL)) {
326 		usba_release_ph_data(ph_impl);
327 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
328 		    "usba_pipe_setup_func_call: async request with "
329 		    "no callback");
330 
331 		return (USB_INVALID_ARGS);
332 	}
333 
334 	request = kmem_zalloc(sizeof (usba_pipe_async_req_t), KM_SLEEP);
335 	request->dip		= dip;
336 	request->ph_impl	= ph_impl;
337 	request->arg		= arg;
338 
339 	/*
340 	 * OR in sleep flag. regardless of calling sync_func directly
341 	 * or in a new thread, we will always wait for completion
342 	 */
343 	request->usb_flags	= usb_flags | USB_FLAGS_SLEEP;
344 	request->sync_func	= sync_func;
345 	request->callback	= callback;
346 	request->callback_arg	= callback_arg;
347 
348 	if (usb_flags & USB_FLAGS_SLEEP) {
349 		rval = sync_func(dip, ph_impl, request, usb_flags);
350 		kmem_free(request, sizeof (usba_pipe_async_req_t));
351 
352 	} else if (usba_async_ph_req(ph_data,
353 	    usba_pipe_do_async_func_thread,
354 	    (void *)request, USB_FLAGS_SLEEP) != USB_SUCCESS) {
355 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
356 		    "usb_async_req failed: ph_impl=0x%p, func=0x%p",
357 		    (void *)ph_impl, (void *)sync_func);
358 
359 		if (callback) {
360 			callback_flags =
361 			    usba_check_intr_context(USB_CB_ASYNC_REQ_FAILED);
362 			callback(pipe_handle, callback_arg, USB_FAILURE,
363 			    callback_flags);
364 		}
365 
366 		kmem_free(request, sizeof (usba_pipe_async_req_t));
367 		usba_release_ph_data(ph_impl);
368 	}
369 
370 	return (rval);
371 }
372 
373 
374 /*
375  * taskq thread function to execute function synchronously
376  * Note: caller must have done a hold on ph_data
377  */
378 static void
usba_pipe_do_async_func_thread(void * arg)379 usba_pipe_do_async_func_thread(void *arg)
380 {
381 	usba_pipe_async_req_t	*request = (usba_pipe_async_req_t *)arg;
382 	usba_ph_impl_t		*ph_impl = request->ph_impl;
383 	usb_pipe_handle_t	pipe_handle = (usb_pipe_handle_t)ph_impl;
384 	int			rval;
385 	usb_cb_flags_t		cb_flags = USB_CB_NO_INFO;
386 
387 	if ((rval = request->sync_func(request->dip, ph_impl,
388 	    request, request->usb_flags | USB_FLAGS_SLEEP)) !=
389 	    USB_SUCCESS) {
390 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
391 		    "sync func failed (%d)", rval);
392 	}
393 
394 	if (request->callback) {
395 		request->callback(pipe_handle, request->callback_arg, rval,
396 		    cb_flags);
397 	}
398 
399 	kmem_free(request, sizeof (usba_pipe_async_req_t));
400 }
401 
402 
403 /*
404  * default endpoint descriptor and pipe policy
405  */
406 usb_ep_descr_t	usba_default_ep_descr =
407 	{7, 5, 0, USB_EP_ATTR_CONTROL, 8, 0};
408 
409 /* set some meaningful defaults */
410 static usb_pipe_policy_t usba_default_ep_pipe_policy = {3};
411 
412 
413 /*
414  * usb_get_ep_index: create an index from endpoint address that can
415  * be used to index into endpoint pipe lists
416  */
417 uchar_t
usb_get_ep_index(uint8_t ep_addr)418 usb_get_ep_index(uint8_t ep_addr)
419 {
420 	return ((ep_addr & USB_EP_NUM_MASK) +
421 	    ((ep_addr & USB_EP_DIR_MASK) ? 16 : 0));
422 }
423 
424 
425 /*
426  * pipe management
427  *	utility functions to init and destroy a pipehandle
428  */
429 static int
usba_init_pipe_handle(dev_info_t * dip,usba_device_t * usba_device,usb_ep_descr_t * ep,usb_pipe_policy_t * pipe_policy,usba_ph_impl_t * ph_impl)430 usba_init_pipe_handle(dev_info_t *dip,
431 	usba_device_t		*usba_device,
432 	usb_ep_descr_t		*ep,
433 	usb_pipe_policy_t	*pipe_policy,
434 	usba_ph_impl_t		*ph_impl)
435 {
436 	int instance = ddi_get_instance(dip);
437 	unsigned int def_instance = instance;
438 	static unsigned int anon_instance = 0;
439 	char tq_name[TASKQ_NAMELEN];
440 
441 	usba_pipe_handle_data_t *ph_data = ph_impl->usba_ph_data;
442 	ddi_iblock_cookie_t	iblock_cookie =
443 	    usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip)->
444 	    hcdi_iblock_cookie;
445 
446 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
447 	    "usba_init_pipe_handle: "
448 	    "usba_device=0x%p ep=0x%x", (void *)usba_device,
449 	    ep->bEndpointAddress);
450 	mutex_init(&ph_data->p_mutex, NULL, MUTEX_DRIVER, iblock_cookie);
451 
452 	/* just to keep warlock happy, there is no contention yet */
453 	mutex_enter(&ph_data->p_mutex);
454 	mutex_enter(&usba_device->usb_mutex);
455 
456 	ASSERT(pipe_policy->pp_max_async_reqs);
457 
458 	if (instance != -1) {
459 		(void) snprintf(tq_name, sizeof (tq_name),
460 		    "USB_%s_%x_pipehndl_tq_%d",
461 		    ddi_driver_name(dip), ep->bEndpointAddress, instance);
462 	} else {
463 		def_instance = atomic_inc_32_nv(&anon_instance);
464 
465 		(void) snprintf(tq_name, sizeof (tq_name),
466 		    "USB_%s_%x_pipehndl_tq_%d_",
467 		    ddi_driver_name(dip), ep->bEndpointAddress, def_instance);
468 	}
469 
470 	ph_data->p_taskq = taskq_create(tq_name,
471 	    pipe_policy->pp_max_async_reqs + 1,
472 	    ((ep->bmAttributes & USB_EP_ATTR_MASK) ==
473 	    USB_EP_ATTR_ISOCH) ?
474 	    (maxclsyspri - 5) : minclsyspri,
475 	    2 * (pipe_policy->pp_max_async_reqs + 1),
476 	    8 * (pipe_policy->pp_max_async_reqs + 1),
477 	    TASKQ_PREPOPULATE);
478 
479 	/*
480 	 * Create a shared taskq.
481 	 */
482 	if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) {
483 		int iface = usb_get_if_number(dip);
484 		if (iface < 0) {
485 			/* we own the device, use first entry */
486 			iface = 0;
487 		}
488 
489 		if (instance != -1) {
490 			(void) snprintf(tq_name, sizeof (tq_name),
491 			    "USB_%s_%x_shared_tq_%d",
492 			    ddi_driver_name(dip), ep->bEndpointAddress,
493 			    instance);
494 		} else {
495 			(void) snprintf(tq_name, sizeof (tq_name),
496 			    "USB_%s_%x_shared_tq_%d_",
497 			    ddi_driver_name(dip), ep->bEndpointAddress,
498 			    def_instance);
499 		}
500 
501 		if (usba_device->usb_shared_taskq_ref_count[iface] == 0) {
502 			usba_device->usb_shared_taskq[iface] =
503 			    taskq_create(tq_name,
504 			    1,				/* Number threads. */
505 			    maxclsyspri - 5,		/* Priority */
506 			    1,				/* minalloc */
507 			    USBA_N_ENDPOINTS + 4,	/* maxalloc */
508 			    TASKQ_PREPOPULATE);
509 			ASSERT(usba_device->usb_shared_taskq[iface] != NULL);
510 		}
511 		usba_device->usb_shared_taskq_ref_count[iface]++;
512 	}
513 
514 	ph_data->p_dip		= dip;
515 	ph_data->p_usba_device	= usba_device;
516 	ph_data->p_ep		= *ep;
517 	ph_data->p_ph_impl	= ph_impl;
518 	if ((ep->bmAttributes & USB_EP_ATTR_MASK) ==
519 	    USB_EP_ATTR_ISOCH) {
520 		ph_data->p_spec_flag |= USBA_PH_FLAG_USE_SOFT_INTR;
521 	}
522 
523 	/* fix up the MaxPacketSize if it is the default endpoint descr */
524 	if ((ep == &usba_default_ep_descr) && usba_device) {
525 		uint16_t	maxpktsize;
526 
527 		maxpktsize = usba_device->usb_dev_descr->bMaxPacketSize0;
528 		USB_DPRINTF_L3(DPRINT_MASK_USBAI, usbai_log_handle,
529 		    "adjusting max packet size from %d to %d",
530 		    ph_data->p_ep.wMaxPacketSize, maxpktsize);
531 
532 		ph_data->p_ep.wMaxPacketSize = maxpktsize;
533 	}
534 
535 	/* now update usba_ph_impl structure */
536 	mutex_enter(&ph_impl->usba_ph_mutex);
537 	ph_impl->usba_ph_dip = dip;
538 	ph_impl->usba_ph_ep = ph_data->p_ep;
539 	ph_impl->usba_ph_policy = ph_data->p_policy = *pipe_policy;
540 	mutex_exit(&ph_impl->usba_ph_mutex);
541 
542 	usba_init_list(&ph_data->p_queue, (usb_opaque_t)ph_data, iblock_cookie);
543 	usba_init_list(&ph_data->p_cb_queue, (usb_opaque_t)ph_data,
544 	    iblock_cookie);
545 	mutex_exit(&usba_device->usb_mutex);
546 	mutex_exit(&ph_data->p_mutex);
547 
548 	return (USB_SUCCESS);
549 }
550 
551 
552 static void
usba_taskq_destroy(void * arg)553 usba_taskq_destroy(void *arg)
554 {
555 	taskq_destroy((taskq_t *)arg);
556 }
557 
558 
559 static void
usba_destroy_pipe_handle(usba_pipe_handle_data_t * ph_data)560 usba_destroy_pipe_handle(usba_pipe_handle_data_t *ph_data)
561 {
562 	usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
563 	int			timeout;
564 	usba_device_t		*usba_device;
565 
566 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
567 	    "usba_destroy_pipe_handle: ph_data=0x%p", (void *)ph_data);
568 
569 	mutex_enter(&ph_data->p_mutex);
570 	mutex_enter(&ph_impl->usba_ph_mutex);
571 
572 	/* check for all activity to drain */
573 	for (timeout = 0; timeout < usba_drain_timeout; timeout++) {
574 		if ((ph_impl->usba_ph_ref_count <= 1) &&
575 		    (ph_data->p_req_count == 0)) {
576 
577 			break;
578 		}
579 		mutex_exit(&ph_data->p_mutex);
580 		mutex_exit(&ph_impl->usba_ph_mutex);
581 		delay(drv_usectohz(1000));
582 		mutex_enter(&ph_data->p_mutex);
583 		mutex_enter(&ph_impl->usba_ph_mutex);
584 	}
585 
586 	/*
587 	 * set state to closed here so any other thread
588 	 * that is waiting for the CLOSED state will
589 	 * continue. Otherwise, taskq_destroy might deadlock
590 	 */
591 	ph_impl->usba_ph_data = NULL;
592 	ph_impl->usba_ph_ref_count = 0;
593 	ph_impl->usba_ph_state = USB_PIPE_STATE_CLOSED;
594 
595 	if (ph_data->p_taskq) {
596 		mutex_exit(&ph_data->p_mutex);
597 		mutex_exit(&ph_impl->usba_ph_mutex);
598 		if (taskq_member(ph_data->p_taskq, curthread)) {
599 			/*
600 			 * use system taskq to destroy ph's taskq to avoid
601 			 * deadlock
602 			 */
603 			(void) taskq_dispatch(system_taskq,
604 			    usba_taskq_destroy, ph_data->p_taskq, TQ_SLEEP);
605 		} else {
606 			taskq_destroy(ph_data->p_taskq);
607 		}
608 	} else {
609 		mutex_exit(&ph_data->p_mutex);
610 		mutex_exit(&ph_impl->usba_ph_mutex);
611 	}
612 
613 	usba_device = ph_data->p_usba_device;
614 	mutex_enter(&ph_data->p_mutex);
615 	if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) {
616 		int iface = usb_get_if_number(ph_data->p_dip);
617 		if (iface < 0) {
618 			/* we own the device, use the first entry */
619 			iface = 0;
620 		}
621 		mutex_enter(&usba_device->usb_mutex);
622 		if (--usba_device->usb_shared_taskq_ref_count[iface] == 0) {
623 			ph_data->p_spec_flag &= ~USBA_PH_FLAG_TQ_SHARE;
624 			if (taskq_member(usba_device->usb_shared_taskq[iface],
625 			    curthread)) {
626 				(void) taskq_dispatch(
627 				    system_taskq,
628 				    usba_taskq_destroy,
629 				    usba_device->usb_shared_taskq[iface],
630 				    TQ_SLEEP);
631 			} else {
632 				taskq_destroy(
633 				    usba_device->usb_shared_taskq[iface]);
634 			}
635 		}
636 		mutex_exit(&usba_device->usb_mutex);
637 	}
638 	mutex_exit(&ph_data->p_mutex);
639 
640 
641 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
642 	    "usba_destroy_pipe_handle: destroying ph_data=0x%p",
643 	    (void *)ph_data);
644 
645 	usba_destroy_list(&ph_data->p_queue);
646 	usba_destroy_list(&ph_data->p_cb_queue);
647 
648 	/* destroy mutexes */
649 	mutex_destroy(&ph_data->p_mutex);
650 
651 	kmem_free(ph_data, sizeof (usba_pipe_handle_data_t));
652 }
653 
654 
655 /*
656  * usba_drain_cbs:
657  *	Drain the request callbacks on the pipe handle
658  */
659 int
usba_drain_cbs(usba_pipe_handle_data_t * ph_data,usb_cb_flags_t cb_flags,usb_cr_t cr)660 usba_drain_cbs(usba_pipe_handle_data_t *ph_data, usb_cb_flags_t cb_flags,
661 	usb_cr_t cr)
662 {
663 	usba_req_wrapper_t	*req_wrp;
664 	int			flush_requests = 1;
665 	usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
666 	int			timeout;
667 	int			rval = USB_SUCCESS;
668 
669 	ASSERT(mutex_owned(&ph_data->p_mutex));
670 
671 	mutex_enter(&ph_impl->usba_ph_mutex);
672 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
673 	    "usba_drain_cbs: ph_data=0x%p ref=%d req=%d cb=0x%x cr=%d",
674 	    (void *)ph_data, ph_impl->usba_ph_ref_count, ph_data->p_req_count,
675 	    cb_flags, cr);
676 	ASSERT(ph_data->p_req_count >= 0);
677 	mutex_exit(&ph_impl->usba_ph_mutex);
678 
679 	if (ph_data->p_dip) {
680 		if (USBA_IS_DEFAULT_PIPE(ph_data)) {
681 			USB_DPRINTF_L4(DPRINT_MASK_USBAI,
682 			    usbai_log_handle,
683 			    "no flushing on default pipe!");
684 
685 			flush_requests = 0;
686 		}
687 	}
688 
689 	if (flush_requests) {
690 		/* flush all requests in the pipehandle queue */
691 		while ((req_wrp = (usba_req_wrapper_t *)
692 		    usba_rm_first_pvt_from_list(&ph_data->p_queue)) != NULL) {
693 			mutex_exit(&ph_data->p_mutex);
694 			usba_do_req_exc_cb(req_wrp, cr, cb_flags);
695 			mutex_enter(&ph_data->p_mutex);
696 		}
697 	}
698 
699 	/*
700 	 * wait for any callbacks in progress but don't wait for
701 	 * for queued requests on the default pipe
702 	 */
703 	for (timeout = 0; (timeout < usba_drain_timeout) &&
704 	    (ph_data->p_req_count >
705 	    usba_list_entry_count(&ph_data->p_queue));
706 	    timeout++) {
707 		mutex_exit(&ph_data->p_mutex);
708 		delay(drv_usectohz(1000));
709 		mutex_enter(&ph_data->p_mutex);
710 	}
711 
712 	mutex_enter(&ph_impl->usba_ph_mutex);
713 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
714 	    "usba_drain_cbs done: ph_data=0x%p ref=%d req=%d",
715 	    (void *)ph_data, ph_impl->usba_ph_ref_count, ph_data->p_req_count);
716 	mutex_exit(&ph_impl->usba_ph_mutex);
717 
718 	if (timeout == usba_drain_timeout) {
719 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
720 		    "draining callbacks timed out!");
721 
722 		rval = USB_FAILURE;
723 	}
724 
725 	return (rval);
726 }
727 
728 
729 /*
730  * usb_pipe_open():
731  *
732  * Before using any pipe including the default pipe, it should be opened
733  * using usb_pipe_open(). On a successful open, a pipe handle is returned
734  * for use in other usb_pipe_*() functions
735  *
736  * The default pipe can only be opened by the hub driver
737  *
738  * The bandwidth has been allocated and guaranteed on successful
739  * opening of an isoc/intr pipes.
740  *
741  * Only the default pipe can be shared. all other control pipes
742  * are excusively opened by default.
743  * A pipe policy and endpoint descriptor must always be provided
744  * except for default pipe
745  *
746  * Arguments:
747  *	dip		- devinfo ptr
748  *	ep		- endpoint descriptor pointer
749  *	pipe_policy	- pointer to pipe policy which provides hints on how
750  *			  the pipe will be used.
751  *	flags		- USB_FLAGS_SLEEP wait for resources
752  *			  to become available
753  *	pipe_handle	- a pipe handle pointer. On a successful open,
754  *			  a pipe_handle is returned in this pointer.
755  *
756  * Return values:
757  *	USB_SUCCESS	 - open succeeded
758  *	USB_FAILURE	 - unspecified open failure or pipe is already open
759  *	USB_NO_RESOURCES - no resources were available to complete the open
760  *	USB_NO_BANDWIDTH - no bandwidth available (isoc/intr pipes)
761  *	USB_*		 - refer to usbai.h
762  */
763 int
usb_pipe_open(dev_info_t * dip,usb_ep_descr_t * ep,usb_pipe_policy_t * pipe_policy,usb_flags_t usb_flags,usb_pipe_handle_t * pipe_handle)764 usb_pipe_open(
765 	dev_info_t		*dip,
766 	usb_ep_descr_t		*ep,
767 	usb_pipe_policy_t	*pipe_policy,
768 	usb_flags_t		usb_flags,
769 	usb_pipe_handle_t	*pipe_handle)
770 {
771 	usba_device_t		*usba_device;
772 	int			rval;
773 	usba_pipe_handle_data_t *ph_data;
774 	usba_ph_impl_t		*ph_impl;
775 	uchar_t			ep_index;
776 	int			kmflag;
777 	size_t			size;
778 
779 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
780 	    "usb_pipe_open:\n\t"
781 	    "dip=0x%p ep=0x%p pp=0x%p uf=0x%x ph=0x%p",
782 	    (void *)dip, (void *)ep, (void *)pipe_policy, usb_flags,
783 	    (void *)pipe_handle);
784 
785 	if ((dip == NULL) || (pipe_handle == NULL)) {
786 
787 		return (USB_INVALID_ARGS);
788 	}
789 
790 	if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) {
791 
792 		return (USB_INVALID_CONTEXT);
793 	}
794 	usba_device = usba_get_usba_device(dip);
795 
796 	if ((ep != NULL) && (pipe_policy == NULL)) {
797 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
798 		    "usb_pipe_open: null pipe policy");
799 
800 		return (USB_INVALID_ARGS);
801 	}
802 
803 	/* is the device still connected? */
804 	if ((ep != NULL) & DEVI_IS_DEVICE_REMOVED(dip)) {
805 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
806 		    "usb_pipe_open: device has been removed");
807 
808 		return (USB_FAILURE);
809 	}
810 
811 
812 	/*
813 	 * if a null endpoint pointer was passed, use the default
814 	 * endpoint descriptor
815 	 */
816 	if (ep == NULL) {
817 		if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) {
818 			USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
819 			    "usb_pipe_open: not allowed to open def pipe");
820 
821 			return (USB_INVALID_PERM);
822 		}
823 
824 		ep = &usba_default_ep_descr;
825 		pipe_policy = &usba_default_ep_pipe_policy;
826 	}
827 
828 	if (usb_flags & USB_FLAGS_SERIALIZED_CB) {
829 		if (((ep->bmAttributes & USB_EP_ATTR_MASK) ==
830 		    USB_EP_ATTR_CONTROL) ||
831 		    ((ep->bmAttributes & USB_EP_ATTR_MASK) ==
832 		    USB_EP_ATTR_ISOCH)) {
833 			USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
834 			    "usb_pipe_open: shared taskq not allowed with "
835 			    "ctrl or isoch pipe");
836 
837 			return (USB_INVALID_ARGS);
838 		}
839 	}
840 
841 	kmflag	= (usb_flags & USB_FLAGS_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
842 	size	= sizeof (usba_pipe_handle_data_t);
843 
844 	if ((ph_data = kmem_zalloc(size, kmflag)) == NULL) {
845 
846 		return (USB_NO_RESOURCES);
847 	}
848 
849 	/* check if pipe is already open and if so fail */
850 	ep_index = usb_get_ep_index(ep->bEndpointAddress);
851 	ph_impl = &usba_device->usb_ph_list[ep_index];
852 
853 	mutex_enter(&usba_device->usb_mutex);
854 	mutex_enter(&ph_impl->usba_ph_mutex);
855 
856 	if (ph_impl->usba_ph_data) {
857 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
858 		    "usb_pipe_open: pipe to ep %d already open", ep_index);
859 		mutex_exit(&ph_impl->usba_ph_mutex);
860 		mutex_exit(&usba_device->usb_mutex);
861 		kmem_free(ph_data, size);
862 
863 		return (USB_BUSY);
864 	}
865 
866 	ph_impl->usba_ph_data = ph_data;
867 
868 	mutex_exit(&ph_impl->usba_ph_mutex);
869 	mutex_exit(&usba_device->usb_mutex);
870 
871 	if (usb_flags & USB_FLAGS_SERIALIZED_CB) {
872 		mutex_enter(&ph_data->p_mutex);
873 		ph_data->p_spec_flag |= USBA_PH_FLAG_TQ_SHARE;
874 		mutex_exit(&ph_data->p_mutex);
875 	}
876 
877 	/*
878 	 * allocate and initialize the pipe handle
879 	 */
880 	if ((rval = usba_init_pipe_handle(dip, usba_device,
881 	    ep, pipe_policy, ph_impl)) != USB_SUCCESS) {
882 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
883 		    "usb_pipe_open: pipe init failed (%d)", rval);
884 
885 		return (rval);
886 	}
887 	ph_data = ph_impl->usba_ph_data;
888 
889 	/*
890 	 * ask the hcd to open the pipe
891 	 */
892 	if ((rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_open(ph_data,
893 	    usb_flags)) != USB_SUCCESS) {
894 		usba_destroy_pipe_handle(ph_data);
895 
896 		*pipe_handle = NULL;
897 	} else {
898 		*pipe_handle = (usb_pipe_handle_t)ph_impl;
899 
900 		/* set the pipe state after a successful hcd open */
901 		mutex_enter(&ph_data->p_mutex);
902 		usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE);
903 		mutex_exit(&ph_data->p_mutex);
904 	}
905 
906 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
907 	    "usb_pipe_open: ph_impl=0x%p (0x%p)",
908 	    (void *)ph_impl, (void *)ph_data);
909 
910 	return (rval);
911 }
912 
913 
914 /*
915  * usb_pipe_close/sync_close:
916  *
917  * Close a pipe and release all resources and free the pipe_handle.
918  * Automatic polling, if active,  will be terminated
919  *
920  * Arguments:
921  *	dip		- devinfo ptr
922  *	pipehandle	- pointer to pipehandle. The pipehandle will be
923  *			  zeroed on successful completion
924  *	flags		- USB_FLAGS_SLEEP:
925  *				wait for resources, pipe
926  *				to become free, all callbacks completed
927  *	callback	- If USB_FLAGS_SLEEP has not been specified, a
928  *			  callback will be performed.
929  *	callback_arg	- the first argument of the callback. Note that
930  *			  the pipehandle will be zeroed and not passed
931  *
932  * Notes:
933  * Pipe close will always succeed regardless whether USB_FLAGS_SLEEP has been
934  * specified or not.
935  * An async close will always succeed if the hint in the pipe policy
936  * has been correct about the max number of async taskq requests required.
937  * If there are really no resources, the pipe handle will be linked into
938  * a garbage pipe list and periodically checked by USBA until it can be
939  * closed. This may cause a hang in the detach of the driver.
940  * USBA will prevent the client from submitting more requests to a pipe
941  * that is being closed
942  * Subsequent usb_pipe_close() requests on the same pipe to USBA will
943  * wait for the previous close(s) to finish.
944  *
945  * Note that once we start closing a pipe, we cannot go back anymore
946  * to a normal pipe state
947  */
948 void
usb_pipe_close(dev_info_t * dip,usb_pipe_handle_t pipe_handle,usb_flags_t usb_flags,void (* callback)(usb_pipe_handle_t pipe_handle,usb_opaque_t arg,int rval,usb_cb_flags_t flags),usb_opaque_t callback_arg)949 usb_pipe_close(dev_info_t	*dip,
950 		usb_pipe_handle_t pipe_handle,
951 		usb_flags_t	usb_flags,
952 		void		(*callback)(
953 				    usb_pipe_handle_t	pipe_handle,
954 				    usb_opaque_t	arg,
955 				    int			rval,
956 				    usb_cb_flags_t	flags),
957 		usb_opaque_t	callback_arg)
958 {
959 	usba_pipe_handle_data_t *ph_data;
960 	usba_ph_impl_t	*ph_impl = (usba_ph_impl_t *)pipe_handle;
961 	usb_cb_flags_t	callback_flags;
962 
963 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
964 	    "usb_pipe_close: ph=0x%p", (void *)pipe_handle);
965 
966 	callback_flags = usba_check_intr_context(USB_CB_NO_INFO);
967 	if ((dip == NULL) || (pipe_handle == NULL)) {
968 		if (callback) {
969 			callback(pipe_handle, callback_arg,
970 			    USB_INVALID_ARGS, callback_flags);
971 		} else {
972 			USB_DPRINTF_L2(DPRINT_MASK_USBAI,
973 			    usbai_log_handle,
974 			    "usb_pipe_close: invalid arguments");
975 		}
976 
977 		return;
978 	}
979 
980 	if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) {
981 		/*
982 		 * It is the client driver doing the pipe close,
983 		 * the pipe is no longer persistent then.
984 		 */
985 		mutex_enter(&ph_impl->usba_ph_mutex);
986 		ph_impl->usba_ph_flags &= ~USBA_PH_DATA_PERSISTENT;
987 		mutex_exit(&ph_impl->usba_ph_mutex);
988 	}
989 
990 	if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) {
991 		if (callback) {
992 			callback(pipe_handle, callback_arg,
993 			    USB_INVALID_CONTEXT, callback_flags);
994 		} else {
995 			USB_DPRINTF_L2(DPRINT_MASK_USBAI,
996 			    usbai_log_handle,
997 			    "usb_pipe_close: invalid context");
998 		}
999 
1000 		return;
1001 	}
1002 
1003 	if ((ph_data = usba_hold_ph_data(pipe_handle)) == NULL) {
1004 
1005 		/* hold pipehandle anyways since we will decrement later */
1006 		mutex_enter(&ph_impl->usba_ph_mutex);
1007 		ph_impl->usba_ph_ref_count++;
1008 		mutex_exit(&ph_impl->usba_ph_mutex);
1009 
1010 		(void) usba_pipe_setup_func_call(dip, usba_pipe_sync_close,
1011 		    ph_impl, NULL, usb_flags, callback, callback_arg);
1012 
1013 		return;
1014 	}
1015 
1016 	mutex_enter(&ph_data->p_mutex);
1017 
1018 	if (USBA_IS_DEFAULT_PIPE(ph_data) &&
1019 	    ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0)) {
1020 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1021 		    "usb_pipe_close: not allowed to close def pipe");
1022 		mutex_exit(&ph_data->p_mutex);
1023 
1024 		usba_release_ph_data(ph_impl);
1025 
1026 		if (callback) {
1027 			callback(pipe_handle, callback_arg,
1028 			    USB_INVALID_PIPE, callback_flags);
1029 		} else {
1030 			USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1031 			    usbai_log_handle,
1032 			    "usb_pipe_close: invalid pipe");
1033 		}
1034 
1035 		return;
1036 	}
1037 
1038 	mutex_exit(&ph_data->p_mutex);
1039 
1040 	(void) usba_pipe_setup_func_call(dip, usba_pipe_sync_close,
1041 	    ph_impl, NULL, usb_flags, callback, callback_arg);
1042 }
1043 
1044 
1045 /*ARGSUSED*/
1046 static int
usba_pipe_sync_close(dev_info_t * dip,usba_ph_impl_t * ph_impl,usba_pipe_async_req_t * request,usb_flags_t usb_flags)1047 usba_pipe_sync_close(dev_info_t *dip, usba_ph_impl_t *ph_impl,
1048 	usba_pipe_async_req_t *request, usb_flags_t usb_flags)
1049 {
1050 	usba_device_t		*usba_device;
1051 	usba_pipe_handle_data_t *ph_data = usba_get_ph_data(
1052 	    (usb_pipe_handle_t)ph_impl);
1053 	int			attribute;
1054 	uchar_t			dir;
1055 	int			timeout;
1056 
1057 	if (ph_impl == NULL) {
1058 
1059 		return (USB_SUCCESS);
1060 	}
1061 
1062 	mutex_enter(&ph_impl->usba_ph_mutex);
1063 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1064 	    "usba_pipe_sync_close: dip=0x%p ph_data=0x%p state=%d ref=%d",
1065 	    (void *)dip, (void *)ph_data, ph_impl->usba_ph_state,
1066 	    ph_impl->usba_ph_ref_count);
1067 
1068 	/*
1069 	 * if another thread opens the pipe again, this loop could
1070 	 * be truly forever
1071 	 */
1072 	if ((ph_data == NULL) ||
1073 	    (ph_impl->usba_ph_state == USB_PIPE_STATE_CLOSING) ||
1074 	    (ph_impl->usba_ph_state == USB_PIPE_STATE_CLOSED)) {
1075 		/* wait forever till really closed */
1076 		mutex_exit(&ph_impl->usba_ph_mutex);
1077 		usba_release_ph_data(ph_impl);
1078 
1079 		while (usba_get_ph_data((usb_pipe_handle_t)ph_impl)) {
1080 			delay(1);
1081 		}
1082 
1083 		return (USB_SUCCESS);
1084 	}
1085 	ph_impl->usba_ph_state = USB_PIPE_STATE_CLOSING;
1086 	mutex_exit(&ph_impl->usba_ph_mutex);
1087 
1088 	mutex_enter(&ph_data->p_mutex);
1089 	mutex_enter(&ph_impl->usba_ph_mutex);
1090 
1091 	attribute = ph_data->p_ep.bmAttributes & USB_EP_ATTR_MASK;
1092 	dir = ph_data->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
1093 
1094 	usba_device = ph_data->p_usba_device;
1095 
1096 	/*
1097 	 * For control and bulk, we will drain till ref_count <= 1 and
1098 	 * req_count == 0 but for isoc and intr IN, we can only wait
1099 	 * till the ref_count === 1 as the req_count will never go to 0
1100 	 */
1101 	for (timeout = 0; timeout < usba_drain_timeout; timeout++) {
1102 		switch (attribute) {
1103 		case USB_EP_ATTR_CONTROL:
1104 		case USB_EP_ATTR_BULK:
1105 			if ((ph_data->p_req_count == 0) &&
1106 			    (ph_impl->usba_ph_ref_count <= 1)) {
1107 				goto done;
1108 			}
1109 			break;
1110 		case USB_EP_ATTR_INTR:
1111 		case USB_EP_ATTR_ISOCH:
1112 			if (dir == USB_EP_DIR_IN) {
1113 				if (ph_impl->usba_ph_ref_count <= 1) {
1114 					goto done;
1115 				}
1116 			} else if ((ph_data->p_req_count == 0) &&
1117 			    (ph_impl->usba_ph_ref_count <= 1)) {
1118 				goto done;
1119 			}
1120 			break;
1121 		}
1122 		mutex_exit(&ph_impl->usba_ph_mutex);
1123 		mutex_exit(&ph_data->p_mutex);
1124 		delay(drv_usectohz(1000));
1125 		mutex_enter(&ph_data->p_mutex);
1126 		mutex_enter(&ph_impl->usba_ph_mutex);
1127 	}
1128 done:
1129 
1130 	mutex_exit(&ph_impl->usba_ph_mutex);
1131 	mutex_exit(&ph_data->p_mutex);
1132 
1133 	if (timeout >= usba_drain_timeout) {
1134 		int draining_succeeded;
1135 
1136 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1137 		    "timeout on draining requests, resetting pipe 0x%p",
1138 		    (void *)ph_impl);
1139 
1140 		(void) usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data,
1141 		    USB_FLAGS_SLEEP);
1142 
1143 		mutex_enter(&ph_data->p_mutex);
1144 		draining_succeeded = usba_drain_cbs(ph_data, USB_CB_RESET_PIPE,
1145 		    USB_CR_PIPE_RESET);
1146 		/* this MUST have succeeded */
1147 		ASSERT(draining_succeeded == USB_SUCCESS);
1148 		mutex_exit(&ph_data->p_mutex);
1149 
1150 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1151 		    "draining requests done");
1152 	}
1153 
1154 	if (usba_device->usb_hcdi_ops->usba_hcdi_pipe_close(ph_data,
1155 	    usb_flags) != USB_SUCCESS) {
1156 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1157 		    "usba_pipe_sync_close: hcd close failed");
1158 		/* carry on regardless! */
1159 	}
1160 
1161 	usba_destroy_pipe_handle(ph_data);
1162 
1163 	return (USB_SUCCESS);
1164 }
1165 
1166 
1167 /*
1168  * usb_pipe_set_private:
1169  *	set private client date in the pipe handle
1170  */
1171 int
usb_pipe_set_private(usb_pipe_handle_t pipe_handle,usb_opaque_t data)1172 usb_pipe_set_private(usb_pipe_handle_t	pipe_handle, usb_opaque_t data)
1173 {
1174 	usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1175 
1176 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1177 	    "usb_pipe_set_private: ");
1178 
1179 	if (ph_data == NULL) {
1180 
1181 		return (USB_INVALID_PIPE);
1182 	}
1183 	if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1184 		usba_release_ph_data(ph_data->p_ph_impl);
1185 
1186 		return (USB_INVALID_PERM);
1187 	}
1188 
1189 	mutex_enter(&ph_data->p_mutex);
1190 	ph_data->p_client_private = data;
1191 	mutex_exit(&ph_data->p_mutex);
1192 
1193 	usba_release_ph_data(ph_data->p_ph_impl);
1194 
1195 	return (USB_SUCCESS);
1196 }
1197 
1198 
1199 /*
1200  * usb_pipe_get_private:
1201  *	get private client date from the pipe handle
1202  */
1203 usb_opaque_t
usb_pipe_get_private(usb_pipe_handle_t pipe_handle)1204 usb_pipe_get_private(usb_pipe_handle_t	pipe_handle)
1205 {
1206 	usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1207 	usb_opaque_t		data;
1208 
1209 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1210 	    "usb_pipe_get_private:");
1211 
1212 	if (ph_data == NULL) {
1213 
1214 		return (NULL);
1215 	}
1216 
1217 	mutex_enter(&ph_data->p_mutex);
1218 	data = ph_data->p_client_private;
1219 	mutex_exit(&ph_data->p_mutex);
1220 
1221 	usba_release_ph_data(ph_data->p_ph_impl);
1222 
1223 	return (data);
1224 }
1225 
1226 
1227 /*
1228  * usb_pipe_reset
1229  * Arguments:
1230  *	dip		- devinfo pointer
1231  *	pipe_handle	- opaque pipe handle
1232  * Returns:
1233  *	USB_SUCCESS	- pipe successfully reset or request queued
1234  *	USB_FAILURE	- undetermined failure
1235  *	USB_INVALID_PIPE - pipe is invalid or already closed
1236  */
1237 void
usb_pipe_reset(dev_info_t * dip,usb_pipe_handle_t pipe_handle,usb_flags_t usb_flags,void (* callback)(usb_pipe_handle_t ph,usb_opaque_t arg,int rval,usb_cb_flags_t flags),usb_opaque_t callback_arg)1238 usb_pipe_reset(dev_info_t		*dip,
1239 		usb_pipe_handle_t	pipe_handle,
1240 		usb_flags_t		usb_flags,
1241 		void			(*callback)(
1242 					    usb_pipe_handle_t	ph,
1243 					    usb_opaque_t	arg,
1244 					    int			rval,
1245 					    usb_cb_flags_t	flags),
1246 		usb_opaque_t		callback_arg)
1247 {
1248 	usba_ph_impl_t		*ph_impl = (usba_ph_impl_t *)pipe_handle;
1249 	usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1250 	usb_cb_flags_t		callback_flags;
1251 
1252 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1253 	    "usb_pipe_reset: dip=0x%p ph=0x%p uf=0x%x",
1254 	    (void *)dip, (void *)pipe_handle, usb_flags);
1255 
1256 	callback_flags = usba_check_intr_context(USB_CB_NO_INFO);
1257 
1258 	if ((dip == NULL) || (ph_data == NULL)) {
1259 		if (callback) {
1260 			callback(pipe_handle, callback_arg,
1261 			    USB_INVALID_ARGS, callback_flags);
1262 		} else {
1263 			USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1264 			    usbai_log_handle,
1265 			    "usb_pipe_reset: invalid arguments");
1266 		}
1267 
1268 		usba_release_ph_data(ph_impl);
1269 
1270 		return;
1271 	}
1272 	if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) {
1273 		if (callback) {
1274 			callback(pipe_handle, callback_arg,
1275 			    USB_INVALID_CONTEXT, callback_flags);
1276 		} else {
1277 			USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1278 			    usbai_log_handle,
1279 			    "usb_pipe_reset: invalid context");
1280 		}
1281 
1282 		usba_release_ph_data(ph_impl);
1283 
1284 		return;
1285 	}
1286 
1287 	mutex_enter(&ph_data->p_mutex);
1288 
1289 	/* is this the default pipe? */
1290 	if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1291 		if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) {
1292 			USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1293 			    "usb_pipe_reset: not allowed to reset def pipe");
1294 			mutex_exit(&ph_data->p_mutex);
1295 
1296 			if (callback) {
1297 				callback(pipe_handle, callback_arg,
1298 				    USB_INVALID_PIPE, callback_flags);
1299 			} else {
1300 				USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1301 				    usbai_log_handle,
1302 				    "usb_pipe_reset: invalid pipe");
1303 			}
1304 			usba_release_ph_data(ph_impl);
1305 
1306 			return;
1307 		}
1308 	}
1309 	mutex_exit(&ph_data->p_mutex);
1310 
1311 	(void) usba_pipe_setup_func_call(dip,
1312 	    usba_pipe_sync_reset, ph_impl, NULL, usb_flags, callback,
1313 	    callback_arg);
1314 }
1315 
1316 
1317 /*ARGSUSED*/
1318 int
usba_pipe_sync_reset(dev_info_t * dip,usba_ph_impl_t * ph_impl,usba_pipe_async_req_t * request,usb_flags_t usb_flags)1319 usba_pipe_sync_reset(dev_info_t	*dip,
1320 	usba_ph_impl_t		*ph_impl,
1321 	usba_pipe_async_req_t	*request,
1322 	usb_flags_t		usb_flags)
1323 {
1324 	int rval, draining_succeeded;
1325 	usba_pipe_handle_data_t *ph_data = usba_get_ph_data((usb_pipe_handle_t)
1326 	    ph_impl);
1327 	usba_device_t		*usba_device;
1328 
1329 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1330 	    "usba_pipe_sync_reset: dip=0x%p ph_data=0x%p uf=0x%x",
1331 	    (void *)dip, (void *)ph_data, usb_flags);
1332 
1333 	mutex_enter(&ph_data->p_mutex);
1334 	usba_device = ph_data->p_usba_device;
1335 	mutex_exit(&ph_data->p_mutex);
1336 
1337 	rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data,
1338 	    usb_flags);
1339 	mutex_enter(&ph_data->p_mutex);
1340 
1341 	/*
1342 	 * The host controller has stopped polling of the endpoint.
1343 	 */
1344 	draining_succeeded = usba_drain_cbs(ph_data, USB_CB_RESET_PIPE,
1345 	    USB_CR_PIPE_RESET);
1346 
1347 	/* this MUST have succeeded */
1348 	ASSERT(draining_succeeded == USB_SUCCESS);
1349 
1350 	usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE);
1351 	mutex_exit(&ph_data->p_mutex);
1352 
1353 	/*
1354 	 * if there are requests still queued on the default pipe,
1355 	 * start them now
1356 	 */
1357 	usba_start_next_req(ph_data);
1358 
1359 	usba_release_ph_data(ph_impl);
1360 
1361 	return (rval);
1362 }
1363 
1364 
1365 /*
1366  * usba_pipe_clear:
1367  *	call hcd to clear pipe but don't wait for draining
1368  */
1369 void
usba_pipe_clear(usb_pipe_handle_t pipe_handle)1370 usba_pipe_clear(usb_pipe_handle_t pipe_handle)
1371 {
1372 	usba_pipe_handle_data_t *ph_data = usba_get_ph_data(pipe_handle);
1373 	usba_device_t		*usba_device;
1374 	usba_req_wrapper_t	*req_wrp;
1375 	int			flush_requests = 1;
1376 
1377 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1378 	    "usba_pipe_clear: ph_data=0x%p", (void *)ph_data);
1379 
1380 	if (ph_data == NULL) {
1381 
1382 		return;
1383 	}
1384 
1385 	mutex_enter(&ph_data->p_mutex);
1386 	if (USBA_PIPE_CLOSING(usba_get_ph_state(ph_data))) {
1387 		mutex_exit(&ph_data->p_mutex);
1388 
1389 		return;
1390 	}
1391 	usba_device = ph_data->p_usba_device;
1392 	mutex_exit(&ph_data->p_mutex);
1393 
1394 	(void) usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data,
1395 	    USB_FLAGS_SLEEP);
1396 
1397 	mutex_enter(&ph_data->p_mutex);
1398 	if (ph_data->p_dip) {
1399 		if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1400 			USB_DPRINTF_L4(DPRINT_MASK_USBAI,
1401 			    usbai_log_handle,
1402 			    "no flushing on default pipe!");
1403 
1404 			flush_requests = 0;
1405 		}
1406 	}
1407 
1408 	if (flush_requests) {
1409 		/* flush all requests in the pipehandle queue */
1410 		while ((req_wrp = (usba_req_wrapper_t *)
1411 		    usba_rm_first_pvt_from_list(&ph_data->p_queue)) != NULL) {
1412 			mutex_exit(&ph_data->p_mutex);
1413 			usba_do_req_exc_cb(req_wrp, USB_CR_FLUSHED,
1414 			    USB_CB_RESET_PIPE);
1415 			mutex_enter(&ph_data->p_mutex);
1416 		}
1417 	}
1418 
1419 	usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE);
1420 	mutex_exit(&ph_data->p_mutex);
1421 }
1422 
1423 
1424 /*
1425  *
1426  * usb_pipe_drain_reqs
1427  *	this function blocks until there are no more requests
1428  *	owned by this dip on the pipe
1429  *
1430  * Arguments:
1431  *	dip		- devinfo pointer
1432  *	pipe_handle	- opaque pipe handle
1433  *	timeout 	- timeout in seconds
1434  *	flags		- USB_FLAGS_SLEEP:
1435  *				wait for completion.
1436  *	cb		- if USB_FLAGS_SLEEP has not been specified
1437  *			  this callback function will be called on
1438  *			  completion. This callback may be NULL
1439  *			  and no notification of completion will then
1440  *			  be provided.
1441  *	cb_arg		- 2nd argument to callback function.
1442  *
1443  * callback and callback_arg should be NULL if USB_FLAGS_SLEEP has
1444  * been specified
1445  *
1446  * Returns:
1447  *	USB_SUCCESS	- pipe successfully reset or request queued
1448  *	USB_FAILURE	- timeout
1449  *	USB_*		- refer to usbai.h
1450  */
1451 int
usb_pipe_drain_reqs(dev_info_t * dip,usb_pipe_handle_t pipe_handle,uint_t time,usb_flags_t usb_flags,void (* cb)(usb_pipe_handle_t ph,usb_opaque_t arg,int rval,usb_cb_flags_t flags),usb_opaque_t cb_arg)1452 usb_pipe_drain_reqs(dev_info_t	*dip,
1453 	usb_pipe_handle_t	pipe_handle,
1454 	uint_t			time,
1455 	usb_flags_t		usb_flags,
1456 	void			(*cb)(
1457 				    usb_pipe_handle_t	ph,
1458 				    usb_opaque_t	arg,   /* cb arg */
1459 				    int			rval,
1460 				    usb_cb_flags_t	flags),
1461 	usb_opaque_t		cb_arg)
1462 {
1463 	usba_ph_impl_t		*ph_impl = (usba_ph_impl_t *)pipe_handle;
1464 	usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1465 
1466 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1467 	    "usb_pipe_drain_reqs: dip=0x%p ph_data=0x%p tm=%d uf=0x%x",
1468 	    (void *)dip, (void *)ph_data, time, usb_flags);
1469 
1470 	if (ph_data == NULL) {
1471 
1472 		return (USB_INVALID_PIPE);
1473 	}
1474 	if (dip == NULL) {
1475 		usba_release_ph_data(ph_impl);
1476 
1477 		return (USB_INVALID_ARGS);
1478 	}
1479 
1480 	if ((usb_flags & USB_FLAGS_SLEEP) && servicing_interrupt()) {
1481 		usba_release_ph_data(ph_impl);
1482 
1483 		return (USB_INVALID_CONTEXT);
1484 	}
1485 
1486 	(void) usba_pipe_setup_func_call(dip, usba_pipe_sync_drain_reqs,
1487 	    ph_impl, (usb_opaque_t)((uintptr_t)time), usb_flags, cb, cb_arg);
1488 
1489 	return (USB_SUCCESS);
1490 }
1491 
1492 
1493 /*
1494  * usba_pipe_sync_drain_reqs
1495  *	this function blocks until there are no more requests
1496  *	owned by this dip on the pipe
1497  *
1498  * Arguments:
1499  *	dip		- devinfo pointer
1500  *	ph_impl		- pipe impl handle
1501  *	timeout		- timeout in seconds
1502  * Returns:
1503  *	USB_SUCCESS	- pipe successfully reset or request queued
1504  *	USB_FAILURE	- timeout
1505  *	USB_*		- see usbai.h
1506  */
1507 /*ARGSUSED*/
1508 int
usba_pipe_sync_drain_reqs(dev_info_t * dip,usba_ph_impl_t * ph_impl,usba_pipe_async_req_t * request,usb_flags_t usb_flags)1509 usba_pipe_sync_drain_reqs(dev_info_t	*dip,
1510 		usba_ph_impl_t		*ph_impl,
1511 		usba_pipe_async_req_t	*request,
1512 		usb_flags_t		usb_flags)
1513 {
1514 	usba_pipe_handle_data_t *ph_data = usba_get_ph_data((usb_pipe_handle_t)
1515 	    ph_impl);
1516 	int		i;
1517 	int		timeout = 100 * (int)((uintptr_t)(request->arg));
1518 						/* delay will be 10 ms */
1519 
1520 	mutex_enter(&ph_data->p_mutex);
1521 
1522 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1523 	    "usba_pipe_sync_drain_reqs: "
1524 	    "dip=0x%p ph_data=0x%p timeout=%d ref=%d req=%d",
1525 	    (void *)dip, (void *)ph_data, timeout,
1526 	    usba_get_ph_ref_count(ph_data),
1527 	    ph_data->p_req_count);
1528 
1529 	ASSERT(ph_data->p_req_count >= 0);
1530 
1531 	/*
1532 	 * for default pipe, we need to check the active request
1533 	 * and the queue
1534 	 * Note that a pipe reset on the default pipe doesn't flush
1535 	 * the queue
1536 	 * for all other pipes we just check ref and req count since
1537 	 * these pipes are unshared
1538 	 */
1539 	if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1540 		for (i = 0; (i < timeout) || (request->arg == 0); i++) {
1541 			usba_list_entry_t *next, *tmpnext;
1542 			usba_req_wrapper_t *req_wrp = (usba_req_wrapper_t *)
1543 			    ph_data->p_active_cntrl_req_wrp;
1544 			int found = 0;
1545 			int count = 0;
1546 
1547 			/* active_req_wrp is only for control pipes */
1548 			if ((req_wrp == NULL) || (req_wrp->wr_dip != dip)) {
1549 				/* walk the queue */
1550 				mutex_enter(&ph_data->p_queue.list_mutex);
1551 				next = ph_data->p_queue.next;
1552 				while (next != NULL) {
1553 					mutex_enter(&next->list_mutex);
1554 					req_wrp = (usba_req_wrapper_t *)
1555 					    next->private;
1556 					found = (req_wrp->wr_dip == dip);
1557 					if (found) {
1558 						mutex_exit(&next->list_mutex);
1559 
1560 						break;
1561 					}
1562 					tmpnext = next->next;
1563 					mutex_exit(&next->list_mutex);
1564 					next = tmpnext;
1565 					count++;
1566 				}
1567 				mutex_exit(&ph_data->p_queue.list_mutex);
1568 				if (found == 0) {
1569 					break;
1570 				}
1571 			}
1572 
1573 			USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1574 			    "usb_pipe_sync_drain_reqs: "
1575 			    "cnt=%d active_req_wrp=0x%p",
1576 			    count, (void *)ph_data->p_active_cntrl_req_wrp);
1577 
1578 			mutex_exit(&ph_data->p_mutex);
1579 			delay(drv_usectohz(10000));
1580 			mutex_enter(&ph_data->p_mutex);
1581 		}
1582 	} else {
1583 		mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex);
1584 		for (i = 0; (i < timeout) || (request->arg == 0); i++) {
1585 			ASSERT(ph_data->p_req_count >= 0);
1586 			if (ph_data->p_req_count ||
1587 			    (ph_data->p_ph_impl->usba_ph_ref_count > 1)) {
1588 				mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex);
1589 				mutex_exit(&ph_data->p_mutex);
1590 				delay(drv_usectohz(10000));
1591 				mutex_enter(&ph_data->p_mutex);
1592 				mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex);
1593 			} else {
1594 				break;
1595 			}
1596 		}
1597 		mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex);
1598 	}
1599 
1600 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1601 	    "usb_pipe_sync_drain_reqs: timeout=%d active_req_wrp=0x%p req=%d",
1602 	    i, (void *)ph_data->p_active_cntrl_req_wrp, ph_data->p_req_count);
1603 
1604 	mutex_exit(&ph_data->p_mutex);
1605 
1606 	usba_release_ph_data(ph_impl);
1607 
1608 	return (i >= timeout ? USB_FAILURE : USB_SUCCESS);
1609 }
1610 
1611 
1612 /*
1613  * usba_persistent_pipe_open
1614  *	Open all the pipes marked persistent for this device
1615  */
1616 int
usba_persistent_pipe_open(usba_device_t * usba_device)1617 usba_persistent_pipe_open(usba_device_t *usba_device)
1618 {
1619 	usba_ph_impl_t		*ph_impl;
1620 	usb_pipe_handle_t	pipe_handle;
1621 	int			i;
1622 	int			rval = USB_SUCCESS;
1623 
1624 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1625 	    "usba_persistent_pipe_open: usba_device=0x%p", (void *)usba_device);
1626 
1627 	if (usba_device != NULL) {
1628 		/* default pipe is the first one to be opened */
1629 		mutex_enter(&usba_device->usb_mutex);
1630 		for (i = 0; (rval == USB_SUCCESS) &&
1631 		    (i < USBA_N_ENDPOINTS); i++) {
1632 
1633 			ph_impl = &usba_device->usb_ph_list[i];
1634 			mutex_enter(&ph_impl->usba_ph_mutex);
1635 			if (ph_impl->usba_ph_flags & USBA_PH_DATA_PERSISTENT) {
1636 				ph_impl->usba_ph_flags &=
1637 				    ~USBA_PH_DATA_PERSISTENT;
1638 				mutex_exit(&ph_impl->usba_ph_mutex);
1639 				mutex_exit(&usba_device->usb_mutex);
1640 
1641 				rval = usb_pipe_open(ph_impl->usba_ph_dip,
1642 				    &ph_impl->usba_ph_ep,
1643 				    &ph_impl->usba_ph_policy,
1644 				    USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED,
1645 				    &pipe_handle);
1646 
1647 				USB_DPRINTF_L3(DPRINT_MASK_USBAI,
1648 				    usbai_log_handle,
1649 				    "usba_persistent_pipe_open: "
1650 				    "ep_index=%d, rval=%d", i, rval);
1651 				mutex_enter(&usba_device->usb_mutex);
1652 				mutex_enter(&ph_impl->usba_ph_mutex);
1653 			}
1654 			mutex_exit(&ph_impl->usba_ph_mutex);
1655 		}
1656 		mutex_exit(&usba_device->usb_mutex);
1657 	}
1658 
1659 	return (rval);
1660 }
1661 
1662 
1663 /*
1664  * usba_persistent_pipe_close
1665  *	Close all pipes of this device and mark them persistent
1666  */
1667 void
usba_persistent_pipe_close(usba_device_t * usba_device)1668 usba_persistent_pipe_close(usba_device_t *usba_device)
1669 {
1670 	usba_ph_impl_t		*ph_impl;
1671 	usb_pipe_handle_t	pipe_handle;
1672 	int			i;
1673 
1674 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1675 	    "usba_persistent_pipe_close: usba_device=0x%p",
1676 	    (void *)usba_device);
1677 
1678 	if (usba_device != NULL) {
1679 		/* default pipe is the last one to be closed */
1680 		mutex_enter(&usba_device->usb_mutex);
1681 
1682 		for (i = (USBA_N_ENDPOINTS - 1); i >= 0; i--) {
1683 			ph_impl = &usba_device->usb_ph_list[i];
1684 			if (ph_impl->usba_ph_data != NULL) {
1685 				mutex_enter(&ph_impl->usba_ph_mutex);
1686 				ph_impl->usba_ph_flags |=
1687 				    USBA_PH_DATA_PERSISTENT;
1688 				mutex_exit(&ph_impl->usba_ph_mutex);
1689 				mutex_exit(&usba_device->usb_mutex);
1690 
1691 				pipe_handle = (usb_pipe_handle_t)ph_impl;
1692 
1693 				usb_pipe_close(ph_impl->usba_ph_dip,
1694 				    pipe_handle,
1695 				    USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED,
1696 				    NULL, NULL);
1697 				mutex_enter(&usba_device->usb_mutex);
1698 				ASSERT(ph_impl->usba_ph_data == NULL);
1699 			}
1700 		}
1701 		mutex_exit(&usba_device->usb_mutex);
1702 	}
1703 }
1704