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.
25 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
26 * Copyright 2016 Joyent, Inc.
31 * USBA: Solaris USB Architecture support
33 * all functions exposed to client drivers have prefix usb_ while all USBA
34 * internal functions or functions exposed to HCD or hubd only have prefix
37 * this file contains all USBAI pipe management
40 * usb_pipe_set_private()
41 * usb_pipe_get_private()
44 * usb_pipe_drain_reqs()
46 #define USBA_FRAMEWORK
47 #include <sys/usb/usba/usba_impl.h>
48 #include <sys/usb/usba/hcdi_impl.h>
49 #include <sys/atomic.h>
51 extern pri_t maxclsyspri
;
52 extern pri_t minclsyspri
;
54 /* function prototypes */
55 static void usba_pipe_do_async_func_thread(void *arg
);
56 static int usba_pipe_sync_close(dev_info_t
*, usba_ph_impl_t
*,
57 usba_pipe_async_req_t
*, usb_flags_t
);
58 static int usba_pipe_sync_reset(dev_info_t
*, usba_ph_impl_t
*,
59 usba_pipe_async_req_t
*, usb_flags_t
);
60 static int usba_pipe_sync_drain_reqs(dev_info_t
*, usba_ph_impl_t
*,
61 usba_pipe_async_req_t
*, usb_flags_t
);
64 int usba_drain_timeout
= 1000; /* in ms */
66 /* return the default pipe for this device */
68 usba_get_dflt_pipe_handle(dev_info_t
*dip
)
70 usba_device_t
*usba_device
;
71 usb_pipe_handle_t pipe_handle
= NULL
;
74 usba_device
= usba_get_usba_device(dip
);
77 (usb_pipe_handle_t
)&usba_device
->usb_ph_list
[0];
85 /* return dip owner of pipe_handle */
87 usba_get_dip(usb_pipe_handle_t pipe_handle
)
89 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
90 dev_info_t
*dip
= NULL
;
93 mutex_enter(&ph_impl
->usba_ph_mutex
);
94 dip
= ph_impl
->usba_ph_dip
;
95 mutex_exit(&ph_impl
->usba_ph_mutex
);
103 usba_usbdev_to_dflt_pipe_handle(usba_device_t
*usba_device
)
105 usb_pipe_handle_t pipe_handle
= NULL
;
108 (usba_device
->usb_ph_list
[0].usba_ph_data
!= NULL
)) {
109 pipe_handle
= (usb_pipe_handle_t
)&usba_device
->usb_ph_list
[0];
112 return (pipe_handle
);
116 usba_pipe_handle_data_t
*
117 usba_get_ph_data(usb_pipe_handle_t pipe_handle
)
119 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
120 usba_pipe_handle_data_t
*ph_data
= NULL
;
123 mutex_enter(&ph_impl
->usba_ph_mutex
);
124 ASSERT(ph_impl
->usba_ph_ref_count
>= 0);
125 ph_data
= ph_impl
->usba_ph_data
;
126 mutex_exit(&ph_impl
->usba_ph_mutex
);
134 usba_get_pipe_handle(usba_pipe_handle_data_t
*ph_data
)
136 usb_pipe_handle_t ph
= NULL
;
139 mutex_enter(&ph_data
->p_mutex
);
140 ASSERT(ph_data
->p_req_count
>= 0);
141 ph
= (usb_pipe_handle_t
)ph_data
->p_ph_impl
;
142 mutex_exit(&ph_data
->p_mutex
);
150 * opaque to pipe handle impl translation with incr of ref count. The caller
151 * must release ph_data when done. Increment the ref count ensures that
152 * the ph_data will not be freed underneath us.
154 usba_pipe_handle_data_t
*
155 usba_hold_ph_data(usb_pipe_handle_t pipe_handle
)
157 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
158 usba_pipe_handle_data_t
*ph_data
= NULL
;
161 mutex_enter(&ph_impl
->usba_ph_mutex
);
163 switch (ph_impl
->usba_ph_state
) {
164 case USB_PIPE_STATE_IDLE
:
165 case USB_PIPE_STATE_ACTIVE
:
166 case USB_PIPE_STATE_ERROR
:
167 ph_data
= ph_impl
->usba_ph_data
;
168 ph_impl
->usba_ph_ref_count
++;
170 case USB_PIPE_STATE_CLOSED
:
171 case USB_PIPE_STATE_CLOSING
:
176 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
177 "usba_hold_ph_data: ph_impl=0x%p state=%d ref=%d",
178 (void *)ph_impl
, ph_impl
->usba_ph_state
,
179 ph_impl
->usba_ph_ref_count
);
181 mutex_exit(&ph_impl
->usba_ph_mutex
);
189 usba_release_ph_data(usba_ph_impl_t
*ph_impl
)
192 mutex_enter(&ph_impl
->usba_ph_mutex
);
194 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
195 "usba_release_ph_data: "
196 "ph_impl=0x%p state=%d ref=%d",
197 (void *)ph_impl
, ph_impl
->usba_ph_state
,
198 ph_impl
->usba_ph_ref_count
);
200 if (ph_impl
->usba_ph_data
) {
201 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
202 "usba_release_ph_data: req_count=%d",
203 ph_impl
->usba_ph_data
->p_req_count
);
204 ASSERT(ph_impl
->usba_ph_data
->p_req_count
>= 0);
206 ph_impl
->usba_ph_ref_count
--;
207 ASSERT(ph_impl
->usba_ph_ref_count
>= 0);
209 mutex_exit(&ph_impl
->usba_ph_mutex
);
215 * get pipe state from ph_data
218 usba_get_ph_state(usba_pipe_handle_data_t
*ph_data
)
220 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
221 usb_pipe_state_t pipe_state
;
223 ASSERT(mutex_owned(&ph_data
->p_mutex
));
224 mutex_enter(&ph_impl
->usba_ph_mutex
);
225 pipe_state
= ph_impl
->usba_ph_state
;
226 mutex_exit(&ph_impl
->usba_ph_mutex
);
233 * get ref_count from ph_data
236 usba_get_ph_ref_count(usba_pipe_handle_data_t
*ph_data
)
238 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
241 mutex_enter(&ph_impl
->usba_ph_mutex
);
242 ref_count
= ph_impl
->usba_ph_ref_count
;
243 mutex_exit(&ph_impl
->usba_ph_mutex
);
251 * We need to hold both pipe mutex and ph_impl mutex
254 usba_pipe_new_state(usba_pipe_handle_data_t
*ph_data
, usb_pipe_state_t state
)
256 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
258 ASSERT(mutex_owned(&ph_data
->p_mutex
));
260 mutex_enter(&ph_impl
->usba_ph_mutex
);
261 ASSERT(ph_data
->p_req_count
>= 0);
262 ASSERT(ph_impl
->usba_ph_ref_count
>= 0);
264 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
265 "usba_pipe_new_state: "
266 "ph_data=0x%p old=%s new=%s ref=%d req=%d",
267 (void *)ph_data
, usb_str_pipe_state(ph_impl
->usba_ph_state
),
268 usb_str_pipe_state(state
),
269 ph_impl
->usba_ph_ref_count
, ph_data
->p_req_count
);
271 switch (ph_impl
->usba_ph_state
) {
272 case USB_PIPE_STATE_IDLE
:
273 case USB_PIPE_STATE_ACTIVE
:
274 case USB_PIPE_STATE_ERROR
:
275 case USB_PIPE_STATE_CLOSED
:
276 ph_impl
->usba_ph_state
= state
;
278 case USB_PIPE_STATE_CLOSING
:
282 mutex_exit(&ph_impl
->usba_ph_mutex
);
287 * async function execution support
289 * dip - devinfo pointer
290 * sync_func - function to be executed
291 * ph_impl - impl pipehandle
294 * callback - function to be called on completion, may be NULL
295 * callback_arg - argument for callback function
297 * Note: The caller must do a hold on ph_data
298 * We sleep for memory resources and taskq_dispatch which will ensure
299 * that this function succeeds
302 usba_pipe_setup_func_call(
304 int (*sync_func
)(dev_info_t
*,
305 usba_ph_impl_t
*, usba_pipe_async_req_t
*,
307 usba_ph_impl_t
*ph_impl
,
309 usb_flags_t usb_flags
,
310 void (*callback
)(usb_pipe_handle_t
,
311 usb_opaque_t
, int, usb_cb_flags_t
),
312 usb_opaque_t callback_arg
)
314 usba_pipe_async_req_t
*request
;
315 usb_pipe_handle_t pipe_handle
= (usb_pipe_handle_t
)ph_impl
;
316 usba_pipe_handle_data_t
*ph_data
= ph_impl
->usba_ph_data
;
317 int rval
= USB_SUCCESS
;
318 usb_cb_flags_t callback_flags
;
320 USB_DPRINTF_L3(DPRINT_MASK_USBAI
, usbai_log_handle
,
321 "usba_pipe_setup_func_call: ph_impl=0x%p, func=0x%p",
322 (void *)ph_impl
, (void *)sync_func
);
324 if (((usb_flags
& USB_FLAGS_SLEEP
) == 0) && (callback
== NULL
)) {
325 usba_release_ph_data(ph_impl
);
326 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
327 "usba_pipe_setup_func_call: async request with "
330 return (USB_INVALID_ARGS
);
333 request
= kmem_zalloc(sizeof (usba_pipe_async_req_t
), KM_SLEEP
);
335 request
->ph_impl
= ph_impl
;
339 * OR in sleep flag. regardless of calling sync_func directly
340 * or in a new thread, we will always wait for completion
342 request
->usb_flags
= usb_flags
| USB_FLAGS_SLEEP
;
343 request
->sync_func
= sync_func
;
344 request
->callback
= callback
;
345 request
->callback_arg
= callback_arg
;
347 if (usb_flags
& USB_FLAGS_SLEEP
) {
348 rval
= sync_func(dip
, ph_impl
, request
, usb_flags
);
349 kmem_free(request
, sizeof (usba_pipe_async_req_t
));
351 } else if (usba_async_ph_req(ph_data
,
352 usba_pipe_do_async_func_thread
,
353 (void *)request
, USB_FLAGS_SLEEP
) != USB_SUCCESS
) {
354 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
355 "usb_async_req failed: ph_impl=0x%p, func=0x%p",
356 (void *)ph_impl
, (void *)sync_func
);
360 usba_check_intr_context(USB_CB_ASYNC_REQ_FAILED
);
361 callback(pipe_handle
, callback_arg
, USB_FAILURE
,
365 kmem_free(request
, sizeof (usba_pipe_async_req_t
));
366 usba_release_ph_data(ph_impl
);
374 * taskq thread function to execute function synchronously
375 * Note: caller must have done a hold on ph_data
378 usba_pipe_do_async_func_thread(void *arg
)
380 usba_pipe_async_req_t
*request
= (usba_pipe_async_req_t
*)arg
;
381 usba_ph_impl_t
*ph_impl
= request
->ph_impl
;
382 usb_pipe_handle_t pipe_handle
= (usb_pipe_handle_t
)ph_impl
;
384 usb_cb_flags_t cb_flags
= USB_CB_NO_INFO
;
386 if ((rval
= request
->sync_func(request
->dip
, ph_impl
,
387 request
, request
->usb_flags
| USB_FLAGS_SLEEP
)) !=
389 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
390 "sync func failed (%d)", rval
);
393 if (request
->callback
) {
394 request
->callback(pipe_handle
, request
->callback_arg
, rval
,
398 kmem_free(request
, sizeof (usba_pipe_async_req_t
));
403 * default endpoint descriptor and pipe policy
405 usb_ep_descr_t usba_default_ep_descr
=
406 {7, 5, 0, USB_EP_ATTR_CONTROL
, 8, 0};
408 /* set some meaningful defaults */
409 static usb_pipe_policy_t usba_default_ep_pipe_policy
= {3};
413 * usb_get_ep_index: create an index from endpoint address that can
414 * be used to index into endpoint pipe lists
417 usb_get_ep_index(uint8_t ep_addr
)
419 return ((ep_addr
& USB_EP_NUM_MASK
) +
420 ((ep_addr
& USB_EP_DIR_MASK
) ? 16 : 0));
426 * utility functions to init and destroy a pipehandle
429 usba_init_pipe_handle(dev_info_t
*dip
,
430 usba_device_t
*usba_device
,
432 usb_ep_xdescr_t
*ep_xdescr
,
433 usb_pipe_policy_t
*pipe_policy
,
434 usba_ph_impl_t
*ph_impl
)
437 int instance
= ddi_get_instance(dip
);
438 unsigned int def_instance
= instance
;
439 static unsigned int anon_instance
= 0;
440 char tq_name
[TASKQ_NAMELEN
];
442 usba_pipe_handle_data_t
*ph_data
= ph_impl
->usba_ph_data
;
443 ddi_iblock_cookie_t iblock_cookie
=
444 usba_hcdi_get_hcdi(usba_device
->usb_root_hub_dip
)->
447 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
448 "usba_init_pipe_handle: "
449 "usba_device=0x%p ep=0x%x", (void *)usba_device
,
450 ep
->bEndpointAddress
);
451 mutex_init(&ph_data
->p_mutex
, NULL
, MUTEX_DRIVER
, iblock_cookie
);
453 /* just to keep warlock happy, there is no contention yet */
454 mutex_enter(&ph_data
->p_mutex
);
455 mutex_enter(&usba_device
->usb_mutex
);
457 ASSERT(pipe_policy
->pp_max_async_reqs
);
459 if (instance
!= -1) {
460 (void) snprintf(tq_name
, sizeof (tq_name
),
461 "USB_%s_%x_pipehndl_tq_%d",
462 ddi_driver_name(dip
), ep
->bEndpointAddress
, instance
);
464 def_instance
= atomic_inc_32_nv(&anon_instance
);
466 (void) snprintf(tq_name
, sizeof (tq_name
),
467 "USB_%s_%x_pipehndl_tq_%d_",
468 ddi_driver_name(dip
), ep
->bEndpointAddress
, def_instance
);
471 ph_data
->p_taskq
= taskq_create(tq_name
,
472 pipe_policy
->pp_max_async_reqs
+ 1,
473 ((ep
->bmAttributes
& USB_EP_ATTR_MASK
) ==
475 (maxclsyspri
- 5) : minclsyspri
,
476 2 * (pipe_policy
->pp_max_async_reqs
+ 1),
477 8 * (pipe_policy
->pp_max_async_reqs
+ 1),
481 * Create a shared taskq.
483 if (ph_data
->p_spec_flag
& USBA_PH_FLAG_TQ_SHARE
) {
484 int iface
= usb_get_if_number(dip
);
486 /* we own the device, use first entry */
490 if (instance
!= -1) {
491 (void) snprintf(tq_name
, sizeof (tq_name
),
492 "USB_%s_%x_shared_tq_%d",
493 ddi_driver_name(dip
), ep
->bEndpointAddress
,
496 (void) snprintf(tq_name
, sizeof (tq_name
),
497 "USB_%s_%x_shared_tq_%d_",
498 ddi_driver_name(dip
), ep
->bEndpointAddress
,
502 if (usba_device
->usb_shared_taskq_ref_count
[iface
] == 0) {
503 usba_device
->usb_shared_taskq
[iface
] =
504 taskq_create(tq_name
,
505 1, /* Number threads. */
506 maxclsyspri
- 5, /* Priority */
508 USBA_N_ENDPOINTS
+ 4, /* maxalloc */
510 ASSERT(usba_device
->usb_shared_taskq
[iface
] != NULL
);
512 usba_device
->usb_shared_taskq_ref_count
[iface
]++;
516 * In the future, when we may have different versions of the extended
517 * endpoint descriptor, they should be normalized to the current version
518 * here such that all of the HCI drivers have a consistent view of the
519 * world. The extended descriptor may be NULL if we are opening the
520 * default control endpoint; however, we create a uniform view for the
523 if (ep_xdescr
== NULL
) {
524 bzero(&xep
, sizeof (usb_ep_xdescr_t
));
525 xep
.uex_version
= USB_EP_XDESCR_CURRENT_VERSION
;
530 ph_data
->p_dip
= dip
;
531 ph_data
->p_usba_device
= usba_device
;
533 ph_data
->p_xep
= *ep_xdescr
;
534 ph_data
->p_ph_impl
= ph_impl
;
535 if ((ep
->bmAttributes
& USB_EP_ATTR_MASK
) ==
537 ph_data
->p_spec_flag
|= USBA_PH_FLAG_USE_SOFT_INTR
;
540 /* fix up the MaxPacketSize if it is the default endpoint descr */
541 if ((ep
== &usba_default_ep_descr
) && usba_device
) {
544 maxpktsize
= usba_device
->usb_dev_descr
->bMaxPacketSize0
;
545 USB_DPRINTF_L3(DPRINT_MASK_USBAI
, usbai_log_handle
,
546 "adjusting max packet size from %d to %d",
547 ph_data
->p_ep
.wMaxPacketSize
, maxpktsize
);
549 ph_data
->p_ep
.wMaxPacketSize
= maxpktsize
;
552 /* now update usba_ph_impl structure */
553 mutex_enter(&ph_impl
->usba_ph_mutex
);
554 ph_impl
->usba_ph_dip
= dip
;
555 ph_impl
->usba_ph_ep
= ph_data
->p_ep
;
556 ph_impl
->usba_ph_policy
= ph_data
->p_policy
= *pipe_policy
;
557 mutex_exit(&ph_impl
->usba_ph_mutex
);
559 usba_init_list(&ph_data
->p_queue
, (usb_opaque_t
)ph_data
, iblock_cookie
);
560 usba_init_list(&ph_data
->p_cb_queue
, (usb_opaque_t
)ph_data
,
562 mutex_exit(&usba_device
->usb_mutex
);
563 mutex_exit(&ph_data
->p_mutex
);
565 return (USB_SUCCESS
);
570 usba_taskq_destroy(void *arg
)
572 taskq_destroy((taskq_t
*)arg
);
577 usba_destroy_pipe_handle(usba_pipe_handle_data_t
*ph_data
)
579 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
581 usba_device_t
*usba_device
;
583 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
584 "usba_destroy_pipe_handle: ph_data=0x%p", (void *)ph_data
);
586 mutex_enter(&ph_data
->p_mutex
);
587 mutex_enter(&ph_impl
->usba_ph_mutex
);
589 /* check for all activity to drain */
590 for (timeout
= 0; timeout
< usba_drain_timeout
; timeout
++) {
591 if ((ph_impl
->usba_ph_ref_count
<= 1) &&
592 (ph_data
->p_req_count
== 0)) {
596 mutex_exit(&ph_data
->p_mutex
);
597 mutex_exit(&ph_impl
->usba_ph_mutex
);
599 mutex_enter(&ph_data
->p_mutex
);
600 mutex_enter(&ph_impl
->usba_ph_mutex
);
604 * set state to closed here so any other thread
605 * that is waiting for the CLOSED state will
606 * continue. Otherwise, taskq_destroy might deadlock
608 ph_impl
->usba_ph_data
= NULL
;
609 ph_impl
->usba_ph_ref_count
= 0;
610 ph_impl
->usba_ph_state
= USB_PIPE_STATE_CLOSED
;
612 if (ph_data
->p_taskq
) {
613 mutex_exit(&ph_data
->p_mutex
);
614 mutex_exit(&ph_impl
->usba_ph_mutex
);
615 if (taskq_member(ph_data
->p_taskq
, curthread
)) {
617 * use system taskq to destroy ph's taskq to avoid
620 (void) taskq_dispatch(system_taskq
,
621 usba_taskq_destroy
, ph_data
->p_taskq
, TQ_SLEEP
);
623 taskq_destroy(ph_data
->p_taskq
);
626 mutex_exit(&ph_data
->p_mutex
);
627 mutex_exit(&ph_impl
->usba_ph_mutex
);
630 usba_device
= ph_data
->p_usba_device
;
631 mutex_enter(&ph_data
->p_mutex
);
632 if (ph_data
->p_spec_flag
& USBA_PH_FLAG_TQ_SHARE
) {
633 int iface
= usb_get_if_number(ph_data
->p_dip
);
635 /* we own the device, use the first entry */
638 mutex_enter(&usba_device
->usb_mutex
);
639 if (--usba_device
->usb_shared_taskq_ref_count
[iface
] == 0) {
640 ph_data
->p_spec_flag
&= ~USBA_PH_FLAG_TQ_SHARE
;
641 if (taskq_member(usba_device
->usb_shared_taskq
[iface
],
643 (void) taskq_dispatch(
646 usba_device
->usb_shared_taskq
[iface
],
650 usba_device
->usb_shared_taskq
[iface
]);
653 mutex_exit(&usba_device
->usb_mutex
);
655 mutex_exit(&ph_data
->p_mutex
);
658 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
659 "usba_destroy_pipe_handle: destroying ph_data=0x%p",
662 usba_destroy_list(&ph_data
->p_queue
);
663 usba_destroy_list(&ph_data
->p_cb_queue
);
665 /* destroy mutexes */
666 mutex_destroy(&ph_data
->p_mutex
);
668 kmem_free(ph_data
, sizeof (usba_pipe_handle_data_t
));
674 * Drain the request callbacks on the pipe handle
677 usba_drain_cbs(usba_pipe_handle_data_t
*ph_data
, usb_cb_flags_t cb_flags
,
680 usba_req_wrapper_t
*req_wrp
;
681 int flush_requests
= 1;
682 usba_ph_impl_t
*ph_impl
= ph_data
->p_ph_impl
;
684 int rval
= USB_SUCCESS
;
686 ASSERT(mutex_owned(&ph_data
->p_mutex
));
688 mutex_enter(&ph_impl
->usba_ph_mutex
);
689 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
690 "usba_drain_cbs: ph_data=0x%p ref=%d req=%d cb=0x%x cr=%d",
691 (void *)ph_data
, ph_impl
->usba_ph_ref_count
, ph_data
->p_req_count
,
693 ASSERT(ph_data
->p_req_count
>= 0);
694 mutex_exit(&ph_impl
->usba_ph_mutex
);
696 if (ph_data
->p_dip
) {
697 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
698 USB_DPRINTF_L4(DPRINT_MASK_USBAI
,
700 "no flushing on default pipe!");
706 if (flush_requests
) {
707 /* flush all requests in the pipehandle queue */
708 while ((req_wrp
= (usba_req_wrapper_t
*)
709 usba_rm_first_pvt_from_list(&ph_data
->p_queue
)) != NULL
) {
710 mutex_exit(&ph_data
->p_mutex
);
711 usba_do_req_exc_cb(req_wrp
, cr
, cb_flags
);
712 mutex_enter(&ph_data
->p_mutex
);
717 * wait for any callbacks in progress but don't wait for
718 * for queued requests on the default pipe
720 for (timeout
= 0; (timeout
< usba_drain_timeout
) &&
721 (ph_data
->p_req_count
>
722 usba_list_entry_count(&ph_data
->p_queue
));
724 mutex_exit(&ph_data
->p_mutex
);
726 mutex_enter(&ph_data
->p_mutex
);
729 mutex_enter(&ph_impl
->usba_ph_mutex
);
730 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
731 "usba_drain_cbs done: ph_data=0x%p ref=%d req=%d",
732 (void *)ph_data
, ph_impl
->usba_ph_ref_count
, ph_data
->p_req_count
);
733 mutex_exit(&ph_impl
->usba_ph_mutex
);
735 if (timeout
== usba_drain_timeout
) {
736 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
737 "draining callbacks timed out!");
749 * Before using any pipe including the default pipe, it should be opened
750 * using usb_pipe_open(). On a successful open, a pipe handle is returned
751 * for use in other usb_pipe_*() functions
753 * The default pipe can only be opened by the hub driver
755 * The bandwidth has been allocated and guaranteed on successful
756 * opening of an isoc/intr pipes.
758 * Only the default pipe can be shared. all other control pipes
759 * are excusively opened by default.
760 * A pipe policy and endpoint descriptor must always be provided
761 * except for default pipe
765 * ep - endpoint descriptor pointer
766 * pipe_policy - pointer to pipe policy which provides hints on how
767 * the pipe will be used.
768 * flags - USB_FLAGS_SLEEP wait for resources
769 * to become available
770 * pipe_handle - a pipe handle pointer. On a successful open,
771 * a pipe_handle is returned in this pointer.
774 * USB_SUCCESS - open succeeded
775 * USB_FAILURE - unspecified open failure or pipe is already open
776 * USB_NO_RESOURCES - no resources were available to complete the open
777 * USB_NO_BANDWIDTH - no bandwidth available (isoc/intr pipes)
778 * USB_* - refer to usbai.h
783 usb_ep_xdescr_t
*ep_xdesc
,
784 usb_pipe_policy_t
*pipe_policy
,
785 usb_flags_t usb_flags
,
786 usb_pipe_handle_t
*pipe_handle
)
789 usba_device_t
*usba_device
;
791 usba_pipe_handle_data_t
*ph_data
;
792 usba_ph_impl_t
*ph_impl
;
797 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
799 "dip=0x%p ep_xdesc=0x%p pp=0x%p uf=0x%x ph=0x%p",
800 (void *)dip
, (void *)ep_xdesc
, (void *)pipe_policy
, usb_flags
,
801 (void *)pipe_handle
);
803 if ((dip
== NULL
) || (pipe_handle
== NULL
)) {
805 return (USB_INVALID_ARGS
);
808 if ((ep_xdesc
!= NULL
) &&
809 ((ep_xdesc
->uex_version
!= USB_EP_XDESCR_CURRENT_VERSION
) ||
810 ((ep_xdesc
->uex_flags
& ~USB_EP_XFLAGS_SS_COMP
) != 0))) {
812 return (USB_INVALID_ARGS
);
815 if (servicing_interrupt() && (usb_flags
& USB_FLAGS_SLEEP
)) {
817 return (USB_INVALID_CONTEXT
);
819 usba_device
= usba_get_usba_device(dip
);
822 * Check the device's speed. If we're being asked to open anything other
823 * than the default endpoint and the device is superspeed or greater and
824 * we only have a usb_ep_descr_t and not the full endpoint data, then
825 * this was coming through usb_pipe_open() and we need to fail this
828 * Some drivers technically cheat and open the default control endpoint
829 * even though they're not supposed to. ugen appears to be the main
830 * offender. To deal with this, we check to see if the endpoint
831 * descriptor bcmps to our default and give them a break, since we don't
832 * need extended info for default control endpoints.
834 if (ep_xdesc
!= NULL
&& ep_xdesc
->uex_flags
== 0 &&
835 bcmp(&ep_xdesc
->uex_ep
, &usba_default_ep_descr
,
836 sizeof (usb_ep_descr_t
)) != 0 &&
837 usba_device
->usb_port_status
>= USBA_SUPER_SPEED_DEV
) {
838 const char *dname
= ddi_driver_name(dip
);
839 const char *prod
, *mfg
;
841 prod
= usba_device
->usb_product_str
;
843 prod
= "Unknown Device";
844 mfg
= usba_device
->usb_mfg_str
;
846 mfg
= "Unknown Manufacturer";
847 cmn_err(CE_NOTE
, "driver %s attempting to open non-default "
848 "of a USB 3.0 or newer device through usb_pipe_open(). "
849 "%s must be updated to use usb_pipe_xopen() to work with "
850 "USB device %s %s.", dname
, dname
, mfg
, prod
);
851 return (USB_FAILURE
);
854 if ((ep_xdesc
!= NULL
) && (pipe_policy
== NULL
)) {
855 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
856 "usb_pipe_open: null pipe policy");
858 return (USB_INVALID_ARGS
);
861 /* is the device still connected? */
862 if ((ep_xdesc
!= NULL
) & DEVI_IS_DEVICE_REMOVED(dip
)) {
863 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
864 "usb_pipe_open: device has been removed");
866 return (USB_FAILURE
);
871 * if a null endpoint pointer was passed, use the default
872 * endpoint descriptor
874 if (ep_xdesc
== NULL
) {
875 if ((usb_flags
& USBA_FLAGS_PRIVILEGED
) == 0) {
876 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
877 "usb_pipe_open: not allowed to open def pipe");
879 return (USB_INVALID_PERM
);
882 ep
= &usba_default_ep_descr
;
883 pipe_policy
= &usba_default_ep_pipe_policy
;
885 ep
= &ep_xdesc
->uex_ep
;
888 if (usb_flags
& USB_FLAGS_SERIALIZED_CB
) {
889 if (((ep
->bmAttributes
& USB_EP_ATTR_MASK
) ==
890 USB_EP_ATTR_CONTROL
) ||
891 ((ep
->bmAttributes
& USB_EP_ATTR_MASK
) ==
892 USB_EP_ATTR_ISOCH
)) {
893 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
894 "usb_pipe_open: shared taskq not allowed with "
895 "ctrl or isoch pipe");
897 return (USB_INVALID_ARGS
);
901 kmflag
= (usb_flags
& USB_FLAGS_SLEEP
) ? KM_SLEEP
: KM_NOSLEEP
;
902 size
= sizeof (usba_pipe_handle_data_t
);
904 if ((ph_data
= kmem_zalloc(size
, kmflag
)) == NULL
) {
906 return (USB_NO_RESOURCES
);
909 /* check if pipe is already open and if so fail */
910 ep_index
= usb_get_ep_index(ep
->bEndpointAddress
);
911 ph_impl
= &usba_device
->usb_ph_list
[ep_index
];
913 mutex_enter(&usba_device
->usb_mutex
);
914 mutex_enter(&ph_impl
->usba_ph_mutex
);
916 if (ph_impl
->usba_ph_data
) {
917 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
918 "usb_pipe_open: pipe to ep %d already open", ep_index
);
919 mutex_exit(&ph_impl
->usba_ph_mutex
);
920 mutex_exit(&usba_device
->usb_mutex
);
921 kmem_free(ph_data
, size
);
926 ph_impl
->usba_ph_data
= ph_data
;
928 mutex_exit(&ph_impl
->usba_ph_mutex
);
929 mutex_exit(&usba_device
->usb_mutex
);
931 if (usb_flags
& USB_FLAGS_SERIALIZED_CB
) {
932 mutex_enter(&ph_data
->p_mutex
);
933 ph_data
->p_spec_flag
|= USBA_PH_FLAG_TQ_SHARE
;
934 mutex_exit(&ph_data
->p_mutex
);
938 * allocate and initialize the pipe handle
940 if ((rval
= usba_init_pipe_handle(dip
, usba_device
,
941 ep
, ep_xdesc
, pipe_policy
, ph_impl
)) != USB_SUCCESS
) {
942 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
943 "usb_pipe_open: pipe init failed (%d)", rval
);
947 ph_data
= ph_impl
->usba_ph_data
;
950 * ask the hcd to open the pipe
952 if ((rval
= usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_open(ph_data
,
953 usb_flags
)) != USB_SUCCESS
) {
954 usba_destroy_pipe_handle(ph_data
);
958 *pipe_handle
= (usb_pipe_handle_t
)ph_impl
;
960 /* set the pipe state after a successful hcd open */
961 mutex_enter(&ph_data
->p_mutex
);
962 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
963 mutex_exit(&ph_data
->p_mutex
);
966 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
967 "usb_pipe_open: ph_impl=0x%p (0x%p)",
968 (void *)ph_impl
, (void *)ph_data
);
977 usb_pipe_policy_t
*pipe_policy
,
978 usb_flags_t usb_flags
,
979 usb_pipe_handle_t
*pipe_handle
)
981 usb_ep_xdescr_t xdesc
, *xp
= NULL
;
984 * ep may be NULL if trying to open the default control endpoint.
987 bzero(&xdesc
, sizeof (usb_ep_xdescr_t
));
988 xdesc
.uex_version
= USB_EP_XDESCR_CURRENT_VERSION
;
993 return (usb_pipe_xopen(dip
, xp
, pipe_policy
, usb_flags
,
998 * usb_pipe_close/sync_close:
1000 * Close a pipe and release all resources and free the pipe_handle.
1001 * Automatic polling, if active, will be terminated
1005 * pipehandle - pointer to pipehandle. The pipehandle will be
1006 * zeroed on successful completion
1007 * flags - USB_FLAGS_SLEEP:
1008 * wait for resources, pipe
1009 * to become free, all callbacks completed
1010 * callback - If USB_FLAGS_SLEEP has not been specified, a
1011 * callback will be performed.
1012 * callback_arg - the first argument of the callback. Note that
1013 * the pipehandle will be zeroed and not passed
1016 * Pipe close will always succeed regardless whether USB_FLAGS_SLEEP has been
1018 * An async close will always succeed if the hint in the pipe policy
1019 * has been correct about the max number of async taskq requests required.
1020 * If there are really no resources, the pipe handle will be linked into
1021 * a garbage pipe list and periodically checked by USBA until it can be
1022 * closed. This may cause a hang in the detach of the driver.
1023 * USBA will prevent the client from submitting more requests to a pipe
1024 * that is being closed
1025 * Subsequent usb_pipe_close() requests on the same pipe to USBA will
1026 * wait for the previous close(s) to finish.
1028 * Note that once we start closing a pipe, we cannot go back anymore
1029 * to a normal pipe state
1032 usb_pipe_close(dev_info_t
*dip
,
1033 usb_pipe_handle_t pipe_handle
,
1034 usb_flags_t usb_flags
,
1036 usb_pipe_handle_t pipe_handle
,
1039 usb_cb_flags_t flags
),
1040 usb_opaque_t callback_arg
)
1042 usba_pipe_handle_data_t
*ph_data
;
1043 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
1044 usb_cb_flags_t callback_flags
;
1046 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1047 "usb_pipe_close: ph=0x%p", (void *)pipe_handle
);
1049 callback_flags
= usba_check_intr_context(USB_CB_NO_INFO
);
1050 if ((dip
== NULL
) || (pipe_handle
== NULL
)) {
1052 callback(pipe_handle
, callback_arg
,
1053 USB_INVALID_ARGS
, callback_flags
);
1055 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
1057 "usb_pipe_close: invalid arguments");
1063 if ((usb_flags
& USBA_FLAGS_PRIVILEGED
) == 0) {
1065 * It is the client driver doing the pipe close,
1066 * the pipe is no longer persistent then.
1068 mutex_enter(&ph_impl
->usba_ph_mutex
);
1069 ph_impl
->usba_ph_flags
&= ~USBA_PH_DATA_PERSISTENT
;
1070 mutex_exit(&ph_impl
->usba_ph_mutex
);
1073 if (servicing_interrupt() && (usb_flags
& USB_FLAGS_SLEEP
)) {
1075 callback(pipe_handle
, callback_arg
,
1076 USB_INVALID_CONTEXT
, callback_flags
);
1078 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
1080 "usb_pipe_close: invalid context");
1086 if ((ph_data
= usba_hold_ph_data(pipe_handle
)) == NULL
) {
1088 /* hold pipehandle anyways since we will decrement later */
1089 mutex_enter(&ph_impl
->usba_ph_mutex
);
1090 ph_impl
->usba_ph_ref_count
++;
1091 mutex_exit(&ph_impl
->usba_ph_mutex
);
1093 (void) usba_pipe_setup_func_call(dip
, usba_pipe_sync_close
,
1094 ph_impl
, NULL
, usb_flags
, callback
, callback_arg
);
1099 mutex_enter(&ph_data
->p_mutex
);
1101 if (USBA_IS_DEFAULT_PIPE(ph_data
) &&
1102 ((usb_flags
& USBA_FLAGS_PRIVILEGED
) == 0)) {
1103 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1104 "usb_pipe_close: not allowed to close def pipe");
1105 mutex_exit(&ph_data
->p_mutex
);
1107 usba_release_ph_data(ph_impl
);
1110 callback(pipe_handle
, callback_arg
,
1111 USB_INVALID_PIPE
, callback_flags
);
1113 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
1115 "usb_pipe_close: invalid pipe");
1121 mutex_exit(&ph_data
->p_mutex
);
1123 (void) usba_pipe_setup_func_call(dip
, usba_pipe_sync_close
,
1124 ph_impl
, NULL
, usb_flags
, callback
, callback_arg
);
1130 usba_pipe_sync_close(dev_info_t
*dip
, usba_ph_impl_t
*ph_impl
,
1131 usba_pipe_async_req_t
*request
, usb_flags_t usb_flags
)
1133 usba_device_t
*usba_device
;
1134 usba_pipe_handle_data_t
*ph_data
= usba_get_ph_data(
1135 (usb_pipe_handle_t
)ph_impl
);
1140 if (ph_impl
== NULL
) {
1142 return (USB_SUCCESS
);
1145 mutex_enter(&ph_impl
->usba_ph_mutex
);
1146 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1147 "usba_pipe_sync_close: dip=0x%p ph_data=0x%p state=%d ref=%d",
1148 (void *)dip
, (void *)ph_data
, ph_impl
->usba_ph_state
,
1149 ph_impl
->usba_ph_ref_count
);
1152 * if another thread opens the pipe again, this loop could
1155 if ((ph_data
== NULL
) ||
1156 (ph_impl
->usba_ph_state
== USB_PIPE_STATE_CLOSING
) ||
1157 (ph_impl
->usba_ph_state
== USB_PIPE_STATE_CLOSED
)) {
1158 /* wait forever till really closed */
1159 mutex_exit(&ph_impl
->usba_ph_mutex
);
1160 usba_release_ph_data(ph_impl
);
1162 while (usba_get_ph_data((usb_pipe_handle_t
)ph_impl
)) {
1166 return (USB_SUCCESS
);
1168 ph_impl
->usba_ph_state
= USB_PIPE_STATE_CLOSING
;
1169 mutex_exit(&ph_impl
->usba_ph_mutex
);
1171 mutex_enter(&ph_data
->p_mutex
);
1172 mutex_enter(&ph_impl
->usba_ph_mutex
);
1174 attribute
= ph_data
->p_ep
.bmAttributes
& USB_EP_ATTR_MASK
;
1175 dir
= ph_data
->p_ep
.bEndpointAddress
& USB_EP_DIR_MASK
;
1177 usba_device
= ph_data
->p_usba_device
;
1180 * For control and bulk, we will drain till ref_count <= 1 and
1181 * req_count == 0 but for isoc and intr IN, we can only wait
1182 * till the ref_count === 1 as the req_count will never go to 0
1184 for (timeout
= 0; timeout
< usba_drain_timeout
; timeout
++) {
1185 switch (attribute
) {
1186 case USB_EP_ATTR_CONTROL
:
1187 case USB_EP_ATTR_BULK
:
1188 if ((ph_data
->p_req_count
== 0) &&
1189 (ph_impl
->usba_ph_ref_count
<= 1)) {
1193 case USB_EP_ATTR_INTR
:
1194 case USB_EP_ATTR_ISOCH
:
1195 if (dir
== USB_EP_DIR_IN
) {
1196 if (ph_impl
->usba_ph_ref_count
<= 1) {
1199 } else if ((ph_data
->p_req_count
== 0) &&
1200 (ph_impl
->usba_ph_ref_count
<= 1)) {
1205 mutex_exit(&ph_impl
->usba_ph_mutex
);
1206 mutex_exit(&ph_data
->p_mutex
);
1208 mutex_enter(&ph_data
->p_mutex
);
1209 mutex_enter(&ph_impl
->usba_ph_mutex
);
1213 mutex_exit(&ph_impl
->usba_ph_mutex
);
1214 mutex_exit(&ph_data
->p_mutex
);
1216 if (timeout
>= usba_drain_timeout
) {
1217 int draining_succeeded
;
1219 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1220 "timeout on draining requests, resetting pipe 0x%p",
1223 (void) usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_reset(ph_data
,
1226 mutex_enter(&ph_data
->p_mutex
);
1227 draining_succeeded
= usba_drain_cbs(ph_data
, USB_CB_RESET_PIPE
,
1229 /* this MUST have succeeded */
1230 ASSERT(draining_succeeded
== USB_SUCCESS
);
1231 mutex_exit(&ph_data
->p_mutex
);
1233 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1234 "draining requests done");
1237 if (usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_close(ph_data
,
1238 usb_flags
) != USB_SUCCESS
) {
1239 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1240 "usba_pipe_sync_close: hcd close failed");
1241 /* carry on regardless! */
1244 usba_destroy_pipe_handle(ph_data
);
1246 return (USB_SUCCESS
);
1251 * usb_pipe_set_private:
1252 * set private client date in the pipe handle
1255 usb_pipe_set_private(usb_pipe_handle_t pipe_handle
, usb_opaque_t data
)
1257 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
1259 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1260 "usb_pipe_set_private: ");
1262 if (ph_data
== NULL
) {
1264 return (USB_INVALID_PIPE
);
1266 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
1267 usba_release_ph_data(ph_data
->p_ph_impl
);
1269 return (USB_INVALID_PERM
);
1272 mutex_enter(&ph_data
->p_mutex
);
1273 ph_data
->p_client_private
= data
;
1274 mutex_exit(&ph_data
->p_mutex
);
1276 usba_release_ph_data(ph_data
->p_ph_impl
);
1278 return (USB_SUCCESS
);
1283 * usb_pipe_get_private:
1284 * get private client date from the pipe handle
1287 usb_pipe_get_private(usb_pipe_handle_t pipe_handle
)
1289 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
1292 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1293 "usb_pipe_get_private:");
1295 if (ph_data
== NULL
) {
1300 mutex_enter(&ph_data
->p_mutex
);
1301 data
= ph_data
->p_client_private
;
1302 mutex_exit(&ph_data
->p_mutex
);
1304 usba_release_ph_data(ph_data
->p_ph_impl
);
1313 * dip - devinfo pointer
1314 * pipe_handle - opaque pipe handle
1316 * USB_SUCCESS - pipe successfully reset or request queued
1317 * USB_FAILURE - undetermined failure
1318 * USB_INVALID_PIPE - pipe is invalid or already closed
1321 usb_pipe_reset(dev_info_t
*dip
,
1322 usb_pipe_handle_t pipe_handle
,
1323 usb_flags_t usb_flags
,
1325 usb_pipe_handle_t ph
,
1328 usb_cb_flags_t flags
),
1329 usb_opaque_t callback_arg
)
1331 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
1332 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
1333 usb_cb_flags_t callback_flags
;
1335 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1336 "usb_pipe_reset: dip=0x%p ph=0x%p uf=0x%x",
1337 (void *)dip
, (void *)pipe_handle
, usb_flags
);
1339 callback_flags
= usba_check_intr_context(USB_CB_NO_INFO
);
1341 if ((dip
== NULL
) || (ph_data
== NULL
)) {
1343 callback(pipe_handle
, callback_arg
,
1344 USB_INVALID_ARGS
, callback_flags
);
1346 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
1348 "usb_pipe_reset: invalid arguments");
1351 usba_release_ph_data(ph_impl
);
1355 if (servicing_interrupt() && (usb_flags
& USB_FLAGS_SLEEP
)) {
1357 callback(pipe_handle
, callback_arg
,
1358 USB_INVALID_CONTEXT
, callback_flags
);
1360 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
1362 "usb_pipe_reset: invalid context");
1365 usba_release_ph_data(ph_impl
);
1370 mutex_enter(&ph_data
->p_mutex
);
1372 /* is this the default pipe? */
1373 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
1374 if ((usb_flags
& USBA_FLAGS_PRIVILEGED
) == 0) {
1375 USB_DPRINTF_L2(DPRINT_MASK_USBAI
, usbai_log_handle
,
1376 "usb_pipe_reset: not allowed to reset def pipe");
1377 mutex_exit(&ph_data
->p_mutex
);
1380 callback(pipe_handle
, callback_arg
,
1381 USB_INVALID_PIPE
, callback_flags
);
1383 USB_DPRINTF_L2(DPRINT_MASK_USBAI
,
1385 "usb_pipe_reset: invalid pipe");
1387 usba_release_ph_data(ph_impl
);
1392 mutex_exit(&ph_data
->p_mutex
);
1394 (void) usba_pipe_setup_func_call(dip
,
1395 usba_pipe_sync_reset
, ph_impl
, NULL
, usb_flags
, callback
,
1402 usba_pipe_sync_reset(dev_info_t
*dip
,
1403 usba_ph_impl_t
*ph_impl
,
1404 usba_pipe_async_req_t
*request
,
1405 usb_flags_t usb_flags
)
1407 int rval
, draining_succeeded
;
1408 usba_pipe_handle_data_t
*ph_data
= usba_get_ph_data((usb_pipe_handle_t
)
1410 usba_device_t
*usba_device
;
1412 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1413 "usba_pipe_sync_reset: dip=0x%p ph_data=0x%p uf=0x%x",
1414 (void *)dip
, (void *)ph_data
, usb_flags
);
1416 mutex_enter(&ph_data
->p_mutex
);
1417 usba_device
= ph_data
->p_usba_device
;
1418 mutex_exit(&ph_data
->p_mutex
);
1420 rval
= usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_reset(ph_data
,
1422 mutex_enter(&ph_data
->p_mutex
);
1425 * The host controller has stopped polling of the endpoint.
1427 draining_succeeded
= usba_drain_cbs(ph_data
, USB_CB_RESET_PIPE
,
1430 /* this MUST have succeeded */
1431 ASSERT(draining_succeeded
== USB_SUCCESS
);
1433 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
1434 mutex_exit(&ph_data
->p_mutex
);
1437 * if there are requests still queued on the default pipe,
1440 usba_start_next_req(ph_data
);
1442 usba_release_ph_data(ph_impl
);
1450 * call hcd to clear pipe but don't wait for draining
1453 usba_pipe_clear(usb_pipe_handle_t pipe_handle
)
1455 usba_pipe_handle_data_t
*ph_data
= usba_get_ph_data(pipe_handle
);
1456 usba_device_t
*usba_device
;
1457 usba_req_wrapper_t
*req_wrp
;
1458 int flush_requests
= 1;
1460 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1461 "usba_pipe_clear: ph_data=0x%p", (void *)ph_data
);
1463 if (ph_data
== NULL
) {
1468 mutex_enter(&ph_data
->p_mutex
);
1469 if (USBA_PIPE_CLOSING(usba_get_ph_state(ph_data
))) {
1470 mutex_exit(&ph_data
->p_mutex
);
1474 usba_device
= ph_data
->p_usba_device
;
1475 mutex_exit(&ph_data
->p_mutex
);
1477 (void) usba_device
->usb_hcdi_ops
->usba_hcdi_pipe_reset(ph_data
,
1480 mutex_enter(&ph_data
->p_mutex
);
1481 if (ph_data
->p_dip
) {
1482 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
1483 USB_DPRINTF_L4(DPRINT_MASK_USBAI
,
1485 "no flushing on default pipe!");
1491 if (flush_requests
) {
1492 /* flush all requests in the pipehandle queue */
1493 while ((req_wrp
= (usba_req_wrapper_t
*)
1494 usba_rm_first_pvt_from_list(&ph_data
->p_queue
)) != NULL
) {
1495 mutex_exit(&ph_data
->p_mutex
);
1496 usba_do_req_exc_cb(req_wrp
, USB_CR_FLUSHED
,
1498 mutex_enter(&ph_data
->p_mutex
);
1502 usba_pipe_new_state(ph_data
, USB_PIPE_STATE_IDLE
);
1503 mutex_exit(&ph_data
->p_mutex
);
1509 * usb_pipe_drain_reqs
1510 * this function blocks until there are no more requests
1511 * owned by this dip on the pipe
1514 * dip - devinfo pointer
1515 * pipe_handle - opaque pipe handle
1516 * timeout - timeout in seconds
1517 * flags - USB_FLAGS_SLEEP:
1518 * wait for completion.
1519 * cb - if USB_FLAGS_SLEEP has not been specified
1520 * this callback function will be called on
1521 * completion. This callback may be NULL
1522 * and no notification of completion will then
1524 * cb_arg - 2nd argument to callback function.
1526 * callback and callback_arg should be NULL if USB_FLAGS_SLEEP has
1530 * USB_SUCCESS - pipe successfully reset or request queued
1531 * USB_FAILURE - timeout
1532 * USB_* - refer to usbai.h
1535 usb_pipe_drain_reqs(dev_info_t
*dip
,
1536 usb_pipe_handle_t pipe_handle
,
1538 usb_flags_t usb_flags
,
1540 usb_pipe_handle_t ph
,
1541 usb_opaque_t arg
, /* cb arg */
1543 usb_cb_flags_t flags
),
1544 usb_opaque_t cb_arg
)
1546 usba_ph_impl_t
*ph_impl
= (usba_ph_impl_t
*)pipe_handle
;
1547 usba_pipe_handle_data_t
*ph_data
= usba_hold_ph_data(pipe_handle
);
1549 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1550 "usb_pipe_drain_reqs: dip=0x%p ph_data=0x%p tm=%d uf=0x%x",
1551 (void *)dip
, (void *)ph_data
, time
, usb_flags
);
1553 if (ph_data
== NULL
) {
1555 return (USB_INVALID_PIPE
);
1558 usba_release_ph_data(ph_impl
);
1560 return (USB_INVALID_ARGS
);
1563 if ((usb_flags
& USB_FLAGS_SLEEP
) && servicing_interrupt()) {
1564 usba_release_ph_data(ph_impl
);
1566 return (USB_INVALID_CONTEXT
);
1569 (void) usba_pipe_setup_func_call(dip
, usba_pipe_sync_drain_reqs
,
1570 ph_impl
, (usb_opaque_t
)((uintptr_t)time
), usb_flags
, cb
, cb_arg
);
1572 return (USB_SUCCESS
);
1577 * usba_pipe_sync_drain_reqs
1578 * this function blocks until there are no more requests
1579 * owned by this dip on the pipe
1582 * dip - devinfo pointer
1583 * ph_impl - pipe impl handle
1584 * timeout - timeout in seconds
1586 * USB_SUCCESS - pipe successfully reset or request queued
1587 * USB_FAILURE - timeout
1588 * USB_* - see usbai.h
1592 usba_pipe_sync_drain_reqs(dev_info_t
*dip
,
1593 usba_ph_impl_t
*ph_impl
,
1594 usba_pipe_async_req_t
*request
,
1595 usb_flags_t usb_flags
)
1597 usba_pipe_handle_data_t
*ph_data
= usba_get_ph_data((usb_pipe_handle_t
)
1600 int timeout
= 100 * (int)((uintptr_t)(request
->arg
));
1601 /* delay will be 10 ms */
1603 mutex_enter(&ph_data
->p_mutex
);
1605 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1606 "usba_pipe_sync_drain_reqs: "
1607 "dip=0x%p ph_data=0x%p timeout=%d ref=%d req=%d",
1608 (void *)dip
, (void *)ph_data
, timeout
,
1609 usba_get_ph_ref_count(ph_data
),
1610 ph_data
->p_req_count
);
1612 ASSERT(ph_data
->p_req_count
>= 0);
1615 * for default pipe, we need to check the active request
1617 * Note that a pipe reset on the default pipe doesn't flush
1619 * for all other pipes we just check ref and req count since
1620 * these pipes are unshared
1622 if (USBA_IS_DEFAULT_PIPE(ph_data
)) {
1623 for (i
= 0; (i
< timeout
) || (request
->arg
== 0); i
++) {
1624 usba_list_entry_t
*next
, *tmpnext
;
1625 usba_req_wrapper_t
*req_wrp
= (usba_req_wrapper_t
*)
1626 ph_data
->p_active_cntrl_req_wrp
;
1630 /* active_req_wrp is only for control pipes */
1631 if ((req_wrp
== NULL
) || (req_wrp
->wr_dip
!= dip
)) {
1632 /* walk the queue */
1633 mutex_enter(&ph_data
->p_queue
.list_mutex
);
1634 next
= ph_data
->p_queue
.next
;
1635 while (next
!= NULL
) {
1636 mutex_enter(&next
->list_mutex
);
1637 req_wrp
= (usba_req_wrapper_t
*)
1639 found
= (req_wrp
->wr_dip
== dip
);
1641 mutex_exit(&next
->list_mutex
);
1645 tmpnext
= next
->next
;
1646 mutex_exit(&next
->list_mutex
);
1650 mutex_exit(&ph_data
->p_queue
.list_mutex
);
1656 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1657 "usb_pipe_sync_drain_reqs: "
1658 "cnt=%d active_req_wrp=0x%p",
1659 count
, (void *)ph_data
->p_active_cntrl_req_wrp
);
1661 mutex_exit(&ph_data
->p_mutex
);
1662 delay(drv_usectohz(10000));
1663 mutex_enter(&ph_data
->p_mutex
);
1666 mutex_enter(&ph_data
->p_ph_impl
->usba_ph_mutex
);
1667 for (i
= 0; (i
< timeout
) || (request
->arg
== 0); i
++) {
1668 ASSERT(ph_data
->p_req_count
>= 0);
1669 if (ph_data
->p_req_count
||
1670 (ph_data
->p_ph_impl
->usba_ph_ref_count
> 1)) {
1671 mutex_exit(&ph_data
->p_ph_impl
->usba_ph_mutex
);
1672 mutex_exit(&ph_data
->p_mutex
);
1673 delay(drv_usectohz(10000));
1674 mutex_enter(&ph_data
->p_mutex
);
1675 mutex_enter(&ph_data
->p_ph_impl
->usba_ph_mutex
);
1680 mutex_exit(&ph_data
->p_ph_impl
->usba_ph_mutex
);
1683 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1684 "usb_pipe_sync_drain_reqs: timeout=%d active_req_wrp=0x%p req=%d",
1685 i
, (void *)ph_data
->p_active_cntrl_req_wrp
, ph_data
->p_req_count
);
1687 mutex_exit(&ph_data
->p_mutex
);
1689 usba_release_ph_data(ph_impl
);
1691 return (i
>= timeout
? USB_FAILURE
: USB_SUCCESS
);
1696 * usba_persistent_pipe_open
1697 * Open all the pipes marked persistent for this device
1700 usba_persistent_pipe_open(usba_device_t
*usba_device
)
1702 usba_ph_impl_t
*ph_impl
;
1703 usb_pipe_handle_t pipe_handle
;
1705 int rval
= USB_SUCCESS
;
1707 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1708 "usba_persistent_pipe_open: usba_device=0x%p", (void *)usba_device
);
1710 if (usba_device
!= NULL
) {
1711 /* default pipe is the first one to be opened */
1712 mutex_enter(&usba_device
->usb_mutex
);
1713 for (i
= 0; (rval
== USB_SUCCESS
) &&
1714 (i
< USBA_N_ENDPOINTS
); i
++) {
1716 ph_impl
= &usba_device
->usb_ph_list
[i
];
1717 mutex_enter(&ph_impl
->usba_ph_mutex
);
1718 if (ph_impl
->usba_ph_flags
& USBA_PH_DATA_PERSISTENT
) {
1719 ph_impl
->usba_ph_flags
&=
1720 ~USBA_PH_DATA_PERSISTENT
;
1721 mutex_exit(&ph_impl
->usba_ph_mutex
);
1722 mutex_exit(&usba_device
->usb_mutex
);
1724 rval
= usb_pipe_open(ph_impl
->usba_ph_dip
,
1725 &ph_impl
->usba_ph_ep
,
1726 &ph_impl
->usba_ph_policy
,
1727 USB_FLAGS_SLEEP
| USBA_FLAGS_PRIVILEGED
,
1730 USB_DPRINTF_L3(DPRINT_MASK_USBAI
,
1732 "usba_persistent_pipe_open: "
1733 "ep_index=%d, rval=%d", i
, rval
);
1734 mutex_enter(&usba_device
->usb_mutex
);
1735 mutex_enter(&ph_impl
->usba_ph_mutex
);
1737 mutex_exit(&ph_impl
->usba_ph_mutex
);
1739 mutex_exit(&usba_device
->usb_mutex
);
1747 * usba_persistent_pipe_close
1748 * Close all pipes of this device and mark them persistent
1751 usba_persistent_pipe_close(usba_device_t
*usba_device
)
1753 usba_ph_impl_t
*ph_impl
;
1754 usb_pipe_handle_t pipe_handle
;
1757 USB_DPRINTF_L4(DPRINT_MASK_USBAI
, usbai_log_handle
,
1758 "usba_persistent_pipe_close: usba_device=0x%p",
1759 (void *)usba_device
);
1761 if (usba_device
!= NULL
) {
1762 /* default pipe is the last one to be closed */
1763 mutex_enter(&usba_device
->usb_mutex
);
1765 for (i
= (USBA_N_ENDPOINTS
- 1); i
>= 0; i
--) {
1766 ph_impl
= &usba_device
->usb_ph_list
[i
];
1767 if (ph_impl
->usba_ph_data
!= NULL
) {
1768 mutex_enter(&ph_impl
->usba_ph_mutex
);
1769 ph_impl
->usba_ph_flags
|=
1770 USBA_PH_DATA_PERSISTENT
;
1771 mutex_exit(&ph_impl
->usba_ph_mutex
);
1772 mutex_exit(&usba_device
->usb_mutex
);
1774 pipe_handle
= (usb_pipe_handle_t
)ph_impl
;
1776 usb_pipe_close(ph_impl
->usba_ph_dip
,
1778 USB_FLAGS_SLEEP
| USBA_FLAGS_PRIVILEGED
,
1780 mutex_enter(&usba_device
->usb_mutex
);
1781 ASSERT(ph_impl
->usba_ph_data
== NULL
);
1784 mutex_exit(&usba_device
->usb_mutex
);