struct list_head *qtd_item;
dwc_otg_qtd_t *qtd;
struct urb *urb;
- struct usb_host_endpoint *ep;
list_for_each(qh_item, _qh_list) {
qh = list_entry(qh_item, dwc_otg_qh_t, qh_list_entry);
qtd_item = qh->qtd_list.next) {
qtd = list_entry(qtd_item, dwc_otg_qtd_t, qtd_list_entry);
if (qtd->urb != NULL) {
- urb = qtd->urb;
- ep = qtd->urb->ep;
+ urb = qtd->urb;
// 20110415 yk
// urb will be re entry to ep->urb_list if use ETIMEOUT
- dwc_otg_hcd_complete_urb(_hcd, qtd->urb,
- -ETIMEDOUT);//ESHUTDOWN
-
- //if(!list_empty(&ep->urb_list))
- DWC_PRINT("%s: urb %p, device %d, ep %d %s, status=%d\n",
- __func__, urb, usb_pipedevice(urb->pipe),
- usb_pipeendpoint(urb->pipe),
- usb_pipein(urb->pipe) ? "IN" : "OUT", urb->unlinked);
-
- if (!urb->unlinked)
- urb->unlinked = -ESHUTDOWN;
-
+ dwc_otg_hcd_complete_urb(_hcd, urb,
+ -ESHUTDOWN);//ETIMEDOUT,ENOENT
}
dwc_otg_hcd_qtd_remove_and_free(qtd);
}
dwc_otg_disable_host_interrupts( dwc_otg_hcd->core_if );
}
-
+
+ spin_lock(&dwc_otg_hcd->global_lock);
/* Respond with an error status to all URBs in the schedule. */
kill_all_urbs(dwc_otg_hcd);
+ spin_unlock(&dwc_otg_hcd->global_lock);
if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
/* Clean up any host channels that were in use. */
/* Initialize the DWC OTG HCD. */
dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
+
+ spin_lock_init(&dwc_otg_hcd->global_lock);
+
dwc_otg_hcd->core_if = otg_dev->core_if;
otg_dev->hcd = dwc_otg_hcd;
dwc_otg_hcd->host_enabled = 0;
#endif
+ spin_lock_init(&dwc_otg_hcd->global_lock);
+
/* Register the HCD CIL Callbacks */
dwc_otg_cil_register_hcd_callbacks(otg_dev->core_if,
dwc_otg_hcd->host_enabled = 0;
#endif
+ spin_lock_init(&dwc_otg_hcd->global_lock);
/* Register the HCD CIL Callbacks */
dwc_otg_cil_register_hcd_callbacks(otg_dev->core_if,
{
dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_hcd);
dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
+ unsigned long flags;
struct usb_bus *bus;
DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
+ local_irq_save(flags);
bus = hcd_to_bus(_hcd);
_hcd->state = HC_STATE_RUNNING;
}
hcd_reinit(dwc_otg_hcd);
out:
+ local_irq_restore(flags);
return 0;
}
int retval;
dwc_otg_hcd_t * dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd);
dwc_otg_qtd_t * qtd;
-#if 0
- retval = usb_hcd_link_urb_to_ep(_hcd, _urb);
- if (retval)
- {
- DWC_PRINT("%s, usb_hcd_link_urb_to_ep error\n", __func__);
- return retval;
- }
-#endif
+
+ if(atomic_read(&_urb->use_count)>1){
+ retval = -EPERM;
+ dump_stack();
+ DWC_PRINT("%s urb %p already in queue, qtd %p, count%d\n", __func__, _urb, _urb->hcpriv, atomic_read(&_urb->use_count));
+ goto out;
+ }
#ifdef DEBUG
if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
dump_urb_info(_urb, "dwc_otg_hcd_urb_enqueue");
}
#endif /* */
if (!dwc_otg_hcd->flags.b.port_connect_status) {
+ DWC_ERROR("DWC OTG No longer connected\n");
/* No longer connected. */
retval = -ENODEV;
goto out;
DWC_SOF_INTR_MASK);
#endif
out:
-
return retval;
}
dwc_otg_hcd_t * dwc_otg_hcd;
dwc_otg_qtd_t * urb_qtd;
dwc_otg_qh_t * qh;
- struct usb_host_endpoint *_ep = _urb->ep;//dwc_urb_to_endpoint(_urb);
- //int retval;
+ struct usb_host_endpoint *_ep;
DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
- local_irq_save(flags);
- urb_qtd = (dwc_otg_qtd_t *) _urb->hcpriv;
+
+ if(((uint32_t)_urb&0xf0000000)==0)
+ DWC_PRINT("%s urb is %p\n", __func__, _urb);
+
+ _ep = dwc_urb_to_endpoint(_urb);
if(_ep==NULL)
{
DWC_PRINT("%s=====================================================\n",__func__);
DWC_PRINT("urb->ep is null\n");
return -1;
}
- qh = (dwc_otg_qh_t *) _ep->hcpriv;
- if(urb_qtd == NULL)
+
+ urb_qtd = (dwc_otg_qtd_t *) _urb->hcpriv;
+ if(((uint32_t)urb_qtd&0xf0000000) == 0)
{
- DWC_PRINT("%s,urb_qtd is null\n",__func__);
- goto urb_qtd_null;
- //return -1;
+ DWC_PRINT("%s,urb_qtd is %p urb %p, count %d\n",__func__, urb_qtd, _urb, atomic_read(&_urb->use_count));
+ if((atomic_read(&_urb->use_count)) == 0)
+ return 0;
+ else
+ return -1;
}
+ qh = (dwc_otg_qh_t *) _ep->hcpriv;
dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd);
+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags);
#ifdef DEBUG
if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
if (urb_qtd == qh->qtd_in_process) {
/* The QTD is in process (it has been assigned to a channel). */
if (dwc_otg_hcd->flags.b.port_connect_status) {
+ DWC_PRINT("%s urb %p in process\n", __func__, _urb);
/*
* If still connected (i.e. in host mode), halt the
dwc_otg_hcd_qh_remove(dwc_otg_hcd, qh);
}
- local_irq_restore(flags);
-urb_qtd_null:
_urb->hcpriv = NULL;
- //usb_hcd_unlink_urb_from_ep(_hcd, _urb);
+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags);
/* Higher layer software sets URB status. */
usb_hcd_giveback_urb(_hcd, _urb, _status);
if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
struct usb_host_endpoint *_ep)
{
+ unsigned long flags;
dwc_otg_qh_t *qh;
dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd);
+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags);
+
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));
_ep->hcpriv = NULL;
}
+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags);
+
return;
}
* This function is called by the USB core when an interrupt occurs */
irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *_hcd)
{
+ irqreturn_t result;
+ unsigned long flags;
dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_hcd);
- return IRQ_RETVAL(dwc_otg_hcd_handle_intr(dwc_otg_hcd));
+
+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags);
+
+ result = IRQ_RETVAL(dwc_otg_hcd_handle_intr(dwc_otg_hcd));
+
+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags);
+
+ return result;
}
/** Creates Status Change bitmap for the root hub and root port. The bitmap is
u16 _wLength)
{
int retval = 0;
+ unsigned long flags;
dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd (_hcd);
dwc_otg_core_if_t *core_if = hcd_to_dwc_otg_hcd (_hcd)->core_if;
hprt0_data_t hprt0 = {.d32 = 0};
uint32_t port_status;
+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags);
switch (_typeReq) {
case ClearHubFeature:
hprt0.b.prtrst = 1;
dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
}
+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags);
/* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
// kever @rk 20110712
// can not use mdelay(60) while irq disable
//MDELAY (60);
msleep(60);
+ spin_lock_irqsave(&dwc_otg_hcd->global_lock, flags);
hprt0.b.prtrst = 0;
dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
break;
break;
}
+ spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags);
return retval;
}
_urb->status = _status;
_urb->hcpriv = NULL;
+ spin_unlock(&_hcd->global_lock);
usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(_hcd), _urb, _status);
+ spin_lock(&_hcd->global_lock);
}
void dwc_otg_clear_halt(struct urb *_urb)
int32_t dwc_otg_hcd_handle_hc_intr (dwc_otg_hcd_t *_dwc_otg_hcd)
{
int retval = 0;
- haint_data_t haint;
+ volatile haint_data_t haint;
int hcnum;
struct list_head *qh_entry;
dwc_otg_qh_t *qh;
+ int i;
/* Clear appropriate bits in HCINTn to clear the interrupt bit in
* GINTSTS */
haint.d32 = dwc_otg_read_host_all_channels_intr(_dwc_otg_hcd->core_if);
#if 0
- int i;
for (i = 0; i < _dwc_otg_hcd->core_if->core_params->host_channels; i++) {
if (haint.b2.chint & (1 << i))
retval |= dwc_otg_hcd_handle_hc_n_intr(_dwc_otg_hcd, i);
qh_entry = qh_entry->next;
if(qh->qh_state != QH_QUEUED)
continue;
+ if(qh->channel == NULL){
+ DWC_PRINT("%s channel NULL 1\n", __func__);
+ break;
+ }
hcnum = qh->channel->hc_num;
if (haint.b2.chint & (1 << hcnum)) {
retval |= dwc_otg_hcd_handle_hc_n_intr (_dwc_otg_hcd, hcnum);
}
}
+ haint.d32 = dwc_otg_read_host_all_channels_intr(_dwc_otg_hcd->core_if);
qh_entry = _dwc_otg_hcd->non_periodic_sched_active.next;
while (&_dwc_otg_hcd->non_periodic_sched_active != qh_entry){
qh = list_entry(qh_entry, dwc_otg_qh_t, qh_list_entry);
qh_entry = qh_entry->next;
+ if(qh->channel == NULL){
+ DWC_PRINT("%s channel NULL 2\n", __func__);
+ break;
+ }
hcnum = qh->channel->hc_num;
if (haint.b2.chint & (1 << hcnum)) {
retval |= dwc_otg_hcd_handle_hc_n_intr (_dwc_otg_hcd, hcnum);
}
}
haint.d32 = dwc_otg_read_host_all_channels_intr(_dwc_otg_hcd->core_if);
- int i;
for (i = 0; i < _dwc_otg_hcd->core_if->core_params->host_channels; i++) {
if (haint.b2.chint & (1 << i))
retval |= dwc_otg_hcd_handle_hc_n_intr(_dwc_otg_hcd, i);
int free_qtd;
int continue_trans = 1;
- if((!_qtd)|(_qtd->urb == NULL))
- {
+ if(((uint32_t) _qtd & 0xf0000000)==0){
+ DWC_PRINT("%s qtd %p, status %d\n", __func__, _qtd, _halt_status);
goto cleanup;
}
+ if(((uint32_t) _qtd->urb & 0xf0000000)==0){
+ DWC_PRINT("%s urb %p, status %d\n", __func__, _qtd->urb, _halt_status);
+ goto cleanup;
+ }
+
DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n",
__func__, _hc->hc_num, _halt_status);
switch (_halt_status) {
{
DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
"Babble Error--\n", _hc->hc_num);
+ DWC_PRINT("%s \n", __func__);
if (_hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
dwc_otg_hcd_complete_urb(_hcd, _qtd->urb, -EOVERFLOW);
halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_BABBLE_ERR);
if((_qtd==NULL)||(_qtd->urb == NULL))
{
+ DWC_PRINT("%s qtd->urb %p NULL\n", __func__, _qtd);
goto out;
}
switch (usb_pipetype(_qtd->urb->pipe)) {
hc = _dwc_otg_hcd->hc_ptr_array[_num];
hc_regs = _dwc_otg_hcd->core_if->host_if->hc_regs[_num];
qtd = list_entry(hc->qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry);
-
hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk);
DWC_DEBUGPL(DBG_HCDV, " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n",