From: Mark Kettenis Subject: azalia(4) diff for 64-bit DMA To: tech@openbsd.org Date: Fri, 08 Nov 2024 11:40:00 +0100 The HD Audio controllers provide a bit that indicates if 64-bit DMA is supported. This diff makes us allocate high addresses for audio bufferes in that case, leaving more low memory available for other stuff. If the Linux driver is to be believed, there are a few chips that advertise 64-bit DMA, but don't support it. I left out quirks for a few obscure controllers for which we don't even have PCI vendor IDs in our pcidevs file. I've only tested a recent Intel machine, so tests on older hardware are welcome. Just check that audio playback still works. ok? Index: dev/pci/azalia.c =================================================================== RCS file: /cvs/src/sys/dev/pci/azalia.c,v retrieving revision 1.290 diff -u -p -r1.290 azalia.c --- dev/pci/azalia.c 18 Aug 2024 14:42:56 -0000 1.290 +++ dev/pci/azalia.c 8 Nov 2024 10:34:22 -0000 @@ -836,6 +836,14 @@ azalia_get_ctrlr_caps(azalia_t *az) DPRINTF(("%s: host: %d output, %d input, and %d bidi streams\n", XNAME(az), az->nostreams, az->nistreams, az->nbstreams)); + /* ATI SB600 has broken 64-bit DMA support */ + if (PCI_VENDOR(az->pciid) == PCI_VENDOR_ATI && + PCI_PRODUCT(az->pciid) == PCI_PRODUCT_ATI_SBX00_HDA) + az->ok64 = 0; + /* Creative products tend to have broken 64-bit DMA support as well */ + if (PCI_VENDOR(az->pciid) == PCI_VENDOR_CREATIVELABS) + az->ok64 = 0; + /* 4.3 Codec discovery */ statests = AZ_READ_2(az, STATESTS); for (i = 0, n = 0; i < HDA_MAX_CODECS; i++) { @@ -1342,12 +1350,13 @@ azalia_rirb_intr(azalia_t *az) int azalia_alloc_dmamem(azalia_t *az, size_t size, size_t align, azalia_dma_t *d) { + int flags = az->ok64 ? BUS_DMA_64BIT : 0; int err; int nsegs; d->size = size; err = bus_dmamem_alloc(az->dmat, size, align, 0, d->segments, 1, - &nsegs, BUS_DMA_NOWAIT); + &nsegs, BUS_DMA_NOWAIT | flags); if (err) return err; if (nsegs != 1) @@ -1357,7 +1366,7 @@ azalia_alloc_dmamem(azalia_t *az, size_t if (err) goto free; err = bus_dmamap_create(az->dmat, size, 1, size, 0, - BUS_DMA_NOWAIT, &d->map); + BUS_DMA_NOWAIT | flags, &d->map); if (err) goto unmap; err = bus_dmamap_load(az->dmat, d->map, d->addr, size,