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