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