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 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_inc_32_nv(&anon_instance); 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 uint16_t maxpktsize; 524 525 maxpktsize = usba_device->usb_dev_descr->bMaxPacketSize0; 526 if (usba_device->usb_is_wireless) { 527 /* 528 * according to wusb 1.0 spec 4.8.1, the host must 529 * assume a wMaxPacketSize of 512 for the default 530 * control pipe of a wusb device 531 */ 532 maxpktsize = 0x200; 533 } 534 USB_DPRINTF_L3(DPRINT_MASK_USBAI, usbai_log_handle, 535 "adjusting max packet size from %d to %d", 536 ph_data->p_ep.wMaxPacketSize, maxpktsize); 537 538 ph_data->p_ep.wMaxPacketSize = maxpktsize; 539 } 540 541 /* now update usba_ph_impl structure */ 542 mutex_enter(&ph_impl->usba_ph_mutex); 543 ph_impl->usba_ph_dip = dip; 544 ph_impl->usba_ph_ep = ph_data->p_ep; 545 ph_impl->usba_ph_policy = ph_data->p_policy = *pipe_policy; 546 mutex_exit(&ph_impl->usba_ph_mutex); 547 548 usba_init_list(&ph_data->p_queue, (usb_opaque_t)ph_data, iblock_cookie); 549 usba_init_list(&ph_data->p_cb_queue, (usb_opaque_t)ph_data, 550 iblock_cookie); 551 mutex_exit(&usba_device->usb_mutex); 552 mutex_exit(&ph_data->p_mutex); 553 554 return (USB_SUCCESS); 555 } 556 557 558 static void 559 usba_taskq_destroy(void *arg) 560 { 561 taskq_destroy((taskq_t *)arg); 562 } 563 564 565 static void 566 usba_destroy_pipe_handle(usba_pipe_handle_data_t *ph_data) 567 { 568 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl; 569 int timeout; 570 usba_device_t *usba_device; 571 572 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 573 "usba_destroy_pipe_handle: ph_data=0x%p", (void *)ph_data); 574 575 mutex_enter(&ph_data->p_mutex); 576 mutex_enter(&ph_impl->usba_ph_mutex); 577 578 /* check for all activity to drain */ 579 for (timeout = 0; timeout < usba_drain_timeout; timeout++) { 580 if ((ph_impl->usba_ph_ref_count <= 1) && 581 (ph_data->p_req_count == 0)) { 582 583 break; 584 } 585 mutex_exit(&ph_data->p_mutex); 586 mutex_exit(&ph_impl->usba_ph_mutex); 587 delay(drv_usectohz(1000)); 588 mutex_enter(&ph_data->p_mutex); 589 mutex_enter(&ph_impl->usba_ph_mutex); 590 } 591 592 /* 593 * set state to closed here so any other thread 594 * that is waiting for the CLOSED state will 595 * continue. Otherwise, taskq_destroy might deadlock 596 */ 597 ph_impl->usba_ph_data = NULL; 598 ph_impl->usba_ph_ref_count = 0; 599 ph_impl->usba_ph_state = USB_PIPE_STATE_CLOSED; 600 601 if (ph_data->p_taskq) { 602 mutex_exit(&ph_data->p_mutex); 603 mutex_exit(&ph_impl->usba_ph_mutex); 604 if (taskq_member(ph_data->p_taskq, curthread)) { 605 /* 606 * use system taskq to destroy ph's taskq to avoid 607 * deadlock 608 */ 609 (void) taskq_dispatch(system_taskq, 610 usba_taskq_destroy, ph_data->p_taskq, TQ_SLEEP); 611 } else { 612 taskq_destroy(ph_data->p_taskq); 613 } 614 } else { 615 mutex_exit(&ph_data->p_mutex); 616 mutex_exit(&ph_impl->usba_ph_mutex); 617 } 618 619 usba_device = ph_data->p_usba_device; 620 mutex_enter(&ph_data->p_mutex); 621 if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) { 622 int iface = usb_get_if_number(ph_data->p_dip); 623 if (iface < 0) { 624 /* we own the device, use the first entry */ 625 iface = 0; 626 } 627 mutex_enter(&usba_device->usb_mutex); 628 if (--usba_device->usb_shared_taskq_ref_count[iface] == 0) { 629 ph_data->p_spec_flag &= ~USBA_PH_FLAG_TQ_SHARE; 630 if (taskq_member(usba_device->usb_shared_taskq[iface], 631 curthread)) { 632 (void) taskq_dispatch( 633 system_taskq, 634 usba_taskq_destroy, 635 usba_device->usb_shared_taskq[iface], 636 TQ_SLEEP); 637 } else { 638 taskq_destroy( 639 usba_device->usb_shared_taskq[iface]); 640 } 641 } 642 mutex_exit(&usba_device->usb_mutex); 643 } 644 mutex_exit(&ph_data->p_mutex); 645 646 647 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 648 "usba_destroy_pipe_handle: destroying ph_data=0x%p", 649 (void *)ph_data); 650 651 usba_destroy_list(&ph_data->p_queue); 652 usba_destroy_list(&ph_data->p_cb_queue); 653 654 /* destroy mutexes */ 655 mutex_destroy(&ph_data->p_mutex); 656 657 kmem_free(ph_data, sizeof (usba_pipe_handle_data_t)); 658 } 659 660 661 /* 662 * usba_drain_cbs: 663 * Drain the request callbacks on the pipe handle 664 */ 665 int 666 usba_drain_cbs(usba_pipe_handle_data_t *ph_data, usb_cb_flags_t cb_flags, 667 usb_cr_t cr) 668 { 669 usba_req_wrapper_t *req_wrp; 670 int flush_requests = 1; 671 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl; 672 int timeout; 673 int rval = USB_SUCCESS; 674 675 ASSERT(mutex_owned(&ph_data->p_mutex)); 676 677 mutex_enter(&ph_impl->usba_ph_mutex); 678 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 679 "usba_drain_cbs: ph_data=0x%p ref=%d req=%d cb=0x%x cr=%d", 680 (void *)ph_data, ph_impl->usba_ph_ref_count, ph_data->p_req_count, 681 cb_flags, cr); 682 ASSERT(ph_data->p_req_count >= 0); 683 mutex_exit(&ph_impl->usba_ph_mutex); 684 685 if (ph_data->p_dip) { 686 if (USBA_IS_DEFAULT_PIPE(ph_data)) { 687 USB_DPRINTF_L4(DPRINT_MASK_USBAI, 688 usbai_log_handle, 689 "no flushing on default pipe!"); 690 691 flush_requests = 0; 692 } 693 } 694 695 if (flush_requests) { 696 /* flush all requests in the pipehandle queue */ 697 while ((req_wrp = (usba_req_wrapper_t *) 698 usba_rm_first_pvt_from_list(&ph_data->p_queue)) != NULL) { 699 mutex_exit(&ph_data->p_mutex); 700 usba_do_req_exc_cb(req_wrp, cr, cb_flags); 701 mutex_enter(&ph_data->p_mutex); 702 } 703 } 704 705 /* 706 * wait for any callbacks in progress but don't wait for 707 * for queued requests on the default pipe 708 */ 709 for (timeout = 0; (timeout < usba_drain_timeout) && 710 (ph_data->p_req_count > 711 usba_list_entry_count(&ph_data->p_queue)); 712 timeout++) { 713 mutex_exit(&ph_data->p_mutex); 714 delay(drv_usectohz(1000)); 715 mutex_enter(&ph_data->p_mutex); 716 } 717 718 mutex_enter(&ph_impl->usba_ph_mutex); 719 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 720 "usba_drain_cbs done: ph_data=0x%p ref=%d req=%d", 721 (void *)ph_data, ph_impl->usba_ph_ref_count, ph_data->p_req_count); 722 mutex_exit(&ph_impl->usba_ph_mutex); 723 724 if (timeout == usba_drain_timeout) { 725 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 726 "draining callbacks timed out!"); 727 728 rval = USB_FAILURE; 729 } 730 731 return (rval); 732 } 733 734 735 /* 736 * usb_pipe_open(): 737 * 738 * Before using any pipe including the default pipe, it should be opened 739 * using usb_pipe_open(). On a successful open, a pipe handle is returned 740 * for use in other usb_pipe_*() functions 741 * 742 * The default pipe can only be opened by the hub driver 743 * 744 * The bandwidth has been allocated and guaranteed on successful 745 * opening of an isoc/intr pipes. 746 * 747 * Only the default pipe can be shared. all other control pipes 748 * are excusively opened by default. 749 * A pipe policy and endpoint descriptor must always be provided 750 * except for default pipe 751 * 752 * Arguments: 753 * dip - devinfo ptr 754 * ep - endpoint descriptor pointer 755 * pipe_policy - pointer to pipe policy which provides hints on how 756 * the pipe will be used. 757 * flags - USB_FLAGS_SLEEP wait for resources 758 * to become available 759 * pipe_handle - a pipe handle pointer. On a successful open, 760 * a pipe_handle is returned in this pointer. 761 * 762 * Return values: 763 * USB_SUCCESS - open succeeded 764 * USB_FAILURE - unspecified open failure or pipe is already open 765 * USB_NO_RESOURCES - no resources were available to complete the open 766 * USB_NO_BANDWIDTH - no bandwidth available (isoc/intr pipes) 767 * USB_* - refer to usbai.h 768 */ 769 int 770 usb_pipe_open( 771 dev_info_t *dip, 772 usb_ep_descr_t *ep, 773 usb_pipe_policy_t *pipe_policy, 774 usb_flags_t usb_flags, 775 usb_pipe_handle_t *pipe_handle) 776 { 777 usba_device_t *usba_device; 778 int rval; 779 usba_pipe_handle_data_t *ph_data; 780 usba_ph_impl_t *ph_impl; 781 uchar_t ep_index; 782 int kmflag; 783 size_t size; 784 785 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 786 "usb_pipe_open:\n\t" 787 "dip=0x%p ep=0x%p pp=0x%p uf=0x%x ph=0x%p", 788 (void *)dip, (void *)ep, (void *)pipe_policy, usb_flags, 789 (void *)pipe_handle); 790 791 if ((dip == NULL) || (pipe_handle == NULL)) { 792 793 return (USB_INVALID_ARGS); 794 } 795 796 if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) { 797 798 return (USB_INVALID_CONTEXT); 799 } 800 usba_device = usba_get_usba_device(dip); 801 802 if ((ep != NULL) && (pipe_policy == NULL)) { 803 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 804 "usb_pipe_open: null pipe policy"); 805 806 return (USB_INVALID_ARGS); 807 } 808 809 /* is the device still connected? */ 810 if ((ep != NULL) & DEVI_IS_DEVICE_REMOVED(dip)) { 811 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 812 "usb_pipe_open: device has been removed"); 813 814 return (USB_FAILURE); 815 } 816 817 818 /* 819 * if a null endpoint pointer was passed, use the default 820 * endpoint descriptor 821 */ 822 if (ep == NULL) { 823 if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) { 824 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 825 "usb_pipe_open: not allowed to open def pipe"); 826 827 return (USB_INVALID_PERM); 828 } 829 830 ep = &usba_default_ep_descr; 831 pipe_policy = &usba_default_ep_pipe_policy; 832 } 833 834 if (usb_flags & USB_FLAGS_SERIALIZED_CB) { 835 if (((ep->bmAttributes & USB_EP_ATTR_MASK) == 836 USB_EP_ATTR_CONTROL) || 837 ((ep->bmAttributes & USB_EP_ATTR_MASK) == 838 USB_EP_ATTR_ISOCH)) { 839 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 840 "usb_pipe_open: shared taskq not allowed with " 841 "ctrl or isoch pipe"); 842 843 return (USB_INVALID_ARGS); 844 } 845 } 846 847 kmflag = (usb_flags & USB_FLAGS_SLEEP) ? KM_SLEEP : KM_NOSLEEP; 848 size = sizeof (usba_pipe_handle_data_t); 849 850 if ((ph_data = kmem_zalloc(size, kmflag)) == NULL) { 851 852 return (USB_NO_RESOURCES); 853 } 854 855 /* check if pipe is already open and if so fail */ 856 ep_index = usb_get_ep_index(ep->bEndpointAddress); 857 ph_impl = &usba_device->usb_ph_list[ep_index]; 858 859 mutex_enter(&usba_device->usb_mutex); 860 mutex_enter(&ph_impl->usba_ph_mutex); 861 862 if (ph_impl->usba_ph_data) { 863 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 864 "usb_pipe_open: pipe to ep %d already open", ep_index); 865 mutex_exit(&ph_impl->usba_ph_mutex); 866 mutex_exit(&usba_device->usb_mutex); 867 kmem_free(ph_data, size); 868 869 return (USB_BUSY); 870 } 871 872 ph_impl->usba_ph_data = ph_data; 873 874 mutex_exit(&ph_impl->usba_ph_mutex); 875 mutex_exit(&usba_device->usb_mutex); 876 877 if (usb_flags & USB_FLAGS_SERIALIZED_CB) { 878 mutex_enter(&ph_data->p_mutex); 879 ph_data->p_spec_flag |= USBA_PH_FLAG_TQ_SHARE; 880 mutex_exit(&ph_data->p_mutex); 881 } 882 883 /* 884 * allocate and initialize the pipe handle 885 */ 886 if ((rval = usba_init_pipe_handle(dip, usba_device, 887 ep, pipe_policy, ph_impl)) != USB_SUCCESS) { 888 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 889 "usb_pipe_open: pipe init failed (%d)", rval); 890 891 return (rval); 892 } 893 ph_data = ph_impl->usba_ph_data; 894 895 /* 896 * ask the hcd to open the pipe 897 */ 898 if ((rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_open(ph_data, 899 usb_flags)) != USB_SUCCESS) { 900 usba_destroy_pipe_handle(ph_data); 901 902 *pipe_handle = NULL; 903 } else { 904 *pipe_handle = (usb_pipe_handle_t)ph_impl; 905 906 /* set the pipe state after a successful hcd open */ 907 mutex_enter(&ph_data->p_mutex); 908 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 909 mutex_exit(&ph_data->p_mutex); 910 } 911 912 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 913 "usb_pipe_open: ph_impl=0x%p (0x%p)", 914 (void *)ph_impl, (void *)ph_data); 915 916 return (rval); 917 } 918 919 920 /* 921 * usb_pipe_close/sync_close: 922 * 923 * Close a pipe and release all resources and free the pipe_handle. 924 * Automatic polling, if active, will be terminated 925 * 926 * Arguments: 927 * dip - devinfo ptr 928 * pipehandle - pointer to pipehandle. The pipehandle will be 929 * zeroed on successful completion 930 * flags - USB_FLAGS_SLEEP: 931 * wait for resources, pipe 932 * to become free, all callbacks completed 933 * callback - If USB_FLAGS_SLEEP has not been specified, a 934 * callback will be performed. 935 * callback_arg - the first argument of the callback. Note that 936 * the pipehandle will be zeroed and not passed 937 * 938 * Notes: 939 * Pipe close will always succeed regardless whether USB_FLAGS_SLEEP has been 940 * specified or not. 941 * An async close will always succeed if the hint in the pipe policy 942 * has been correct about the max number of async taskq requests required. 943 * If there are really no resources, the pipe handle will be linked into 944 * a garbage pipe list and periodically checked by USBA until it can be 945 * closed. This may cause a hang in the detach of the driver. 946 * USBA will prevent the client from submitting more requests to a pipe 947 * that is being closed 948 * Subsequent usb_pipe_close() requests on the same pipe to USBA will 949 * wait for the previous close(s) to finish. 950 * 951 * Note that once we start closing a pipe, we cannot go back anymore 952 * to a normal pipe state 953 */ 954 void 955 usb_pipe_close(dev_info_t *dip, 956 usb_pipe_handle_t pipe_handle, 957 usb_flags_t usb_flags, 958 void (*callback)( 959 usb_pipe_handle_t pipe_handle, 960 usb_opaque_t arg, 961 int rval, 962 usb_cb_flags_t flags), 963 usb_opaque_t callback_arg) 964 { 965 usba_pipe_handle_data_t *ph_data; 966 usba_ph_impl_t *ph_impl = (usba_ph_impl_t *)pipe_handle; 967 usb_cb_flags_t callback_flags; 968 969 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 970 "usb_pipe_close: ph=0x%p", (void *)pipe_handle); 971 972 callback_flags = usba_check_intr_context(USB_CB_NO_INFO); 973 if ((dip == NULL) || (pipe_handle == NULL)) { 974 if (callback) { 975 callback(pipe_handle, callback_arg, 976 USB_INVALID_ARGS, callback_flags); 977 } else { 978 USB_DPRINTF_L2(DPRINT_MASK_USBAI, 979 usbai_log_handle, 980 "usb_pipe_close: invalid arguments"); 981 } 982 983 return; 984 } 985 986 if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) { 987 /* 988 * It is the client driver doing the pipe close, 989 * the pipe is no longer persistent then. 990 */ 991 mutex_enter(&ph_impl->usba_ph_mutex); 992 ph_impl->usba_ph_flags &= ~USBA_PH_DATA_PERSISTENT; 993 mutex_exit(&ph_impl->usba_ph_mutex); 994 } 995 996 if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) { 997 if (callback) { 998 callback(pipe_handle, callback_arg, 999 USB_INVALID_CONTEXT, callback_flags); 1000 } else { 1001 USB_DPRINTF_L2(DPRINT_MASK_USBAI, 1002 usbai_log_handle, 1003 "usb_pipe_close: invalid context"); 1004 } 1005 1006 return; 1007 } 1008 1009 if ((ph_data = usba_hold_ph_data(pipe_handle)) == NULL) { 1010 1011 /* hold pipehandle anyways since we will decrement later */ 1012 mutex_enter(&ph_impl->usba_ph_mutex); 1013 ph_impl->usba_ph_ref_count++; 1014 mutex_exit(&ph_impl->usba_ph_mutex); 1015 1016 (void) usba_pipe_setup_func_call(dip, usba_pipe_sync_close, 1017 ph_impl, NULL, usb_flags, callback, callback_arg); 1018 1019 return; 1020 } 1021 1022 mutex_enter(&ph_data->p_mutex); 1023 1024 if (USBA_IS_DEFAULT_PIPE(ph_data) && 1025 ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0)) { 1026 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1027 "usb_pipe_close: not allowed to close def pipe"); 1028 mutex_exit(&ph_data->p_mutex); 1029 1030 usba_release_ph_data(ph_impl); 1031 1032 if (callback) { 1033 callback(pipe_handle, callback_arg, 1034 USB_INVALID_PIPE, callback_flags); 1035 } else { 1036 USB_DPRINTF_L2(DPRINT_MASK_USBAI, 1037 usbai_log_handle, 1038 "usb_pipe_close: invalid pipe"); 1039 } 1040 1041 return; 1042 } 1043 1044 mutex_exit(&ph_data->p_mutex); 1045 1046 (void) usba_pipe_setup_func_call(dip, usba_pipe_sync_close, 1047 ph_impl, NULL, usb_flags, callback, callback_arg); 1048 } 1049 1050 1051 /*ARGSUSED*/ 1052 static int 1053 usba_pipe_sync_close(dev_info_t *dip, usba_ph_impl_t *ph_impl, 1054 usba_pipe_async_req_t *request, usb_flags_t usb_flags) 1055 { 1056 usba_device_t *usba_device; 1057 usba_pipe_handle_data_t *ph_data = usba_get_ph_data( 1058 (usb_pipe_handle_t)ph_impl); 1059 int attribute; 1060 uchar_t dir; 1061 int timeout; 1062 1063 if (ph_impl == NULL) { 1064 1065 return (USB_SUCCESS); 1066 } 1067 1068 mutex_enter(&ph_impl->usba_ph_mutex); 1069 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1070 "usba_pipe_sync_close: dip=0x%p ph_data=0x%p state=%d ref=%d", 1071 (void *)dip, (void *)ph_data, ph_impl->usba_ph_state, 1072 ph_impl->usba_ph_ref_count); 1073 1074 /* 1075 * if another thread opens the pipe again, this loop could 1076 * be truly forever 1077 */ 1078 if ((ph_data == NULL) || 1079 (ph_impl->usba_ph_state == USB_PIPE_STATE_CLOSING) || 1080 (ph_impl->usba_ph_state == USB_PIPE_STATE_CLOSED)) { 1081 /* wait forever till really closed */ 1082 mutex_exit(&ph_impl->usba_ph_mutex); 1083 usba_release_ph_data(ph_impl); 1084 1085 while (usba_get_ph_data((usb_pipe_handle_t)ph_impl)) { 1086 delay(1); 1087 } 1088 1089 return (USB_SUCCESS); 1090 } 1091 ph_impl->usba_ph_state = USB_PIPE_STATE_CLOSING; 1092 mutex_exit(&ph_impl->usba_ph_mutex); 1093 1094 mutex_enter(&ph_data->p_mutex); 1095 mutex_enter(&ph_impl->usba_ph_mutex); 1096 1097 attribute = ph_data->p_ep.bmAttributes & USB_EP_ATTR_MASK; 1098 dir = ph_data->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 1099 1100 usba_device = ph_data->p_usba_device; 1101 1102 /* 1103 * For control and bulk, we will drain till ref_count <= 1 and 1104 * req_count == 0 but for isoc and intr IN, we can only wait 1105 * till the ref_count === 1 as the req_count will never go to 0 1106 */ 1107 for (timeout = 0; timeout < usba_drain_timeout; timeout++) { 1108 switch (attribute) { 1109 case USB_EP_ATTR_CONTROL: 1110 case USB_EP_ATTR_BULK: 1111 if ((ph_data->p_req_count == 0) && 1112 (ph_impl->usba_ph_ref_count <= 1)) { 1113 goto done; 1114 } 1115 break; 1116 case USB_EP_ATTR_INTR: 1117 case USB_EP_ATTR_ISOCH: 1118 if (dir == USB_EP_DIR_IN) { 1119 if (ph_impl->usba_ph_ref_count <= 1) { 1120 goto done; 1121 } 1122 } else if ((ph_data->p_req_count == 0) && 1123 (ph_impl->usba_ph_ref_count <= 1)) { 1124 goto done; 1125 } 1126 break; 1127 } 1128 mutex_exit(&ph_impl->usba_ph_mutex); 1129 mutex_exit(&ph_data->p_mutex); 1130 delay(drv_usectohz(1000)); 1131 mutex_enter(&ph_data->p_mutex); 1132 mutex_enter(&ph_impl->usba_ph_mutex); 1133 } 1134 done: 1135 1136 mutex_exit(&ph_impl->usba_ph_mutex); 1137 mutex_exit(&ph_data->p_mutex); 1138 1139 if (timeout >= usba_drain_timeout) { 1140 int draining_succeeded; 1141 1142 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1143 "timeout on draining requests, resetting pipe 0x%p", 1144 (void *)ph_impl); 1145 1146 (void) usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data, 1147 USB_FLAGS_SLEEP); 1148 1149 mutex_enter(&ph_data->p_mutex); 1150 draining_succeeded = usba_drain_cbs(ph_data, USB_CB_RESET_PIPE, 1151 USB_CR_PIPE_RESET); 1152 /* this MUST have succeeded */ 1153 ASSERT(draining_succeeded == USB_SUCCESS); 1154 mutex_exit(&ph_data->p_mutex); 1155 1156 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1157 "draining requests done"); 1158 } 1159 1160 if (usba_device->usb_hcdi_ops->usba_hcdi_pipe_close(ph_data, 1161 usb_flags) != USB_SUCCESS) { 1162 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1163 "usba_pipe_sync_close: hcd close failed"); 1164 /* carry on regardless! */ 1165 } 1166 1167 usba_destroy_pipe_handle(ph_data); 1168 1169 return (USB_SUCCESS); 1170 } 1171 1172 1173 /* 1174 * usb_pipe_set_private: 1175 * set private client date in the pipe handle 1176 */ 1177 int 1178 usb_pipe_set_private(usb_pipe_handle_t pipe_handle, usb_opaque_t data) 1179 { 1180 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1181 1182 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1183 "usb_pipe_set_private: "); 1184 1185 if (ph_data == NULL) { 1186 1187 return (USB_INVALID_PIPE); 1188 } 1189 if (USBA_IS_DEFAULT_PIPE(ph_data)) { 1190 usba_release_ph_data(ph_data->p_ph_impl); 1191 1192 return (USB_INVALID_PERM); 1193 } 1194 1195 mutex_enter(&ph_data->p_mutex); 1196 ph_data->p_client_private = data; 1197 mutex_exit(&ph_data->p_mutex); 1198 1199 usba_release_ph_data(ph_data->p_ph_impl); 1200 1201 return (USB_SUCCESS); 1202 } 1203 1204 1205 /* 1206 * usb_pipe_get_private: 1207 * get private client date from the pipe handle 1208 */ 1209 usb_opaque_t 1210 usb_pipe_get_private(usb_pipe_handle_t pipe_handle) 1211 { 1212 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1213 usb_opaque_t data; 1214 1215 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1216 "usb_pipe_get_private:"); 1217 1218 if (ph_data == NULL) { 1219 1220 return (NULL); 1221 } 1222 1223 mutex_enter(&ph_data->p_mutex); 1224 data = ph_data->p_client_private; 1225 mutex_exit(&ph_data->p_mutex); 1226 1227 usba_release_ph_data(ph_data->p_ph_impl); 1228 1229 return (data); 1230 } 1231 1232 1233 /* 1234 * usb_pipe_reset 1235 * Arguments: 1236 * dip - devinfo pointer 1237 * pipe_handle - opaque pipe handle 1238 * Returns: 1239 * USB_SUCCESS - pipe successfully reset or request queued 1240 * USB_FAILURE - undetermined failure 1241 * USB_INVALID_PIPE - pipe is invalid or already closed 1242 */ 1243 void 1244 usb_pipe_reset(dev_info_t *dip, 1245 usb_pipe_handle_t pipe_handle, 1246 usb_flags_t usb_flags, 1247 void (*callback)( 1248 usb_pipe_handle_t ph, 1249 usb_opaque_t arg, 1250 int rval, 1251 usb_cb_flags_t flags), 1252 usb_opaque_t callback_arg) 1253 { 1254 usba_ph_impl_t *ph_impl = (usba_ph_impl_t *)pipe_handle; 1255 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1256 usb_cb_flags_t callback_flags; 1257 1258 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1259 "usb_pipe_reset: dip=0x%p ph=0x%p uf=0x%x", 1260 (void *)dip, (void *)pipe_handle, usb_flags); 1261 1262 callback_flags = usba_check_intr_context(USB_CB_NO_INFO); 1263 1264 if ((dip == NULL) || (ph_data == NULL)) { 1265 if (callback) { 1266 callback(pipe_handle, callback_arg, 1267 USB_INVALID_ARGS, callback_flags); 1268 } else { 1269 USB_DPRINTF_L2(DPRINT_MASK_USBAI, 1270 usbai_log_handle, 1271 "usb_pipe_reset: invalid arguments"); 1272 } 1273 1274 usba_release_ph_data(ph_impl); 1275 1276 return; 1277 } 1278 if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) { 1279 if (callback) { 1280 callback(pipe_handle, callback_arg, 1281 USB_INVALID_CONTEXT, callback_flags); 1282 } else { 1283 USB_DPRINTF_L2(DPRINT_MASK_USBAI, 1284 usbai_log_handle, 1285 "usb_pipe_reset: invalid context"); 1286 } 1287 1288 usba_release_ph_data(ph_impl); 1289 1290 return; 1291 } 1292 1293 mutex_enter(&ph_data->p_mutex); 1294 1295 /* is this the default pipe? */ 1296 if (USBA_IS_DEFAULT_PIPE(ph_data)) { 1297 if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) { 1298 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle, 1299 "usb_pipe_reset: not allowed to reset def pipe"); 1300 mutex_exit(&ph_data->p_mutex); 1301 1302 if (callback) { 1303 callback(pipe_handle, callback_arg, 1304 USB_INVALID_PIPE, callback_flags); 1305 } else { 1306 USB_DPRINTF_L2(DPRINT_MASK_USBAI, 1307 usbai_log_handle, 1308 "usb_pipe_reset: invalid pipe"); 1309 } 1310 usba_release_ph_data(ph_impl); 1311 1312 return; 1313 } 1314 } 1315 mutex_exit(&ph_data->p_mutex); 1316 1317 (void) usba_pipe_setup_func_call(dip, 1318 usba_pipe_sync_reset, ph_impl, NULL, usb_flags, callback, 1319 callback_arg); 1320 } 1321 1322 1323 /*ARGSUSED*/ 1324 int 1325 usba_pipe_sync_reset(dev_info_t *dip, 1326 usba_ph_impl_t *ph_impl, 1327 usba_pipe_async_req_t *request, 1328 usb_flags_t usb_flags) 1329 { 1330 int rval, draining_succeeded; 1331 usba_pipe_handle_data_t *ph_data = usba_get_ph_data((usb_pipe_handle_t) 1332 ph_impl); 1333 usba_device_t *usba_device; 1334 1335 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1336 "usba_pipe_sync_reset: dip=0x%p ph_data=0x%p uf=0x%x", 1337 (void *)dip, (void *)ph_data, usb_flags); 1338 1339 mutex_enter(&ph_data->p_mutex); 1340 usba_device = ph_data->p_usba_device; 1341 mutex_exit(&ph_data->p_mutex); 1342 1343 rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data, 1344 usb_flags); 1345 mutex_enter(&ph_data->p_mutex); 1346 1347 /* 1348 * The host controller has stopped polling of the endpoint. 1349 */ 1350 draining_succeeded = usba_drain_cbs(ph_data, USB_CB_RESET_PIPE, 1351 USB_CR_PIPE_RESET); 1352 1353 /* this MUST have succeeded */ 1354 ASSERT(draining_succeeded == USB_SUCCESS); 1355 1356 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 1357 mutex_exit(&ph_data->p_mutex); 1358 1359 /* 1360 * if there are requests still queued on the default pipe, 1361 * start them now 1362 */ 1363 usba_start_next_req(ph_data); 1364 1365 usba_release_ph_data(ph_impl); 1366 1367 return (rval); 1368 } 1369 1370 1371 /* 1372 * usba_pipe_clear: 1373 * call hcd to clear pipe but don't wait for draining 1374 */ 1375 void 1376 usba_pipe_clear(usb_pipe_handle_t pipe_handle) 1377 { 1378 usba_pipe_handle_data_t *ph_data = usba_get_ph_data(pipe_handle); 1379 usba_device_t *usba_device; 1380 usba_req_wrapper_t *req_wrp; 1381 int flush_requests = 1; 1382 1383 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1384 "usba_pipe_clear: ph_data=0x%p", (void *)ph_data); 1385 1386 if (ph_data == NULL) { 1387 1388 return; 1389 } 1390 1391 mutex_enter(&ph_data->p_mutex); 1392 if (USBA_PIPE_CLOSING(usba_get_ph_state(ph_data))) { 1393 mutex_exit(&ph_data->p_mutex); 1394 1395 return; 1396 } 1397 usba_device = ph_data->p_usba_device; 1398 mutex_exit(&ph_data->p_mutex); 1399 1400 (void) usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data, 1401 USB_FLAGS_SLEEP); 1402 1403 mutex_enter(&ph_data->p_mutex); 1404 if (ph_data->p_dip) { 1405 if (USBA_IS_DEFAULT_PIPE(ph_data)) { 1406 USB_DPRINTF_L4(DPRINT_MASK_USBAI, 1407 usbai_log_handle, 1408 "no flushing on default pipe!"); 1409 1410 flush_requests = 0; 1411 } 1412 } 1413 1414 if (flush_requests) { 1415 /* flush all requests in the pipehandle queue */ 1416 while ((req_wrp = (usba_req_wrapper_t *) 1417 usba_rm_first_pvt_from_list(&ph_data->p_queue)) != NULL) { 1418 mutex_exit(&ph_data->p_mutex); 1419 usba_do_req_exc_cb(req_wrp, USB_CR_FLUSHED, 1420 USB_CB_RESET_PIPE); 1421 mutex_enter(&ph_data->p_mutex); 1422 } 1423 } 1424 1425 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE); 1426 mutex_exit(&ph_data->p_mutex); 1427 } 1428 1429 1430 /* 1431 * 1432 * usb_pipe_drain_reqs 1433 * this function blocks until there are no more requests 1434 * owned by this dip on the pipe 1435 * 1436 * Arguments: 1437 * dip - devinfo pointer 1438 * pipe_handle - opaque pipe handle 1439 * timeout - timeout in seconds 1440 * flags - USB_FLAGS_SLEEP: 1441 * wait for completion. 1442 * cb - if USB_FLAGS_SLEEP has not been specified 1443 * this callback function will be called on 1444 * completion. This callback may be NULL 1445 * and no notification of completion will then 1446 * be provided. 1447 * cb_arg - 2nd argument to callback function. 1448 * 1449 * callback and callback_arg should be NULL if USB_FLAGS_SLEEP has 1450 * been specified 1451 * 1452 * Returns: 1453 * USB_SUCCESS - pipe successfully reset or request queued 1454 * USB_FAILURE - timeout 1455 * USB_* - refer to usbai.h 1456 */ 1457 int 1458 usb_pipe_drain_reqs(dev_info_t *dip, 1459 usb_pipe_handle_t pipe_handle, 1460 uint_t time, 1461 usb_flags_t usb_flags, 1462 void (*cb)( 1463 usb_pipe_handle_t ph, 1464 usb_opaque_t arg, /* cb arg */ 1465 int rval, 1466 usb_cb_flags_t flags), 1467 usb_opaque_t cb_arg) 1468 { 1469 usba_ph_impl_t *ph_impl = (usba_ph_impl_t *)pipe_handle; 1470 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle); 1471 1472 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1473 "usb_pipe_drain_reqs: dip=0x%p ph_data=0x%p tm=%d uf=0x%x", 1474 (void *)dip, (void *)ph_data, time, usb_flags); 1475 1476 if (ph_data == NULL) { 1477 1478 return (USB_INVALID_PIPE); 1479 } 1480 if (dip == NULL) { 1481 usba_release_ph_data(ph_impl); 1482 1483 return (USB_INVALID_ARGS); 1484 } 1485 1486 if ((usb_flags & USB_FLAGS_SLEEP) && servicing_interrupt()) { 1487 usba_release_ph_data(ph_impl); 1488 1489 return (USB_INVALID_CONTEXT); 1490 } 1491 1492 (void) usba_pipe_setup_func_call(dip, usba_pipe_sync_drain_reqs, 1493 ph_impl, (usb_opaque_t)((uintptr_t)time), usb_flags, cb, cb_arg); 1494 1495 return (USB_SUCCESS); 1496 } 1497 1498 1499 /* 1500 * usba_pipe_sync_drain_reqs 1501 * this function blocks until there are no more requests 1502 * owned by this dip on the pipe 1503 * 1504 * Arguments: 1505 * dip - devinfo pointer 1506 * ph_impl - pipe impl handle 1507 * timeout - timeout in seconds 1508 * Returns: 1509 * USB_SUCCESS - pipe successfully reset or request queued 1510 * USB_FAILURE - timeout 1511 * USB_* - see usbai.h 1512 */ 1513 /*ARGSUSED*/ 1514 int 1515 usba_pipe_sync_drain_reqs(dev_info_t *dip, 1516 usba_ph_impl_t *ph_impl, 1517 usba_pipe_async_req_t *request, 1518 usb_flags_t usb_flags) 1519 { 1520 usba_pipe_handle_data_t *ph_data = usba_get_ph_data((usb_pipe_handle_t) 1521 ph_impl); 1522 int i; 1523 int timeout = 100 * (int)((uintptr_t)(request->arg)); 1524 /* delay will be 10 ms */ 1525 1526 mutex_enter(&ph_data->p_mutex); 1527 1528 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1529 "usba_pipe_sync_drain_reqs: " 1530 "dip=0x%p ph_data=0x%p timeout=%d ref=%d req=%d", 1531 (void *)dip, (void *)ph_data, timeout, 1532 usba_get_ph_ref_count(ph_data), 1533 ph_data->p_req_count); 1534 1535 ASSERT(ph_data->p_req_count >= 0); 1536 1537 /* 1538 * for default pipe, we need to check the active request 1539 * and the queue 1540 * Note that a pipe reset on the default pipe doesn't flush 1541 * the queue 1542 * for all other pipes we just check ref and req count since 1543 * these pipes are unshared 1544 */ 1545 if (USBA_IS_DEFAULT_PIPE(ph_data)) { 1546 for (i = 0; (i < timeout) || (request->arg == 0); i++) { 1547 usba_list_entry_t *next, *tmpnext; 1548 usba_req_wrapper_t *req_wrp = (usba_req_wrapper_t *) 1549 ph_data->p_active_cntrl_req_wrp; 1550 int found = 0; 1551 int count = 0; 1552 1553 /* active_req_wrp is only for control pipes */ 1554 if ((req_wrp == NULL) || (req_wrp->wr_dip != dip)) { 1555 /* walk the queue */ 1556 mutex_enter(&ph_data->p_queue.list_mutex); 1557 next = ph_data->p_queue.next; 1558 while (next != NULL) { 1559 mutex_enter(&next->list_mutex); 1560 req_wrp = (usba_req_wrapper_t *) 1561 next->private; 1562 found = (req_wrp->wr_dip == dip); 1563 if (found) { 1564 mutex_exit(&next->list_mutex); 1565 1566 break; 1567 } 1568 tmpnext = next->next; 1569 mutex_exit(&next->list_mutex); 1570 next = tmpnext; 1571 count++; 1572 } 1573 mutex_exit(&ph_data->p_queue.list_mutex); 1574 if (found == 0) { 1575 break; 1576 } 1577 } 1578 1579 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1580 "usb_pipe_sync_drain_reqs: " 1581 "cnt=%d active_req_wrp=0x%p", 1582 count, (void *)ph_data->p_active_cntrl_req_wrp); 1583 1584 mutex_exit(&ph_data->p_mutex); 1585 delay(drv_usectohz(10000)); 1586 mutex_enter(&ph_data->p_mutex); 1587 } 1588 } else { 1589 mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex); 1590 for (i = 0; (i < timeout) || (request->arg == 0); i++) { 1591 ASSERT(ph_data->p_req_count >= 0); 1592 if (ph_data->p_req_count || 1593 (ph_data->p_ph_impl->usba_ph_ref_count > 1)) { 1594 mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex); 1595 mutex_exit(&ph_data->p_mutex); 1596 delay(drv_usectohz(10000)); 1597 mutex_enter(&ph_data->p_mutex); 1598 mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex); 1599 } else { 1600 break; 1601 } 1602 } 1603 mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex); 1604 } 1605 1606 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1607 "usb_pipe_sync_drain_reqs: timeout=%d active_req_wrp=0x%p req=%d", 1608 i, (void *)ph_data->p_active_cntrl_req_wrp, ph_data->p_req_count); 1609 1610 mutex_exit(&ph_data->p_mutex); 1611 1612 usba_release_ph_data(ph_impl); 1613 1614 return (i >= timeout ? USB_FAILURE : USB_SUCCESS); 1615 } 1616 1617 1618 /* 1619 * usba_persistent_pipe_open 1620 * Open all the pipes marked persistent for this device 1621 */ 1622 int 1623 usba_persistent_pipe_open(usba_device_t *usba_device) 1624 { 1625 usba_ph_impl_t *ph_impl; 1626 usb_pipe_handle_t pipe_handle; 1627 int i; 1628 int rval = USB_SUCCESS; 1629 1630 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1631 "usba_persistent_pipe_open: usba_device=0x%p", (void *)usba_device); 1632 1633 if (usba_device != NULL) { 1634 /* default pipe is the first one to be opened */ 1635 mutex_enter(&usba_device->usb_mutex); 1636 for (i = 0; (rval == USB_SUCCESS) && 1637 (i < USBA_N_ENDPOINTS); i++) { 1638 1639 ph_impl = &usba_device->usb_ph_list[i]; 1640 mutex_enter(&ph_impl->usba_ph_mutex); 1641 if (ph_impl->usba_ph_flags & USBA_PH_DATA_PERSISTENT) { 1642 ph_impl->usba_ph_flags &= 1643 ~USBA_PH_DATA_PERSISTENT; 1644 mutex_exit(&ph_impl->usba_ph_mutex); 1645 mutex_exit(&usba_device->usb_mutex); 1646 1647 rval = usb_pipe_open(ph_impl->usba_ph_dip, 1648 &ph_impl->usba_ph_ep, 1649 &ph_impl->usba_ph_policy, 1650 USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED, 1651 &pipe_handle); 1652 1653 USB_DPRINTF_L3(DPRINT_MASK_USBAI, 1654 usbai_log_handle, 1655 "usba_persistent_pipe_open: " 1656 "ep_index=%d, rval=%d", i, rval); 1657 mutex_enter(&usba_device->usb_mutex); 1658 mutex_enter(&ph_impl->usba_ph_mutex); 1659 } 1660 mutex_exit(&ph_impl->usba_ph_mutex); 1661 } 1662 mutex_exit(&usba_device->usb_mutex); 1663 } 1664 1665 return (rval); 1666 } 1667 1668 1669 /* 1670 * usba_persistent_pipe_close 1671 * Close all pipes of this device and mark them persistent 1672 */ 1673 void 1674 usba_persistent_pipe_close(usba_device_t *usba_device) 1675 { 1676 usba_ph_impl_t *ph_impl; 1677 usb_pipe_handle_t pipe_handle; 1678 int i; 1679 1680 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle, 1681 "usba_persistent_pipe_close: usba_device=0x%p", 1682 (void *)usba_device); 1683 1684 if (usba_device != NULL) { 1685 /* default pipe is the last one to be closed */ 1686 mutex_enter(&usba_device->usb_mutex); 1687 1688 for (i = (USBA_N_ENDPOINTS - 1); i >= 0; i--) { 1689 ph_impl = &usba_device->usb_ph_list[i]; 1690 if (ph_impl->usba_ph_data != NULL) { 1691 mutex_enter(&ph_impl->usba_ph_mutex); 1692 ph_impl->usba_ph_flags |= 1693 USBA_PH_DATA_PERSISTENT; 1694 mutex_exit(&ph_impl->usba_ph_mutex); 1695 mutex_exit(&usba_device->usb_mutex); 1696 1697 pipe_handle = (usb_pipe_handle_t)ph_impl; 1698 1699 usb_pipe_close(ph_impl->usba_ph_dip, 1700 pipe_handle, 1701 USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED, 1702 NULL, NULL); 1703 mutex_enter(&usba_device->usb_mutex); 1704 ASSERT(ph_impl->usba_ph_data == NULL); 1705 } 1706 } 1707 mutex_exit(&usba_device->usb_mutex); 1708 } 1709 }