Skip to content
Permalink
Browse files

Enable fiq fix by default. Add NAK holdoff scheme. Enabled by default…

…, disable with dwc_otg.nak_holdoff_enable=0. Thanks gsh
  • Loading branch information...
popcornmix committed Sep 13, 2012
1 parent 9b2353b commit a8afdd5fbccb49a1e4cce13fd93346a8ef0cc462
@@ -241,7 +241,10 @@ static struct dwc_otg_driver_module_params dwc_otg_module_params = {
};

//Global variable to switch the fiq fix on or off
bool fiq_fix_enable = false;
bool fiq_fix_enable = true;

//Global variable to switch the nak holdoff on or off
bool nak_holdoff_enable = true;


/**
@@ -1086,6 +1089,7 @@ static int __init dwc_otg_driver_init(void)
return retval;
}
printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled");
printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff_enable ? "enabled":"disabled");

error = driver_create_file(drv, &driver_attr_version);
#ifdef DEBUG
@@ -1366,9 +1370,10 @@ MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0");
module_param(microframe_schedule, bool, 0444);
MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler");


module_param(fiq_fix_enable, bool, 0444);
MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix");
module_param(nak_holdoff_enable, bool, 0444);
MODULE_PARM_DESC(nak_holdoff_enable, "Enable the NAK holdoff");

/** @page "Module Parameters"
*
@@ -527,6 +527,8 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
{
dwc_otg_qh_t *qh;
dwc_otg_qtd_t *urb_qtd;
BUG_ON(!hcd);
BUG_ON(!dwc_otg_urb);

#ifdef DEBUG /* integrity checks (Broadcom) */

@@ -543,14 +545,17 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd,
return -DWC_E_INVALID;
}
urb_qtd = dwc_otg_urb->qtd;
BUG_ON(!urb_qtd);
if (urb_qtd->qh == NULL) {
DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n");
return -DWC_E_INVALID;
}
#else
urb_qtd = dwc_otg_urb->qtd;
BUG_ON(!urb_qtd);
#endif
qh = urb_qtd->qh;
BUG_ON(!qh);
if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
if (urb_qtd->in_process) {
dump_channel_info(hcd, qh);
@@ -1309,6 +1314,22 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
num_channels - hcd->periodic_channels) &&
!DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) {

qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);

/*
* Check to see if this is a NAK'd retransmit, in which case ignore for retransmission
* we hold off on bulk retransmissions to reduce NAK interrupt overhead for
* cheeky devices that just hold off using NAKs
*/
if (dwc_full_frame_num(qh->nak_frame) == dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {
// Make fiq interrupt run on next frame (i.e. 8 uframes)
g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM;
qh_ptr = DWC_LIST_NEXT(qh_ptr);
continue;
}
else
qh->nak_frame = 0xffff;

if (microframe_schedule) {
DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
if (hcd->available_host_channels < 1) {
@@ -1321,7 +1342,6 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
last_sel_trans_num_nonper_scheduled++;
#endif /* DEBUG_HOST_CHANNELS */
}
qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry);

assign_and_init_hc(hcd, qh);

@@ -321,6 +321,11 @@ typedef struct dwc_otg_qh {
*/
uint16_t sched_frame;

/*
** Frame a NAK was received on this queue head, used to minimise NAK retransmission
*/
uint16_t nak_frame;

/** (micro)frame at which last start split was initialized. */
uint16_t start_split_frame;

@@ -56,7 +56,12 @@ int fiq_done, int_done;
int g_next_sched_frame, g_np_count, g_np_sent, g_work_expected;
static int mphi_int_count = 0 ;

extern bool fiq_fix_enable;
extern bool fiq_fix_enable, nak_holdoff_enable;

hcchar_data_t nak_hcchar;
hctsiz_data_t nak_hctsiz;
hcsplt_data_t nak_hcsplt;
int nak_count;

void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void)
{
@@ -230,7 +235,7 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31));
mphi_int_count = 0;
}
int_done++;
int_done++;
if((jiffies / HZ) > last_time)
{
/* Once a second output the fiq and irq numbers, useful for debug */
@@ -1418,6 +1423,18 @@ static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
"NAK Received--\n", hc->hc_num);

/*
* When we get bulk NAKs then remember this so we holdoff on this qh until
* the beginning of the next frame
*/
switch(dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
case UE_BULK:
//case UE_INTERRUPT:
//case UE_CONTROL:
if (nak_holdoff_enable)
hc->qh->nak_frame = dwc_otg_hcd_get_frame_number(hcd);
}

/*
* Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
* interrupt. Re-start the SSPLIT transfer.
@@ -181,6 +181,7 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb)
if (microframe_schedule)
qh->speed = dev_speed;

qh->nak_frame = 0xffff;

if (((dev_speed == USB_SPEED_LOW) ||
(dev_speed == USB_SPEED_FULL)) &&
@@ -764,6 +765,24 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh,
int sched_next_periodic_split)
{
if (dwc_qh_is_non_per(qh)) {

dwc_otg_qh_t *qh_tmp;
dwc_list_link_t *qh_list;
DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive)
{
qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry);
if(qh_tmp == qh)
{
/*
* FIQ is being disabled because this one nevers gets a np_count increment
* This is still not absolutely correct, but it should fix itself with
* just an unnecessary extra interrupt
*/
g_np_sent = g_np_count;
}
}


dwc_otg_hcd_qh_remove(hcd, qh);
if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) {
/* Add back to inactive non-periodic schedule. */

0 comments on commit a8afdd5

Please sign in to comment.
You can’t perform that action at this time.