From nobody Mon Nov 02 16:01:35 2026 X-Original-To: dev-commits-src-all@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 4jJGff6Hs3z6xvDN for ; Mon, 02 Nov 2026 16:01:46 +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) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4jJGff4jVvz4g22 for ; Mon, 02 Nov 2026 16:01:46 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793635306; 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=nNjIaGSqccBf9GOxR9J4TISMENOA6/ap2bSnz7aZ4NU=; b=wMPpolW6rRtm+GJrEzAsMZ5BQ0JzSZXSDdClnkGj0t5TGkGqFmSquAsY2BwryzSdacPiuX cxt7eAvNjwpcA4oiBCaW8FNEu6VqPG29M9sFe0+CuZeS7UCPXUPYrvJWrs6ByFXRpsf79+ huD7PBTTAKnzkcyNaOfcGKEAqMdMRhzB3a/VOtvU4fU+fQKgl4eyhLNcWfmtDJUf/AONdx +jf2nOEb8qNEOKAkh/Vfw9c/Hh9bbnb8v1wRheaggisU21jqAGgfqz6Uq3Vpn2wAD1h3rT R+Cw31Flp7zBYGO6C5Gwzz0W+4jp/0HsHVaYZoBsDFOjuIXb6xaev0hC5cFd5A== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1793635306; b=yAufSGfilTBojNi44EkZHpltokjo+AYeDWHJZ7SlosOZCx5rhWvyrTJw9p7nPc6kI5SEVZ 1b5PrCwmyW7QaqKhRMFPjetbhNPk1kCLWzfFH3RgSiRNdKX8YGVGXw9Wqg0BJ8bLaLUgIg 797gU3D/pXBIZP9hRB/5i5GHAF0vZz3Zt2bcJNoq5GS0WL8SoqyeFqK3bvajj2Vwfs44r8 nM63Fa7zjH6Ay71tz/43qAE2exchWYjIPg7NonaqZfK1nGaOXAnvX2bIKmIVXqAI+aa2xr 0b7Yoj6fa0E6cCdMAvCDe/5cgDUe4Erm870btD0dzZ7ZS//Y/EsOAYQZtm9wIg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793635306; 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=nNjIaGSqccBf9GOxR9J4TISMENOA6/ap2bSnz7aZ4NU=; b=JVLKoVg6PnHC+bgrPDFqZsYpXsdx93GeyItBMAfShOdGFfXdN6Agq43YyIB0pzlvOpdyX+ Rt9Bmnan4zmHyVAx94UZue8YD8SYxJVCxtaQGOAz5uY2Nx2pq7E50R7iw2ATcJGXkxxtPH BQGy2yfeBeXbbvp46Q8OJTePsBOcFB9eLN9LLYO6z3yfFBHYf27pXa6W3fMLoMAz6tourZ +ETs7wJR0qAQA4P5hni/kCNt9SmQEbIY73SNj9KU4BEQC5/C//jGs3pH0I2mfA22uVV87B Eejkh3C8j43OvFQLL3IrueB5OtIAZ2oS9sBepj+ozNDPQ64UwbOPms1EihO5fw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4jJGff3sJ6zsDl for ; Mon, 02 Nov 2026 16:01:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 4668b by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 02 Nov 2026 16:01:35 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 46b338381400 - main - snd_hdspe: Use busdma for DMA buffers List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: Commit messages for all branches of the src repository 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: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 46b338381400cb8106d6d2af945e7950553c16f4 Auto-Submitted: auto-generated Date: Mon, 02 Nov 2026 16:01:35 +0000 Message-Id: <6ae8b3df.4668b.557a60b2@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=46b338381400cb8106d6d2af945e7950553c16f4 commit 46b338381400cb8106d6d2af945e7950553c16f4 Author: Kevin Bowling AuthorDate: 2026-07-21 03:36:02 +0000 Commit: Kevin Bowling CommitDate: 2026-11-02 16:01:30 +0000 snd_hdspe: Use busdma for DMA buffers Program DMA pages from busdma segments and synchronize buffer ownership. Unwind partially allocated resources on failure. Reviewed by: br MFC after: 3 days Sponsored by: BBOX.io Differential Revision: https://reviews.freebsd.org/D58372 --- sys/dev/sound/pci/hdspe-pcm.c | 24 ++++++-- sys/dev/sound/pci/hdspe.c | 132 ++++++++++++++++++++++++++++++++---------- sys/dev/sound/pci/hdspe.h | 5 ++ 3 files changed, 126 insertions(+), 35 deletions(-) diff --git a/sys/dev/sound/pci/hdspe-pcm.c b/sys/dev/sound/pci/hdspe-pcm.c index 017142949d62..0914d8b13b0f 100644 --- a/sys/dev/sound/pci/hdspe-pcm.c +++ b/sys/dev/sound/pci/hdspe-pcm.c @@ -562,14 +562,13 @@ buffer_copy(struct sc_chinfo *ch) length -= offset; } } else { - /* Position per channel is n times smaller than PCM. */ + /* Snapshot the write position before synchronizing the buffer. */ pos = sndbuf_getfreeptr(ch->buffer) / n; - /* Get DMA buffer write position. */ dma_pos = hdspe_read_2(sc, HDSPE_STATUS_REG); dma_pos &= HDSPE_BUF_POSITION_MASK; - /* Copy what is newly available. */ length = (dma_pos + HDSPE_CHANBUF_SIZE) - pos; length %= HDSPE_CHANBUF_SIZE; + bus_dmamap_sync(sc->dmat, sc->rmap, BUS_DMASYNC_POSTREAD); } /* Position and length in samples (4 bytes). */ @@ -598,6 +597,12 @@ buffer_copy(struct sc_chinfo *ch) row = hdspe_port_first(ports); } + if (ch->dir == PCMDIR_PLAY && length > 0) { + bus_dmamap_sync(sc->dmat, sc->pmap, BUS_DMASYNC_PREWRITE); + } else if (ch->dir == PCMDIR_REC) { + bus_dmamap_sync(sc->dmat, sc->rmap, BUS_DMASYNC_PREREAD); + } + ch->position = ((pos + length) * 4) % HDSPE_CHANBUF_SIZE; } @@ -617,6 +622,11 @@ clean(struct sc_chinfo *ch) if (ch->dir == PCMDIR_PLAY) buf = sc->pbuf; + if (ch->dir == PCMDIR_PLAY) + bus_dmamap_sync(sc->dmat, sc->pmap, BUS_DMASYNC_POSTWRITE); + else + bus_dmamap_sync(sc->dmat, sc->rmap, BUS_DMASYNC_POSTREAD); + /* Iterate through rows of ports with contiguous slots. */ ports = ch->ports; row = hdspe_port_first_row(ports); @@ -632,6 +642,12 @@ clean(struct sc_chinfo *ch) row = hdspe_port_first_row(ports); } + if (ch->dir == PCMDIR_PLAY) + bus_dmamap_sync(sc->dmat, sc->pmap, BUS_DMASYNC_PREWRITE); + else + bus_dmamap_sync(sc->dmat, sc->rmap, + BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + ch->position = 0; return (0); @@ -762,8 +778,8 @@ hdspechan_trigger(kobj_t obj, void *data, int go) #if 0 device_printf(scp->dev, "hdspechan_trigger(): stop or abort\n"); #endif - clean(ch); hdspechan_enable(ch, 0); + clean(ch); hdspe_stop_audio(sc); break; diff --git a/sys/dev/sound/pci/hdspe.c b/sys/dev/sound/pci/hdspe.c index d5a092a2e5f8..b129083f4b60 100644 --- a/sys/dev/sound/pci/hdspe.c +++ b/sys/dev/sound/pci/hdspe.c @@ -137,17 +137,57 @@ hdspe_intr(void *p) mtx_unlock(&sc->lock); } +struct hdspe_dma_map { + uint32_t *pages; + unsigned int npages; + int error; +}; + static void -hdspe_dmapsetmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) +hdspe_dma_map_pages(void *arg, bus_dma_segment_t *segs, int nseg, int error) { -#if 0 - device_printf(sc->dev, "hdspe_dmapsetmap()\n"); -#endif + struct hdspe_dma_map *map; + bus_addr_t addr; + bus_size_t len; + int i; + + map = arg; + map->npages = 0; + map->error = error; + if (error != 0) + return; + + for (i = 0; i < nseg; i++) { + addr = segs[i].ds_addr; + len = segs[i].ds_len; + if (addr % HDSPE_DMA_PAGE_SIZE != 0 || + len % HDSPE_DMA_PAGE_SIZE != 0) { + map->error = EINVAL; + return; + } + while (len != 0) { + if (map->npages == HDSPE_DMA_PAGES) { + map->error = EFBIG; + return; + } + map->pages[map->npages++] = (uint32_t)addr; + addr += HDSPE_DMA_PAGE_SIZE; + len -= HDSPE_DMA_PAGE_SIZE; + } + } + if (map->npages != HDSPE_DMA_PAGES) + map->error = EFBIG; } static int hdspe_alloc_resources(struct sc_info *sc) { + struct hdspe_dma_map map; + bool pmap_loaded, rmap_loaded; + int error; + + pmap_loaded = false; + rmap_loaded = false; /* Allocate resource. */ sc->csid = PCIR_BAR(0); @@ -171,76 +211,103 @@ hdspe_alloc_resources(struct sc_info *sc) bus_setup_intr(sc->dev, sc->irq, INTR_MPSAFE | INTR_TYPE_AV, NULL, hdspe_intr, sc, &sc->ih)) { device_printf(sc->dev, "Unable to alloc interrupt resource.\n"); - return (ENXIO); + goto fail; } - /* Allocate DMA resources. */ + /* Allocate page-aligned DMA segments for each direction. */ if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(sc->dev), - /*alignment*/4, + /*alignment*/HDSPE_DMA_PAGE_SIZE, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, - /*maxsize*/2 * HDSPE_DMASEGSIZE, - /*nsegments*/2, + /*maxsize*/HDSPE_DMASEGSIZE, + /*nsegments*/HDSPE_DMA_PAGES, /*maxsegsz*/HDSPE_DMASEGSIZE, /*flags*/0, /*lockfunc*/NULL, /*lockarg*/NULL, /*dmatag*/&sc->dmat) != 0) { device_printf(sc->dev, "Unable to create dma tag.\n"); - return (ENXIO); + goto fail; } sc->bufsize = HDSPE_DMASEGSIZE; /* pbuf (play buffer). */ - if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, BUS_DMA_WAITOK, - &sc->pmap)) { + if (bus_dmamem_alloc(sc->dmat, (void **)&sc->pbuf, + BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->pmap)) { device_printf(sc->dev, "Can't alloc pbuf.\n"); - return (ENXIO); + goto fail; } - if (bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->bufsize, - hdspe_dmapsetmap, sc, BUS_DMA_NOWAIT)) { + map.pages = sc->paddr; + map.error = 0; + error = bus_dmamap_load(sc->dmat, sc->pmap, sc->pbuf, sc->bufsize, + hdspe_dma_map_pages, &map, BUS_DMA_NOWAIT); + if (error == 0) + pmap_loaded = true; + if (error != 0 || map.error != 0) { device_printf(sc->dev, "Can't load pbuf.\n"); - return (ENXIO); + goto fail; } /* rbuf (rec buffer). */ - if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, BUS_DMA_WAITOK, - &sc->rmap)) { + if (bus_dmamem_alloc(sc->dmat, (void **)&sc->rbuf, + BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->rmap)) { device_printf(sc->dev, "Can't alloc rbuf.\n"); - return (ENXIO); + goto fail; } - if (bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->bufsize, - hdspe_dmapsetmap, sc, BUS_DMA_NOWAIT)) { + map.pages = sc->raddr; + map.error = 0; + error = bus_dmamap_load(sc->dmat, sc->rmap, sc->rbuf, sc->bufsize, + hdspe_dma_map_pages, &map, BUS_DMA_NOWAIT); + if (error == 0) + rmap_loaded = true; + if (error != 0 || map.error != 0) { device_printf(sc->dev, "Can't load rbuf.\n"); - return (ENXIO); + goto fail; } - bzero(sc->pbuf, sc->bufsize); - bzero(sc->rbuf, sc->bufsize); + /* Synchronize the buffers before the first DMA cycle. */ + bus_dmamap_sync(sc->dmat, sc->pmap, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(sc->dmat, sc->rmap, BUS_DMASYNC_PREREAD); return (0); + +fail: + if (sc->ih != NULL) + bus_teardown_intr(sc->dev, sc->irq, sc->ih); + if (rmap_loaded) + bus_dmamap_unload(sc->dmat, sc->rmap); + if (sc->rbuf != NULL) + bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); + if (pmap_loaded) + bus_dmamap_unload(sc->dmat, sc->pmap); + if (sc->pbuf != NULL) + bus_dmamem_free(sc->dmat, sc->pbuf, sc->pmap); + if (sc->dmat != NULL) + bus_dma_tag_destroy(sc->dmat); + if (sc->irq != NULL) + bus_release_resource(sc->dev, SYS_RES_IRQ, sc->irqid, sc->irq); + if (sc->cs != NULL) + bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->csid, sc->cs); + return (ENXIO); } static void hdspe_map_dmabuf(struct sc_info *sc) { - uint32_t paddr, raddr; int i; - paddr = vtophys(sc->pbuf); - raddr = vtophys(sc->rbuf); - - for (i = 0; i < HDSPE_MAX_SLOTS * 16; i++) { + /* Program the hardware page tables with DMA page addresses. */ + for (i = 0; i < HDSPE_DMA_PAGES; i++) { hdspe_write_4(sc, HDSPE_PAGE_ADDR_BUF_OUT + 4 * i, - paddr + i * 4096); + sc->paddr[i]); hdspe_write_4(sc, HDSPE_PAGE_ADDR_BUF_IN + 4 * i, - raddr + i * 4096); + sc->raddr[i]); } } @@ -770,6 +837,7 @@ hdspe_attach(device_t dev) err = hdspe_alloc_resources(sc); if (err) { device_printf(dev, "Unable to allocate system resources.\n"); + mtx_destroy(&sc->lock); return (ENXIO); } @@ -857,6 +925,8 @@ static void hdspe_dmafree(struct sc_info *sc) { + bus_dmamap_sync(sc->dmat, sc->rmap, BUS_DMASYNC_POSTREAD); + bus_dmamap_sync(sc->dmat, sc->pmap, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->dmat, sc->rmap); bus_dmamap_unload(sc->dmat, sc->pmap); bus_dmamem_free(sc->dmat, sc->rbuf, sc->rmap); diff --git a/sys/dev/sound/pci/hdspe.h b/sys/dev/sound/pci/hdspe.h index 2ad955eb1784..05c88594d585 100644 --- a/sys/dev/sound/pci/hdspe.h +++ b/sys/dev/sound/pci/hdspe.h @@ -125,6 +125,8 @@ #define HDSPE_CHANBUF_SAMPLES (16 * 1024) #define HDSPE_CHANBUF_SIZE (4 * HDSPE_CHANBUF_SAMPLES) #define HDSPE_DMASEGSIZE (HDSPE_CHANBUF_SIZE * HDSPE_MAX_SLOTS) +#define HDSPE_DMA_PAGE_SIZE 4096 +#define HDSPE_DMA_PAGES (HDSPE_DMASEGSIZE / HDSPE_DMA_PAGE_SIZE) #define HDSPE_CHAN_AIO_LINE (1 << 0) #define HDSPE_CHAN_AIO_EXT (1 << 1) @@ -240,6 +242,9 @@ struct sc_info { uint32_t bufsize; bus_dmamap_t pmap; bus_dmamap_t rmap; + /* DMA buffer page addresses. */ + uint32_t paddr[HDSPE_DMA_PAGES]; + uint32_t raddr[HDSPE_DMA_PAGES]; uint32_t period; uint32_t speed; uint32_t force_period;