Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xhci: make isoc_bei_interval variable interrupter specific.

isoc_bei_interval is used to balance how often completed isochronous
events cause interrupts. If interval is too large then the event ring
may fill up before the completed isoc TRBs are handled.

isoc_bei_interval is tuned based on how full the event ring is.

isoc_bei_interval variable needs to be per interrupter as
with several interrupters each one has its own event ring.

move isoc_bei_interval variable to the interrupter structure.

if a secondary interrupter does not care about this feature then
keep isoc_bei_interval 0.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
Link: https://lore.kernel.org/r/20240217001017.29969-4-quic_wcheng@quicinc.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Mathias Nyman and committed by
Greg Kroah-Hartman
becbd202 ace21625

+11 -8
+1 -1
drivers/usb/host/xhci-mem.c
··· 2533 2533 if (xhci_add_interrupter(xhci, ir, 0)) 2534 2534 goto fail; 2535 2535 2536 - xhci->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX; 2536 + ir->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX; 2537 2537 2538 2538 /* 2539 2539 * XXX: Might need to set the Interrupter Moderation Register to
+9 -6
drivers/usb/host/xhci-ring.c
··· 3153 3153 event_ring_deq = ir->event_ring->dequeue; 3154 3154 3155 3155 /* ring is half-full, force isoc trbs to interrupt more often */ 3156 - if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN) 3157 - xhci->isoc_bei_interval = xhci->isoc_bei_interval / 2; 3156 + if (ir->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN) 3157 + ir->isoc_bei_interval = ir->isoc_bei_interval / 2; 3158 3158 3159 3159 event_loop = 0; 3160 3160 } ··· 4022 4022 } 4023 4023 4024 4024 /* Check if we should generate event interrupt for a TD in an isoc URB */ 4025 - static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i) 4025 + static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i, 4026 + struct xhci_interrupter *ir) 4026 4027 { 4027 4028 if (xhci->hci_version < 0x100) 4028 4029 return false; ··· 4034 4033 * If AVOID_BEI is set the host handles full event rings poorly, 4035 4034 * generate an event at least every 8th TD to clear the event ring 4036 4035 */ 4037 - if (i && xhci->quirks & XHCI_AVOID_BEI) 4038 - return !!(i % xhci->isoc_bei_interval); 4036 + if (i && ir->isoc_bei_interval && xhci->quirks & XHCI_AVOID_BEI) 4037 + return !!(i % ir->isoc_bei_interval); 4039 4038 4040 4039 return true; 4041 4040 } ··· 4044 4043 static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, 4045 4044 struct urb *urb, int slot_id, unsigned int ep_index) 4046 4045 { 4046 + struct xhci_interrupter *ir; 4047 4047 struct xhci_ring *ep_ring; 4048 4048 struct urb_priv *urb_priv; 4049 4049 struct xhci_td *td; ··· 4062 4060 4063 4061 xep = &xhci->devs[slot_id]->eps[ep_index]; 4064 4062 ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; 4063 + ir = xhci->interrupters[0]; 4065 4064 4066 4065 num_tds = urb->number_of_packets; 4067 4066 if (num_tds < 1) { ··· 4150 4147 td->last_trb = ep_ring->enqueue; 4151 4148 td->last_trb_seg = ep_ring->enq_seg; 4152 4149 field |= TRB_IOC; 4153 - if (trb_block_event_intr(xhci, num_tds, i)) 4150 + if (trb_block_event_intr(xhci, num_tds, i, ir)) 4154 4151 field |= TRB_BEI; 4155 4152 } 4156 4153 /* Calculate TRB length */
+1 -1
drivers/usb/host/xhci.h
··· 1433 1433 struct xhci_intr_reg __iomem *ir_set; 1434 1434 unsigned int intr_num; 1435 1435 bool ip_autoclear; 1436 + u32 isoc_bei_interval; 1436 1437 /* For interrupter registers save and restore over suspend/resume */ 1437 1438 u32 s3_irq_pending; 1438 1439 u32 s3_irq_control; ··· 1506 1505 u8 isoc_threshold; 1507 1506 /* imod_interval in ns (I * 250ns) */ 1508 1507 u32 imod_interval; 1509 - u32 isoc_bei_interval; 1510 1508 int event_ring_max; 1511 1509 /* 4KB min, 128MB max */ 1512 1510 int page_size;