Changeset d2c3dcd in mainline
- Timestamp:
- 2018-01-15T20:48:54Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c4e84ed6
- Parents:
- 309d9865
- git-author:
- Ondřej Hlavatý <aearsis@…> (2018-01-15 20:45:08)
- git-committer:
- Ondřej Hlavatý <aearsis@…> (2018-01-15 20:48:54)
- Location:
- uspace/drv/bus/usb/xhci
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/commands.c
r309d9865 rd2c3dcd 168 168 } 169 169 170 static void cr_set_state(xhci_cmd_ring_t *cr, xhci_cr_state_t state) 171 { 172 assert(fibril_mutex_is_locked(&cr->guard)); 173 174 cr->state = state; 175 if (state == XHCI_CR_STATE_OPEN 176 || state == XHCI_CR_STATE_CLOSED) 177 fibril_condvar_broadcast(&cr->state_cv); 178 } 179 180 static int wait_for_ring_open(xhci_cmd_ring_t *cr) 181 { 182 assert(fibril_mutex_is_locked(&cr->guard)); 183 184 while (true) { 185 switch (cr->state) { 186 case XHCI_CR_STATE_CHANGING: 187 case XHCI_CR_STATE_FULL: 188 fibril_condvar_wait(&cr->state_cv, &cr->guard); 189 break; 190 case XHCI_CR_STATE_OPEN: 191 return EOK; 192 case XHCI_CR_STATE_CLOSED: 193 return ENAK; 194 } 195 } 196 } 197 170 198 /** 171 199 * Enqueue a command on the TRB ring. Ring the doorbell to initiate processing. … … 179 207 fibril_mutex_lock(&cr->guard); 180 208 181 while (cr->state == XHCI_CR_STATE_CHANGING) 182 fibril_condvar_wait(&cr->state_cv, &cr->guard); 183 184 if (cr->state != XHCI_CR_STATE_OPEN) { 209 if (wait_for_ring_open(cr)) { 185 210 fibril_mutex_unlock(&cr->guard); 186 211 return ENAK; … … 191 216 list_append(&cmd->_header.link, &cr->cmd_list); 192 217 193 xhci_trb_ring_enqueue(&cr->trb_ring, &cmd->_header.trb, &cmd->_header.trb_phys); 194 hc_ring_doorbell(hc, 0, 0); 218 int err = EOK; 219 while (err == EOK) { 220 err = xhci_trb_ring_enqueue(&cr->trb_ring, 221 &cmd->_header.trb, &cmd->_header.trb_phys); 222 if (err != EAGAIN) 223 break; 224 225 cr_set_state(cr, XHCI_CR_STATE_FULL); 226 err = wait_for_ring_open(cr); 227 } 228 229 if (err == EOK) 230 hc_ring_doorbell(hc, 0, 0); 195 231 196 232 fibril_mutex_unlock(&cr->guard); 197 233 198 return EOK;234 return err; 199 235 } 200 236 … … 210 246 211 247 // Prevent others from starting CR again. 212 cr->state = XHCI_CR_STATE_CLOSED; 213 fibril_condvar_broadcast(&cr->state_cv); 248 cr_set_state(cr, XHCI_CR_STATE_CLOSED); 214 249 215 250 XHCI_REG_SET(hc->op_regs, XHCI_OP_CS, 1); … … 299 334 300 335 int code = TRB_GET_CODE(*trb); 301 const uint64_t phys = TRB_GET_PHYS(*trb);302 303 xhci_trb_ring_update_dequeue(&cr->trb_ring, phys);304 336 305 337 if (code == XHCI_TRBC_COMMAND_RING_STOPPED) { … … 316 348 return EOK; 317 349 } 350 351 const uint64_t phys = TRB_GET_PHYS(*trb); 352 xhci_trb_ring_update_dequeue(&cr->trb_ring, phys); 353 354 if (cr->state == XHCI_CR_STATE_FULL) 355 cr_set_state(cr, XHCI_CR_STATE_OPEN); 318 356 319 357 xhci_cmd_t *command = find_command(hc, phys); … … 592 630 fibril_mutex_lock(&cr->guard); 593 631 594 if (cr->state != XHCI_CR_STATE_OPEN) { 595 // The CR is either stopped, or different fibril is already 596 // restarting it. 597 usb_log_debug2("Command ring already being stopped."); 632 if (cr->state == XHCI_CR_STATE_CLOSED) { 633 fibril_mutex_unlock(&cr->guard); 634 return ENAK; 635 } 636 637 if (cr->state == XHCI_CR_STATE_CHANGING) { 598 638 fibril_mutex_unlock(&cr->guard); 599 639 return EOK; … … 602 642 usb_log_error("Timeout while waiting for command: aborting current command."); 603 643 604 cr->state = XHCI_CR_STATE_CHANGING; 605 fibril_condvar_broadcast(&cr->state_cv); 644 cr_set_state(cr, XHCI_CR_STATE_CHANGING); 606 645 607 646 abort_command_ring(hc); … … 616 655 usb_log_error("Command didn't abort."); 617 656 618 cr->state = XHCI_CR_STATE_CLOSED; 619 fibril_condvar_broadcast(&cr->state_cv); 657 cr_set_state(cr, XHCI_CR_STATE_CLOSED); 620 658 621 659 // TODO: Reset HC completely. … … 626 664 } 627 665 666 cr_set_state(cr, XHCI_CR_STATE_OPEN); 667 668 fibril_mutex_unlock(&cr->guard); 669 628 670 usb_log_error("Command ring stopped. Starting again."); 629 671 hc_ring_doorbell(hc, 0, 0); 630 672 631 cr->state = XHCI_CR_STATE_OPEN;632 fibril_condvar_broadcast(&cr->state_cv);633 634 fibril_mutex_unlock(&cr->guard);635 673 return EOK; 636 674 } -
uspace/drv/bus/usb/xhci/commands.h
r309d9865 rd2c3dcd 73 73 XHCI_CR_STATE_OPEN, /**< Commands are enqueued normally. */ 74 74 XHCI_CR_STATE_CHANGING, /**< Commands wait until state changes. */ 75 } xhci_cr_state; 75 XHCI_CR_STATE_FULL, /**< Commands wait until something completes. */ 76 } xhci_cr_state_t; 76 77 77 78 typedef struct xhci_command_ring { … … 81 82 list_t cmd_list; 82 83 83 xhci_cr_state state; /**< Whether commands are allowed to be84 xhci_cr_state_t state; /**< Whether commands are allowed to be 84 85 added. */ 85 86 fibril_condvar_t state_cv; /**< For waiting on CR state change. */
Note:
See TracChangeset
for help on using the changeset viewer.