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