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