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