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_no_resources, 347 "No Resources", KSTAT_DATA_UINT64); 348 kstat_named_init(&esp->cc_unspecified_err, 349 "Unspecified Error", KSTAT_DATA_UINT64); 350 kstat_named_init(&esp->cc_stopped_polling, 351 "Stopped Polling", KSTAT_DATA_UINT64); 352 kstat_named_init(&esp->cc_pipe_closing, 353 "Pipe Closing", KSTAT_DATA_UINT64); 354 kstat_named_init(&esp->cc_pipe_reset, 355 "Pipe Reset", KSTAT_DATA_UINT64); 356 kstat_named_init(&esp->cc_not_supported, 357 "Command Not Supported", KSTAT_DATA_UINT64); 358 kstat_named_init(&esp->cc_flushed, 359 "Request Flushed", KSTAT_DATA_UINT64); 360 361 HCDI_ERROR_STATS(hcdi)->ks_private = hcdi; 362 HCDI_ERROR_STATS(hcdi)->ks_update = nulldev; 363 kstat_install(HCDI_ERROR_STATS(hcdi)); 364 } 365 } 366 367 368 /* 369 * Do actual error stats 370 */ 371 void 372 usba_hcdi_update_error_stats(usba_hcdi_t *hcdi, usb_cr_t completion_reason) 373 { 374 if (HCDI_ERROR_STATS(hcdi) == NULL) { 375 376 return; 377 } 378 379 switch (completion_reason) { 380 case USB_CR_OK: 381 break; 382 case USB_CR_CRC: 383 HCDI_ERROR_STATS_DATA(hcdi)->cc_crc.value.ui64++; 384 break; 385 case USB_CR_BITSTUFFING: 386 HCDI_ERROR_STATS_DATA(hcdi)->cc_bitstuffing.value.ui64++; 387 break; 388 case USB_CR_DATA_TOGGLE_MM: 389 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_toggle_mm.value.ui64++; 390 break; 391 case USB_CR_STALL: 392 HCDI_ERROR_STATS_DATA(hcdi)->cc_stall.value.ui64++; 393 break; 394 case USB_CR_DEV_NOT_RESP: 395 HCDI_ERROR_STATS_DATA(hcdi)->cc_dev_not_resp.value.ui64++; 396 break; 397 case USB_CR_PID_CHECKFAILURE: 398 HCDI_ERROR_STATS_DATA(hcdi)->cc_pid_checkfailure.value.ui64++; 399 break; 400 case USB_CR_UNEXP_PID: 401 HCDI_ERROR_STATS_DATA(hcdi)->cc_unexp_pid.value.ui64++; 402 break; 403 case USB_CR_DATA_OVERRUN: 404 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_overrun.value.ui64++; 405 break; 406 case USB_CR_DATA_UNDERRUN: 407 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_underrun.value.ui64++; 408 break; 409 case USB_CR_BUFFER_OVERRUN: 410 HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_overrun.value.ui64++; 411 break; 412 case USB_CR_BUFFER_UNDERRUN: 413 HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_underrun.value.ui64++; 414 break; 415 case USB_CR_TIMEOUT: 416 HCDI_ERROR_STATS_DATA(hcdi)->cc_timeout.value.ui64++; 417 break; 418 case USB_CR_NOT_ACCESSED: 419 HCDI_ERROR_STATS_DATA(hcdi)->cc_not_accessed.value.ui64++; 420 break; 421 case USB_CR_NO_RESOURCES: 422 HCDI_ERROR_STATS_DATA(hcdi)->cc_no_resources.value.ui64++; 423 break; 424 case USB_CR_UNSPECIFIED_ERR: 425 HCDI_ERROR_STATS_DATA(hcdi)->cc_unspecified_err.value.ui64++; 426 break; 427 case USB_CR_STOPPED_POLLING: 428 HCDI_ERROR_STATS_DATA(hcdi)->cc_stopped_polling.value.ui64++; 429 break; 430 case USB_CR_PIPE_CLOSING: 431 HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_closing.value.ui64++; 432 break; 433 case USB_CR_PIPE_RESET: 434 HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_reset.value.ui64++; 435 break; 436 case USB_CR_NOT_SUPPORTED: 437 HCDI_ERROR_STATS_DATA(hcdi)->cc_not_supported.value.ui64++; 438 break; 439 case USB_CR_FLUSHED: 440 HCDI_ERROR_STATS_DATA(hcdi)->cc_flushed.value.ui64++; 441 break; 442 default: 443 break; 444 } 445 } 446 447 448 /* 449 * Destroy the hotplug kstats structure 450 */ 451 static void 452 usba_hcdi_destroy_stats(usba_hcdi_t *hcdi) 453 { 454 if (HCDI_HOTPLUG_STATS(hcdi)) { 455 kstat_delete(HCDI_HOTPLUG_STATS(hcdi)); 456 HCDI_HOTPLUG_STATS(hcdi) = NULL; 457 } 458 459 if (HCDI_ERROR_STATS(hcdi)) { 460 kstat_delete(HCDI_ERROR_STATS(hcdi)); 461 HCDI_ERROR_STATS(hcdi) = NULL; 462 } 463 } 464 465 466 /* 467 * HCD callback handling 468 */ 469 void 470 usba_hcdi_cb(usba_pipe_handle_data_t *ph_data, 471 usb_opaque_t req, 472 usb_cr_t completion_reason) 473 { 474 475 usba_device_t *usba_device = ph_data->p_usba_device; 476 usba_hcdi_t *hcdi = usba_hcdi_get_hcdi( 477 usba_device->usb_root_hub_dip); 478 usba_req_wrapper_t *req_wrp = USBA_REQ2WRP(req); 479 usb_ep_descr_t *eptd = &ph_data->p_ep; 480 481 mutex_enter(&ph_data->p_mutex); 482 483 #ifdef DEBUG 484 mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex); 485 486 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 487 "usba_hcdi_cb: " 488 "ph_data=0x%p req=0x%p state=%d ref=%d cnt=%d cr=%d", 489 (void *)ph_data, (void *)req, ph_data->p_ph_impl->usba_ph_state, 490 ph_data->p_ph_impl->usba_ph_ref_count, ph_data->p_req_count, 491 completion_reason); 492 493 mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex); 494 #endif 495 496 /* Set the completion reason */ 497 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) { 498 case USB_EP_ATTR_CONTROL: 499 ((usb_ctrl_req_t *)req)-> 500 ctrl_completion_reason = completion_reason; 501 break; 502 case USB_EP_ATTR_BULK: 503 ((usb_bulk_req_t *)req)-> 504 bulk_completion_reason = completion_reason; 505 break; 506 case USB_EP_ATTR_INTR: 507 ((usb_intr_req_t *)req)-> 508 intr_completion_reason = completion_reason; 509 break; 510 case USB_EP_ATTR_ISOCH: 511 ((usb_isoc_req_t *)req)-> 512 isoc_completion_reason = completion_reason; 513 break; 514 } 515 516 /* 517 * exception callbacks will still go thru a taskq thread 518 * but should occur after the soft interrupt callback 519 * By design of periodic pipes, polling will stop on any 520 * exception 521 */ 522 if ((ph_data->p_spec_flag & USBA_PH_FLAG_USE_SOFT_INTR) && 523 (completion_reason == USB_CR_OK)) { 524 ph_data->p_soft_intr++; 525 mutex_exit(&ph_data->p_mutex); 526 527 usba_add_to_list(&hcdi->hcdi_cb_queue, &req_wrp->wr_queue); 528 529 if (ddi_intr_trigger_softint(hcdi->hcdi_softint_hdl, NULL) != 530 DDI_SUCCESS) 531 USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 532 "usba_hcdi_cb: ddi_intr_trigger_softint failed"); 533 534 return; 535 } 536 537 /* 538 * USBA_PH_FLAG_TQ_SHARE is for bulk and intr requests, 539 * USBA_PH_FLAG_USE_SOFT_INTR is only for isoch, 540 * so there are no conflicts. 541 */ 542 if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) { 543 int iface; 544 545 mutex_exit(&ph_data->p_mutex); 546 iface = usb_get_if_number(ph_data->p_dip); 547 if (iface < 0) { 548 /* we own the device, use the first taskq */ 549 iface = 0; 550 } 551 if (taskq_dispatch(usba_device->usb_shared_taskq[iface], 552 hcdi_shared_cb_thread, req_wrp, TQ_NOSLEEP) == 553 NULL) { 554 usba_req_exc_cb(req_wrp, 555 USB_CR_NO_RESOURCES, USB_CB_ASYNC_REQ_FAILED); 556 } 557 558 return; 559 } 560 561 /* Add the callback to the pipehandles callback list */ 562 usba_add_to_list(&ph_data->p_cb_queue, &req_wrp->wr_queue); 563 564 /* only dispatch if there is no thread running */ 565 if (ph_data->p_thread_id == 0) { 566 if (usba_async_ph_req(ph_data, hcdi_cb_thread, 567 ph_data, USB_FLAGS_NOSLEEP) != USB_SUCCESS) { 568 USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 569 "usba_hcdi_cb: taskq_dispatch failed"); 570 if (usba_rm_from_list(&ph_data->p_cb_queue, 571 &req_wrp->wr_queue) == USB_SUCCESS) { 572 mutex_exit(&ph_data->p_mutex); 573 usba_req_exc_cb(req_wrp, 574 USB_CR_NO_RESOURCES, 575 USB_CB_ASYNC_REQ_FAILED); 576 577 return; 578 } 579 } else { 580 ph_data->p_thread_id = (kthread_t *)1; 581 } 582 } 583 mutex_exit(&ph_data->p_mutex); 584 } 585 586 587 /* 588 * thread to perform the callbacks 589 */ 590 static void 591 hcdi_cb_thread(void *arg) 592 { 593 usba_pipe_handle_data_t *ph_data = 594 (usba_pipe_handle_data_t *)arg; 595 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl; 596 usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(ph_data-> 597 p_usba_device->usb_root_hub_dip); 598 usba_req_wrapper_t *req_wrp; 599 600 mutex_enter(&ph_data->p_mutex); 601 ASSERT(ph_data->p_thread_id == (kthread_t *)1); 602 ph_data->p_thread_id = curthread; 603 604 /* 605 * hold the ph_data. we can't use usba_hold_ph_data() since 606 * it will return NULL if we are closing the pipe which would 607 * then leave all requests stuck in the cb_queue 608 */ 609 mutex_enter(&ph_impl->usba_ph_mutex); 610 ph_impl->usba_ph_ref_count++; 611 612 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 613 "hcdi_cb_thread: ph_data=0x%p ref=%d", (void *)ph_data, 614 ph_impl->usba_ph_ref_count); 615 616 mutex_exit(&ph_impl->usba_ph_mutex); 617 618 /* 619 * wait till soft interrupt callbacks are taken care of 620 */ 621 while (ph_data->p_soft_intr) { 622 mutex_exit(&ph_data->p_mutex); 623 delay(1); 624 mutex_enter(&ph_data->p_mutex); 625 } 626 627 while ((req_wrp = (usba_req_wrapper_t *) 628 usba_rm_first_pvt_from_list(&ph_data->p_cb_queue)) != NULL) { 629 hcdi_do_cb(ph_data, req_wrp, hcdi); 630 } 631 632 ph_data->p_thread_id = 0; 633 mutex_exit(&ph_data->p_mutex); 634 635 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 636 "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data); 637 638 usba_release_ph_data(ph_impl); 639 } 640 641 642 static void 643 hcdi_do_cb(usba_pipe_handle_data_t *ph_data, usba_req_wrapper_t *req_wrp, 644 usba_hcdi_t *hcdi) 645 { 646 usb_cr_t completion_reason; 647 usb_req_attrs_t attrs = req_wrp->wr_attrs; 648 649 switch (req_wrp->wr_ph_data->p_ep.bmAttributes & 650 USB_EP_ATTR_MASK) { 651 case USB_EP_ATTR_CONTROL: 652 completion_reason = 653 USBA_WRP2CTRL_REQ(req_wrp)->ctrl_completion_reason; 654 break; 655 case USB_EP_ATTR_INTR: 656 completion_reason = 657 USBA_WRP2INTR_REQ(req_wrp)->intr_completion_reason; 658 break; 659 case USB_EP_ATTR_BULK: 660 completion_reason = 661 USBA_WRP2BULK_REQ(req_wrp)->bulk_completion_reason; 662 break; 663 case USB_EP_ATTR_ISOCH: 664 completion_reason = 665 USBA_WRP2ISOC_REQ(req_wrp)->isoc_completion_reason; 666 break; 667 } 668 req_wrp->wr_cr = completion_reason; 669 670 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 671 "hcdi_do_cb: wrp=0x%p cr=0x%x", (void *)req_wrp, completion_reason); 672 673 /* 674 * Normal callbacks: 675 */ 676 if (completion_reason == USB_CR_OK) { 677 mutex_exit(&ph_data->p_mutex); 678 usba_req_normal_cb(req_wrp); 679 mutex_enter(&ph_data->p_mutex); 680 } else { 681 usb_pipe_state_t pipe_state; 682 683 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 684 "exception callback handling: attrs=0x%x", attrs); 685 686 /* 687 * In exception callback handling, if we were 688 * not able to clear stall, we need to modify 689 * pipe state. Also if auto-clearing is not set 690 * pipe state needs to be modified. 691 */ 692 pipe_state = usba_get_ph_state(ph_data); 693 694 if (!USBA_PIPE_CLOSING(pipe_state)) { 695 switch (completion_reason) { 696 case USB_CR_STOPPED_POLLING: 697 if (pipe_state == 698 USB_PIPE_STATE_ACTIVE) { 699 usba_pipe_new_state(ph_data, 700 USB_PIPE_STATE_IDLE); 701 } 702 break; 703 case USB_CR_NOT_SUPPORTED: 704 usba_pipe_new_state(ph_data, 705 USB_PIPE_STATE_IDLE); 706 break; 707 case USB_CR_PIPE_RESET: 708 case USB_CR_FLUSHED: 709 break; 710 default: 711 usba_pipe_new_state(ph_data, 712 USB_PIPE_STATE_ERROR); 713 break; 714 } 715 } 716 717 pipe_state = usba_get_ph_state(ph_data); 718 719 mutex_exit(&ph_data->p_mutex); 720 if (attrs & USB_ATTRS_PIPE_RESET) { 721 if ((completion_reason != USB_CR_PIPE_RESET) && 722 (pipe_state == USB_PIPE_STATE_ERROR)) { 723 724 hcdi_autoclearing(req_wrp); 725 } 726 } 727 728 usba_req_exc_cb(req_wrp, 0, 0); 729 mutex_enter(&ph_data->p_mutex); 730 } 731 732 /* Update the hcdi error kstats */ 733 if (completion_reason) { 734 mutex_enter(&hcdi->hcdi_mutex); 735 usba_hcdi_update_error_stats(hcdi, completion_reason); 736 mutex_exit(&hcdi->hcdi_mutex); 737 } 738 739 /* 740 * Once the callback is finished, release the pipe handle 741 * we start the next request first to avoid that the 742 * pipe gets closed while starting the next request 743 */ 744 mutex_exit(&ph_data->p_mutex); 745 usba_start_next_req(ph_data); 746 747 mutex_enter(&ph_data->p_mutex); 748 } 749 750 751 /* 752 * thread to perform callbacks on the shared queue 753 */ 754 static void 755 hcdi_shared_cb_thread(void *arg) 756 { 757 usba_req_wrapper_t *req_wrp = (usba_req_wrapper_t *)arg; 758 usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data; 759 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl; 760 usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(ph_data-> 761 p_usba_device->usb_root_hub_dip); 762 /* 763 * hold the ph_data. we can't use usba_hold_ph_data() since 764 * it will return NULL if we are closing the pipe which would 765 * then leave all requests stuck in the cb_queue 766 */ 767 mutex_enter(&ph_impl->usba_ph_mutex); 768 ph_impl->usba_ph_ref_count++; 769 770 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 771 "hcdi_shared_cb_thread: ph_data=0x%p ref=%d req=0x%p", 772 (void *)ph_data, ph_impl->usba_ph_ref_count, (void *)req_wrp); 773 mutex_exit(&ph_impl->usba_ph_mutex); 774 775 /* do the callback */ 776 mutex_enter(&ph_data->p_mutex); 777 hcdi_do_cb(ph_data, req_wrp, hcdi); 778 mutex_exit(&ph_data->p_mutex); 779 780 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 781 "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data); 782 783 usba_release_ph_data(ph_impl); 784 } 785 786 787 /* 788 * soft interrupt handler 789 */ 790 /*ARGSUSED*/ 791 static uint_t 792 hcdi_soft_intr(caddr_t arg1, caddr_t arg2) 793 { 794 usba_hcdi_t *hcdi = (void *)arg1; 795 usba_req_wrapper_t *req_wrp; 796 int count = 0; 797 798 while ((req_wrp = (usba_req_wrapper_t *) 799 usba_rm_first_pvt_from_list(&hcdi->hcdi_cb_queue)) != NULL) { 800 usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data; 801 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl; 802 803 /* hold the pipe */ 804 mutex_enter(&ph_impl->usba_ph_mutex); 805 ph_impl->usba_ph_ref_count++; 806 mutex_exit(&ph_impl->usba_ph_mutex); 807 808 /* do the callback */ 809 usba_req_normal_cb(req_wrp); 810 811 /* decrement the soft interrupt count */ 812 mutex_enter(&ph_data->p_mutex); 813 ph_data->p_soft_intr--; 814 mutex_exit(&ph_data->p_mutex); 815 816 /* release the pipe */ 817 mutex_enter(&ph_impl->usba_ph_mutex); 818 ph_impl->usba_ph_ref_count--; 819 mutex_exit(&ph_impl->usba_ph_mutex); 820 821 count++; 822 } 823 824 return (count == 0 ? DDI_INTR_UNCLAIMED : DDI_INTR_CLAIMED); 825 } 826 827 828 /* 829 * hcdi_autoclearing: 830 * This function is called under the taskq context. It 831 * resets the pipe, and clears the stall, if necessary 832 */ 833 static void 834 hcdi_autoclearing(usba_req_wrapper_t *req_wrp) 835 { 836 usb_cr_t cr = req_wrp->wr_cr; 837 usb_pipe_handle_t pipe_handle, def_pipe_handle; 838 usb_cr_t completion_reason; 839 usb_cb_flags_t cb_flags; 840 int rval; 841 usba_device_t *usba_device = 842 req_wrp->wr_ph_data->p_usba_device; 843 usba_hcdi_t *hcdi = usba_hcdi_get_hcdi( 844 usba_device->usb_root_hub_dip); 845 usb_req_attrs_t attrs = req_wrp->wr_attrs; 846 847 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle, 848 "hcdi_autoclearing: wrp=0x%p", (void *)req_wrp); 849 850 pipe_handle = usba_get_pipe_handle(req_wrp->wr_ph_data); 851 def_pipe_handle = usba_get_dflt_pipe_handle(req_wrp->wr_ph_data->p_dip); 852 853 /* 854 * first reset the pipe synchronously 855 */ 856 if ((attrs & USB_ATTRS_PIPE_RESET) == USB_ATTRS_PIPE_RESET) { 857 usba_pipe_clear(pipe_handle); 858 usba_req_set_cb_flags(req_wrp, USB_CB_RESET_PIPE); 859 } 860 861 ASSERT(def_pipe_handle); 862 863 /* Do not clear if this request was a usb_get_status request */ 864 if ((pipe_handle == def_pipe_handle) && 865 (USBA_WRP2CTRL_REQ(req_wrp)->ctrl_bRequest == 866 USB_REQ_GET_STATUS)) { 867 USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle, 868 "hcdi_autoclearing: usb_get_status failed, no clearing"); 869 870 /* if default pipe and stall no auto clearing */ 871 } else if ((pipe_handle == def_pipe_handle) && (cr == USB_CR_STALL)) { 872 USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle, 873 "hcdi_autoclearing: default pipe stalled, no clearing"); 874 875 usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL); 876 877 /* else do auto clearing */ 878 } else if (((attrs & USB_ATTRS_AUTOCLEARING) == 879 USB_ATTRS_AUTOCLEARING) && (cr == USB_CR_STALL)) { 880 ushort_t status = 0; 881 882 rval = usb_get_status(req_wrp->wr_dip, def_pipe_handle, 883 USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_EP, 884 req_wrp->wr_ph_data->p_ep.bEndpointAddress, 885 &status, USB_FLAGS_SLEEP); 886 if (rval != USB_SUCCESS) { 887 USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle, 888 "get status (STALL) failed: rval=%d", rval); 889 890 usba_pipe_clear(def_pipe_handle); 891 } 892 893 if ((rval != USB_SUCCESS) || 894 (status & USB_EP_HALT_STATUS)) { 895 usba_req_set_cb_flags(req_wrp, USB_CB_FUNCTIONAL_STALL); 896 897 if ((rval = usb_pipe_sync_ctrl_xfer( 898 req_wrp->wr_dip, def_pipe_handle, 899 USB_DEV_REQ_HOST_TO_DEV | 900 USB_DEV_REQ_RCPT_EP, 901 USB_REQ_CLEAR_FEATURE, 902 0, 903 req_wrp->wr_ph_data->p_ep.bEndpointAddress, 904 0, 905 NULL, 0, 906 &completion_reason, 907 &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) { 908 USB_DPRINTF_L2(DPRINT_MASK_USBAI, 909 hcdi->hcdi_log_handle, 910 "auto clearing (STALL) failed: " 911 "rval=%d, cr=0x%x cb=0x%x", 912 rval, completion_reason, cb_flags); 913 914 usba_pipe_clear(def_pipe_handle); 915 } else { 916 usba_req_set_cb_flags(req_wrp, 917 USB_CB_STALL_CLEARED); 918 } 919 } else { 920 usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL); 921 } 922 } 923 } 924 925 926 /* 927 * usba_hcdi_get_req_private: 928 * This function is used to get the HCD private field 929 * maintained by USBA. HCD calls this function. 930 * 931 * Arguments: 932 * req - pointer to usb_*_req_t 933 * 934 * Return Values: 935 * wr_hcd_private field from wrapper 936 */ 937 usb_opaque_t 938 usba_hcdi_get_req_private(usb_opaque_t req) 939 { 940 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 941 942 return (wrp->wr_hcd_private); 943 } 944 945 946 /* 947 * usba_hcdi_set_req_private: 948 * This function is used to set the HCD private field 949 * maintained by USBA. HCD calls this function. 950 * 951 * Arguments: 952 * req - pointer to usb_*_req_t 953 * hcd_private - wr_hcd_private field from wrapper 954 */ 955 void 956 usba_hcdi_set_req_private(usb_opaque_t req, 957 usb_opaque_t hcd_private) 958 { 959 usba_req_wrapper_t *wrp = USBA_REQ2WRP(req); 960 961 wrp->wr_hcd_private = hcd_private; 962 } 963 964 965 /* get data toggle information for this endpoint */ 966 uchar_t 967 usba_hcdi_get_data_toggle(usba_device_t *usba_device, uint8_t ep_addr) 968 { 969 uchar_t toggle; 970 usba_ph_impl_t *ph_impl; 971 int ep_index; 972 973 ep_index = usb_get_ep_index(ep_addr); 974 mutex_enter(&usba_device->usb_mutex); 975 ph_impl = &usba_device->usb_ph_list[ep_index]; 976 mutex_enter(&ph_impl->usba_ph_mutex); 977 toggle = (uchar_t)(ph_impl->usba_ph_flags & USBA_PH_DATA_TOGGLE); 978 mutex_exit(&ph_impl->usba_ph_mutex); 979 mutex_exit(&usba_device->usb_mutex); 980 981 return (toggle); 982 } 983 984 985 /* set data toggle information for this endpoint */ 986 void 987 usba_hcdi_set_data_toggle(usba_device_t *usba_device, uint8_t ep_addr, 988 uchar_t toggle) 989 { 990 usba_ph_impl_t *ph_impl; 991 int ep_index; 992 993 ep_index = usb_get_ep_index(ep_addr); 994 mutex_enter(&usba_device->usb_mutex); 995 ph_impl = &usba_device->usb_ph_list[ep_index]; 996 mutex_enter(&ph_impl->usba_ph_mutex); 997 ph_impl->usba_ph_flags &= ~USBA_PH_DATA_TOGGLE; 998 ph_impl->usba_ph_flags |= (USBA_PH_DATA_TOGGLE & toggle); 999 mutex_exit(&ph_impl->usba_ph_mutex); 1000 mutex_exit(&usba_device->usb_mutex); 1001 } 1002 1003 1004 /* get pipe_handle_impl ptr for this ep */ 1005 usba_pipe_handle_data_t * 1006 usba_hcdi_get_ph_data(usba_device_t *usba_device, uint8_t ep_addr) 1007 { 1008 return (usba_device->usb_ph_list[usb_get_ep_index(ep_addr)]. 1009 usba_ph_data); 1010 }