Skip to content

Commit

Permalink
Merge pull request #352 from P33M/rpi-3.6.y
Browse files Browse the repository at this point in the history
dwc_otg: root port and FIQ bugfixes
  • Loading branch information
popcornmix committed Aug 7, 2013
2 parents 833f700 + 6ea91ce commit 9b22cc2
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 6 deletions.
6 changes: 6 additions & 0 deletions drivers/usb/host/dwc_otg/dwc_otg_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1070,6 +1070,12 @@ static int __init dwc_otg_driver_init(void)
int retval = 0;
int error;
struct device_driver *drv;

if(fiq_split_enable && !fiq_fix_enable) {
printk(KERN_WARNING "dwc_otg: fiq_split_enable was set without fiq_fix_enable! Correcting.\n");
fiq_fix_enable = 1;
}

printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name,
DWC_DRIVER_VERSION,
#ifdef LM_INTERFACE
Expand Down
44 changes: 38 additions & 6 deletions drivers/usb/host/dwc_otg/dwc_otg_hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ static int last_sel_trans_num_avail_hc_at_end = 0;

extern int g_next_sched_frame, g_np_count, g_np_sent;

extern haint_data_t haint_saved;
extern hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS];
extern hcint_data_t hcint_saved[MAX_EPS_CHANNELS];
extern gintsts_data_t ginsts_saved;

dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void)
{
return DWC_ALLOC(sizeof(dwc_otg_hcd_t));
Expand Down Expand Up @@ -168,31 +173,43 @@ static void del_timers(dwc_otg_hcd_t * hcd)

/**
* Processes all the URBs in a single list of QHs. Completes them with
* -ETIMEDOUT and frees the QTD.
* -ESHUTDOWN and frees the QTD.
*/
static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
{
dwc_list_link_t *qh_item;
dwc_list_link_t *qh_item, *qh_tmp;
dwc_otg_qh_t *qh;
dwc_otg_qtd_t *qtd, *qtd_tmp;

DWC_LIST_FOREACH(qh_item, qh_list) {
DWC_LIST_FOREACH_SAFE(qh_item, qh_tmp, qh_list) {
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) {
qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
if (qtd->urb != NULL) {
hcd->fops->complete(hcd, qtd->urb->priv,
qtd->urb, -DWC_E_TIMEOUT);
qtd->urb, -DWC_E_SHUTDOWN);
dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
}

}
if(qh->channel) {
/* Using hcchar.chen == 1 is not a reliable test.
* It is possible that the channel has already halted
* but not yet been through the IRQ handler.
*/
dwc_otg_hc_halt(hcd->core_if, qh->channel,
DWC_OTG_HC_XFER_URB_DEQUEUE);
if(microframe_schedule)
hcd->available_host_channels++;
qh->channel = NULL;
}
dwc_otg_hcd_qh_remove(hcd, qh);
}
}

/**
* Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
* Responds with an error status of ESHUTDOWN to all URBs in the non-periodic
* and periodic schedules. The QTD associated with each URB is removed from
* the schedule and freed. This function may be called when a disconnect is
* detected or when the HCD is being stopped.
Expand Down Expand Up @@ -278,7 +295,8 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *p)
*/
dwc_otg_hcd->flags.b.port_connect_status_change = 1;
dwc_otg_hcd->flags.b.port_connect_status = 0;

if(fiq_fix_enable)
local_fiq_disable();
/*
* Shutdown any transfers in process by clearing the Tx FIFO Empty
* interrupt mask and status bits and disabling subsequent host
Expand Down Expand Up @@ -374,8 +392,22 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *p)
channel->qh = NULL;
}
}
if(fiq_split_enable) {
for(i=0; i < 128; i++) {
dwc_otg_hcd->hub_port[i] = 0;
}
haint_saved.d32 = 0;
for(i=0; i < MAX_EPS_CHANNELS; i++) {
hcint_saved[i].d32 = 0;
hcintmsk_saved[i].d32 = 0;
}
}

}

if(fiq_fix_enable)
local_fiq_enable();

if (dwc_otg_hcd->fops->disconnect) {
dwc_otg_hcd->fops->disconnect(dwc_otg_hcd);
}
Expand Down
7 changes: 7 additions & 0 deletions drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2660,6 +2660,13 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)

hc = dwc_otg_hcd->hc_ptr_array[num];
hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
if(hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
/* We are responding to a channel disable. Driver
* state is cleared - our qtd has gone away.
*/
release_channel(dwc_otg_hcd, hc, NULL, hc->halt_status);
return 1;
}
qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);

hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
Expand Down
11 changes: 11 additions & 0 deletions drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
case -DWC_E_OVERFLOW:
status = -EOVERFLOW;
break;
case -DWC_E_SHUTDOWN:
status = -ESHUTDOWN;
break;
default:
if (status) {
DWC_PRINTF("Uknown urb status %d\n", status);
Expand Down Expand Up @@ -794,11 +797,19 @@ static int dwc_otg_urb_enqueue(struct usb_hcd *hcd,
#if USB_URB_EP_LINKING
usb_hcd_unlink_urb_from_ep(hcd, urb);
#endif
DWC_FREE(dwc_otg_urb);
urb->hcpriv = NULL;
if (retval == -DWC_E_NO_DEVICE)
retval = -ENODEV;
}
}
#if USB_URB_EP_LINKING
else
{
DWC_FREE(dwc_otg_urb);
urb->hcpriv = NULL;
}
#endif
DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags);
return retval;
}
Expand Down

0 comments on commit 9b22cc2

Please sign in to comment.