1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 /*
28  * USBA: Solaris USB Architecture support
29  *
30  * all functions exposed to client drivers  have prefix usb_ while all USBA
31  * internal functions or functions exposed to HCD or hubd only have prefix
32  * usba_
33  *
34  * this file contains all USBAI pipe management
35  *	usb_pipe_open()
36  *	usb_pipe_close()
37  *	usb_pipe_set_private()
38  *	usb_pipe_get_private()
39  *	usb_pipe_abort()
40  *	usb_pipe_reset()
41  *	usb_pipe_drain_reqs()
42  */
43 #define	USBA_FRAMEWORK
44 #include <sys/usb/usba/usba_impl.h>
45 #include <sys/usb/usba/hcdi_impl.h>
46 #include <sys/atomic.h>
47 
48 extern	pri_t	maxclsyspri;
49 extern	pri_t	minclsyspri;
50 
51 /* function prototypes */
52 static	void	usba_pipe_do_async_func_thread(void *arg);
53 static	int	usba_pipe_sync_close(dev_info_t *, usba_ph_impl_t *,
54 			usba_pipe_async_req_t *, usb_flags_t);
55 static	int	usba_pipe_sync_abort(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
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 *
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
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 *
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
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 *
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
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
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
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
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
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
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
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
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_add_32_nv(&anon_instance, 1);
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 		USB_DPRINTF_L3(DPRINT_MASK_USBAI, usbai_log_handle,
526 		    "adjusting max packet size from %d to %d",
527 		    ph_data->p_ep.wMaxPacketSize,
528 		    usba_device->usb_dev_descr->bMaxPacketSize0);
529 
530 		ph_data->p_ep.wMaxPacketSize = usba_device->usb_dev_descr->
531 		    bMaxPacketSize0;
532 	}
533 
534 	/* now update usba_ph_impl structure */
535 	mutex_enter(&ph_impl->usba_ph_mutex);
536 	ph_impl->usba_ph_dip = dip;
537 	ph_impl->usba_ph_ep = ph_data->p_ep;
538 	ph_impl->usba_ph_policy = ph_data->p_policy = *pipe_policy;
539 	mutex_exit(&ph_impl->usba_ph_mutex);
540 
541 	usba_init_list(&ph_data->p_queue, (usb_opaque_t)ph_data, iblock_cookie);
542 	usba_init_list(&ph_data->p_cb_queue, (usb_opaque_t)ph_data,
543 	    iblock_cookie);
544 	mutex_exit(&usba_device->usb_mutex);
545 	mutex_exit(&ph_data->p_mutex);
546 
547 	return (USB_SUCCESS);
548 }
549 
550 
551 static void
552 usba_taskq_destroy(void *arg)
553 {
554 	taskq_destroy((taskq_t *)arg);
555 }
556 
557 
558 static void
559 usba_destroy_pipe_handle(usba_pipe_handle_data_t *ph_data)
560 {
561 	usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
562 	int			timeout;
563 	usba_device_t		*usba_device;
564 
565 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
566 	    "usba_destroy_pipe_handle: ph_data=0x%p", (void *)ph_data);
567 
568 	mutex_enter(&ph_data->p_mutex);
569 	mutex_enter(&ph_impl->usba_ph_mutex);
570 
571 	/* check for all activity to drain */
572 	for (timeout = 0; timeout < usba_drain_timeout; timeout++) {
573 		if ((ph_impl->usba_ph_ref_count <= 1) &&
574 		    (ph_data->p_req_count == 0)) {
575 
576 			break;
577 		}
578 		mutex_exit(&ph_data->p_mutex);
579 		mutex_exit(&ph_impl->usba_ph_mutex);
580 		delay(drv_usectohz(1000));
581 		mutex_enter(&ph_data->p_mutex);
582 		mutex_enter(&ph_impl->usba_ph_mutex);
583 	}
584 
585 	/*
586 	 * set state to closed here so any other thread
587 	 * that is waiting for the CLOSED state will
588 	 * continue. Otherwise, taskq_destroy might deadlock
589 	 */
590 	ph_impl->usba_ph_data = NULL;
591 	ph_impl->usba_ph_ref_count = 0;
592 	ph_impl->usba_ph_state = USB_PIPE_STATE_CLOSED;
593 
594 	if (ph_data->p_taskq) {
595 		mutex_exit(&ph_data->p_mutex);
596 		mutex_exit(&ph_impl->usba_ph_mutex);
597 		if (taskq_member(ph_data->p_taskq, curthread)) {
598 			/*
599 			 * use system taskq to destroy ph's taskq to avoid
600 			 * deadlock
601 			 */
602 			(void) taskq_dispatch(system_taskq,
603 			    usba_taskq_destroy, ph_data->p_taskq, TQ_SLEEP);
604 		} else {
605 			taskq_destroy(ph_data->p_taskq);
606 		}
607 	} else {
608 		mutex_exit(&ph_data->p_mutex);
609 		mutex_exit(&ph_impl->usba_ph_mutex);
610 	}
611 
612 	usba_device = ph_data->p_usba_device;
613 	mutex_enter(&ph_data->p_mutex);
614 	if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) {
615 		int iface = usb_get_if_number(ph_data->p_dip);
616 		if (iface < 0) {
617 			/* we own the device, use the first entry */
618 			iface = 0;
619 		}
620 		mutex_enter(&usba_device->usb_mutex);
621 		if (--usba_device->usb_shared_taskq_ref_count[iface] == 0) {
622 			ph_data->p_spec_flag &= ~USBA_PH_FLAG_TQ_SHARE;
623 			if (taskq_member(usba_device->usb_shared_taskq[iface],
624 			    curthread)) {
625 				(void) taskq_dispatch(
626 				    system_taskq,
627 				    usba_taskq_destroy,
628 				    usba_device->usb_shared_taskq[iface],
629 				    TQ_SLEEP);
630 			} else {
631 				taskq_destroy(
632 				    usba_device->usb_shared_taskq[iface]);
633 			}
634 		}
635 		mutex_exit(&usba_device->usb_mutex);
636 	}
637 	mutex_exit(&ph_data->p_mutex);
638 
639 
640 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
641 	    "usba_destroy_pipe_handle: destroying ph_data=0x%p",
642 	    (void *)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 	    (void *)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 	    (void *)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 	    (void *)dip, (void *)ep, (void *)pipe_policy, usb_flags,
782 	    (void *)pipe_handle);
783 
784 	if ((dip == NULL) || (pipe_handle == NULL)) {
785 
786 		return (USB_INVALID_ARGS);
787 	}
788 
789 	if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) {
790 
791 		return (USB_INVALID_CONTEXT);
792 	}
793 	usba_device = usba_get_usba_device(dip);
794 
795 	if ((ep != NULL) && (pipe_policy == NULL)) {
796 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
797 		    "usb_pipe_open: null pipe policy");
798 
799 		return (USB_INVALID_ARGS);
800 	}
801 
802 	/* is the device still connected? */
803 	if ((ep != NULL) & DEVI_IS_DEVICE_REMOVED(dip)) {
804 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
805 		    "usb_pipe_open: device has been removed");
806 
807 		return (USB_FAILURE);
808 	}
809 
810 
811 	/*
812 	 * if a null endpoint pointer was passed, use the default
813 	 * endpoint descriptor
814 	 */
815 	if (ep == NULL) {
816 		if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) {
817 			USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
818 			    "usb_pipe_open: not allowed to open def pipe");
819 
820 			return (USB_INVALID_PERM);
821 		}
822 
823 		ep = &usba_default_ep_descr;
824 		pipe_policy = &usba_default_ep_pipe_policy;
825 	}
826 
827 	if (usb_flags & USB_FLAGS_SERIALIZED_CB) {
828 		if (((ep->bmAttributes & USB_EP_ATTR_MASK) ==
829 		    USB_EP_ATTR_CONTROL) ||
830 		    ((ep->bmAttributes & USB_EP_ATTR_MASK) ==
831 		    USB_EP_ATTR_ISOCH)) {
832 			USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
833 			    "usb_pipe_open: shared taskq not allowed with "
834 			    "ctrl or isoch pipe");
835 
836 			return (USB_INVALID_ARGS);
837 		}
838 	}
839 
840 	kmflag	= (usb_flags & USB_FLAGS_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
841 	size	= sizeof (usba_pipe_handle_data_t);
842 
843 	if ((ph_data = kmem_zalloc(size, kmflag)) == NULL) {
844 
845 		return (USB_NO_RESOURCES);
846 	}
847 
848 	/* check if pipe is already open and if so fail */
849 	ep_index = usb_get_ep_index(ep->bEndpointAddress);
850 	ph_impl = &usba_device->usb_ph_list[ep_index];
851 
852 	mutex_enter(&usba_device->usb_mutex);
853 	mutex_enter(&ph_impl->usba_ph_mutex);
854 
855 	if (ph_impl->usba_ph_data) {
856 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
857 		    "usb_pipe_open: pipe to ep %d already open", ep_index);
858 		mutex_exit(&ph_impl->usba_ph_mutex);
859 		mutex_exit(&usba_device->usb_mutex);
860 		kmem_free(ph_data, size);
861 
862 		return (USB_BUSY);
863 	}
864 
865 	ph_impl->usba_ph_data = ph_data;
866 
867 	mutex_exit(&ph_impl->usba_ph_mutex);
868 	mutex_exit(&usba_device->usb_mutex);
869 
870 	if (usb_flags & USB_FLAGS_SERIALIZED_CB) {
871 		mutex_enter(&ph_data->p_mutex);
872 		ph_data->p_spec_flag |= USBA_PH_FLAG_TQ_SHARE;
873 		mutex_exit(&ph_data->p_mutex);
874 	}
875 
876 	/*
877 	 * allocate and initialize the pipe handle
878 	 */
879 	if ((rval = usba_init_pipe_handle(dip, usba_device,
880 	    ep, pipe_policy, ph_impl)) != USB_SUCCESS) {
881 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
882 		    "usb_pipe_open: pipe init failed (%d)", rval);
883 
884 		return (rval);
885 	}
886 	ph_data = ph_impl->usba_ph_data;
887 
888 	/*
889 	 * ask the hcd to open the pipe
890 	 */
891 	if ((rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_open(ph_data,
892 	    usb_flags)) != USB_SUCCESS) {
893 		usba_destroy_pipe_handle(ph_data);
894 
895 		*pipe_handle = NULL;
896 	} else {
897 		*pipe_handle = (usb_pipe_handle_t)ph_impl;
898 
899 		/* set the pipe state after a successful hcd open */
900 		mutex_enter(&ph_data->p_mutex);
901 		usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE);
902 		mutex_exit(&ph_data->p_mutex);
903 	}
904 
905 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
906 	    "usb_pipe_open: ph_impl=0x%p (0x%p)",
907 	    (void *)ph_impl, (void *)ph_data);
908 
909 	return (rval);
910 }
911 
912 
913 /*
914  * usb_pipe_close/sync_close:
915  *
916  * Close a pipe and release all resources and free the pipe_handle.
917  * Automatic polling, if active,  will be terminated
918  *
919  * Arguments:
920  *	dip		- devinfo ptr
921  *	pipehandle	- pointer to pipehandle. The pipehandle will be
922  *			  zeroed on successful completion
923  *	flags		- USB_FLAGS_SLEEP:
924  *				wait for resources, pipe
925  *				to become free, all callbacks completed
926  *	callback	- If USB_FLAGS_SLEEP has not been specified, a
927  *			  callback will be performed.
928  *	callback_arg	- the first argument of the callback. Note that
929  *			  the pipehandle will be zeroed and not passed
930  *
931  * Notes:
932  * Pipe close will always succeed regardless whether USB_FLAGS_SLEEP has been
933  * specified or not.
934  * An async close will always succeed if the hint in the pipe policy
935  * has been correct about the max number of async taskq requests required.
936  * If there are really no resources, the pipe handle will be linked into
937  * a garbage pipe list and periodically checked by USBA until it can be
938  * closed. This may cause a hang in the detach of the driver.
939  * USBA will prevent the client from submitting more requests to a pipe
940  * that is being closed
941  * Subsequent usb_pipe_close() requests on the same pipe to USBA will
942  * wait for the previous close(s) to finish.
943  *
944  * Note that once we start closing a pipe, we cannot go back anymore
945  * to a normal pipe state
946  */
947 void
948 usb_pipe_close(dev_info_t	*dip,
949 		usb_pipe_handle_t pipe_handle,
950 		usb_flags_t	usb_flags,
951 		void		(*callback)(
952 				    usb_pipe_handle_t	pipe_handle,
953 				    usb_opaque_t	arg,
954 				    int			rval,
955 				    usb_cb_flags_t	flags),
956 		usb_opaque_t	callback_arg)
957 {
958 	usba_pipe_handle_data_t *ph_data;
959 	usba_ph_impl_t	*ph_impl = (usba_ph_impl_t *)pipe_handle;
960 	usb_cb_flags_t	callback_flags;
961 
962 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
963 	    "usb_pipe_close: ph=0x%p", (void *)pipe_handle);
964 
965 	callback_flags = usba_check_intr_context(USB_CB_NO_INFO);
966 	if ((dip == NULL) || (pipe_handle == NULL)) {
967 		if (callback) {
968 			callback(pipe_handle, callback_arg,
969 			    USB_INVALID_ARGS, callback_flags);
970 		} else {
971 			USB_DPRINTF_L2(DPRINT_MASK_USBAI,
972 			    usbai_log_handle,
973 			    "usb_pipe_close: invalid arguments");
974 		}
975 
976 		return;
977 	}
978 
979 	if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) {
980 		/*
981 		 * It is the client driver doing the pipe close,
982 		 * the pipe is no longer persistent then.
983 		 */
984 		mutex_enter(&ph_impl->usba_ph_mutex);
985 		ph_impl->usba_ph_flags &= ~USBA_PH_DATA_PERSISTENT;
986 		mutex_exit(&ph_impl->usba_ph_mutex);
987 	}
988 
989 	if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) {
990 		if (callback) {
991 			callback(pipe_handle, callback_arg,
992 			    USB_INVALID_CONTEXT, callback_flags);
993 		} else {
994 			USB_DPRINTF_L2(DPRINT_MASK_USBAI,
995 			    usbai_log_handle,
996 			    "usb_pipe_close: invalid context");
997 		}
998 
999 		return;
1000 	}
1001 
1002 	if ((ph_data = usba_hold_ph_data(pipe_handle)) == NULL) {
1003 
1004 		/* hold pipehandle anyways since we will decrement later */
1005 		mutex_enter(&ph_impl->usba_ph_mutex);
1006 		ph_impl->usba_ph_ref_count++;
1007 		mutex_exit(&ph_impl->usba_ph_mutex);
1008 
1009 		(void) usba_pipe_setup_func_call(dip, usba_pipe_sync_close,
1010 		    ph_impl, NULL, usb_flags, callback, callback_arg);
1011 
1012 		return;
1013 	}
1014 
1015 	mutex_enter(&ph_data->p_mutex);
1016 
1017 	if (USBA_IS_DEFAULT_PIPE(ph_data) &&
1018 	    ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0)) {
1019 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1020 		    "usb_pipe_close: not allowed to close def pipe");
1021 		mutex_exit(&ph_data->p_mutex);
1022 
1023 		usba_release_ph_data(ph_impl);
1024 
1025 		if (callback) {
1026 			callback(pipe_handle, callback_arg,
1027 			    USB_INVALID_PIPE, callback_flags);
1028 		} else {
1029 			USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1030 			    usbai_log_handle,
1031 			    "usb_pipe_close: invalid pipe");
1032 		}
1033 
1034 		return;
1035 	}
1036 
1037 	mutex_exit(&ph_data->p_mutex);
1038 
1039 	(void) usba_pipe_setup_func_call(dip, usba_pipe_sync_close,
1040 	    ph_impl, NULL, usb_flags, callback, callback_arg);
1041 }
1042 
1043 
1044 /*ARGSUSED*/
1045 static int
1046 usba_pipe_sync_close(dev_info_t *dip, usba_ph_impl_t *ph_impl,
1047 	usba_pipe_async_req_t *request, usb_flags_t usb_flags)
1048 {
1049 	usba_device_t		*usba_device;
1050 	usba_pipe_handle_data_t *ph_data = usba_get_ph_data(
1051 	    (usb_pipe_handle_t)ph_impl);
1052 	int			attribute;
1053 	uchar_t			dir;
1054 	int			timeout;
1055 
1056 	if (ph_impl == NULL) {
1057 
1058 		return (USB_SUCCESS);
1059 	}
1060 
1061 	mutex_enter(&ph_impl->usba_ph_mutex);
1062 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1063 	    "usba_pipe_sync_close: dip=0x%p ph_data=0x%p state=%d ref=%d",
1064 	    (void *)dip, (void *)ph_data, ph_impl->usba_ph_state,
1065 	    ph_impl->usba_ph_ref_count);
1066 
1067 	/*
1068 	 * if another thread opens the pipe again, this loop could
1069 	 * be truly forever
1070 	 */
1071 	if ((ph_data == NULL) ||
1072 	    (ph_impl->usba_ph_state == USB_PIPE_STATE_CLOSING) ||
1073 	    (ph_impl->usba_ph_state == USB_PIPE_STATE_CLOSED)) {
1074 		/* wait forever till really closed */
1075 		mutex_exit(&ph_impl->usba_ph_mutex);
1076 		usba_release_ph_data(ph_impl);
1077 
1078 		while (usba_get_ph_data((usb_pipe_handle_t)ph_impl)) {
1079 			delay(1);
1080 		}
1081 
1082 		return (USB_SUCCESS);
1083 	}
1084 	ph_impl->usba_ph_state = USB_PIPE_STATE_CLOSING;
1085 	mutex_exit(&ph_impl->usba_ph_mutex);
1086 
1087 	mutex_enter(&ph_data->p_mutex);
1088 	mutex_enter(&ph_impl->usba_ph_mutex);
1089 
1090 	attribute = ph_data->p_ep.bmAttributes & USB_EP_ATTR_MASK;
1091 	dir = ph_data->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
1092 
1093 	usba_device = ph_data->p_usba_device;
1094 
1095 	/*
1096 	 * For control and bulk, we will drain till ref_count <= 1 and
1097 	 * req_count == 0 but for isoc and intr IN, we can only wait
1098 	 * till the ref_count === 1 as the req_count will never go to 0
1099 	 */
1100 	for (timeout = 0; timeout < usba_drain_timeout; timeout++) {
1101 		switch (attribute) {
1102 		case USB_EP_ATTR_CONTROL:
1103 		case USB_EP_ATTR_BULK:
1104 			if ((ph_data->p_req_count == 0) &&
1105 			    (ph_impl->usba_ph_ref_count <= 1)) {
1106 				goto done;
1107 			}
1108 			break;
1109 		case USB_EP_ATTR_INTR:
1110 		case USB_EP_ATTR_ISOCH:
1111 			if (dir == USB_EP_DIR_IN) {
1112 				if (ph_impl->usba_ph_ref_count <= 1) {
1113 					goto done;
1114 				}
1115 			} else if ((ph_data->p_req_count == 0) &&
1116 			    (ph_impl->usba_ph_ref_count <= 1)) {
1117 				goto done;
1118 			}
1119 			break;
1120 		}
1121 		mutex_exit(&ph_impl->usba_ph_mutex);
1122 		mutex_exit(&ph_data->p_mutex);
1123 		delay(drv_usectohz(1000));
1124 		mutex_enter(&ph_data->p_mutex);
1125 		mutex_enter(&ph_impl->usba_ph_mutex);
1126 	}
1127 done:
1128 
1129 	mutex_exit(&ph_impl->usba_ph_mutex);
1130 	mutex_exit(&ph_data->p_mutex);
1131 
1132 	if (timeout >= usba_drain_timeout) {
1133 		int draining_succeeded;
1134 
1135 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1136 		    "timeout on draining requests, resetting pipe 0x%p",
1137 		    (void *)ph_impl);
1138 
1139 		(void) usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data,
1140 		    USB_FLAGS_SLEEP);
1141 
1142 		mutex_enter(&ph_data->p_mutex);
1143 		draining_succeeded = usba_drain_cbs(ph_data, USB_CB_RESET_PIPE,
1144 		    USB_CR_PIPE_RESET);
1145 		/* this MUST have succeeded */
1146 		ASSERT(draining_succeeded == USB_SUCCESS);
1147 		mutex_exit(&ph_data->p_mutex);
1148 
1149 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1150 		    "draining requests done");
1151 	}
1152 
1153 	if (usba_device->usb_hcdi_ops->usba_hcdi_pipe_close(ph_data,
1154 	    usb_flags) != USB_SUCCESS) {
1155 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1156 		    "usba_pipe_sync_close: hcd close failed");
1157 		/* carry on regardless! */
1158 	}
1159 
1160 	usba_destroy_pipe_handle(ph_data);
1161 
1162 	return (USB_SUCCESS);
1163 }
1164 
1165 
1166 /*
1167  * usb_pipe_set_private:
1168  *	set private client date in the pipe handle
1169  */
1170 int
1171 usb_pipe_set_private(usb_pipe_handle_t	pipe_handle, usb_opaque_t data)
1172 {
1173 	usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1174 
1175 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1176 	    "usb_pipe_set_private: ");
1177 
1178 	if (ph_data == NULL) {
1179 
1180 		return (USB_INVALID_PIPE);
1181 	}
1182 	if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1183 		usba_release_ph_data(ph_data->p_ph_impl);
1184 
1185 		return (USB_INVALID_PERM);
1186 	}
1187 
1188 	mutex_enter(&ph_data->p_mutex);
1189 	ph_data->p_client_private = data;
1190 	mutex_exit(&ph_data->p_mutex);
1191 
1192 	usba_release_ph_data(ph_data->p_ph_impl);
1193 
1194 	return (USB_SUCCESS);
1195 }
1196 
1197 
1198 /*
1199  * usb_pipe_get_private:
1200  *	get private client date from the pipe handle
1201  */
1202 usb_opaque_t
1203 usb_pipe_get_private(usb_pipe_handle_t	pipe_handle)
1204 {
1205 	usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1206 	usb_opaque_t		data;
1207 
1208 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1209 	    "usb_pipe_get_private:");
1210 
1211 	if (ph_data == NULL) {
1212 
1213 		return (NULL);
1214 	}
1215 
1216 	mutex_enter(&ph_data->p_mutex);
1217 	data = ph_data->p_client_private;
1218 	mutex_exit(&ph_data->p_mutex);
1219 
1220 	usba_release_ph_data(ph_data->p_ph_impl);
1221 
1222 	return (data);
1223 }
1224 
1225 
1226 /*
1227  * usb_pipe_reset
1228  * Arguments:
1229  *	dip		- devinfo pointer
1230  *	pipe_handle	- opaque pipe handle
1231  * Returns:
1232  *	USB_SUCCESS	- pipe successfully reset or request queued
1233  *	USB_FAILURE	- undetermined failure
1234  *	USB_INVALID_PIPE - pipe is invalid or already closed
1235  */
1236 void
1237 usb_pipe_reset(dev_info_t		*dip,
1238 		usb_pipe_handle_t	pipe_handle,
1239 		usb_flags_t		usb_flags,
1240 		void			(*callback)(
1241 					    usb_pipe_handle_t	ph,
1242 					    usb_opaque_t	arg,
1243 					    int			rval,
1244 					    usb_cb_flags_t	flags),
1245 		usb_opaque_t		callback_arg)
1246 {
1247 	usba_ph_impl_t		*ph_impl = (usba_ph_impl_t *)pipe_handle;
1248 	usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1249 	usb_cb_flags_t		callback_flags;
1250 
1251 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1252 	    "usb_pipe_reset: dip=0x%p ph=0x%p uf=0x%x",
1253 	    (void *)dip, (void *)pipe_handle, usb_flags);
1254 
1255 	callback_flags = usba_check_intr_context(USB_CB_NO_INFO);
1256 
1257 	if ((dip == NULL) || (ph_data == NULL)) {
1258 		if (callback) {
1259 			callback(pipe_handle, callback_arg,
1260 			    USB_INVALID_ARGS, callback_flags);
1261 		} else {
1262 			USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1263 			    usbai_log_handle,
1264 			    "usb_pipe_reset: invalid arguments");
1265 		}
1266 
1267 		usba_release_ph_data(ph_impl);
1268 
1269 		return;
1270 	}
1271 	if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) {
1272 		if (callback) {
1273 			callback(pipe_handle, callback_arg,
1274 			    USB_INVALID_CONTEXT, callback_flags);
1275 		} else {
1276 			USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1277 			    usbai_log_handle,
1278 			    "usb_pipe_reset: invalid context");
1279 		}
1280 
1281 		usba_release_ph_data(ph_impl);
1282 
1283 		return;
1284 	}
1285 
1286 	mutex_enter(&ph_data->p_mutex);
1287 
1288 	/* is this the default pipe? */
1289 	if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1290 		if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) {
1291 			USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1292 			    "usb_pipe_reset: not allowed to reset def pipe");
1293 			mutex_exit(&ph_data->p_mutex);
1294 
1295 			if (callback) {
1296 				callback(pipe_handle, callback_arg,
1297 				    USB_INVALID_PIPE, callback_flags);
1298 			} else {
1299 				USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1300 				    usbai_log_handle,
1301 				    "usb_pipe_reset: invalid pipe");
1302 			}
1303 			usba_release_ph_data(ph_impl);
1304 
1305 			return;
1306 		}
1307 	}
1308 	mutex_exit(&ph_data->p_mutex);
1309 
1310 	(void) usba_pipe_setup_func_call(dip,
1311 	    usba_pipe_sync_reset, ph_impl, NULL, usb_flags, callback,
1312 	    callback_arg);
1313 }
1314 
1315 
1316 /*ARGSUSED*/
1317 int
1318 usba_pipe_sync_reset(dev_info_t	*dip,
1319 	usba_ph_impl_t		*ph_impl,
1320 	usba_pipe_async_req_t	*request,
1321 	usb_flags_t		usb_flags)
1322 {
1323 	int rval, draining_succeeded;
1324 	usba_pipe_handle_data_t *ph_data = usba_get_ph_data((usb_pipe_handle_t)
1325 	    ph_impl);
1326 	usba_device_t		*usba_device;
1327 
1328 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1329 	    "usba_pipe_sync_reset: dip=0x%p ph_data=0x%p uf=0x%x",
1330 	    (void *)dip, (void *)ph_data, usb_flags);
1331 
1332 	mutex_enter(&ph_data->p_mutex);
1333 	usba_device = ph_data->p_usba_device;
1334 	mutex_exit(&ph_data->p_mutex);
1335 
1336 	rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data,
1337 	    usb_flags);
1338 	mutex_enter(&ph_data->p_mutex);
1339 
1340 	/*
1341 	 * The host controller has stopped polling of the endpoint.
1342 	 */
1343 	draining_succeeded = usba_drain_cbs(ph_data, USB_CB_RESET_PIPE,
1344 	    USB_CR_PIPE_RESET);
1345 
1346 	/* this MUST have succeeded */
1347 	ASSERT(draining_succeeded == USB_SUCCESS);
1348 
1349 	usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE);
1350 	mutex_exit(&ph_data->p_mutex);
1351 
1352 	/*
1353 	 * if there are requests still queued on the default pipe,
1354 	 * start them now
1355 	 */
1356 	usba_start_next_req(ph_data);
1357 
1358 	usba_release_ph_data(ph_impl);
1359 
1360 	return (rval);
1361 }
1362 
1363 
1364 /*
1365  * usba_pipe_clear:
1366  *	call hcd to clear pipe but don't wait for draining
1367  */
1368 void
1369 usba_pipe_clear(usb_pipe_handle_t pipe_handle)
1370 {
1371 	usba_pipe_handle_data_t *ph_data = usba_get_ph_data(pipe_handle);
1372 	usba_device_t		*usba_device;
1373 	usba_req_wrapper_t	*req_wrp;
1374 	int			flush_requests = 1;
1375 
1376 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1377 	    "usba_pipe_clear: ph_data=0x%p", (void *)ph_data);
1378 
1379 	if (ph_data == NULL) {
1380 
1381 		return;
1382 	}
1383 
1384 	mutex_enter(&ph_data->p_mutex);
1385 	if (USBA_PIPE_CLOSING(usba_get_ph_state(ph_data))) {
1386 		mutex_exit(&ph_data->p_mutex);
1387 
1388 		return;
1389 	}
1390 	usba_device = ph_data->p_usba_device;
1391 	mutex_exit(&ph_data->p_mutex);
1392 
1393 	(void) usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data,
1394 	    USB_FLAGS_SLEEP);
1395 
1396 	mutex_enter(&ph_data->p_mutex);
1397 	if (ph_data->p_dip) {
1398 		if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1399 			USB_DPRINTF_L4(DPRINT_MASK_USBAI,
1400 			    usbai_log_handle,
1401 			    "no flushing on default pipe!");
1402 
1403 			flush_requests = 0;
1404 		}
1405 	}
1406 
1407 	if (flush_requests) {
1408 		/* flush all requests in the pipehandle queue */
1409 		while ((req_wrp = (usba_req_wrapper_t *)
1410 		    usba_rm_first_pvt_from_list(&ph_data->p_queue)) != NULL) {
1411 			mutex_exit(&ph_data->p_mutex);
1412 			usba_do_req_exc_cb(req_wrp, USB_CR_FLUSHED,
1413 			    USB_CB_RESET_PIPE);
1414 			mutex_enter(&ph_data->p_mutex);
1415 		}
1416 	}
1417 
1418 	usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE);
1419 	mutex_exit(&ph_data->p_mutex);
1420 }
1421 
1422 
1423 /*
1424  *
1425  * usb_pipe_drain_reqs
1426  *	this function blocks until there are no more requests
1427  *	owned by this dip on the pipe
1428  *
1429  * Arguments:
1430  *	dip		- devinfo pointer
1431  *	pipe_handle	- opaque pipe handle
1432  *	timeout 	- timeout in seconds
1433  *	flags		- USB_FLAGS_SLEEP:
1434  *				wait for completion.
1435  *	cb		- if USB_FLAGS_SLEEP has not been specified
1436  *			  this callback function will be called on
1437  *			  completion. This callback may be NULL
1438  *			  and no notification of completion will then
1439  *			  be provided.
1440  *	cb_arg		- 2nd argument to callback function.
1441  *
1442  * callback and callback_arg should be NULL if USB_FLAGS_SLEEP has
1443  * been specified
1444  *
1445  * Returns:
1446  *	USB_SUCCESS	- pipe successfully reset or request queued
1447  *	USB_FAILURE	- timeout
1448  *	USB_*		- refer to usbai.h
1449  */
1450 int
1451 usb_pipe_drain_reqs(dev_info_t	*dip,
1452 	usb_pipe_handle_t	pipe_handle,
1453 	uint_t			time,
1454 	usb_flags_t		usb_flags,
1455 	void			(*cb)(
1456 				    usb_pipe_handle_t	ph,
1457 				    usb_opaque_t	arg,   /* cb arg */
1458 				    int			rval,
1459 				    usb_cb_flags_t	flags),
1460 	usb_opaque_t		cb_arg)
1461 {
1462 	usba_ph_impl_t		*ph_impl = (usba_ph_impl_t *)pipe_handle;
1463 	usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1464 
1465 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1466 	    "usb_pipe_drain_reqs: dip=0x%p ph_data=0x%p tm=%d uf=0x%x",
1467 	    (void *)dip, (void *)ph_data, time, usb_flags);
1468 
1469 	if (ph_data == NULL) {
1470 
1471 		return (USB_INVALID_PIPE);
1472 	}
1473 	if (dip == NULL) {
1474 		usba_release_ph_data(ph_impl);
1475 
1476 		return (USB_INVALID_ARGS);
1477 	}
1478 
1479 	if ((usb_flags & USB_FLAGS_SLEEP) && servicing_interrupt()) {
1480 		usba_release_ph_data(ph_impl);
1481 
1482 		return (USB_INVALID_CONTEXT);
1483 	}
1484 
1485 	(void) usba_pipe_setup_func_call(dip, usba_pipe_sync_drain_reqs,
1486 	    ph_impl, (usb_opaque_t)((uintptr_t)time), usb_flags, cb, cb_arg);
1487 
1488 	return (USB_SUCCESS);
1489 }
1490 
1491 
1492 /*
1493  * usba_pipe_sync_drain_reqs
1494  *	this function blocks until there are no more requests
1495  *	owned by this dip on the pipe
1496  *
1497  * Arguments:
1498  *	dip		- devinfo pointer
1499  *	ph_impl		- pipe impl handle
1500  *	timeout		- timeout in seconds
1501  * Returns:
1502  *	USB_SUCCESS	- pipe successfully reset or request queued
1503  *	USB_FAILURE	- timeout
1504  *	USB_*		- see usbai.h
1505  */
1506 /*ARGSUSED*/
1507 int
1508 usba_pipe_sync_drain_reqs(dev_info_t	*dip,
1509 		usba_ph_impl_t		*ph_impl,
1510 		usba_pipe_async_req_t	*request,
1511 		usb_flags_t		usb_flags)
1512 {
1513 	usba_pipe_handle_data_t *ph_data = usba_get_ph_data((usb_pipe_handle_t)
1514 	    ph_impl);
1515 	int		i;
1516 	int		timeout = 100 * (int)((uintptr_t)(request->arg));
1517 						/* delay will be 10 ms */
1518 
1519 	mutex_enter(&ph_data->p_mutex);
1520 
1521 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1522 	    "usba_pipe_sync_drain_reqs: "
1523 	    "dip=0x%p ph_data=0x%p timeout=%d ref=%d req=%d",
1524 	    (void *)dip, (void *)ph_data, timeout,
1525 	    usba_get_ph_ref_count(ph_data),
1526 	    ph_data->p_req_count);
1527 
1528 	ASSERT(ph_data->p_req_count >= 0);
1529 
1530 	/*
1531 	 * for default pipe, we need to check the active request
1532 	 * and the queue
1533 	 * Note that a pipe reset on the default pipe doesn't flush
1534 	 * the queue
1535 	 * for all other pipes we just check ref and req count since
1536 	 * these pipes are unshared
1537 	 */
1538 	if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1539 		for (i = 0; (i < timeout) || (request->arg == 0); i++) {
1540 			usba_list_entry_t *next, *tmpnext;
1541 			usba_req_wrapper_t *req_wrp = (usba_req_wrapper_t *)
1542 			    ph_data->p_active_cntrl_req_wrp;
1543 			int found = 0;
1544 			int count = 0;
1545 
1546 			/* active_req_wrp is only for control pipes */
1547 			if ((req_wrp == NULL) || (req_wrp->wr_dip != dip)) {
1548 				/* walk the queue */
1549 				mutex_enter(&ph_data->p_queue.list_mutex);
1550 				next = ph_data->p_queue.next;
1551 				while (next != NULL) {
1552 					mutex_enter(&next->list_mutex);
1553 					req_wrp = (usba_req_wrapper_t *)
1554 					    next->private;
1555 					found = (req_wrp->wr_dip == dip);
1556 					if (found) {
1557 						mutex_exit(&next->list_mutex);
1558 
1559 						break;
1560 					}
1561 					tmpnext = next->next;
1562 					mutex_exit(&next->list_mutex);
1563 					next = tmpnext;
1564 					count++;
1565 				}
1566 				mutex_exit(&ph_data->p_queue.list_mutex);
1567 				if (found == 0) {
1568 					break;
1569 				}
1570 			}
1571 
1572 			USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1573 			    "usb_pipe_sync_drain_reqs: "
1574 			    "cnt=%d active_req_wrp=0x%p",
1575 			    count, (void *)ph_data->p_active_cntrl_req_wrp);
1576 
1577 			mutex_exit(&ph_data->p_mutex);
1578 			delay(drv_usectohz(10000));
1579 			mutex_enter(&ph_data->p_mutex);
1580 		}
1581 	} else {
1582 		mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex);
1583 		for (i = 0; (i < timeout) || (request->arg == 0); i++) {
1584 			ASSERT(ph_data->p_req_count >= 0);
1585 			if (ph_data->p_req_count ||
1586 			    (ph_data->p_ph_impl->usba_ph_ref_count > 1)) {
1587 				mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex);
1588 				mutex_exit(&ph_data->p_mutex);
1589 				delay(drv_usectohz(10000));
1590 				mutex_enter(&ph_data->p_mutex);
1591 				mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex);
1592 			} else {
1593 				break;
1594 			}
1595 		}
1596 		mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex);
1597 	}
1598 
1599 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1600 	    "usb_pipe_sync_drain_reqs: timeout=%d active_req_wrp=0x%p req=%d",
1601 	    i, (void *)ph_data->p_active_cntrl_req_wrp, ph_data->p_req_count);
1602 
1603 	mutex_exit(&ph_data->p_mutex);
1604 
1605 	usba_release_ph_data(ph_impl);
1606 
1607 	return (i >= timeout ? USB_FAILURE : USB_SUCCESS);
1608 }
1609 
1610 
1611 /*
1612  * usba_persistent_pipe_open
1613  *	Open all the pipes marked persistent for this device
1614  */
1615 int
1616 usba_persistent_pipe_open(usba_device_t *usba_device)
1617 {
1618 	usba_ph_impl_t		*ph_impl;
1619 	usb_pipe_handle_t	pipe_handle;
1620 	int			i;
1621 	int			rval = USB_SUCCESS;
1622 
1623 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1624 	    "usba_persistent_pipe_open: usba_device=0x%p", (void *)usba_device);
1625 
1626 	if (usba_device != NULL) {
1627 		/* default pipe is the first one to be opened */
1628 		mutex_enter(&usba_device->usb_mutex);
1629 		for (i = 0; (rval == USB_SUCCESS) &&
1630 		    (i < USBA_N_ENDPOINTS); i++) {
1631 
1632 			ph_impl = &usba_device->usb_ph_list[i];
1633 			mutex_enter(&ph_impl->usba_ph_mutex);
1634 			if (ph_impl->usba_ph_flags & USBA_PH_DATA_PERSISTENT) {
1635 				ph_impl->usba_ph_flags &=
1636 				    ~USBA_PH_DATA_PERSISTENT;
1637 				mutex_exit(&ph_impl->usba_ph_mutex);
1638 				mutex_exit(&usba_device->usb_mutex);
1639 
1640 				rval = usb_pipe_open(ph_impl->usba_ph_dip,
1641 				    &ph_impl->usba_ph_ep,
1642 				    &ph_impl->usba_ph_policy,
1643 				    USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED,
1644 				    &pipe_handle);
1645 
1646 				USB_DPRINTF_L3(DPRINT_MASK_USBAI,
1647 				    usbai_log_handle,
1648 				    "usba_persistent_pipe_open: "
1649 				    "ep_index=%d, rval=%d", i, rval);
1650 				mutex_enter(&usba_device->usb_mutex);
1651 				mutex_enter(&ph_impl->usba_ph_mutex);
1652 			}
1653 			mutex_exit(&ph_impl->usba_ph_mutex);
1654 		}
1655 		mutex_exit(&usba_device->usb_mutex);
1656 	}
1657 
1658 	return (rval);
1659 }
1660 
1661 
1662 /*
1663  * usba_persistent_pipe_close
1664  *	Close all pipes of this device and mark them persistent
1665  */
1666 void
1667 usba_persistent_pipe_close(usba_device_t *usba_device)
1668 {
1669 	usba_ph_impl_t		*ph_impl;
1670 	usb_pipe_handle_t	pipe_handle;
1671 	int			i;
1672 
1673 	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1674 	    "usba_persistent_pipe_close: usba_device=0x%p",
1675 	    (void *)usba_device);
1676 
1677 	if (usba_device != NULL) {
1678 		/* default pipe is the last one to be closed */
1679 		mutex_enter(&usba_device->usb_mutex);
1680 
1681 		for (i = (USBA_N_ENDPOINTS - 1); i >= 0; i--) {
1682 			ph_impl = &usba_device->usb_ph_list[i];
1683 			if (ph_impl->usba_ph_data != NULL) {
1684 				mutex_enter(&ph_impl->usba_ph_mutex);
1685 				ph_impl->usba_ph_flags |=
1686 				    USBA_PH_DATA_PERSISTENT;
1687 				mutex_exit(&ph_impl->usba_ph_mutex);
1688 				mutex_exit(&usba_device->usb_mutex);
1689 
1690 				pipe_handle = (usb_pipe_handle_t)ph_impl;
1691 
1692 				usb_pipe_close(ph_impl->usba_ph_dip,
1693 				    pipe_handle,
1694 				    USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED,
1695 				    NULL, NULL);
1696 				mutex_enter(&usba_device->usb_mutex);
1697 				ASSERT(ph_impl->usba_ph_data == NULL);
1698 			}
1699 		}
1700 		mutex_exit(&usba_device->usb_mutex);
1701 	}
1702 }
1703