From nobody Fri Aug 21 02:26:47 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hR41z4qFWz6pXXs for ; Fri, 21 Aug 2026 02:26:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hR41z3fKzz4Q24 for ; Fri, 21 Aug 2026 02:26:47 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787279207; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NJ41o8ARkGZINiM61tNv/+NCY0bS1CaJ6Zd7CzX8SKs=; b=DjlbtSpZNWFWFSc+znFV8wosRugLWBg6QxkfcNYw8hq+hdUG/hJwfI1GZP0JKZzGAtwB2X yZh+Pukitu9rGvt/ke63haYaW7rytfQAK8J11GPcV6i39SS+8lnHqzap3Zku940LitGBGV oUvWuR7saJJkz5eG5qtGh57ydlakbouARano5BKJZOkllYYBLk5Z2P46H1fkbkw/aqAshZ zfPKsbyA4kpsxqn0P3nvZ7VQ5izZ3NiKgcHZmschQX9D6zMhN8VOH1AwwqfRJETJ6a//tt rnpLi0CcY5GwtFqBdxZk6ZLwa6LREWHOHUUxyY9/9Mj9bMhy5MnPG1o/cim2ug== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1787279207; a=rsa-sha256; cv=none; b=JYrbo5ZNsiNKDSKUl9Ra+QLqALLyq+dze+nqhAAh9mG/Dwu5UH6eMV5zl5Eem7RbwPg/m4 ZoXnA/ATGziyl9bFP2guq/Kx+S+8E0nZ/aXTH4IOJgqki3py5XQYyW+IE7HLLmC2tVwDJz X0TVV1JdFXk/M5WnYyyImkgQY15mfK+k13tO+jNvOFVsegnid5UPJMQXH3+Yf6shTkXoji jjrYStg9R8Kv5vVrI/YZFV3wRlZDJNLRbuPg8IXiJa4xnZ6IJwtirEPQsignyAS7TaQK2+ XoU5H5nbj1FzNd9MKIFIikUJmNAf5HxpkStNTULvSRSRWrDEztTbqynDIjja+A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787279207; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NJ41o8ARkGZINiM61tNv/+NCY0bS1CaJ6Zd7CzX8SKs=; b=E52a13Lelpko6HzAO6FDYCnaYrtjM6neDew12mJYr/7CzkWf0by8hoshmn6UaphCw/MYN+ UxMxnEfh7zBRrgcUcIbK6BxjvTJqc6w4+y5fC+aHjJV2KxrBdX9i6zE7kCcKbdc0GC2NoU yTqF3YeUYunmvJkCy/wc9cwfktWJx9Od+k0oltwC8WE0SLPaUx1flmfU7b0elq11ajRsAB lHU4Yoci5kucEngxocyKkMGqYHxRSS7P6TL1QButBQz2lf5GHBmsjqxYcNGSmmy9AnQwZh NdvPxEMU5AGFqkxRgJqgarRYRYvHpri09A3xut5TQxBtKwtWhJgDM5e7aBzmKQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hR41z2B10zl5X for ; Fri, 21 Aug 2026 02:26:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3686a by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 21 Aug 2026 02:26:47 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Justin Hibbits Subject: git: 601312bf9fc6 - main - powerpc/dma: Fix accounting and loading large segments List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhibbits X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 601312bf9fc644aa0345374861f1fa5b640cb47d Auto-Submitted: auto-generated Date: Fri, 21 Aug 2026 02:26:47 +0000 Message-Id: <6a87b767.3686a.7a5b8642@gitrepo.freebsd.org> The branch main has been updated by jhibbits: URL: https://cgit.FreeBSD.org/src/commit/?id=601312bf9fc644aa0345374861f1fa5b640cb47d commit 601312bf9fc644aa0345374861f1fa5b640cb47d Author: Justin Hibbits AuthorDate: 2026-08-21 01:28:33 +0000 Commit: Justin Hibbits CommitDate: 2026-08-21 02:26:08 +0000 powerpc/dma: Fix accounting and loading large segments When the first page of a segment fits alignment, the second likely does not, so the DMA infrastructure (must_bounce()) thinks it needs to bounce the pages. Fix this by passing the previous end (address of byte following the previous segment) as a third argument to must_bounce(), so that the alignment check is done against the start of a new segment if and only if necessary, instead of the current page. Reviewed by: adrian Differential Revision: https://reviews.freebsd.org/D58627 --- sys/powerpc/powerpc/busdma_bounce.c | 67 ++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/sys/powerpc/powerpc/busdma_bounce.c b/sys/powerpc/powerpc/busdma_bounce.c index b3f629a50472..422231a8b71a 100644 --- a/sys/powerpc/powerpc/busdma_bounce.c +++ b/sys/powerpc/powerpc/busdma_bounce.c @@ -115,17 +115,34 @@ static SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, #include "../../kern/subr_busdma_bounce.c" /* - * Returns true if the address falls within the tag's exclusion window, or - * fails to meet its alignment requirements. + * Returns true if this page needs bouncing. + * + * A page needs bouncing if either: + * (1) its physical address is outside the tag's allowed range, or + * (2) it starts a new segment (i.e., paddr is not the direct continuation + * of the previous segment's end) and doesn't satisfy the tag's + * alignment constraint on that new segment's start. + * + * `seg_end` is the expected physical address of the byte immediately after + * the previous segment (i.e., prev_curaddr + prev_sgsize as passed to + * _bus_dmamap_addseg). Callers walking a buffer page-by-page should pass + * ~(bus_addr_t)0 for the first page (no previous segment) and update + * seg_end after each iteration from the actual curaddr they added to the + * segment list (source paddr if not bounced, bounce paddr if bounced). + * A page whose paddr matches seg_end continues the previous segment via + * addseg's coalescer and inherits alignment from the segment head; only + * physically-discontiguous pages start new segments requiring alignment + * re-check. */ static __inline bool -must_bounce(bus_dma_tag_t dmat, bus_addr_t paddr) +must_bounce(bus_dma_tag_t dmat, bus_addr_t paddr, bus_addr_t seg_end) { if (dmat->iommu == NULL && paddr > dmat->common.lowaddr && paddr <= dmat->common.highaddr) return (true); - if (!vm_addr_align_ok(paddr, dmat->common.alignment)) + if (paddr != seg_end && + !vm_addr_align_ok(paddr, dmat->common.alignment)) return (true); return (false); @@ -476,12 +493,24 @@ _bus_dmamap_count_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf, * needed in order to complete this transfer */ curaddr = buf; + /* + * Track the expected end of the previous segment so we mirror + * load_phys()'s decisions and don't under-count bounces. After + * a "would bounce" page, load will have replaced curaddr with a + * bounce paddr that won't match the next source paddr; count + * simulates that by resetting seg_end to 0 (which no source + * paddr can match on modern PPC where page 0 is reserved). + */ + bus_addr_t seg_end = ~(bus_addr_t)0; while (buflen != 0) { sgsize = buflen; - if (must_bounce(dmat, curaddr)) { + if (must_bounce(dmat, curaddr, seg_end)) { sgsize = MIN(sgsize, PAGE_SIZE - (curaddr & PAGE_MASK)); map->pagesneeded++; + seg_end = 0; + } else { + seg_end = curaddr + sgsize; } curaddr += sgsize; buflen -= sgsize; @@ -509,6 +538,7 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, */ vaddr = (vm_offset_t)buf; vendaddr = (vm_offset_t)buf + buflen; + bus_addr_t seg_end = ~(bus_addr_t)0; while (vaddr < vendaddr) { bus_size_t sg_len; @@ -519,9 +549,12 @@ _bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, pmap_t pmap, paddr = pmap_kextract(vaddr); else paddr = pmap_extract(pmap, vaddr); - if (must_bounce(dmat, paddr)) { + if (must_bounce(dmat, paddr, seg_end)) { sg_len = roundup2(sg_len, dmat->common.alignment); map->pagesneeded++; + seg_end = 0; + } else { + seg_end = paddr + sg_len; } vaddr += sg_len; } @@ -557,10 +590,12 @@ bounce_bus_dmamap_load_phys(bus_dma_tag_t dmat, } } + bus_addr_t seg_end = ~(bus_addr_t)0; while (buflen > 0) { curaddr = buf; sgsize = buflen; - if (map->pagesneeded != 0 && must_bounce(dmat, curaddr)) { + if (map->pagesneeded != 0 && + must_bounce(dmat, curaddr, seg_end)) { sgsize = MIN(sgsize, PAGE_SIZE - (curaddr & PAGE_MASK)); curaddr = add_bounce_page(dmat, map, 0, curaddr, sgsize); @@ -568,6 +603,13 @@ bounce_bus_dmamap_load_phys(bus_dma_tag_t dmat, if (!_bus_dmamap_addsegs(dmat, map, curaddr, sgsize, segs, segp)) break; + /* + * Track the added segment's end so must_bounce() on the next + * iteration correctly identifies whether we're continuing a + * segment (source contiguous with previous curaddr, which may + * itself be a bounce paddr) or starting a new one. + */ + seg_end = curaddr + sgsize; buf += sgsize; buflen -= sgsize; } @@ -619,6 +661,7 @@ bounce_bus_dmamap_load_buffer(bus_dma_tag_t dmat, } vaddr = buf; + bus_addr_t seg_end = ~(bus_addr_t)0; while (buflen > 0) { /* @@ -636,7 +679,8 @@ bounce_bus_dmamap_load_buffer(bus_dma_tag_t dmat, * Compute the segment size, and adjust counts. */ sgsize = MIN(buflen, PAGE_SIZE - (curaddr & PAGE_MASK)); - if (map->pagesneeded != 0 && must_bounce(dmat, curaddr)) { + if (map->pagesneeded != 0 && + must_bounce(dmat, curaddr, seg_end)) { sgsize = roundup2(sgsize, dmat->common.alignment); sgsize = MIN(sgsize, buflen); curaddr = add_bounce_page(dmat, map, kvaddr, curaddr, @@ -646,6 +690,13 @@ bounce_bus_dmamap_load_buffer(bus_dma_tag_t dmat, if (!_bus_dmamap_addsegs(dmat, map, curaddr, sgsize, segs, segp)) break; + /* + * Track the added segment's end so must_bounce() on the next + * iteration correctly identifies whether we're continuing a + * segment (source contiguous with previous curaddr, which may + * itself be a bounce paddr) or starting a new one. + */ + seg_end = curaddr + sgsize; vaddr += sgsize; buflen -= MIN(sgsize, buflen); /* avoid underflow */ }