aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_hcd.c24
-rw-r--r--drivers/usb/gadget/dwc_otg/dwc_otg_hcd_intr.c8
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);
}
}
}