usbai_pipe_mgmt.c revision 7492:2387323b838f
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
48extern	pri_t	maxclsyspri;
49extern	pri_t	minclsyspri;
50
51/* function prototypes */
52static	void	usba_pipe_do_async_func_thread(void *arg);
53static	int	usba_pipe_sync_close(dev_info_t *, usba_ph_impl_t *,
54			usba_pipe_async_req_t *, usb_flags_t);
55static	int	usba_pipe_sync_reset(dev_info_t *, usba_ph_impl_t *,
56			usba_pipe_async_req_t *, usb_flags_t);
57static	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 */
61int	usba_drain_timeout = 1000;	/* in ms */
62
63/* return the default pipe for this device */
64usb_pipe_handle_t
65usba_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 */
83dev_info_t *
84usba_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
99usb_pipe_handle_t
100usba_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
113usba_pipe_handle_data_t *
114usba_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
130usb_pipe_handle_t
131usba_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 */
151usba_pipe_handle_data_t *
152usba_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
185void
186usba_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 */
216usb_pipe_state_t
217usba_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 */
234int
235usba_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 */
252void
253usba_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 */
300int
301usba_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 */
376static void
377usba_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 */
404usb_ep_descr_t	usba_default_ep_descr =
405	{7, 5, 0, USB_EP_ATTR_CONTROL, 8, 0};
406
407/* set some meaningful defaults */
408static 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 */
415uchar_t
416usb_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 */
427static int
428usba_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
549static void
550usba_taskq_destroy(void *arg)
551{
552	taskq_destroy((taskq_t *)arg);
553}
554
555
556static void
557usba_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 */
656int
657usba_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 */
760int
761usb_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 */
945void
946usb_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*/
1043static int
1044usba_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	}
1125done:
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 */
1168int
1169usb_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 */
1200usb_opaque_t
1201usb_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 */
1234void
1235usb_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*/
1315int
1316usba_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 */
1366void
1367usba_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 */
1448int
1449usb_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*/
1505int
1506usba_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 */
1613int
1614usba_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 */
1664void
1665usba_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