IN SSPLIT/CSPLIT transfers, NAK packet will cause DWC_OTG
ctrl to generate lots of SSPLIT/CSPLIT transfer interrupts,
and seriously affect the performance of the system. So need
to stop queue transactions after receive SSPLIT/CSPLIT NAK.
*/
uint8_t do_split; /**< Enable split for the channel */
uint8_t complete_split; /**< Enable complete split */
*/
uint8_t do_split; /**< Enable split for the channel */
uint8_t complete_split; /**< Enable complete split */
uint8_t hub_addr; /**< Address of high speed hub */
uint8_t port_addr; /**< Port of the low/full speed device */
uint8_t hub_addr; /**< Address of high speed hub */
uint8_t port_addr; /**< Port of the low/full speed device */
* Set the split attributes
*/
hc->do_split = 0;
* Set the split attributes
*/
hc->do_split = 0;
if (qh->do_split) {
uint32_t hub_addr, port_addr;
hc->do_split = 1;
if (qh->do_split) {
uint32_t hub_addr, port_addr;
hc->do_split = 1;
{
dwc_otg_transaction_type_e tr_type;
int free_qtd;
{
dwc_otg_transaction_type_e tr_type;
int free_qtd;
+ int continue_trans = 1;
DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n",
__func__, hc->hc_num, halt_status);
DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n",
__func__, hc->hc_num, halt_status);
* deactivated. Don't want to do anything except release the
* host channel and try to queue more transfers.
*/
* deactivated. Don't want to do anything except release the
* host channel and try to queue more transfers.
*/
goto cleanup;
case DWC_OTG_HC_XFER_NO_HALT_STATUS:
free_qtd = 0;
goto cleanup;
case DWC_OTG_HC_XFER_NO_HALT_STATUS:
free_qtd = 0;
+ if (hc->csplit_nak) {
+ continue_trans = 0;
+ hc->csplit_nak = 0;
+ }
deactivate_qh(hcd, hc->qh, free_qtd);
cleanup:
deactivate_qh(hcd, hc->qh, free_qtd);
cleanup:
}
/* Try to queue more transfers now that there's a free channel. */
}
/* Try to queue more transfers now that there's a free channel. */
- tr_type = dwc_otg_hcd_select_transactions(hcd);
- if (tr_type != DWC_OTG_TRANSACTION_NONE) {
- dwc_otg_hcd_queue_transactions(hcd, tr_type);
+ if (continue_trans) {
+ tr_type = dwc_otg_hcd_select_transactions(hcd);
+ if (tr_type != DWC_OTG_TRANSACTION_NONE)
+ dwc_otg_hcd_queue_transactions(hcd, tr_type);
if (hc->complete_split) {
qtd->error_count = 0;
}
if (hc->complete_split) {
qtd->error_count = 0;
}
qtd->complete_split = 0;
halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
goto handle_nak_done;
qtd->complete_split = 0;
halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
goto handle_nak_done;