Changeset 4db49344 in mainline for uspace/drv/bus/usb/uhci/hc.c
- Timestamp:
- 2018-01-23T21:52:28Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3dd80f8
- Parents:
- a6afb4c
- git-author:
- Ondřej Hlavatý <aearsis@…> (2018-01-23 20:49:35)
- git-committer:
- Ondřej Hlavatý <aearsis@…> (2018-01-23 21:52:28)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/hc.c
ra6afb4c r4db49344 97 97 98 98 static void hc_init_hw(const hc_t *instance); 99 static int hc_init_mem_structures(hc_t *instance , hc_device_t *);99 static int hc_init_mem_structures(hc_t *instance); 100 100 static int hc_init_transfer_lists(hc_t *instance); 101 101 … … 164 164 /* Lower 2 bits are transaction error and transaction complete */ 165 165 if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) { 166 LIST_INITIALIZE(done); 167 transfer_list_remove_finished( 168 &instance->transfers_interrupt, &done); 169 transfer_list_remove_finished( 170 &instance->transfers_control_slow, &done); 171 transfer_list_remove_finished( 172 &instance->transfers_control_full, &done); 173 transfer_list_remove_finished( 174 &instance->transfers_bulk_full, &done); 175 176 list_foreach_safe(done, current, next) { 177 list_remove(current); 178 uhci_transfer_batch_t *batch = 179 uhci_transfer_batch_from_link(current); 180 usb_transfer_batch_finish(&batch->base); 181 } 182 } 166 transfer_list_check_finished(&instance->transfers_interrupt); 167 transfer_list_check_finished(&instance->transfers_control_slow); 168 transfer_list_check_finished(&instance->transfers_control_full); 169 transfer_list_check_finished(&instance->transfers_bulk_full); 170 } 171 183 172 /* Resume interrupts are not supported */ 184 173 if (status & UHCI_STATUS_RESUME) { … … 239 228 hw_res->io_ranges.ranges[0].size); 240 229 241 ret = hc_init_mem_structures(instance , hcd);230 ret = hc_init_mem_structures(instance); 242 231 if (ret != EOK) { 243 232 usb_log_error("Failed to init UHCI memory structures: %s.", … … 328 317 } 329 318 319 static int endpoint_register(endpoint_t *ep) 320 { 321 hc_t * const hc = bus_to_hc(endpoint_get_bus(ep)); 322 323 const int err = usb2_bus_ops.endpoint_register(ep); 324 if (err) 325 return err; 326 327 transfer_list_t *list = hc->transfers[ep->device->speed][ep->transfer_type]; 328 if (!list) 329 /* 330 * We don't support this combination (e.g. isochronous). Do not 331 * fail early, because that would block any device with these 332 * endpoints from connecting. Instead, make sure these transfers 333 * are denied soon enough with ENOTSUP not to fail on asserts. 334 */ 335 return EOK; 336 337 endpoint_set_online(ep, &list->guard); 338 return EOK; 339 } 340 330 341 static void endpoint_unregister(endpoint_t *ep) 331 342 { 332 343 hc_t * const hc = bus_to_hc(endpoint_get_bus(ep)); 333 344 usb2_bus_ops.endpoint_unregister(ep); 334 335 uhci_transfer_batch_t *batch = NULL;336 345 337 346 // Check for the roothub, as it does not schedule into lists … … 344 353 345 354 transfer_list_t *list = hc->transfers[ep->device->speed][ep->transfer_type]; 346 347 355 if (!list) 348 356 /* … … 352 360 return; 353 361 354 // To avoid ABBA deadlock, we need to take the list first355 362 fibril_mutex_lock(&list->guard); 356 fibril_mutex_lock(&ep->guard); 357 if (ep->active_batch) { 358 batch = uhci_transfer_batch_get(ep->active_batch); 359 endpoint_deactivate_locked(ep); 360 transfer_list_remove_batch(list, batch); 361 } 362 fibril_mutex_unlock(&ep->guard); 363 364 endpoint_set_offline_locked(ep); 365 /* From now on, no other transfer will be scheduled. */ 366 367 if (!ep->active_batch) { 368 fibril_mutex_unlock(&list->guard); 369 return; 370 } 371 372 /* First, offer the batch a short chance to be finished. */ 373 endpoint_wait_timeout_locked(ep, 10000); 374 375 if (!ep->active_batch) { 376 fibril_mutex_unlock(&list->guard); 377 return; 378 } 379 380 uhci_transfer_batch_t * const batch = 381 uhci_transfer_batch_get(ep->active_batch); 382 383 /* Remove the batch from the schedule to stop it from being finished. */ 384 endpoint_deactivate_locked(ep); 385 transfer_list_remove_batch(list, batch); 386 363 387 fibril_mutex_unlock(&list->guard); 364 388 365 if (batch) { 366 // The HW could have been looking at the batch. 367 // Better wait two frames before we release the buffers. 368 async_usleep(2000); 369 batch->base.error = EINTR; 370 batch->base.transferred_size = 0; 371 usb_transfer_batch_finish(&batch->base); 372 } 389 /* 390 * We removed the batch from software schedule only, it's still possible 391 * that HC has it in its caches. Better wait a while before we release 392 * the buffers. 393 */ 394 async_usleep(20000); 395 batch->base.error = EINTR; 396 batch->base.transferred_size = 0; 397 usb_transfer_batch_finish(&batch->base); 373 398 } 374 399 … … 382 407 .status = hc_status, 383 408 409 .endpoint_register = endpoint_register, 384 410 .endpoint_unregister = endpoint_unregister, 385 411 .endpoint_count_bw = bandwidth_count_usb11, … … 400 426 * - frame list page (needs to be one UHCI hw accessible 4K page) 401 427 */ 402 int hc_init_mem_structures(hc_t *instance , hc_device_t *hcd)428 int hc_init_mem_structures(hc_t *instance) 403 429 { 404 430 assert(instance); … … 425 451 return ENOMEM; 426 452 } 453 list_initialize(&instance->pending_endpoints); 427 454 usb_log_debug("Initialized transfer lists."); 428 455 … … 514 541 } 515 542 516 /** Schedule batch for execution. 543 /** 544 * Schedule batch for execution. 517 545 * 518 546 * @param[in] instance UHCI structure to use. 519 547 * @param[in] batch Transfer batch to schedule. 520 548 * @return Error code 521 *522 * Checks for bandwidth availability and appends the batch to the proper queue.523 549 */ 524 550 static int hc_schedule(usb_transfer_batch_t *batch) … … 531 557 return uhci_rh_schedule(&hc->rh, batch); 532 558 533 534 const int err = uhci_transfer_batch_prepare(uhci_batch); 535 if (err) 559 transfer_list_t * const list = 560 hc->transfers[ep->device->speed][ep->transfer_type]; 561 562 if (!list) 563 return ENOTSUP; 564 565 int err; 566 if ((err = uhci_transfer_batch_prepare(uhci_batch))) 536 567 return err; 537 568 538 transfer_list_t *list = hc->transfers[ep->device->speed][ep->transfer_type]; 539 assert(list); 540 transfer_list_add_batch(list, uhci_batch); 541 542 return EOK; 543 } 544 545 int hc_unschedule_batch(usb_transfer_batch_t *batch) 546 { 547 548 return EOK; 569 return transfer_list_add_batch(list, uhci_batch); 549 570 } 550 571
Note:
See TracChangeset
for help on using the changeset viewer.