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 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 * 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 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 * 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 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 * 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 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 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 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 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 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 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 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 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 553 usba_taskq_destroy(void *arg) 554 { 555 taskq_destroy((taskq_t *)arg); 556 } 557 558 559 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 }