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