68 lines
2.7 KiB
Diff
68 lines
2.7 KiB
Diff
From 370cbdb4a5ec521d9312b02bbaf269ed520b1451 Mon Sep 17 00:00:00 2001
|
|
From: P33M <P33M@github.com>
|
|
Date: Mon, 22 Apr 2013 00:08:36 +0100
|
|
Subject: [PATCH 060/174] dwc_otg: fix NAK holdoff and allow on split
|
|
transactions only
|
|
|
|
This corrects a bug where if a single active non-periodic endpoint
|
|
had at least one transaction in its qh, on frnum == MAX_FRNUM the qh
|
|
would get skipped and never get queued again. This would result in
|
|
a silent device until error detection (automatic or otherwise) would
|
|
either reset the device or flush and requeue the URBs.
|
|
|
|
Additionally the NAK holdoff was enabled for all transactions - this
|
|
would potentially stall a HS endpoint for 1ms if a previous error state
|
|
enabled this interrupt and the next response was a NAK. Fix so that
|
|
only split transactions get held off.
|
|
---
|
|
drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 28 ++++++++++++++++++----------
|
|
1 file changed, 18 insertions(+), 10 deletions(-)
|
|
|
|
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
|
|
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
|
|
@@ -46,7 +46,7 @@
|
|
#include "dwc_otg_hcd.h"
|
|
#include "dwc_otg_regs.h"
|
|
|
|
-extern bool microframe_schedule;
|
|
+extern bool microframe_schedule, nak_holdoff_enable;
|
|
|
|
//#define DEBUG_HOST_CHANNELS
|
|
#ifdef DEBUG_HOST_CHANNELS
|
|
@@ -1349,18 +1349,26 @@ dwc_otg_transaction_type_e dwc_otg_hcd_s
|
|
|
|
/*
|
|
* 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
|
|
+ * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed
|
|
* 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;
|
|
+ if (nak_holdoff_enable && qh->do_split) {
|
|
+ if (qh->nak_frame != 0xffff &&
|
|
+ dwc_full_frame_num(qh->nak_frame) ==
|
|
+ dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {
|
|
+ /*
|
|
+ * Revisit: Need to avoid trampling on periodic scheduling.
|
|
+ * Currently we are safe because g_np_count != g_np_sent whenever we hit this,
|
|
+ * but if this behaviour is changed then periodic endpoints will get a slower
|
|
+ * polling rate.
|
|
+ */
|
|
+ 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;
|
|
+ }
|
|
}
|
|
- else
|
|
- qh->nak_frame = 0xffff;
|
|
-
|
|
if (microframe_schedule) {
|
|
DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
|
|
if (hcd->available_host_channels < 1) {
|