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