diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/dwc_otg/dwc_otg_hcd.c | 24 | ||||
-rw-r--r-- | drivers/usb/gadget/dwc_otg/dwc_otg_hcd_intr.c | 8 |
2 files changed, 28 insertions, 4 deletions
diff --git a/drivers/usb/gadget/dwc_otg/dwc_otg_hcd.c b/drivers/usb/gadget/dwc_otg/dwc_otg_hcd.c index 6b83ee46440..2fdf0ca99ea 100644 --- a/drivers/usb/gadget/dwc_otg/dwc_otg_hcd.c +++ b/drivers/usb/gadget/dwc_otg/dwc_otg_hcd.c @@ -273,6 +273,7 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *_p) dwc_hc_t * channel; dwc_otg_hc_regs_t * hc_regs; hcchar_data_t hcchar; + unsigned long flags; num_channels = dwc_otg_hcd->core_if->core_params->host_channels; if (!dwc_otg_hcd->core_if->dma_enable) { /* Flush out any channel requests in slave mode. */ @@ -303,6 +304,10 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *_p) dwc_otg_hc_cleanup(dwc_otg_hcd->core_if,channel); list_add_tail(&channel->hc_list_entry, &dwc_otg_hcd->free_hc_list); + local_irq_save(flags); + dwc_otg_hcd->available_host_channels ++; + local_irq_restore(flags); + } } } @@ -1042,23 +1047,38 @@ void dwc_otg_hcd_endpoint_disable(struct usb_hcd *_hcd, { dwc_otg_qh_t * qh; dwc_otg_hcd_t * dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd); + unsigned long flags; + int retry = 0; + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, " "endpoint=%d\n", _ep->desc.bEndpointAddress, dwc_ep_addr_to_endpoint(_ep->desc.bEndpointAddress)); + +rescan: + local_irq_save(flags); + qh = (dwc_otg_qh_t *) (_ep->hcpriv); if (qh != NULL) { -#ifdef CONFIG_DWC_DEBUG /** Check that the QTD list is really empty */ if (!list_empty(&qh->qtd_list)) { + if (retry++ < 250) { + local_irq_restore(flags); + schedule_timeout_uninterruptible(1); + goto rescan; + } +#ifdef CONFIG_DWC_DEBUG DWC_WARN("DWC OTG HCD EP DISABLE:" " QTD List for this endpoint is not empty\n"); +#endif /* */ } -#endif /* */ dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd, qh); _ep->hcpriv = NULL; } + + local_irq_restore(flags); + return; } diff --git a/drivers/usb/gadget/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/gadget/dwc_otg/dwc_otg_hcd_intr.c index 153c9a98c4a..595ea57e534 100644 --- a/drivers/usb/gadget/dwc_otg/dwc_otg_hcd_intr.c +++ b/drivers/usb/gadget/dwc_otg/dwc_otg_hcd_intr.c @@ -665,6 +665,7 @@ static dwc_otg_halt_status_e update_isoc_urb_state(dwc_otg_hcd_t * _hcd, frame_desc->status = -EPROTO; frame_desc->actual_length = get_actual_xfer_length(_hc, _hc_regs, _qtd, _halt_status,NULL); + break; default: DWC_ERROR("%s: Unhandled _halt_status (%d)\n", __func__, _halt_status); BUG(); @@ -752,7 +753,8 @@ static void release_channel(dwc_otg_hcd_t * _hcd, DWC_ERROR("%s: No halt_status, channel %d\n", __func__, _hc->hc_num); #endif - free_qtd = 0; + free_qtd = 1; + dwc_otg_hcd_complete_urb(_hcd, _qtd->urb, -EPROTO); break; default: free_qtd = 0; @@ -1197,6 +1199,7 @@ static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * _hcd, halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_ACK, must_free); } } else { +#if 0 _qtd->error_count = 0; if (_hc->qh->ping_state) { _hc->qh->ping_state = 0; @@ -1212,6 +1215,7 @@ static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * _hcd, } else { halt_channel(_hcd, _hc, _qtd, _hc->halt_status, must_free); } +#endif } /* @@ -1638,7 +1642,7 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * _hcd, __func__, _hc->hc_num, hcint.b.nyet, hcint.d32, dwc_read_reg32(&_hcd->core_if->core_global_regs->gintsts)); #endif - halt_channel(_hcd, _hc, _qtd, _hc->halt_status, must_free); + halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS, must_free); } } } |