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