qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry);
DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp,
&qh->qtd_list, qtd_list_entry) {
+ if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list))
+ return;
qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
if (qtd->urb != NULL) {
hcd->fops->complete(hcd, qtd->urb->priv,
qtd->urb, -DWC_E_SHUTDOWN);
dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
+ } else {
+ return;
}
}
dwc_otg_hcd->non_periodic_qh_ptr = &dwc_otg_hcd->non_periodic_sched_active;
dwc_otg_hcd->non_periodic_channels = 0;
dwc_otg_hcd->periodic_channels = 0;
+ dwc_otg_hcd->frame_number =0;
hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
/* In some case, we don't disconnect a usb device, but
* disconnect intr was triggered, so check hprt0 here. */
- if ((!hprt0.b.prtenchng)
+ if (((!hprt0.b.prtenchng)
&& (!hprt0.b.prtconndet)
- && hprt0.b.prtconnsts) {
- DWC_PRINTF("%s: hprt0 = 0x%08x\n", __func__, hprt0.d32);
+ && hprt0.b.prtconnsts)
+ || !hprt0.b.prtenchng) {
+ DWC_PRINTF("%s: Invalid disconnect interrupt "
+ "hprt0 = 0x%08x\n", __func__, hprt0.d32);
return 1;
}
/*
*
* @param p void pointer to the <code>struct usb_hcd</code>
*/
-extern inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t *dwc_otg_hcd);
static int dwc_otg_hcd_rem_wakeup_cb(void *p)
{
dwc_otg_hcd_t *dwc_otg_hcd = p;
- struct usb_hcd *hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);
+ struct usb_hcd *hcd = dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
if (dwc_otg_hcd->core_if->lx_state == DWC_OTG_L2) {
dwc_otg_hcd->flags.b.port_suspend_change = 1;
{
hprt0_data_t hprt0 = {.d32 = 0 };
struct dwc_otg_platform_data *pldata;
- pldata = hcd->core_if->otg_dev->pldata;
+ dwc_irqflags_t flags;
+ pldata = hcd->core_if->otg_dev->pldata;
DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n");
+ /*
+ * Set status flags for the hub driver.
+ */
+ hcd->flags.b.port_connect_status_change = 1;
+ hcd->flags.b.port_connect_status = 0;
+
/*
* The root hub should be disconnected before this function is called.
* The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue)
* and the QH lists (via ..._hcd_endpoint_disable).
*/
-
+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
/* Turn off all host-specific interrupts. */
dwc_otg_disable_host_interrupts(hcd->core_if);
+ kill_all_urbs(hcd);
+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
+
/* Turn off the vbus power */
DWC_PRINTF("PortPower off\n");
hprt0.b.prtpwr = 0;
dwc_otg_qtd_t *urb_qtd;
urb_qtd = dwc_otg_urb->qtd;
- if (((uint32_t) urb_qtd & 0xf0000000) == 0) {
+ if (!urb_qtd) {
DWC_PRINTF("%s error: urb_qtd is %p dwc_otg_urb %p!!!\n",
__func__, urb_qtd, dwc_otg_urb);
return 0;
int i;
dwc_hc_t *channel;
dwc_hc_t *channel_tmp;
+ dwc_irqflags_t flags;
+ dwc_spinlock_t *temp_lock;
hcd->flags.d32 = 0;
-
hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active;
hcd->non_periodic_channels = 0;
hcd->periodic_channels = 0;
+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
/*
* Put all channels in the free channel list and clean up channel
* states.
hc_list_entry);
dwc_otg_hc_cleanup(hcd->core_if, channel);
}
-
+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
/* Initialize the DWC core for host mode operation. */
dwc_otg_core_host_init(hcd->core_if);
/* Set core_if's lock pointer to the hcd->lock */
- hcd->core_if->lock = hcd->lock;
+ /* Should get this lock before modify it */
+ if (hcd->core_if->lock) {
+ DWC_SPINLOCK_IRQSAVE(hcd->core_if->lock, &flags);
+ temp_lock = hcd->core_if->lock;
+ hcd->core_if->lock = hcd->lock;
+ DWC_SPINUNLOCK_IRQRESTORE(temp_lock, flags);
+ } else {
+ hcd->core_if->lock = hcd->lock;
+ }
}
/**
* Set the split attributes
*/
hc->do_split = 0;
+ hc->csplit_nak = 0;
if (qh->do_split) {
uint32_t hub_addr, port_addr;
hc->do_split = 1;
dwc_hc_t *hc, uint16_t fifo_dwords_avail)
{
int retval;
-
+ if (!hc || !(hc->qh))
+ return -ENODEV;
if (hcd->core_if->dma_enable) {
if (hcd->core_if->dma_desc_enable) {
if (!hc->xfer_started
hc->qh->ping_state = 0;
}
} else if (!hc->xfer_started) {
+ if (!hc || !(hc->qh))
+ return -ENODEV;
dwc_otg_hc_start_transfer(hcd->core_if, hc);
hc->qh->ping_state = 0;
}