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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * USBA: Solaris USB Architecture support
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
34 * this file contains all USBAI pipe management
37 * usb_pipe_set_private()
38 * usb_pipe_get_private()
41 * usb_pipe_drain_reqs()
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>
48 extern pri_t maxclsyspri
;
49 extern pri_t minclsyspri
;
51 /* function prototypes */
52 static void usba_pipe_do_async_func_thread(void *arg
);
53 static int usba_pipe_sync_close(dev_info_t
*, usba_ph_impl_t
*,
54 usba_pipe_async_req_t
*, usb_flags_t
);
55 static int usba_pipe_sync_reset(dev_info_t
*, usba_ph_impl_t
*,
56 usba_pipe_async_req_t
*, usb_flags_t
);
57 static int usba_pipe_sync_drain_reqs(dev_info_t
*, usba_ph_impl_t
*,
58 usba_pipe_async_req_t
*, usb_flags_t
);
61 int usba_drain_timeout
= 1000; /* in ms */
63 /* return the default pipe for this device */
65 usba_get_dflt_pipe_handle(dev_info_t
*dip
)
67 usba_device_t
*usba_device
;
68 usb_pipe_handle_t pipe_handle
= NULL
;
71 usba_device
= usba_get_usba_device(dip
);
74 (usb_pipe_handle_t
)&usba_device
->usb_ph_list
[0];
82 /* return dip owner of pipe_handle */
84 usba_get_dip(usb_pipe_handle_t pipe_handle
)
86 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
87 dev_info_t
*dip
= NULL
;
90 mutex_enter(&ph_impl
->usba_ph_mutex
);
91 dip
= ph_impl
->usba_ph_dip
;
92 mutex_exit(&ph_impl
->usba_ph_mutex
);
100 usba_usbdev_to_dflt_pipe_handle(usba_device_t
*usba_device
)
102 usb_pipe_handle_t pipe_handle
= NULL
;
105 (usba_device
->usb_ph_list
[0].usba_ph_data
!= NULL
)) {
106 pipe_handle
= (usb_pipe_handle_t
)&usba_device
->usb_ph_list
[0];
109 return (pipe_handle
);
113 usba_pipe_handle_data_t
*
114 usba_get_ph_data(usb_pipe_handle_t pipe_handle
)
116 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
117 usba_pipe_handle_data_t
*ph_data
= NULL
;
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
);
131 usba_get_pipe_handle(usba_pipe_handle_data_t
*ph_data
)
133 usb_pipe_handle_t ph
= NULL
;
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
);
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.
151 usba_pipe_handle_data_t
*
152 usba_hold_ph_data(usb_pipe_handle_t pipe_handle
)
154 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
155 usba_pipe_handle_data_t
*ph_data
= NULL
;
158 mutex_enter(&ph_impl
->usba_ph_mutex
);
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
++;
167 case USB_PIPE_STATE_CLOSED
:
168 case USB_PIPE_STATE_CLOSING
:
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
);
178 mutex_exit(&ph_impl
->usba_ph_mutex
);
186 usba_release_ph_data(usba_ph_impl_t
*ph_impl
)
189 mutex_enter(&ph_impl
->usba_ph_mutex
);
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
);
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);
205 ph_impl
->usba_ph_ref_count
--;
206 ASSERT(ph_impl
->usba_ph_ref_count
>= 0);
208 mutex_exit(&ph_impl
->usba_ph_mutex
);
214 * get pipe state from ph_data
217 usba_get_ph_state(usba_pipe_handle_data_t
*ph_data
)
219 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
220 usb_pipe_state_t pipe_state
;
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
);
232 * get ref_count from ph_data
235 usba_get_ph_ref_count(usba_pipe_handle_data_t
*ph_data
)
237 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
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
);
250 * We need to hold both pipe mutex and ph_impl mutex
253 usba_pipe_new_state(usba_pipe_handle_data_t
*ph_data
, usb_pipe_state_t state
)
255 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
257 ASSERT(mutex_owned(&ph_data
->p_mutex
));
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);
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
);
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
;
277 case USB_PIPE_STATE_CLOSING
:
281 mutex_exit(&ph_impl
->usba_ph_mutex
);
286 * async function execution support
288 * dip - devinfo pointer
289 * sync_func - function to be executed
290 * ph_impl - impl pipehandle
293 * callback - function to be called on completion, may be NULL
294 * callback_arg - argument for callback function
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
301 usba_pipe_setup_func_call(
303 int (*sync_func
)(dev_info_t
*,
304 usba_ph_impl_t
*, usba_pipe_async_req_t
*,
306 usba_ph_impl_t
*ph_impl
,
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
)
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
;
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
);
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 "
329 return (USB_INVALID_ARGS
);
332 request
= kmem_zalloc(sizeof (usba_pipe_async_req_t
), KM_SLEEP
);
334 request
->ph_impl
= ph_impl
;
338 * OR in sleep flag. regardless of calling sync_func directly
339 * or in a new thread, we will always wait for completion
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
;
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
));
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
);
359 usba_check_intr_context(USB_CB_ASYNC_REQ_FAILED
);
360 callback(pipe_handle
, callback_arg
, USB_FAILURE
,
364 kmem_free(request
, sizeof (usba_pipe_async_req_t
));
365 usba_release_ph_data(ph_impl
);
373 * taskq thread function to execute function synchronously
374 * Note: caller must have done a hold on ph_data
377 usba_pipe_do_async_func_thread(void *arg
)
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
;
383 usb_cb_flags_t cb_flags
= USB_CB_NO_INFO
;
385 if ((rval
= request
->sync_func(request
->dip
, ph_impl
,
386 request
, request
->usb_flags
| USB_FLAGS_SLEEP
)) !=
388 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
389 "sync func failed (%d)", rval
);
392 if (request
->callback
) {
393 request
->callback(pipe_handle
, request
->callback_arg
, rval
,
397 kmem_free(request
, sizeof (usba_pipe_async_req_t
));
402 * default endpoint descriptor and pipe policy
404 usb_ep_descr_t usba_default_ep_descr
=
405 {7, 5, 0, USB_EP_ATTR_CONTROL
, 8, 0};
407 /* set some meaningful defaults */
408 static usb_pipe_policy_t usba_default_ep_pipe_policy
= {3};
412 * usb_get_ep_index: create an index from endpoint address that can
413 * be used to index into endpoint pipe lists
416 usb_get_ep_index(uint8_t ep_addr
)
418 return ((ep_addr
& USB_EP_NUM_MASK
) +
419 ((ep_addr
& USB_EP_DIR_MASK
) ? 16 : 0));
425 * utility functions to init and destroy a pipehandle
428 usba_init_pipe_handle(dev_info_t
*dip
,
429 usba_device_t
*usba_device
,
431 usb_pipe_policy_t
*pipe_policy
,
432 usba_ph_impl_t
*ph_impl
)
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
];
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
)->
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
);
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
);
454 ASSERT(pipe_policy
->pp_max_async_reqs
);
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
);
461 def_instance
= atomic_inc_32_nv(&anon_instance
);
463 (void) snprintf(tq_name
, sizeof (tq_name
),
464 "USB_%s_%x_pipehndl_tq_%d_",
465 ddi_driver_name(dip
), ep
->bEndpointAddress
, def_instance
);
468 ph_data
->p_taskq
= taskq_create(tq_name
,
469 pipe_policy
->pp_max_async_reqs
+ 1,
470 ((ep
->bmAttributes
& USB_EP_ATTR_MASK
) ==
472 (maxclsyspri
- 5) : minclsyspri
,
473 2 * (pipe_policy
->pp_max_async_reqs
+ 1),
474 8 * (pipe_policy
->pp_max_async_reqs
+ 1),
478 * Create a shared taskq.
480 if (ph_data
->p_spec_flag
& USBA_PH_FLAG_TQ_SHARE
) {
481 int iface
= usb_get_if_number(dip
);
483 /* we own the device, use first entry */
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
,
493 (void) snprintf(tq_name
, sizeof (tq_name
),
494 "USB_%s_%x_shared_tq_%d_",
495 ddi_driver_name(dip
), ep
->bEndpointAddress
,
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 */
505 USBA_N_ENDPOINTS
+ 4, /* maxalloc */
507 ASSERT(usba_device
->usb_shared_taskq
[iface
] != NULL
);
509 usba_device
->usb_shared_taskq_ref_count
[iface
]++;
512 ph_data
->p_dip
= dip
;
513 ph_data
->p_usba_device
= usba_device
;
515 ph_data
->p_ph_impl
= ph_impl
;
516 if ((ep
->bmAttributes
& USB_EP_ATTR_MASK
) ==
518 ph_data
->p_spec_flag
|= USBA_PH_FLAG_USE_SOFT_INTR
;
521 /* fix up the MaxPacketSize if it is the default endpoint descr */
522 if ((ep
== &usba_default_ep_descr
) && usba_device
) {
525 maxpktsize
= usba_device
->usb_dev_descr
->bMaxPacketSize0
;
526 if (usba_device
->usb_is_wireless
) {
528 * according to wusb 1.0 spec 4.8.1, the host must
529 * assume a wMaxPacketSize of 512 for the default
530 * control pipe of a wusb device
534 USB_DPRINTF_L3(DPRINT_MASK_USBAI
, usbai_log_handle
,
535 "adjusting max packet size from %d to %d",
536 ph_data
->p_ep
.wMaxPacketSize
, maxpktsize
);
538 ph_data
->p_ep
.wMaxPacketSize
= maxpktsize
;
541 /* now update usba_ph_impl structure */
542 mutex_enter(&ph_impl
->usba_ph_mutex
);
543 ph_impl
->usba_ph_dip
= dip
;
544 ph_impl
->usba_ph_ep
= ph_data
->p_ep
;
545 ph_impl
->usba_ph_policy
= ph_data
->p_policy
= *pipe_policy
;
546 mutex_exit(&ph_impl
->usba_ph_mutex
);
548 usba_init_list(&ph_data
->p_queue
, (usb_opaque_t
)ph_data
, iblock_cookie
);
549 usba_init_list(&ph_data
->p_cb_queue
, (usb_opaque_t
)ph_data
,
551 mutex_exit(&usba_device
->usb_mutex
);
552 mutex_exit(&ph_data
->p_mutex
);
554 return (USB_SUCCESS
);
559 usba_taskq_destroy(void *arg
)
561 taskq_destroy((taskq_t
*)arg
);
566 usba_destroy_pipe_handle(usba_pipe_handle_data_t
*ph_data
)
568 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
570 usba_device_t
*usba_device
;
572 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
573 "usba_destroy_pipe_handle: ph_data=0x%p", (void *)ph_data
);
575 mutex_enter(&ph_data
->p_mutex
);
576 mutex_enter(&ph_impl
->usba_ph_mutex
);
578 /* check for all activity to drain */
579 for (timeout
= 0; timeout
< usba_drain_timeout
; timeout
++) {
580 if ((ph_impl
->usba_ph_ref_count
<= 1) &&
581 (ph_data
->p_req_count
== 0)) {
585 mutex_exit(&ph_data
->p_mutex
);
586 mutex_exit(&ph_impl
->usba_ph_mutex
);
587 delay(drv_usectohz(1000));
588 mutex_enter(&ph_data
->p_mutex
);
589 mutex_enter(&ph_impl
->usba_ph_mutex
);
593 * set state to closed here so any other thread
594 * that is waiting for the CLOSED state will
595 * continue. Otherwise, taskq_destroy might deadlock
597 ph_impl
->usba_ph_data
= NULL
;
598 ph_impl
->usba_ph_ref_count
= 0;
599 ph_impl
->usba_ph_state
= USB_PIPE_STATE_CLOSED
;
601 if (ph_data
->p_taskq
) {
602 mutex_exit(&ph_data
->p_mutex
);
603 mutex_exit(&ph_impl
->usba_ph_mutex
);
604 if (taskq_member(ph_data
->p_taskq
, curthread
)) {
606 * use system taskq to destroy ph's taskq to avoid
609 (void) taskq_dispatch(system_taskq
,
610 usba_taskq_destroy
, ph_data
->p_taskq
, TQ_SLEEP
);
612 taskq_destroy(ph_data
->p_taskq
);
615 mutex_exit(&ph_data
->p_mutex
);
616 mutex_exit(&ph_impl
->usba_ph_mutex
);
619 usba_device
= ph_data
->p_usba_device
;
620 mutex_enter(&ph_data
->p_mutex
);
621 if (ph_data
->p_spec_flag
& USBA_PH_FLAG_TQ_SHARE
) {
622 int iface
= usb_get_if_number(ph_data
->p_dip
);
624 /* we own the device, use the first entry */
627 mutex_enter(&usba_device
->usb_mutex
);
628 if (--usba_device
->usb_shared_taskq_ref_count
[iface
] == 0) {
629 ph_data
->p_spec_flag
&= ~USBA_PH_FLAG_TQ_SHARE
;
630 if (taskq_member(usba_device
->usb_shared_taskq
[iface
],
632 (void) taskq_dispatch(
635 usba_device
->usb_shared_taskq
[iface
],
639 usba_device
->usb_shared_taskq
[iface
]);
642 mutex_exit(&usba_device
->usb_mutex
);
644 mutex_exit(&ph_data
->p_mutex
);
647 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
648 "usba_destroy_pipe_handle: destroying ph_data=0x%p",
651 usba_destroy_list(&ph_data
->p_queue
);
652 usba_destroy_list(&ph_data
->p_cb_queue
);
654 /* destroy mutexes */
655 mutex_destroy(&ph_data
->p_mutex
);
657 kmem_free(ph_data
, sizeof (usba_pipe_handle_data_t
));
663 * Drain the request callbacks on the pipe handle
666 usba_drain_cbs(usba_pipe_handle_data_t
*ph_data
, usb_cb_flags_t cb_flags
,
669 usba_req_wrapper_t
*req_wrp
;
670 int flush_requests
= 1;
671 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
673 int rval
= USB_SUCCESS
;
675 ASSERT(mutex_owned(&ph_data
->p_mutex
));
677 mutex_enter(&ph_impl
->usba_ph_mutex
);
678 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
679 "usba_drain_cbs: ph_data=0x%p ref=%d req=%d cb=0x%x cr=%d",
680 (void *)ph_data
, ph_impl
->usba_ph_ref_count
, ph_data
->p_req_count
,
682 ASSERT(ph_data
->p_req_count
>= 0);
683 mutex_exit(&ph_impl
->usba_ph_mutex
);
685 if (ph_data
->p_dip
) {
686 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
687 USB_DPRINTF_L4(DPRINT_MASK_USBAI
,
689 "no flushing on default pipe!");
695 if (flush_requests
) {
696 /* flush all requests in the pipehandle queue */
697 while ((req_wrp
= (usba_req_wrapper_t
*)
698 usba_rm_first_pvt_from_list(&ph_data
->p_queue
)) != NULL
) {
699 mutex_exit(&ph_data
->p_mutex
);
700 usba_do_req_exc_cb(req_wrp
, cr
, cb_flags
);
701 mutex_enter(&ph_data
->p_mutex
);
706 * wait for any callbacks in progress but don't wait for
707 * for queued requests on the default pipe
709 for (timeout
= 0; (timeout
< usba_drain_timeout
) &&
710 (ph_data
->p_req_count
>
711 usba_list_entry_count(&ph_data
->p_queue
));
713 mutex_exit(&ph_data
->p_mutex
);
714 delay(drv_usectohz(1000));
715 mutex_enter(&ph_data
->p_mutex
);
718 mutex_enter(&ph_impl
->usba_ph_mutex
);
719 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
720 "usba_drain_cbs done: ph_data=0x%p ref=%d req=%d",
721 (void *)ph_data
, ph_impl
->usba_ph_ref_count
, ph_data
->p_req_count
);
722 mutex_exit(&ph_impl
->usba_ph_mutex
);
724 if (timeout
== usba_drain_timeout
) {
725 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
726 "draining callbacks timed out!");
738 * Before using any pipe including the default pipe, it should be opened
739 * using usb_pipe_open(). On a successful open, a pipe handle is returned
740 * for use in other usb_pipe_*() functions
742 * The default pipe can only be opened by the hub driver
744 * The bandwidth has been allocated and guaranteed on successful
745 * opening of an isoc/intr pipes.
747 * Only the default pipe can be shared. all other control pipes
748 * are excusively opened by default.
749 * A pipe policy and endpoint descriptor must always be provided
750 * except for default pipe
754 * ep - endpoint descriptor pointer
755 * pipe_policy - pointer to pipe policy which provides hints on how
756 * the pipe will be used.
757 * flags - USB_FLAGS_SLEEP wait for resources
758 * to become available
759 * pipe_handle - a pipe handle pointer. On a successful open,
760 * a pipe_handle is returned in this pointer.
763 * USB_SUCCESS - open succeeded
764 * USB_FAILURE - unspecified open failure or pipe is already open
765 * USB_NO_RESOURCES - no resources were available to complete the open
766 * USB_NO_BANDWIDTH - no bandwidth available (isoc/intr pipes)
767 * USB_* - refer to usbai.h
773 usb_pipe_policy_t
*pipe_policy
,
774 usb_flags_t usb_flags
,
775 usb_pipe_handle_t
*pipe_handle
)
777 usba_device_t
*usba_device
;
779 usba_pipe_handle_data_t
*ph_data
;
780 usba_ph_impl_t
*ph_impl
;
785 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
787 "dip=0x%p ep=0x%p pp=0x%p uf=0x%x ph=0x%p",
788 (void *)dip
, (void *)ep
, (void *)pipe_policy
, usb_flags
,
789 (void *)pipe_handle
);
791 if ((dip
== NULL
) || (pipe_handle
== NULL
)) {
793 return (USB_INVALID_ARGS
);
796 if (servicing_interrupt() && (usb_flags
& USB_FLAGS_SLEEP
)) {
798 return (USB_INVALID_CONTEXT
);
800 usba_device
= usba_get_usba_device(dip
);
802 if ((ep
!= NULL
) && (pipe_policy
== NULL
)) {
803 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
804 "usb_pipe_open: null pipe policy");
806 return (USB_INVALID_ARGS
);
809 /* is the device still connected? */
810 if ((ep
!= NULL
) & DEVI_IS_DEVICE_REMOVED(dip
)) {
811 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
812 "usb_pipe_open: device has been removed");
814 return (USB_FAILURE
);
819 * if a null endpoint pointer was passed, use the default
820 * endpoint descriptor
823 if ((usb_flags
& USBA_FLAGS_PRIVILEGED
) == 0) {
824 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
825 "usb_pipe_open: not allowed to open def pipe");
827 return (USB_INVALID_PERM
);
830 ep
= &usba_default_ep_descr
;
831 pipe_policy
= &usba_default_ep_pipe_policy
;
834 if (usb_flags
& USB_FLAGS_SERIALIZED_CB
) {
835 if (((ep
->bmAttributes
& USB_EP_ATTR_MASK
) ==
836 USB_EP_ATTR_CONTROL
) ||
837 ((ep
->bmAttributes
& USB_EP_ATTR_MASK
) ==
838 USB_EP_ATTR_ISOCH
)) {
839 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
840 "usb_pipe_open: shared taskq not allowed with "
841 "ctrl or isoch pipe");
843 return (USB_INVALID_ARGS
);
847 kmflag
= (usb_flags
& USB_FLAGS_SLEEP
) ? KM_SLEEP
: KM_NOSLEEP
;
848 size
= sizeof (usba_pipe_handle_data_t
);
850 if ((ph_data
= kmem_zalloc(size
, kmflag
)) == NULL
) {
852 return (USB_NO_RESOURCES
);
855 /* check if pipe is already open and if so fail */
856 ep_index
= usb_get_ep_index(ep
->bEndpointAddress
);
857 ph_impl
= &usba_device
->usb_ph_list
[ep_index
];
859 mutex_enter(&usba_device
->usb_mutex
);
860 mutex_enter(&ph_impl
->usba_ph_mutex
);
862 if (ph_impl
->usba_ph_data
) {
863 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
864 "usb_pipe_open: pipe to ep %d already open", ep_index
);
865 mutex_exit(&ph_impl
->usba_ph_mutex
);
866 mutex_exit(&usba_device
->usb_mutex
);
867 kmem_free(ph_data
, size
);
872 ph_impl
->usba_ph_data
= ph_data
;
874 mutex_exit(&ph_impl
->usba_ph_mutex
);
875 mutex_exit(&usba_device
->usb_mutex
);
877 if (usb_flags
& USB_FLAGS_SERIALIZED_CB
) {
878 mutex_enter(&ph_data
->p_mutex
);
879 ph_data
->p_spec_flag
|= USBA_PH_FLAG_TQ_SHARE
;
880 mutex_exit(&ph_data
->p_mutex
);
884 * allocate and initialize the pipe handle
886 if ((rval
= usba_init_pipe_handle(dip
, usba_device
,
887 ep
, pipe_policy
, ph_impl
)) != USB_SUCCESS
) {
888 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
889 "usb_pipe_open: pipe init failed (%d)", rval
);
893 ph_data
= ph_impl
->usba_ph_data
;
896 * ask the hcd to open the pipe
898 if ((rval
= usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_open(ph_data
,
899 usb_flags
)) != USB_SUCCESS
) {
900 usba_destroy_pipe_handle(ph_data
);
904 *pipe_handle
= (usb_pipe_handle_t
)ph_impl
;
906 /* set the pipe state after a successful hcd open */
907 mutex_enter(&ph_data
->p_mutex
);
908 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
909 mutex_exit(&ph_data
->p_mutex
);
912 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
913 "usb_pipe_open: ph_impl=0x%p (0x%p)",
914 (void *)ph_impl
, (void *)ph_data
);
921 * usb_pipe_close/sync_close:
923 * Close a pipe and release all resources and free the pipe_handle.
924 * Automatic polling, if active, will be terminated
928 * pipehandle - pointer to pipehandle. The pipehandle will be
929 * zeroed on successful completion
930 * flags - USB_FLAGS_SLEEP:
931 * wait for resources, pipe
932 * to become free, all callbacks completed
933 * callback - If USB_FLAGS_SLEEP has not been specified, a
934 * callback will be performed.
935 * callback_arg - the first argument of the callback. Note that
936 * the pipehandle will be zeroed and not passed
939 * Pipe close will always succeed regardless whether USB_FLAGS_SLEEP has been
941 * An async close will always succeed if the hint in the pipe policy
942 * has been correct about the max number of async taskq requests required.
943 * If there are really no resources, the pipe handle will be linked into
944 * a garbage pipe list and periodically checked by USBA until it can be
945 * closed. This may cause a hang in the detach of the driver.
946 * USBA will prevent the client from submitting more requests to a pipe
947 * that is being closed
948 * Subsequent usb_pipe_close() requests on the same pipe to USBA will
949 * wait for the previous close(s) to finish.
951 * Note that once we start closing a pipe, we cannot go back anymore
952 * to a normal pipe state
955 usb_pipe_close(dev_info_t
*dip
,
956 usb_pipe_handle_t pipe_handle
,
957 usb_flags_t usb_flags
,
959 usb_pipe_handle_t pipe_handle
,
962 usb_cb_flags_t flags
),
963 usb_opaque_t callback_arg
)
965 usba_pipe_handle_data_t
*ph_data
;
966 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
967 usb_cb_flags_t callback_flags
;
969 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
970 "usb_pipe_close: ph=0x%p", (void *)pipe_handle
);
972 callback_flags
= usba_check_intr_context(USB_CB_NO_INFO
);
973 if ((dip
== NULL
) || (pipe_handle
== NULL
)) {
975 callback(pipe_handle
, callback_arg
,
976 USB_INVALID_ARGS
, callback_flags
);
978 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
980 "usb_pipe_close: invalid arguments");
986 if ((usb_flags
& USBA_FLAGS_PRIVILEGED
) == 0) {
988 * It is the client driver doing the pipe close,
989 * the pipe is no longer persistent then.
991 mutex_enter(&ph_impl
->usba_ph_mutex
);
992 ph_impl
->usba_ph_flags
&= ~USBA_PH_DATA_PERSISTENT
;
993 mutex_exit(&ph_impl
->usba_ph_mutex
);
996 if (servicing_interrupt() && (usb_flags
& USB_FLAGS_SLEEP
)) {
998 callback(pipe_handle
, callback_arg
,
999 USB_INVALID_CONTEXT
, callback_flags
);
1001 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
1003 "usb_pipe_close: invalid context");
1009 if ((ph_data
= usba_hold_ph_data(pipe_handle
)) == NULL
) {
1011 /* hold pipehandle anyways since we will decrement later */
1012 mutex_enter(&ph_impl
->usba_ph_mutex
);
1013 ph_impl
->usba_ph_ref_count
++;
1014 mutex_exit(&ph_impl
->usba_ph_mutex
);
1016 (void) usba_pipe_setup_func_call(dip
, usba_pipe_sync_close
,
1017 ph_impl
, NULL
, usb_flags
, callback
, callback_arg
);
1022 mutex_enter(&ph_data
->p_mutex
);
1024 if (USBA_IS_DEFAULT_PIPE(ph_data
) &&
1025 ((usb_flags
& USBA_FLAGS_PRIVILEGED
) == 0)) {
1026 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1027 "usb_pipe_close: not allowed to close def pipe");
1028 mutex_exit(&ph_data
->p_mutex
);
1030 usba_release_ph_data(ph_impl
);
1033 callback(pipe_handle
, callback_arg
,
1034 USB_INVALID_PIPE
, callback_flags
);
1036 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
1038 "usb_pipe_close: invalid pipe");
1044 mutex_exit(&ph_data
->p_mutex
);
1046 (void) usba_pipe_setup_func_call(dip
, usba_pipe_sync_close
,
1047 ph_impl
, NULL
, usb_flags
, callback
, callback_arg
);
1053 usba_pipe_sync_close(dev_info_t
*dip
, usba_ph_impl_t
*ph_impl
,
1054 usba_pipe_async_req_t
*request
, usb_flags_t usb_flags
)
1056 usba_device_t
*usba_device
;
1057 usba_pipe_handle_data_t
*ph_data
= usba_get_ph_data(
1058 (usb_pipe_handle_t
)ph_impl
);
1063 if (ph_impl
== NULL
) {
1065 return (USB_SUCCESS
);
1068 mutex_enter(&ph_impl
->usba_ph_mutex
);
1069 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1070 "usba_pipe_sync_close: dip=0x%p ph_data=0x%p state=%d ref=%d",
1071 (void *)dip
, (void *)ph_data
, ph_impl
->usba_ph_state
,
1072 ph_impl
->usba_ph_ref_count
);
1075 * if another thread opens the pipe again, this loop could
1078 if ((ph_data
== NULL
) ||
1079 (ph_impl
->usba_ph_state
== USB_PIPE_STATE_CLOSING
) ||
1080 (ph_impl
->usba_ph_state
== USB_PIPE_STATE_CLOSED
)) {
1081 /* wait forever till really closed */
1082 mutex_exit(&ph_impl
->usba_ph_mutex
);
1083 usba_release_ph_data(ph_impl
);
1085 while (usba_get_ph_data((usb_pipe_handle_t
)ph_impl
)) {
1089 return (USB_SUCCESS
);
1091 ph_impl
->usba_ph_state
= USB_PIPE_STATE_CLOSING
;
1092 mutex_exit(&ph_impl
->usba_ph_mutex
);
1094 mutex_enter(&ph_data
->p_mutex
);
1095 mutex_enter(&ph_impl
->usba_ph_mutex
);
1097 attribute
= ph_data
->p_ep
.bmAttributes
& USB_EP_ATTR_MASK
;
1098 dir
= ph_data
->p_ep
.bEndpointAddress
& USB_EP_DIR_MASK
;
1100 usba_device
= ph_data
->p_usba_device
;
1103 * For control and bulk, we will drain till ref_count <= 1 and
1104 * req_count == 0 but for isoc and intr IN, we can only wait
1105 * till the ref_count === 1 as the req_count will never go to 0
1107 for (timeout
= 0; timeout
< usba_drain_timeout
; timeout
++) {
1108 switch (attribute
) {
1109 case USB_EP_ATTR_CONTROL
:
1110 case USB_EP_ATTR_BULK
:
1111 if ((ph_data
->p_req_count
== 0) &&
1112 (ph_impl
->usba_ph_ref_count
<= 1)) {
1116 case USB_EP_ATTR_INTR
:
1117 case USB_EP_ATTR_ISOCH
:
1118 if (dir
== USB_EP_DIR_IN
) {
1119 if (ph_impl
->usba_ph_ref_count
<= 1) {
1122 } else if ((ph_data
->p_req_count
== 0) &&
1123 (ph_impl
->usba_ph_ref_count
<= 1)) {
1128 mutex_exit(&ph_impl
->usba_ph_mutex
);
1129 mutex_exit(&ph_data
->p_mutex
);
1130 delay(drv_usectohz(1000));
1131 mutex_enter(&ph_data
->p_mutex
);
1132 mutex_enter(&ph_impl
->usba_ph_mutex
);
1136 mutex_exit(&ph_impl
->usba_ph_mutex
);
1137 mutex_exit(&ph_data
->p_mutex
);
1139 if (timeout
>= usba_drain_timeout
) {
1140 int draining_succeeded
;
1142 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1143 "timeout on draining requests, resetting pipe 0x%p",
1146 (void) usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_reset(ph_data
,
1149 mutex_enter(&ph_data
->p_mutex
);
1150 draining_succeeded
= usba_drain_cbs(ph_data
, USB_CB_RESET_PIPE
,
1152 /* this MUST have succeeded */
1153 ASSERT(draining_succeeded
== USB_SUCCESS
);
1154 mutex_exit(&ph_data
->p_mutex
);
1156 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1157 "draining requests done");
1160 if (usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_close(ph_data
,
1161 usb_flags
) != USB_SUCCESS
) {
1162 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1163 "usba_pipe_sync_close: hcd close failed");
1164 /* carry on regardless! */
1167 usba_destroy_pipe_handle(ph_data
);
1169 return (USB_SUCCESS
);
1174 * usb_pipe_set_private:
1175 * set private client date in the pipe handle
1178 usb_pipe_set_private(usb_pipe_handle_t pipe_handle
, usb_opaque_t data
)
1180 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
1182 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1183 "usb_pipe_set_private: ");
1185 if (ph_data
== NULL
) {
1187 return (USB_INVALID_PIPE
);
1189 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
1190 usba_release_ph_data(ph_data
->p_ph_impl
);
1192 return (USB_INVALID_PERM
);
1195 mutex_enter(&ph_data
->p_mutex
);
1196 ph_data
->p_client_private
= data
;
1197 mutex_exit(&ph_data
->p_mutex
);
1199 usba_release_ph_data(ph_data
->p_ph_impl
);
1201 return (USB_SUCCESS
);
1206 * usb_pipe_get_private:
1207 * get private client date from the pipe handle
1210 usb_pipe_get_private(usb_pipe_handle_t pipe_handle
)
1212 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
1215 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1216 "usb_pipe_get_private:");
1218 if (ph_data
== NULL
) {
1223 mutex_enter(&ph_data
->p_mutex
);
1224 data
= ph_data
->p_client_private
;
1225 mutex_exit(&ph_data
->p_mutex
);
1227 usba_release_ph_data(ph_data
->p_ph_impl
);
1236 * dip - devinfo pointer
1237 * pipe_handle - opaque pipe handle
1239 * USB_SUCCESS - pipe successfully reset or request queued
1240 * USB_FAILURE - undetermined failure
1241 * USB_INVALID_PIPE - pipe is invalid or already closed
1244 usb_pipe_reset(dev_info_t
*dip
,
1245 usb_pipe_handle_t pipe_handle
,
1246 usb_flags_t usb_flags
,
1248 usb_pipe_handle_t ph
,
1251 usb_cb_flags_t flags
),
1252 usb_opaque_t callback_arg
)
1254 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
1255 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
1256 usb_cb_flags_t callback_flags
;
1258 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1259 "usb_pipe_reset: dip=0x%p ph=0x%p uf=0x%x",
1260 (void *)dip
, (void *)pipe_handle
, usb_flags
);
1262 callback_flags
= usba_check_intr_context(USB_CB_NO_INFO
);
1264 if ((dip
== NULL
) || (ph_data
== NULL
)) {
1266 callback(pipe_handle
, callback_arg
,
1267 USB_INVALID_ARGS
, callback_flags
);
1269 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
1271 "usb_pipe_reset: invalid arguments");
1274 usba_release_ph_data(ph_impl
);
1278 if (servicing_interrupt() && (usb_flags
& USB_FLAGS_SLEEP
)) {
1280 callback(pipe_handle
, callback_arg
,
1281 USB_INVALID_CONTEXT
, callback_flags
);
1283 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
1285 "usb_pipe_reset: invalid context");
1288 usba_release_ph_data(ph_impl
);
1293 mutex_enter(&ph_data
->p_mutex
);
1295 /* is this the default pipe? */
1296 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
1297 if ((usb_flags
& USBA_FLAGS_PRIVILEGED
) == 0) {
1298 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1299 "usb_pipe_reset: not allowed to reset def pipe");
1300 mutex_exit(&ph_data
->p_mutex
);
1303 callback(pipe_handle
, callback_arg
,
1304 USB_INVALID_PIPE
, callback_flags
);
1306 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
1308 "usb_pipe_reset: invalid pipe");
1310 usba_release_ph_data(ph_impl
);
1315 mutex_exit(&ph_data
->p_mutex
);
1317 (void) usba_pipe_setup_func_call(dip
,
1318 usba_pipe_sync_reset
, ph_impl
, NULL
, usb_flags
, callback
,
1325 usba_pipe_sync_reset(dev_info_t
*dip
,
1326 usba_ph_impl_t
*ph_impl
,
1327 usba_pipe_async_req_t
*request
,
1328 usb_flags_t usb_flags
)
1330 int rval
, draining_succeeded
;
1331 usba_pipe_handle_data_t
*ph_data
= usba_get_ph_data((usb_pipe_handle_t
)
1333 usba_device_t
*usba_device
;
1335 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1336 "usba_pipe_sync_reset: dip=0x%p ph_data=0x%p uf=0x%x",
1337 (void *)dip
, (void *)ph_data
, usb_flags
);
1339 mutex_enter(&ph_data
->p_mutex
);
1340 usba_device
= ph_data
->p_usba_device
;
1341 mutex_exit(&ph_data
->p_mutex
);
1343 rval
= usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_reset(ph_data
,
1345 mutex_enter(&ph_data
->p_mutex
);
1348 * The host controller has stopped polling of the endpoint.
1350 draining_succeeded
= usba_drain_cbs(ph_data
, USB_CB_RESET_PIPE
,
1353 /* this MUST have succeeded */
1354 ASSERT(draining_succeeded
== USB_SUCCESS
);
1356 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
1357 mutex_exit(&ph_data
->p_mutex
);
1360 * if there are requests still queued on the default pipe,
1363 usba_start_next_req(ph_data
);
1365 usba_release_ph_data(ph_impl
);
1373 * call hcd to clear pipe but don't wait for draining
1376 usba_pipe_clear(usb_pipe_handle_t pipe_handle
)
1378 usba_pipe_handle_data_t
*ph_data
= usba_get_ph_data(pipe_handle
);
1379 usba_device_t
*usba_device
;
1380 usba_req_wrapper_t
*req_wrp
;
1381 int flush_requests
= 1;
1383 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1384 "usba_pipe_clear: ph_data=0x%p", (void *)ph_data
);
1386 if (ph_data
== NULL
) {
1391 mutex_enter(&ph_data
->p_mutex
);
1392 if (USBA_PIPE_CLOSING(usba_get_ph_state(ph_data
))) {
1393 mutex_exit(&ph_data
->p_mutex
);
1397 usba_device
= ph_data
->p_usba_device
;
1398 mutex_exit(&ph_data
->p_mutex
);
1400 (void) usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_reset(ph_data
,
1403 mutex_enter(&ph_data
->p_mutex
);
1404 if (ph_data
->p_dip
) {
1405 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
1406 USB_DPRINTF_L4(DPRINT_MASK_USBAI
,
1408 "no flushing on default pipe!");
1414 if (flush_requests
) {
1415 /* flush all requests in the pipehandle queue */
1416 while ((req_wrp
= (usba_req_wrapper_t
*)
1417 usba_rm_first_pvt_from_list(&ph_data
->p_queue
)) != NULL
) {
1418 mutex_exit(&ph_data
->p_mutex
);
1419 usba_do_req_exc_cb(req_wrp
, USB_CR_FLUSHED
,
1421 mutex_enter(&ph_data
->p_mutex
);
1425 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
1426 mutex_exit(&ph_data
->p_mutex
);
1432 * usb_pipe_drain_reqs
1433 * this function blocks until there are no more requests
1434 * owned by this dip on the pipe
1437 * dip - devinfo pointer
1438 * pipe_handle - opaque pipe handle
1439 * timeout - timeout in seconds
1440 * flags - USB_FLAGS_SLEEP:
1441 * wait for completion.
1442 * cb - if USB_FLAGS_SLEEP has not been specified
1443 * this callback function will be called on
1444 * completion. This callback may be NULL
1445 * and no notification of completion will then
1447 * cb_arg - 2nd argument to callback function.
1449 * callback and callback_arg should be NULL if USB_FLAGS_SLEEP has
1453 * USB_SUCCESS - pipe successfully reset or request queued
1454 * USB_FAILURE - timeout
1455 * USB_* - refer to usbai.h
1458 usb_pipe_drain_reqs(dev_info_t
*dip
,
1459 usb_pipe_handle_t pipe_handle
,
1461 usb_flags_t usb_flags
,
1463 usb_pipe_handle_t ph
,
1464 usb_opaque_t arg
, /* cb arg */
1466 usb_cb_flags_t flags
),
1467 usb_opaque_t cb_arg
)
1469 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
1470 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
1472 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1473 "usb_pipe_drain_reqs: dip=0x%p ph_data=0x%p tm=%d uf=0x%x",
1474 (void *)dip
, (void *)ph_data
, time
, usb_flags
);
1476 if (ph_data
== NULL
) {
1478 return (USB_INVALID_PIPE
);
1481 usba_release_ph_data(ph_impl
);
1483 return (USB_INVALID_ARGS
);
1486 if ((usb_flags
& USB_FLAGS_SLEEP
) && servicing_interrupt()) {
1487 usba_release_ph_data(ph_impl
);
1489 return (USB_INVALID_CONTEXT
);
1492 (void) usba_pipe_setup_func_call(dip
, usba_pipe_sync_drain_reqs
,
1493 ph_impl
, (usb_opaque_t
)((uintptr_t)time
), usb_flags
, cb
, cb_arg
);
1495 return (USB_SUCCESS
);
1500 * usba_pipe_sync_drain_reqs
1501 * this function blocks until there are no more requests
1502 * owned by this dip on the pipe
1505 * dip - devinfo pointer
1506 * ph_impl - pipe impl handle
1507 * timeout - timeout in seconds
1509 * USB_SUCCESS - pipe successfully reset or request queued
1510 * USB_FAILURE - timeout
1511 * USB_* - see usbai.h
1515 usba_pipe_sync_drain_reqs(dev_info_t
*dip
,
1516 usba_ph_impl_t
*ph_impl
,
1517 usba_pipe_async_req_t
*request
,
1518 usb_flags_t usb_flags
)
1520 usba_pipe_handle_data_t
*ph_data
= usba_get_ph_data((usb_pipe_handle_t
)
1523 int timeout
= 100 * (int)((uintptr_t)(request
->arg
));
1524 /* delay will be 10 ms */
1526 mutex_enter(&ph_data
->p_mutex
);
1528 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1529 "usba_pipe_sync_drain_reqs: "
1530 "dip=0x%p ph_data=0x%p timeout=%d ref=%d req=%d",
1531 (void *)dip
, (void *)ph_data
, timeout
,
1532 usba_get_ph_ref_count(ph_data
),
1533 ph_data
->p_req_count
);
1535 ASSERT(ph_data
->p_req_count
>= 0);
1538 * for default pipe, we need to check the active request
1540 * Note that a pipe reset on the default pipe doesn't flush
1542 * for all other pipes we just check ref and req count since
1543 * these pipes are unshared
1545 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
1546 for (i
= 0; (i
< timeout
) || (request
->arg
== 0); i
++) {
1547 usba_list_entry_t
*next
, *tmpnext
;
1548 usba_req_wrapper_t
*req_wrp
= (usba_req_wrapper_t
*)
1549 ph_data
->p_active_cntrl_req_wrp
;
1553 /* active_req_wrp is only for control pipes */
1554 if ((req_wrp
== NULL
) || (req_wrp
->wr_dip
!= dip
)) {
1555 /* walk the queue */
1556 mutex_enter(&ph_data
->p_queue
.list_mutex
);
1557 next
= ph_data
->p_queue
.next
;
1558 while (next
!= NULL
) {
1559 mutex_enter(&next
->list_mutex
);
1560 req_wrp
= (usba_req_wrapper_t
*)
1562 found
= (req_wrp
->wr_dip
== dip
);
1564 mutex_exit(&next
->list_mutex
);
1568 tmpnext
= next
->next
;
1569 mutex_exit(&next
->list_mutex
);
1573 mutex_exit(&ph_data
->p_queue
.list_mutex
);
1579 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1580 "usb_pipe_sync_drain_reqs: "
1581 "cnt=%d active_req_wrp=0x%p",
1582 count
, (void *)ph_data
->p_active_cntrl_req_wrp
);
1584 mutex_exit(&ph_data
->p_mutex
);
1585 delay(drv_usectohz(10000));
1586 mutex_enter(&ph_data
->p_mutex
);
1589 mutex_enter(&ph_data
->p_ph_impl
->usba_ph_mutex
);
1590 for (i
= 0; (i
< timeout
) || (request
->arg
== 0); i
++) {
1591 ASSERT(ph_data
->p_req_count
>= 0);
1592 if (ph_data
->p_req_count
||
1593 (ph_data
->p_ph_impl
->usba_ph_ref_count
> 1)) {
1594 mutex_exit(&ph_data
->p_ph_impl
->usba_ph_mutex
);
1595 mutex_exit(&ph_data
->p_mutex
);
1596 delay(drv_usectohz(10000));
1597 mutex_enter(&ph_data
->p_mutex
);
1598 mutex_enter(&ph_data
->p_ph_impl
->usba_ph_mutex
);
1603 mutex_exit(&ph_data
->p_ph_impl
->usba_ph_mutex
);
1606 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1607 "usb_pipe_sync_drain_reqs: timeout=%d active_req_wrp=0x%p req=%d",
1608 i
, (void *)ph_data
->p_active_cntrl_req_wrp
, ph_data
->p_req_count
);
1610 mutex_exit(&ph_data
->p_mutex
);
1612 usba_release_ph_data(ph_impl
);
1614 return (i
>= timeout
? USB_FAILURE
: USB_SUCCESS
);
1619 * usba_persistent_pipe_open
1620 * Open all the pipes marked persistent for this device
1623 usba_persistent_pipe_open(usba_device_t
*usba_device
)
1625 usba_ph_impl_t
*ph_impl
;
1626 usb_pipe_handle_t pipe_handle
;
1628 int rval
= USB_SUCCESS
;
1630 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1631 "usba_persistent_pipe_open: usba_device=0x%p", (void *)usba_device
);
1633 if (usba_device
!= NULL
) {
1634 /* default pipe is the first one to be opened */
1635 mutex_enter(&usba_device
->usb_mutex
);
1636 for (i
= 0; (rval
== USB_SUCCESS
) &&
1637 (i
< USBA_N_ENDPOINTS
); i
++) {
1639 ph_impl
= &usba_device
->usb_ph_list
[i
];
1640 mutex_enter(&ph_impl
->usba_ph_mutex
);
1641 if (ph_impl
->usba_ph_flags
& USBA_PH_DATA_PERSISTENT
) {
1642 ph_impl
->usba_ph_flags
&=
1643 ~USBA_PH_DATA_PERSISTENT
;
1644 mutex_exit(&ph_impl
->usba_ph_mutex
);
1645 mutex_exit(&usba_device
->usb_mutex
);
1647 rval
= usb_pipe_open(ph_impl
->usba_ph_dip
,
1648 &ph_impl
->usba_ph_ep
,
1649 &ph_impl
->usba_ph_policy
,
1650 USB_FLAGS_SLEEP
| USBA_FLAGS_PRIVILEGED
,
1653 USB_DPRINTF_L3(DPRINT_MASK_USBAI
,
1655 "usba_persistent_pipe_open: "
1656 "ep_index=%d, rval=%d", i
, rval
);
1657 mutex_enter(&usba_device
->usb_mutex
);
1658 mutex_enter(&ph_impl
->usba_ph_mutex
);
1660 mutex_exit(&ph_impl
->usba_ph_mutex
);
1662 mutex_exit(&usba_device
->usb_mutex
);
1670 * usba_persistent_pipe_close
1671 * Close all pipes of this device and mark them persistent
1674 usba_persistent_pipe_close(usba_device_t
*usba_device
)
1676 usba_ph_impl_t
*ph_impl
;
1677 usb_pipe_handle_t pipe_handle
;
1680 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1681 "usba_persistent_pipe_close: usba_device=0x%p",
1682 (void *)usba_device
);
1684 if (usba_device
!= NULL
) {
1685 /* default pipe is the last one to be closed */
1686 mutex_enter(&usba_device
->usb_mutex
);
1688 for (i
= (USBA_N_ENDPOINTS
- 1); i
>= 0; i
--) {
1689 ph_impl
= &usba_device
->usb_ph_list
[i
];
1690 if (ph_impl
->usba_ph_data
!= NULL
) {
1691 mutex_enter(&ph_impl
->usba_ph_mutex
);
1692 ph_impl
->usba_ph_flags
|=
1693 USBA_PH_DATA_PERSISTENT
;
1694 mutex_exit(&ph_impl
->usba_ph_mutex
);
1695 mutex_exit(&usba_device
->usb_mutex
);
1697 pipe_handle
= (usb_pipe_handle_t
)ph_impl
;
1699 usb_pipe_close(ph_impl
->usba_ph_dip
,
1701 USB_FLAGS_SLEEP
| USBA_FLAGS_PRIVILEGED
,
1703 mutex_enter(&usba_device
->usb_mutex
);
1704 ASSERT(ph_impl
->usba_ph_data
== NULL
);
1707 mutex_exit(&usba_device
->usb_mutex
);