Index | Thread | Search

From:
Mark Kettenis <mark.kettenis@xs4all.nl>
Subject:
azalia(4) diff for 64-bit DMA
To:
tech@openbsd.org
Date:
Fri, 08 Nov 2024 11:40:00 +0100

Download raw body.

Thread
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,