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