Skip to content

Commit ecba5d7

Browse files
P33Mpopcornmix
P33M
authored andcommitted
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.
1 parent 9956047 commit ecba5d7

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

drivers/usb/host/dwc_otg/dwc_otg_hcd.c

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
#include "dwc_otg_hcd.h"
4747
#include "dwc_otg_regs.h"
4848

49-
extern bool microframe_schedule;
49+
extern bool microframe_schedule, nak_holdoff_enable;
5050

5151
//#define DEBUG_HOST_CHANNELS
5252
#ifdef DEBUG_HOST_CHANNELS
@@ -1349,18 +1349,26 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd)
13491349

13501350
/*
13511351
* Check to see if this is a NAK'd retransmit, in which case ignore for retransmission
1352-
* we hold off on bulk retransmissions to reduce NAK interrupt overhead for
1352+
* we hold off on bulk retransmissions to reduce NAK interrupt overhead for full-speed
13531353
* cheeky devices that just hold off using NAKs
13541354
*/
1355-
if (dwc_full_frame_num(qh->nak_frame) == dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {
1356-
// Make fiq interrupt run on next frame (i.e. 8 uframes)
1357-
g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM;
1358-
qh_ptr = DWC_LIST_NEXT(qh_ptr);
1359-
continue;
1355+
if (nak_holdoff_enable && qh->do_split) {
1356+
if (qh->nak_frame != 0xffff &&
1357+
dwc_full_frame_num(qh->nak_frame) ==
1358+
dwc_full_frame_num(dwc_otg_hcd_get_frame_number(hcd))) {
1359+
/*
1360+
* Revisit: Need to avoid trampling on periodic scheduling.
1361+
* Currently we are safe because g_np_count != g_np_sent whenever we hit this,
1362+
* but if this behaviour is changed then periodic endpoints will get a slower
1363+
* polling rate.
1364+
*/
1365+
g_next_sched_frame = ((qh->nak_frame + 8) & ~7) & DWC_HFNUM_MAX_FRNUM;
1366+
qh_ptr = DWC_LIST_NEXT(qh_ptr);
1367+
continue;
1368+
} else {
1369+
qh->nak_frame = 0xffff;
1370+
}
13601371
}
1361-
else
1362-
qh->nak_frame = 0xffff;
1363-
13641372
if (microframe_schedule) {
13651373
DWC_SPINLOCK_IRQSAVE(channel_lock, &flags);
13661374
if (hcd->available_host_channels < 1) {

0 commit comments

Comments
 (0)