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