[PATCH v4 0/5] Add larger page size support for USB audio offload path
From: Wesley Cheng <hidden>
Date: 2026-09-10 01:51:06
Also in:
linux-usb, lkml
On some environments, 16kB pages can be enabled from the Linux subsystem, which manages the IOMMU mappings for the audio DSP within the system. In the current design, the following assumptions break when 16k pages are utilized: 1. xHCI ring size is equal to PAGE_SIZE 2. Ring addresses start at the beginning of a page When the USB offload driver maps the rings (w/ the audio DSP SID), it is set with a 16k granular, which is a problem, as several xHCI rings could exist on the same page. This is because the rings are currently allocated from the segment_pool. Hence, potentially mapping non USB audio related rings into the region accessible by the audio DSP. To mitigate this, this series introduces a separate segment_pool associated to a sideband ring. Before the USB audio offload path is enabled, the USB audio data streams/endpoint are not active. Only when the class driver issues a usb_set_interface() call (done from snd_usb_endpoint_prepare()), will the xHCI allocate the transfer ring resources. Which pool is selected is all based on if the sideband path is being enabled, and if so, memory can be allocated from that pool, which expects to be owned in conjunction with the audio DSP. This concept allows to keep the same model existing in xHCI, where multiple 4k segments can reside on the same page, which reduces potentially over allocating based on the page size. Likewise this mechanism also allows for the offload client driver to determine which SID is associated to the segment_pool if it decides to map outside of the Linux subsystem. The new ring allocation flow for sideband/offload clients will be as follows: qc_usb_audio_offload_probe() ├─ segment_pool = dma_pool_create(...) ▼ xhci_sideband_register(intf, XHCI_SIDEBAND_VENDOR, segment_pool, notify_client) │ sb->segment_pool = segment_pool ▼ uadev[card_num].sb = sb handle_uaudio_stream_req() ▼ enable_audio_stream(subs, ..., pcm_card_num) ├─ data_ep = uaudio_find_host_endpoint(subs, subs->data_endpoint) ├─ xhci_sideband_add_endpoint(sb, data_ep) ← ep->sideband = sb; sb->eps[ep_index] = ep ├─ snd_usb_endpoint_prepare(chip, sync_endpoint) ─┐ ├─ snd_usb_endpoint_prepare(chip, data_endpoint) ├─→ xhci_check_bandwidth() │ ▼ │ xhci_endpoint_init(xhci, virt_dev, ep, ...) │ pool = sideband ? sideband->segment_pool : xhci->segment_pool │ new_ring = xhci_ring_alloc_from_pool(..., pool, ...) │ ▼ │ xhci_ring_alloc_from_pool(..., pool, flags) │ ring->segment_pool = pool │ ▼ │ xhci_alloc_segments_for_ring(xhci, ring, flags) │ xhci_segment_alloc(xhci, ring->segment_pool, max_packet, num, flags) │ ▼ │ xhci_segment_alloc(xhci, pool, max_packet, num, flags) │ seg->trbs = dma_pool_zalloc(pool, flags, &dma) ▼ xhci_sideband_get_endpoint_buffer(sb, data_ep) → xhci_ring_to_sgtable() qc_usb_audio_offload_disconnect() / unreg_xhci: ├─ segment_pool = sb->segment_pool ├─ xhci_sideband_unregister(sb) ▼ dma_pool_destroy(segment_pool) Similar logic is added for the secondary interrupter path as well. The USB offload class driver calls xhci_sideband_create_interrupter(), which will be responsible for allocating the secondary event ring. There is one point that was seen during disconnecting the USB audio device while audio offload was active, where the offload client driver was pre-maturely freeing the DMA pool before xHCI core was able to free the DMA memory allocated for the rings. This is the reason for needing to explicitly call the ring free during the sideband unregister path. This was confirmed to work on the SM8350 MTP platform, with the CONFIG_ARM64_16K_PAGES config enabled, alongside tinyaudio binaries: tinymix -D 0 set 513 1 (Enables USB_RX multimedia#1 path) tinyplay -D 0 -d 0.... (Routes PCM data to ASoC platform sound card) Signed-off-by: Wesley Cheng <redacted> --- Changes in v4: - Split xHCI patches from xHCI core and xHCI sideband. - Make the dedicated offload segment pool optional for secondary interrupter creation. (xfer rings support this already in previous revs) - Fixed some inter-patch build/functionality failures in qc_audio_offload. Incremental builds between patches now work on 4k pages. (16k support at end) - Link to v3: https://patch.msgid.link/20260903-16k_offload_v1_b4-v3-0-135928dc2408@oss.qualcomm.com Changes in v3: - Moved sideband segment pool assignment to when a sideband endpoint is added. - Address an issue where during USB device disconnect (while offload active), where the offload client driver is freeing the DMA pool before xHCI core is able to free the dma allocations. - Update xhci_ring_to_sgtable to correctly allocate and fill the sg table which capture rings within page offsets. - Link to v2: https://patch.msgid.link/20260828-16k_offload_v1_b4-v2-0-8a46369ebbb6@oss.qualcomm.com Changes in v2: - Moved from using alignment_req to having the offload driver maintain its own segment pool. - Fixed OOB condition seen in xhci_ring_to_sgtable() and will capture page offsets properly. - Addressed inter-patch build failures. - Link to v1: https://patch.msgid.link/20260824-16k_offload_v1_b4-v1-0-49a6be60ca30@oss.qualcomm.com To: Mathias Nyman <mathias.nyman@intel.com> To: Greg Kroah-Hartman <gregkh@linuxfoundation.org> To: Jaroslav Kysela <perex@perex.cz> To: Takashi Iwai <tiwai@suse.com> Cc: linux-usb@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-sound@vger.kernel.org --- Wesley Cheng (5): usb: xhci: sideband: fix ring sg table for sub-page TRB segments usb: xhci: Allow to specify a different segment pool for allocations usb: xhci: sideband: allocate sideband ring segments from a dedicated pool ALSA: usb-audio: qcom: tag sideband endpoints before ring allocation ALSA: usb-audio: qcom: fix xfer ring IOMMU unmap on 16K+ page kernels drivers/usb/host/xhci-mem.c | 63 ++++++++++------ drivers/usb/host/xhci-sideband.c | 97 +++++++++++++----------- drivers/usb/host/xhci.h | 16 ++-- include/linux/usb/xhci-sideband.h | 20 ++++- sound/usb/qcom/qc_audio_offload.c | 151 ++++++++++++++++++++++++++++++++------ 5 files changed, 247 insertions(+), 100 deletions(-) --- base-commit: e1e6e541c5c9cf548e9fdc35fc26808c82074440 change-id: 20260824-16k_offload_v1_b4-3d1460405774 Best regards, -- Wesley Cheng [off-list ref]