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