1 From 3cb2c23c6dba5ae74976e85329b880876fadd787 Mon Sep 17 00:00:00 2001
2 From: P33M <P33M@github.com>
3 Date: Mon, 22 Apr 2013 00:08:36 +0100
4 Subject: [PATCH 060/196] dwc_otg: fix NAK holdoff and allow on split
7 This corrects a bug where if a single active non-periodic endpoint
8 had at least one transaction in its qh, on frnum == MAX_FRNUM the qh
9 would get skipped and never get queued again. This would result in
10 a silent device until error detection (automatic or otherwise) would
11 either reset the device or flush and requeue the URBs.
13 Additionally the NAK holdoff was enabled for all transactions - this
14 would potentially stall a HS endpoint for 1ms if a previous error state
15 enabled this interrupt and the next response was a NAK. Fix so that
16 only split transactions get held off.
18 drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 28 ++++++++++++++++++----------
19 1 file changed, 18 insertions(+), 10 deletions(-)
21 diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
22 index 91eefec..eaa8f38 100644
23 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
24 +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
26 #include "dwc_otg_hcd.h"
27 #include "dwc_otg_regs.h"
29 -extern bool microframe_schedule;
30 +extern bool microframe_schedule, nak_holdoff_enable;
32 //#define DEBUG_HOST_CHANNELS
33 #ifdef DEBUG_HOST_CHANNELS
34 @@ -1349,18 +1349,26 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
37 * Check to see if this is a NAK'd retransmit, in which case ignore for retransmission
38 - * we hold off on bulk retransmissions to reduce NAK interrupt overhead for
39 + * we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed
40 * cheeky devices that just hold off using NAKs
42 - if (dwc_full_frame_num(qh->nak_frame) == dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {
43 - // Make fiq interrupt run on next frame (i.e. 8 uframes)
44 - g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM;
45 - qh_ptr = DWC_LIST_NEXT(qh_ptr);
47 + if (nak_holdoff_enable && qh->do_split) {
48 + if (qh->nak_frame != 0xffff &&
49 + dwc_full_frame_num(qh->nak_frame) ==
50 + dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {
52 + * Revisit: Need to avoid trampling on periodic scheduling.
53 + * Currently we are safe because g_np_count != g_np_sent whenever we hit this,
54 + * but if this behaviour is changed then periodic endpoints will get a slower
57 + g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM;
58 + qh_ptr = DWC_LIST_NEXT(qh_ptr);
61 + qh->nak_frame = 0xffff;
65 - qh->nak_frame = 0xffff;
67 if (microframe_schedule) {
68 DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
69 if (hcd->available_host_channels < 1) {