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