Skip to content

Commit edcc09c

Browse files
committed
xhci: Set DESI bits in ERDP register correctly
When using more than one Event Ring segment (ERSTSZ > 1), software shall set the DESI bits in the ERDP register to the number of the segment to which the upper ERDP bits are pointing. The xHC may use the DESI bits as a shortcut to determine whether it needs to check for an Event Ring Full condition: If it's enqueueing events in a different segment, it need not compare its internal Enqueue Pointer with the Dequeue Pointer in the upper bits of the ERDP register (sec 5.5.2.3.3). Not setting the DESI bits correctly can result in the xHC enqueueing events past the Dequeue Pointer. On Renesas uPD720201 host controllers, incorrect DESI bits cause an interrupt storm. For comparison, VIA VL805 host controllers do not exhibit such problems. Perhaps they do not take advantage of the optimization afforded by the DESI bits. To fix the issue, assign the segment number to each struct xhci_segment in xhci_segment_alloc(). When advancing the Dequeue Pointer in xhci_update_erst_dequeue(), write the segment number to the DESI bits. On driver probe, set the DESI bits to zero in xhci_set_hc_event_deq() as processing starts in segment 0. Previously that function (incorrectly) treated the DESI bits as if they're declared RsvdP. Signed-off-by: Lukas Wunner <lukas@wunner.de>
1 parent b9757bf commit edcc09c

3 files changed

Lines changed: 12 additions & 11 deletions

File tree

drivers/usb/host/xhci-mem.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,
2929
unsigned int cycle_state,
3030
unsigned int max_packet,
31+
unsigned int num,
3132
gfp_t flags)
3233
{
3334
struct xhci_segment *seg;
@@ -59,6 +60,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,
5960
for (i = 0; i < TRBS_PER_SEGMENT; i++)
6061
seg->trbs[i].link.control = cpu_to_le32(TRB_CYCLE);
6162
}
63+
seg->num = num;
6264
seg->dma = dma;
6365
seg->next = NULL;
6466

@@ -328,23 +330,25 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
328330
unsigned int max_packet, gfp_t flags)
329331
{
330332
struct xhci_segment *prev;
333+
unsigned int num = 0;
331334
bool chain_links;
332335

333336
/* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */
334337
chain_links = !!(xhci_link_trb_quirk(xhci) ||
335338
(type == TYPE_ISOC &&
336339
(xhci->quirks & XHCI_AMD_0x96_HOST)));
337340

338-
prev = xhci_segment_alloc(xhci, cycle_state, max_packet, flags);
341+
prev = xhci_segment_alloc(xhci, cycle_state, max_packet, num, flags);
339342
if (!prev)
340343
return -ENOMEM;
341-
num_segs--;
344+
num++;
342345

343346
*first = prev;
344-
while (num_segs > 0) {
347+
while (num < num_segs) {
345348
struct xhci_segment *next;
346349

347-
next = xhci_segment_alloc(xhci, cycle_state, max_packet, flags);
350+
next = xhci_segment_alloc(xhci, cycle_state, max_packet, num,
351+
flags);
348352
if (!next) {
349353
prev = *first;
350354
while (prev) {
@@ -357,7 +361,7 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
357361
xhci_link_segments(prev, next, trbs_per_seg, type, chain_links);
358362

359363
prev = next;
360-
num_segs--;
364+
num++;
361365
}
362366
xhci_link_segments(prev, *first, trbs_per_seg, type, chain_links);
363367
*last = prev;
@@ -2133,7 +2137,6 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci)
21332137

21342138
static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
21352139
{
2136-
u64 temp;
21372140
dma_addr_t deq;
21382141

21392142
deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
@@ -2142,16 +2145,13 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
21422145
xhci_warn(xhci, "WARN something wrong with SW event ring "
21432146
"dequeue ptr.\n");
21442147
/* Update HC event ring dequeue pointer */
2145-
temp = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
2146-
temp &= ERST_PTR_MASK;
21472148
/* Don't clear the EHB bit (which is RW1C) because
21482149
* there might be more events to service.
21492150
*/
2150-
temp &= ~ERST_EHB;
21512151
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
21522152
"// Write event ring dequeue pointer, "
21532153
"preserving EHB bit");
2154-
xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK) | temp,
2154+
xhci_write_64(xhci, ((u64) deq & (u64) ~ERST_PTR_MASK),
21552155
&xhci->ir_set->erst_dequeue);
21562156
}
21572157

drivers/usb/host/xhci-ring.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3043,7 +3043,7 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
30433043
return;
30443044

30453045
/* Update HC event ring dequeue pointer */
3046-
temp_64 &= ERST_DESI_MASK;
3046+
temp_64 = xhci->event_ring->deq_seg->num & ERST_DESI_MASK;
30473047
temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK);
30483048
}
30493049

drivers/usb/host/xhci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,7 @@ struct xhci_segment {
15421542
union xhci_trb *trbs;
15431543
/* private to HCD */
15441544
struct xhci_segment *next;
1545+
unsigned int num;
15451546
dma_addr_t dma;
15461547
/* Max packet sized bounce buffer for td-fragmant alignment */
15471548
dma_addr_t bounce_dma;

0 commit comments

Comments
 (0)