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