1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright 2016 Joyent, Inc. 26 */ 27 28 /* 29 * USBA: Solaris USB Architecture support 30 * 31 * hcdi.c contains the code for client driver callbacks. A host controller 32 * driver registers/unregisters with usba through usba_hcdi_register/unregister. 33 * 34 * When the transfer has finished, the host controller driver will call into 35 * usba with the result. The call is usba_hcdi_cb(). 36 * 37 * The callback queue is maintained in FIFO order. usba_hcdi_cb 38 * adds to the queue, and hcdi_cb_thread takes the callbacks off the queue 39 * and executes them. 40 */ 41 #define USBA_FRAMEWORK 42 #include <sys/usb/usba/usba_impl.h> 43 #include <sys/usb/usba/hcdi_impl.h> 44 #include <sys/kstat.h> 45 #include <sys/ddi_impldefs.h> 46 47 /* function prototypes, XXXX use hcdi_ prefix? */ 48 static void usba_hcdi_create_stats(usba_hcdi_t *, int); 49 static void usba_hcdi_update_error_stats(usba_hcdi_t *, usb_cr_t); 50 static void usba_hcdi_destroy_stats(usba_hcdi_t *); 51 52 /* internal functions */ 53 static uint_t hcdi_soft_intr(caddr_t arg1, caddr_t arg2); 54 55 static void hcdi_cb_thread(void *); 56 static void hcdi_shared_cb_thread(void *); 57 static void hcdi_do_cb(usba_pipe_handle_data_t *, usba_req_wrapper_t *, 58 usba_hcdi_t *); 59 static void hcdi_autoclearing(usba_req_wrapper_t *); 60 61 /* private function from USBAI */ 62 void usba_pipe_clear(usb_pipe_handle_t); 63 64 /* for debug messages */ 65 uint_t hcdi_errmask = (uint_t)DPRINT_MASK_ALL; 66 uint_t hcdi_errlevel = USB_LOG_L4; 67 uint_t hcdi_instance_debug = (uint_t)-1; 68 69 void 70 usba_hcdi_initialization() 71 { 72 } 73 74 75 void 76 usba_hcdi_destroy() 77 { 78 } 79 80 81 /* 82 * store hcdi structure in the dip 83 */ 84 void 85 usba_hcdi_set_hcdi(dev_info_t *dip, usba_hcdi_t *hcdi) 86 { 87 ddi_set_driver_private(dip, hcdi); 88 } 89 90 91 /* 92 * retrieve hcdi structure from the dip 93 */ 94 usba_hcdi_t * 95 usba_hcdi_get_hcdi(dev_info_t *dip) 96 { 97 return (ddi_get_driver_private(dip)); 98 } 99 100 /* 101 * Called by an HCD to attach an instance of the driver 102 * make this instance known to USBA 103 * the HCD should initialize usba_hcdi structure prior 104 * to calling this interface 105 */ 106 int 107 usba_hcdi_register(usba_hcdi_register_args_t *args, uint_t flags) 108 { 109 char *datap; 110 uint_t soft_prip; 111 usba_hcdi_t *hcdi = kmem_zalloc(sizeof (usba_hcdi_t), KM_SLEEP); 112 113 if (args->usba_hcdi_register_version != HCDI_REGISTER_VERS_0) { 114 kmem_free(hcdi, sizeof (usba_hcdi_t)); 115 116 return (USB_FAILURE); 117 } 118 119 hcdi->hcdi_dip = args->usba_hcdi_register_dip; 120 121 /* 122 * The hcd driver cannot use private data as we're going to store our 123 * data there. If it does, fail the registration immediately. 124 */ 125 if (ddi_get_driver_private(hcdi->hcdi_dip) != NULL) { 126 cmn_err(CE_WARN, "failed attempt to register USB hcd, " 127 "detected private data!"); 128 kmem_free(hcdi, sizeof (usba_hcdi_t)); 129 130 return (USB_FAILURE); 131 } 132 133 134 /* 135 * Create a log_handle 136 */ 137 hcdi->hcdi_log_handle = usb_alloc_log_hdl(hcdi->hcdi_dip, NULL, 138 &hcdi_errlevel, &hcdi_errmask, &hcdi_instance_debug, 139 0); 140 141 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 142 "usba_hcdi_register: %s", ddi_node_name(hcdi->hcdi_dip)); 143 144 /* 145 * Initialize the mutex. Use the iblock cookie passed in 146 * by the host controller driver. 147 */ 148 mutex_init(&hcdi->hcdi_mutex, NULL, MUTEX_DRIVER, 149 args->usba_hcdi_register_iblock_cookie); 150 151 /* add soft interrupt */ 152 if (ddi_intr_add_softint(hcdi->hcdi_dip, &hcdi->hcdi_softint_hdl, 153 DDI_INTR_SOFTPRI_MAX, hcdi_soft_intr, (caddr_t)hcdi) != 154 DDI_SUCCESS) { 155 USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 156 "usba_hcd_register: add soft interrupt failed"); 157 mutex_destroy(&hcdi->hcdi_mutex); 158 usb_free_log_hdl(hcdi->hcdi_log_handle); 159 kmem_free(hcdi, sizeof (usba_hcdi_t)); 160 161 return (USB_FAILURE); 162 } 163 164 if (ddi_intr_get_softint_pri(hcdi->hcdi_softint_hdl, &soft_prip) != 165 DDI_SUCCESS) { 166 USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 167 "usba_hcd_register: get soft interrupt priority failed"); 168 (void) ddi_intr_remove_softint(hcdi->hcdi_softint_hdl); 169 mutex_destroy(&hcdi->hcdi_mutex); 170 usb_free_log_hdl(hcdi->hcdi_log_handle); 171 kmem_free(hcdi, sizeof (usba_hcdi_t)); 172 173 return (USB_FAILURE); 174 } 175 176 /* 177 * Priority and iblock_cookie are one and the same 178 * (However, retaining hcdi_soft_iblock_cookie for now 179 * assigning it w/ priority. In future all iblock_cookie 180 * could just go) 181 */ 182 hcdi->hcdi_soft_iblock_cookie = 183 (ddi_iblock_cookie_t)(uintptr_t)soft_prip; 184 185 usba_init_list(&hcdi->hcdi_cb_queue, NULL, NULL); 186 187 hcdi->hcdi_dma_attr = args->usba_hcdi_register_dma_attr; 188 hcdi->hcdi_flags = flags; 189 hcdi->hcdi_ops = args->usba_hcdi_register_ops; 190 hcdi->hcdi_iblock_cookie = args->usba_hcdi_register_iblock_cookie; 191 usba_hcdi_create_stats(hcdi, ddi_get_instance(hcdi->hcdi_dip)); 192 193 hcdi->hcdi_min_xfer = hcdi->hcdi_dma_attr->dma_attr_minxfer; 194 hcdi->hcdi_min_burst_size = 195 (1<<(ddi_ffs(hcdi->hcdi_dma_attr->dma_attr_burstsizes)-1)); 196 hcdi->hcdi_max_burst_size = 197 (1<<(ddi_fls(hcdi->hcdi_dma_attr->dma_attr_burstsizes)-1)); 198 199 usba_hcdi_set_hcdi(hcdi->hcdi_dip, hcdi); 200 201 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, 202 hcdi->hcdi_dip, 203 DDI_PROP_DONTPASS, "ugen-default-binding", &datap) == 204 DDI_PROP_SUCCESS) { 205 if (strcmp(datap, "device") == 0) { 206 hcdi->hcdi_ugen_default_binding = 207 USBA_UGEN_DEVICE_BINDING; 208 } else if (strcmp(datap, "interface") == 0) { 209 hcdi->hcdi_ugen_default_binding = 210 USBA_UGEN_INTERFACE_BINDING; 211 } else if (strcmp(datap, "interface-association") == 0) { 212 hcdi->hcdi_ugen_default_binding = 213 USBA_UGEN_INTERFACE_ASSOCIATION_BINDING; 214 } else { 215 USB_DPRINTF_L2(DPRINT_MASK_HCDI, 216 hcdi->hcdi_log_handle, 217 "illegal value (%s) for " 218 "ugen_default_binding property", 219 datap); 220 } 221 ddi_prop_free(datap); 222 } 223 224 return (USB_SUCCESS); 225 } 226 227 228 /* 229 * Called by an HCD to detach an instance of the driver 230 */ 231 /*ARGSUSED*/ 232 void 233 usba_hcdi_unregister(dev_info_t *dip) 234 { 235 usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(dip); 236 237 if (hcdi) { 238 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 239 "usba_hcdi_unregister: %s", ddi_node_name(dip)); 240 241 usba_hcdi_set_hcdi(dip, NULL); 242 243 mutex_destroy(&hcdi->hcdi_mutex); 244 usba_hcdi_destroy_stats(hcdi); 245 usb_free_log_hdl(hcdi->hcdi_log_handle); 246 247 /* Destroy the soft interrupt */ 248 (void) ddi_intr_remove_softint(hcdi->hcdi_softint_hdl); 249 kmem_free(hcdi, sizeof (usba_hcdi_t)); 250 } 251 } 252 253 254 /* 255 * alloc usba_hcdi_ops structure 256 * called from the HCD attach routine 257 */ 258 usba_hcdi_ops_t * 259 usba_alloc_hcdi_ops() 260 { 261 usba_hcdi_ops_t *usba_hcdi_ops; 262 263 usba_hcdi_ops = kmem_zalloc(sizeof (usba_hcdi_ops_t), KM_SLEEP); 264 265 return (usba_hcdi_ops); 266 } 267 268 269 /* 270 * dealloc usba_hcdi_ops structure 271 */ 272 void 273 usba_free_hcdi_ops(usba_hcdi_ops_t *hcdi_ops) 274 { 275 if (hcdi_ops) { 276 kmem_free(hcdi_ops, sizeof (usba_hcdi_ops_t)); 277 } 278 } 279 280 281 /* 282 * Allocate the hotplug kstats structure 283 */ 284 void 285 usba_hcdi_create_stats(usba_hcdi_t *hcdi, int instance) 286 { 287 char kstatname[KSTAT_STRLEN]; 288 const char *dname = ddi_driver_name(hcdi->hcdi_dip); 289 hcdi_hotplug_stats_t *hsp; 290 hcdi_error_stats_t *esp; 291 292 if (HCDI_HOTPLUG_STATS(hcdi) == NULL) { 293 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,hotplug", 294 dname, instance); 295 HCDI_HOTPLUG_STATS(hcdi) = kstat_create("usba", instance, 296 kstatname, "usb_hotplug", KSTAT_TYPE_NAMED, 297 sizeof (hcdi_hotplug_stats_t) / sizeof (kstat_named_t), 298 KSTAT_FLAG_PERSISTENT); 299 300 if (HCDI_HOTPLUG_STATS(hcdi) == NULL) { 301 302 return; 303 } 304 305 hsp = HCDI_HOTPLUG_STATS_DATA(hcdi); 306 kstat_named_init(&hsp->hcdi_hotplug_total_success, 307 "Total Hotplug Successes", KSTAT_DATA_UINT64); 308 kstat_named_init(&hsp->hcdi_hotplug_success, 309 "Hotplug Successes", KSTAT_DATA_UINT64); 310 kstat_named_init(&hsp->hcdi_hotplug_total_failure, 311 "Hotplug Total Failures", KSTAT_DATA_UINT64); 312 kstat_named_init(&hsp->hcdi_hotplug_failure, 313 "Hotplug Failures", KSTAT_DATA_UINT64); 314 kstat_named_init(&hsp->hcdi_device_count, 315 "Device Count", KSTAT_DATA_UINT64); 316 317 HCDI_HOTPLUG_STATS(hcdi)->ks_private = hcdi; 318 HCDI_HOTPLUG_STATS(hcdi)->ks_update = nulldev; 319 kstat_install(HCDI_HOTPLUG_STATS(hcdi)); 320 } 321 322 if (HCDI_ERROR_STATS(hcdi) == NULL) { 323 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,error", 324 dname, instance); 325 HCDI_ERROR_STATS(hcdi) = kstat_create("usba", instance, 326 kstatname, "usb_errors", KSTAT_TYPE_NAMED, 327 sizeof (hcdi_error_stats_t) / sizeof (kstat_named_t), 328 KSTAT_FLAG_PERSISTENT); 329 330 if (HCDI_ERROR_STATS(hcdi) == NULL) { 331 332 return; 333 } 334 335 esp = HCDI_ERROR_STATS_DATA(hcdi); 336 kstat_named_init(&esp->cc_crc, "CRC Errors", KSTAT_DATA_UINT64); 337 kstat_named_init(&esp->cc_bitstuffing, 338 "Bit Stuffing Violations", KSTAT_DATA_UINT64); 339 kstat_named_init(&esp->cc_data_toggle_mm, 340 "Data Toggle PID Errors", KSTAT_DATA_UINT64); 341 kstat_named_init(&esp->cc_stall, 342 "Endpoint Stalls", KSTAT_DATA_UINT64); 343 kstat_named_init(&esp->cc_dev_not_resp, 344 "Device Not Responding", KSTAT_DATA_UINT64); 345 kstat_named_init(&esp->cc_pid_checkfailure, 346 "PID Check Bit Errors", KSTAT_DATA_UINT64); 347 kstat_named_init(&esp->cc_unexp_pid, 348 "Invalid PID Errors", KSTAT_DATA_UINT64); 349 kstat_named_init(&esp->cc_data_overrun, 350 "Data Overruns", KSTAT_DATA_UINT64); 351 kstat_named_init(&esp->cc_data_underrun, 352 "Data Underruns", KSTAT_DATA_UINT64); 353 kstat_named_init(&esp->cc_buffer_overrun, 354 "Buffer Overruns", KSTAT_DATA_UINT64); 355 kstat_named_init(&esp->cc_buffer_underrun, 356 "Buffer Underruns", KSTAT_DATA_UINT64); 357 kstat_named_init(&esp->cc_timeout, 358 "Command Timed Out", KSTAT_DATA_UINT64); 359 kstat_named_init(&esp->cc_not_accessed, 360 "Not Accessed By Hardware", KSTAT_DATA_UINT64); 361 kstat_named_init(&esp->cc_no_resources, 362 "No Resources", KSTAT_DATA_UINT64); 363 kstat_named_init(&esp->cc_unspecified_err, 364 "Unspecified Error", KSTAT_DATA_UINT64); 365 kstat_named_init(&esp->cc_stopped_polling, 366 "Stopped Polling", KSTAT_DATA_UINT64); 367 kstat_named_init(&esp->cc_pipe_closing, 368 "Pipe Closing", KSTAT_DATA_UINT64); 369 kstat_named_init(&esp->cc_pipe_reset, 370 "Pipe Reset", KSTAT_DATA_UINT64); 371 kstat_named_init(&esp->cc_not_supported, 372 "Command Not Supported", KSTAT_DATA_UINT64); 373 kstat_named_init(&esp->cc_flushed, 374 "Request Flushed", KSTAT_DATA_UINT64); 375 376 HCDI_ERROR_STATS(hcdi)->ks_private = hcdi; 377 HCDI_ERROR_STATS(hcdi)->ks_update = nulldev; 378 kstat_install(HCDI_ERROR_STATS(hcdi)); 379 } 380 } 381 382 383 /* 384 * Do actual error stats 385 */ 386 void 387 usba_hcdi_update_error_stats(usba_hcdi_t *hcdi, usb_cr_t completion_reason) 388 { 389 if (HCDI_ERROR_STATS(hcdi) == NULL) { 390 391 return; 392 } 393 394 switch (completion_reason) { 395 case USB_CR_OK: 396 break; 397 case USB_CR_CRC: 398 HCDI_ERROR_STATS_DATA(hcdi)->cc_crc.value.ui64++; 399 break; 400 case USB_CR_BITSTUFFING: 401 HCDI_ERROR_STATS_DATA(hcdi)->cc_bitstuffing.value.ui64++; 402 break; 403 case USB_CR_DATA_TOGGLE_MM: 404 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_toggle_mm.value.ui64++; 405 break; 406 case USB_CR_STALL: 407 HCDI_ERROR_STATS_DATA(hcdi)->cc_stall.value.ui64++; 408 break; 409 case USB_CR_DEV_NOT_RESP: 410 HCDI_ERROR_STATS_DATA(hcdi)->cc_dev_not_resp.value.ui64++; 411 break; 412 case USB_CR_PID_CHECKFAILURE: 413 HCDI_ERROR_STATS_DATA(hcdi)->cc_pid_checkfailure.value.ui64++; 414 break; 415 case USB_CR_UNEXP_PID: 416 HCDI_ERROR_STATS_DATA(hcdi)->cc_unexp_pid.value.ui64++; 417 break; 418 case USB_CR_DATA_OVERRUN: 419 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_overrun.value.ui64++; 420 break; 421 case USB_CR_DATA_UNDERRUN: 422 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_underrun.value.ui64++; 423 break; 424 case USB_CR_BUFFER_OVERRUN: 425 HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_overrun.value.ui64++; 426 break; 427 case USB_CR_BUFFER_UNDERRUN: 428 HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_underrun.value.ui64++; 429 break; 430 case USB_CR_TIMEOUT: 431 HCDI_ERROR_STATS_DATA(hcdi)->cc_timeout.value.ui64++; 432 break; 433 case USB_CR_NOT_ACCESSED: 434 HCDI_ERROR_STATS_DATA(hcdi)->cc_not_accessed.value.ui64++; 435 break; 436 case USB_CR_NO_RESOURCES: 437 HCDI_ERROR_STATS_DATA(hcdi)->cc_no_resources.value.ui64++; 438 break; 439 case USB_CR_UNSPECIFIED_ERR: 440 HCDI_ERROR_STATS_DATA(hcdi)->cc_unspecified_err.value.ui64++; 441 break; 442 case USB_CR_STOPPED_POLLING: 443 HCDI_ERROR_STATS_DATA(hcdi)->cc_stopped_polling.value.ui64++; 444 break; 445 case USB_CR_PIPE_CLOSING: 446 HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_closing.value.ui64++; 447 break; 448 case USB_CR_PIPE_RESET: 449 HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_reset.value.ui64++; 450 break; 451 case USB_CR_NOT_SUPPORTED: 452 HCDI_ERROR_STATS_DATA(hcdi)->cc_not_supported.value.ui64++; 453 break; 454 case USB_CR_FLUSHED: 455 HCDI_ERROR_STATS_DATA(hcdi)->cc_flushed.value.ui64++; 456 break; 457 default: 458 break; 459 } 460 } 461 462 463 /* 464 * Destroy the hotplug kstats structure 465 */ 466 static void 467 usba_hcdi_destroy_stats(usba_hcdi_t *hcdi) 468 { 469 if (HCDI_HOTPLUG_STATS(hcdi)) { 470 kstat_delete(HCDI_HOTPLUG_STATS(hcdi)); 471 HCDI_HOTPLUG_STATS(hcdi) = NULL; 472 } 473 474 if (HCDI_ERROR_STATS(hcdi)) { 475 kstat_delete(HCDI_ERROR_STATS(hcdi)); 476 HCDI_ERROR_STATS(hcdi) = NULL; 477 } 478 } 479 480 481 /* 482 * HCD callback handling 483 */ 484 void 485 usba_hcdi_cb(usba_pipe_handle_data_t *ph_data, usb_opaque_t req, 486 usb_cr_t completion_reason) 487 { 488 489 usba_device_t *usba_device = ph_data->p_usba_device; 490 usba_hcdi_t *hcdi = usba_hcdi_get_hcdi( 491 usba_device->usb_root_hub_dip); 492 usba_req_wrapper_t *req_wrp = USBA_REQ2WRP(req); 493 usb_ep_descr_t *eptd = &ph_data->p_ep; 494 495 mutex_enter(&ph_data->p_mutex); 496 497 #ifdef DEBUG 498 mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex); 499 500 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 501 "usba_hcdi_cb: " 502 "ph_data=0x%p req=0x%p state=%d ref=%d cnt=%d cr=%d", 503 (void *)ph_data, (void *)req, ph_data->p_ph_impl->usba_ph_state, 504 ph_data->p_ph_impl->usba_ph_ref_count, ph_data->p_req_count, 505 completion_reason); 506 507 mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex); 508 #endif 509 510 /* Set the completion reason */ 511 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) { 512 case USB_EP_ATTR_CONTROL: 513 ((usb_ctrl_req_t *)req)-> 514 ctrl_completion_reason = completion_reason; 515 break; 516 case USB_EP_ATTR_BULK: 517 ((usb_bulk_req_t *)req)-> 518 bulk_completion_reason = completion_reason; 519 break; 520 case USB_EP_ATTR_INTR: 521 ((usb_intr_req_t *)req)-> 522 intr_completion_reason = completion_reason; 523 break; 524 case USB_EP_ATTR_ISOCH: 525 ((usb_isoc_req_t *)req)-> 526 isoc_completion_reason = completion_reason; 527 break; 528 } 529 530 /* 531 * exception callbacks will still go thru a taskq thread 532 * but should occur after the soft interrupt callback 533 * By design of periodic pipes, polling will stop on any 534 * exception 535 */ 536 if ((ph_data->p_spec_flag & USBA_PH_FLAG_USE_SOFT_INTR) && 537 (completion_reason == USB_CR_OK)) { 538 ph_data->p_soft_intr++; 539 mutex_exit(&ph_data->p_mutex); 540 541 usba_add_to_list(&hcdi->hcdi_cb_queue, &req_wrp->wr_queue); 542 543 if (ddi_intr_trigger_softint(hcdi->hcdi_softint_hdl, NULL) != 544 DDI_SUCCESS) 545 USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 546 "usba_hcdi_cb: ddi_intr_trigger_softint failed"); 547 548 return; 549 } 550 551 /* 552 * USBA_PH_FLAG_TQ_SHARE is for bulk and intr requests, 553 * USBA_PH_FLAG_USE_SOFT_INTR is only for isoch, 554 * so there are no conflicts. 555 */ 556 if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) { 557 int iface; 558 559 mutex_exit(&ph_data->p_mutex); 560 iface = usb_get_if_number(ph_data->p_dip); 561 if (iface < 0) { 562 /* we own the device, use the first taskq */ 563 iface = 0; 564 } 565 if (taskq_dispatch(usba_device->usb_shared_taskq[iface], 566 hcdi_shared_cb_thread, req_wrp, TQ_NOSLEEP) == 567 TASKQID_INVALID) { 568 usba_req_exc_cb(req_wrp, 569 USB_CR_NO_RESOURCES, USB_CB_ASYNC_REQ_FAILED); 570 } 571 572 return; 573 } 574 575 /* Add the callback to the pipehandles callback list */ 576 usba_add_to_list(&ph_data->p_cb_queue, &req_wrp->wr_queue); 577 578 /* only dispatch if there is no thread running */ 579 if (ph_data->p_thread_id == 0) { 580 if (usba_async_ph_req(ph_data, hcdi_cb_thread, 581 ph_data, USB_FLAGS_NOSLEEP) != USB_SUCCESS) { 582 USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 583 "usba_hcdi_cb: taskq_dispatch failed"); 584 if (usba_rm_from_list(&ph_data->p_cb_queue, 585 &req_wrp->wr_queue) == USB_SUCCESS) { 586 mutex_exit(&ph_data->p_mutex); 587 usba_req_exc_cb(req_wrp, 588 USB_CR_NO_RESOURCES, 589 USB_CB_ASYNC_REQ_FAILED); 590 591 return; 592 } 593 } else { 594 ph_data->p_thread_id = (kthread_t *)1; 595 } 596 } 597 mutex_exit(&ph_data->p_mutex); 598 } 599 600 601 /* 602 * thread to perform the callbacks 603 */ 604 static void 605 hcdi_cb_thread(void *arg) 606 { 607 usba_pipe_handle_data_t *ph_data = 608 (usba_pipe_handle_data_t *)arg; 609 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl; 610 usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(ph_data-> 611 p_usba_device->usb_root_hub_dip); 612 usba_req_wrapper_t *req_wrp; 613 614 mutex_enter(&ph_data->p_mutex); 615 ASSERT(ph_data->p_thread_id == (kthread_t *)1); 616 ph_data->p_thread_id = curthread; 617 618 /* 619 * hold the ph_data. we can't use usba_hold_ph_data() since 620 * it will return NULL if we are closing the pipe which would 621 * then leave all requests stuck in the cb_queue 622 */ 623 mutex_enter(&ph_impl->usba_ph_mutex); 624 ph_impl->usba_ph_ref_count++; 625 626 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 627 "hcdi_cb_thread: ph_data=0x%p ref=%d", (void *)ph_data, 628 ph_impl->usba_ph_ref_count); 629 630 mutex_exit(&ph_impl->usba_ph_mutex); 631 632 /* 633 * wait till soft interrupt callbacks are taken care of 634 */ 635 while (ph_data->p_soft_intr) { 636 mutex_exit(&ph_data->p_mutex); 637 delay(1); 638 mutex_enter(&ph_data->p_mutex); 639 } 640 641 while ((req_wrp = (usba_req_wrapper_t *) 642 usba_rm_first_pvt_from_list(&ph_data->p_cb_queue)) != NULL) { 643 hcdi_do_cb(ph_data, req_wrp, hcdi); 644 } 645 646 ph_data->p_thread_id = 0; 647 mutex_exit(&ph_data->p_mutex); 648 649 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 650 "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data); 651 652 usba_release_ph_data(ph_impl); 653 } 654 655 656 static void 657 hcdi_do_cb(usba_pipe_handle_data_t *ph_data, usba_req_wrapper_t *req_wrp, 658 usba_hcdi_t *hcdi) 659 { 660 usb_cr_t completion_reason; 661 usb_req_attrs_t attrs = req_wrp->wr_attrs; 662 663 switch (req_wrp->wr_ph_data->p_ep.bmAttributes & 664 USB_EP_ATTR_MASK) { 665 case USB_EP_ATTR_CONTROL: 666 completion_reason = 667 USBA_WRP2CTRL_REQ(req_wrp)->ctrl_completion_reason; 668 break; 669 case USB_EP_ATTR_INTR: 670 completion_reason = 671 USBA_WRP2INTR_REQ(req_wrp)->intr_completion_reason; 672 break; 673 case USB_EP_ATTR_BULK: 674 completion_reason = 675 USBA_WRP2BULK_REQ(req_wrp)->bulk_completion_reason; 676 break; 677 case USB_EP_ATTR_ISOCH: 678 completion_reason = 679 USBA_WRP2ISOC_REQ(req_wrp)->isoc_completion_reason; 680 break; 681 } 682 req_wrp->wr_cr = completion_reason; 683 684 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 685 "hcdi_do_cb: wrp=0x%p cr=0x%x", (void *)req_wrp, completion_reason); 686 687 /* 688 * Normal callbacks: 689 */ 690 if (completion_reason == USB_CR_OK) { 691 mutex_exit(&ph_data->p_mutex); 692 usba_req_normal_cb(req_wrp); 693 mutex_enter(&ph_data->p_mutex); 694 } else { 695 usb_pipe_state_t pipe_state; 696 697 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 698 "exception callback handling: attrs=0x%x", attrs); 699 700 /* 701 * In exception callback handling, if we were 702 * not able to clear stall, we need to modify 703 * pipe state. Also if auto-clearing is not set 704 * pipe state needs to be modified. 705 */ 706 pipe_state = usba_get_ph_state(ph_data); 707 708 if (!USBA_PIPE_CLOSING(pipe_state)) { 709 switch (completion_reason) { 710 case USB_CR_STOPPED_POLLING: 711 if (pipe_state == 712 USB_PIPE_STATE_ACTIVE) { 713 usba_pipe_new_state(ph_data, 714 USB_PIPE_STATE_IDLE); 715 } 716 break; 717 case USB_CR_NOT_SUPPORTED: 718 usba_pipe_new_state(ph_data, 719 USB_PIPE_STATE_IDLE); 720 break; 721 case USB_CR_PIPE_RESET: 722 case USB_CR_FLUSHED: 723 break; 724 default: 725 usba_pipe_new_state(ph_data, 726 USB_PIPE_STATE_ERROR); 727 break; 728 } 729 } 730 731 pipe_state = usba_get_ph_state(ph_data); 732 733 mutex_exit(&ph_data->p_mutex); 734 if (attrs & USB_ATTRS_PIPE_RESET) { 735 if ((completion_reason != USB_CR_PIPE_RESET) && 736 (pipe_state == USB_PIPE_STATE_ERROR)) { 737 738 hcdi_autoclearing(req_wrp); 739 } 740 } 741 742 usba_req_exc_cb(req_wrp, 0, 0); 743 mutex_enter(&ph_data->p_mutex); 744 } 745 746 /* Update the hcdi error kstats */ 747 if (completion_reason) { 748 mutex_enter(&hcdi->hcdi_mutex); 749 usba_hcdi_update_error_stats(hcdi, completion_reason); 750 mutex_exit(&hcdi->hcdi_mutex); 751 } 752 753 /* 754 * Once the callback is finished, release the pipe handle 755 * we start the next request first to avoid that the 756 * pipe gets closed while starting the next request 757 */ 758 mutex_exit(&ph_data->p_mutex); 759 usba_start_next_req(ph_data); 760 761 mutex_enter(&ph_data->p_mutex); 762 } 763 764 765 /* 766 * thread to perform callbacks on the shared queue 767 */ 768 static void 769 hcdi_shared_cb_thread(void *arg) 770 { 771 usba_req_wrapper_t *req_wrp = (usba_req_wrapper_t *)arg; 772 usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data; 773 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl; 774 usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(ph_data-> 775 p_usba_device->usb_root_hub_dip); 776 /* 777 * hold the ph_data. we can't use usba_hold_ph_data() since 778 * it will return NULL if we are closing the pipe which would 779 * then leave all requests stuck in the cb_queue 780 */ 781 mutex_enter(&ph_impl->usba_ph_mutex); 782 ph_impl->usba_ph_ref_count++; 783 784 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 785 "hcdi_shared_cb_thread: ph_data=0x%p ref=%d req=0x%p", 786 (void *)ph_data, ph_impl->usba_ph_ref_count, (void *)req_wrp); 787 mutex_exit(&ph_impl->usba_ph_mutex); 788 789 /* do the callback */ 790 mutex_enter(&ph_data->p_mutex); 791 hcdi_do_cb(ph_data, req_wrp, hcdi); 792 mutex_exit(&ph_data->p_mutex); 793 794 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 795 "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data); 796 797 usba_release_ph_data(ph_impl); 798 } 799 800 801 /* 802 * soft interrupt handler 803 */ 804 /*ARGSUSED*/ 805 static uint_t 806 hcdi_soft_intr(caddr_t arg1, caddr_t arg2) 807 { 808 usba_hcdi_t *hcdi = (void *)arg1; 809 usba_req_wrapper_t *req_wrp; 810 int count = 0; 811 812 while ((req_wrp = (usba_req_wrapper_t *) 813 usba_rm_first_pvt_from_list(&hcdi->hcdi_cb_queue)) != NULL) { 814 usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data; 815 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl; 816 817 /* hold the pipe */ 818 mutex_enter(&ph_impl->usba_ph_mutex); 819 ph_impl->usba_ph_ref_count++; 820 mutex_exit(&ph_impl->usba_ph_mutex); 821 822 /* do the callback */ 823 usba_req_normal_cb(req_wrp); 824 825 /* decrement the soft interrupt count */ 826 mutex_enter(&ph_data->p_mutex); 827 ph_data->p_soft_intr--; 828 mutex_exit(&ph_data->p_mutex); 829 830 /* release the pipe */ 831 mutex_enter(&ph_impl->usba_ph_mutex); 832 ph_impl->usba_ph_ref_count--; 833 mutex_exit(&ph_impl->usba_ph_mutex); 834 835 count++; 836 } 837 838 return (count == 0 ? DDI_INTR_UNCLAIMED : DDI_INTR_CLAIMED); 839 } 840 841 842 /* 843 * hcdi_autoclearing: 844 * This function is called under the taskq context. It 845 * resets the pipe, and clears the stall, if necessary 846 */ 847 static void 848 hcdi_autoclearing(usba_req_wrapper_t *req_wrp) 849 { 850 usb_cr_t cr = req_wrp->wr_cr; 851 usb_pipe_handle_t pipe_handle, def_pipe_handle; 852 usb_cr_t completion_reason; 853 usb_cb_flags_t cb_flags; 854 int rval; 855 usba_device_t *usba_device = 856 req_wrp->wr_ph_data->p_usba_device; 857 usba_hcdi_t *hcdi = usba_hcdi_get_hcdi( 858 usba_device->usb_root_hub_dip); 859 usb_req_attrs_t attrs = req_wrp->wr_attrs; 860 861 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 862 "hcdi_autoclearing: wrp=0x%p", (void *)req_wrp); 863 864 pipe_handle = usba_get_pipe_handle(req_wrp->wr_ph_data); 865 def_pipe_handle = usba_get_dflt_pipe_handle(req_wrp->wr_ph_data->p_dip); 866 867 /* 868 * first reset the pipe synchronously 869 */ 870 if ((attrs & USB_ATTRS_PIPE_RESET) == USB_ATTRS_PIPE_RESET) { 871 usba_pipe_clear(pipe_handle); 872 usba_req_set_cb_flags(req_wrp, USB_CB_RESET_PIPE); 873 } 874 875 ASSERT(def_pipe_handle); 876 877 /* Do not clear if this request was a usb_get_status request */ 878 if ((pipe_handle == def_pipe_handle) && 879 (USBA_WRP2CTRL_REQ(req_wrp)->ctrl_bRequest == 880 USB_REQ_GET_STATUS)) { 881 USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle, 882 "hcdi_autoclearing: usb_get_status failed, no clearing"); 883 884 /* if default pipe and stall no auto clearing */ 885 } else if ((pipe_handle == def_pipe_handle) && (cr == USB_CR_STALL)) { 886 USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle, 887 "hcdi_autoclearing: default pipe stalled, no clearing"); 888 889 usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL); 890 891 /* else do auto clearing */ 892 } else if (((attrs & USB_ATTRS_AUTOCLEARING) == 893 USB_ATTRS_AUTOCLEARING) && (cr == USB_CR_STALL)) { 894 ushort_t status = 0; 895 896 rval = usb_get_status(req_wrp->wr_dip, def_pipe_handle, 897 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_EP, 898 req_wrp->wr_ph_data->p_ep.bEndpointAddress, 899 &status, USB_FLAGS_SLEEP); 900 if (rval != USB_SUCCESS) { 901 USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle, 902 "get status (STALL) failed: rval=%d", rval); 903 904 usba_pipe_clear(def_pipe_handle); 905 } 906 907 if ((rval != USB_SUCCESS) || 908 (status & USB_EP_HALT_STATUS)) { 909 usba_req_set_cb_flags(req_wrp, USB_CB_FUNCTIONAL_STALL); 910 911 if ((rval = usb_pipe_sync_ctrl_xfer( 912 req_wrp->wr_dip, def_pipe_handle, 913 USB_DEV_REQ_HOST_TO_DEV | 914 USB_DEV_REQ_RCPT_EP, 915 USB_REQ_CLEAR_FEATURE, 916 0, 917 req_wrp->wr_ph_data->p_ep.bEndpointAddress, 918 0, 919 NULL, 0, 920 &completion_reason, 921 &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) { 922 USB_DPRINTF_L2(DPRINT_MASK_USBAI, 923 hcdi->hcdi_log_handle, 924 "auto clearing (STALL) failed: " 925 "rval=%d, cr=0x%x cb=0x%x", 926 rval, completion_reason, cb_flags); 927 928 usba_pipe_clear(def_pipe_handle); 929 } else { 930 usba_req_set_cb_flags(req_wrp, 931 USB_CB_STALL_CLEARED); 932 } 933 } else { 934 usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL); 935 } 936 } 937 } 938 939 940 /* 941 * usba_hcdi_get_req_private: 942 * This function is used to get the HCD private field 943 * maintained by USBA. HCD calls this function. 944 * 945 * Arguments: 946 * req - pointer to usb_*_req_t 947 * 948 * Return Values: 949 * wr_hcd_private field from wrapper 950 */ 951 usb_opaque_t 952 usba_hcdi_get_req_private(usb_opaque_t req) 953 { 954 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 955 956 return (wrp->wr_hcd_private); 957 } 958 959 960 /* 961 * usba_hcdi_set_req_private: 962 * This function is used to set the HCD private field 963 * maintained by USBA. HCD calls this function. 964 * 965 * Arguments: 966 * req - pointer to usb_*_req_t 967 * hcd_private - wr_hcd_private field from wrapper 968 */ 969 void 970 usba_hcdi_set_req_private(usb_opaque_t req, usb_opaque_t hcd_private) 971 { 972 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 973 974 wrp->wr_hcd_private = hcd_private; 975 } 976 977 978 /* get data toggle information for this endpoint */ 979 uchar_t 980 usba_hcdi_get_data_toggle(usba_device_t *usba_device, uint8_t ep_addr) 981 { 982 uchar_t toggle; 983 usba_ph_impl_t *ph_impl; 984 int ep_index; 985 986 ep_index = usb_get_ep_index(ep_addr); 987 mutex_enter(&usba_device->usb_mutex); 988 ph_impl = &usba_device->usb_ph_list[ep_index]; 989 mutex_enter(&ph_impl->usba_ph_mutex); 990 toggle = (uchar_t)(ph_impl->usba_ph_flags & USBA_PH_DATA_TOGGLE); 991 mutex_exit(&ph_impl->usba_ph_mutex); 992 mutex_exit(&usba_device->usb_mutex); 993 994 return (toggle); 995 } 996 997 998 /* set data toggle information for this endpoint */ 999 void 1000 usba_hcdi_set_data_toggle(usba_device_t *usba_device, uint8_t ep_addr, 1001 uchar_t toggle) 1002 { 1003 usba_ph_impl_t *ph_impl; 1004 int ep_index; 1005 1006 ep_index = usb_get_ep_index(ep_addr); 1007 mutex_enter(&usba_device->usb_mutex); 1008 ph_impl = &usba_device->usb_ph_list[ep_index]; 1009 mutex_enter(&ph_impl->usba_ph_mutex); 1010 ph_impl->usba_ph_flags &= ~USBA_PH_DATA_TOGGLE; 1011 ph_impl->usba_ph_flags |= (USBA_PH_DATA_TOGGLE & toggle); 1012 mutex_exit(&ph_impl->usba_ph_mutex); 1013 mutex_exit(&usba_device->usb_mutex); 1014 } 1015 1016 1017 /* get pipe_handle_impl ptr for this ep */ 1018 usba_pipe_handle_data_t * 1019 usba_hcdi_get_ph_data(usba_device_t *usba_device, uint8_t ep_addr) 1020 { 1021 return (usba_device->usb_ph_list[usb_get_ep_index(ep_addr)]. 1022 usba_ph_data); 1023 } 1024 1025 void * 1026 usba_hcdi_get_device_private(usba_device_t *usba_device) 1027 { 1028 return (usba_device->usb_hcd_private); 1029 } 1030