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