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