From nobody Mon Aug 17 17:45:44 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 4hP0cG2kt4z6p5hF for ; Mon, 17 Aug 2026 17:45:50 +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 4hP0cG17BKz3Dbg for ; Mon, 17 Aug 2026 17:45:50 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786988750; 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=iqSXTE1fPe7cpKAseA8aE8UO2IGTfSlL38XmVN2q7uE=; b=O9ddtkBXHFfpO9tltDNqGfar9Xva0PVJElcNfRLn5I08fylEOjqSuML+ojbAxDuaMlYc/v Q6mR8aYtxQLdPa8rPM1fyoiuaW24YXLIQ3x8xu1u1/5hFTxL82SxRhkKh8ZVhBEACx3m9c P1c5TOhBB0OWYKvCh4Ov8nGEAcUMfjhUkROEB/SFfNBHnDzBruGJ3nG0EUGoOQdE9c8P6o Gmusi4s9mlC++0/r6D7ghVznWoJKuUWAeHnihVx002RLEKyb8LSPMqG7YpDgwguai/JvLg 18nBo9oC1EHVmMarUnpm2KxQ/hNiDBcNqhZFCHGgA7LKcfOs29ajpBQ2Q6bT4A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1786988750; a=rsa-sha256; cv=none; b=j7a3RRpEvDyefthrM3nRBRXDRVrTlC/00jbJqFZRTggZd7HzS3aDvU3NKuSQGn2rDWnclW JTO1BC2OcMCYwZjjAKbk3wQQqTFTwNY4LB9aoAhmNSiG0Eu+bvJZ4SZl8vnIZ3pmQRJV1u hheo365pdoEI49FOFQd+Rx/AXYJNK2cXK9+2bdcUfDAa/r2KxagG1Fuc9TKxbr+YMiv/dm 97nNErSpw1VuYk9dIIhWMoYkMR57aJMWqiiSm036y/uoYVhBEEhWdH+Crmdyuidcz6kJOz KnQL4uaOa/pi0ElHGd+VSYnaK/iUJtWytOjOkevDJfTZTak8XmraX6OuZ8n51Q== 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=1786988750; 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=iqSXTE1fPe7cpKAseA8aE8UO2IGTfSlL38XmVN2q7uE=; b=JqsUItzffXPvUumDZP0sJZLySx74KCSPhuXjsRo+P4W3yleJMs/TURK9mnTUVtwuuIcTKI l3mfK3Ng6rTobf69+Y2tLGMRxMzOnpHftyTKpOxeCWIu5EnNZ8E1PhNqa0XQKGoVxZy4Ab P/IUSwhff+L2wIHcoOv9sOsugATxqHlowy89eGU2tdg7+rCgK6xn28pAeV9bfli/p0QrgL PvRaip/F6x0zChuc+rR/gdYWLtvpyZi3SG6x6wItn1WgeM0cR2K97pCC1rk+nzo61R7Ws/ +U1bgYBTw2S5VR1JfpxNU9Gg7VhKUFuQeqdyjSzdFYZ7Co/yn3A/uwWXZpjjqg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hP0cG02pTz1NK9 for ; Mon, 17 Aug 2026 17:45:50 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 376fb by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 17 Aug 2026 17:45:44 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 4c1004c00ff2 - main - snd_hdspe: Avoid allocation in the interrupt handler List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@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: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 4c1004c00ff250f2a9e5bff5ae90c25d6b70feb3 Auto-Submitted: auto-generated Date: Mon, 17 Aug 2026 17:45:44 +0000 Message-Id: <6a8348c8.376fb.6a5f6df6@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=4c1004c00ff250f2a9e5bff5ae90c25d6b70feb3 commit 4c1004c00ff250f2a9e5bff5ae90c25d6b70feb3 Author: Kevin Bowling AuthorDate: 2026-07-21 03:31:57 +0000 Commit: Kevin Bowling CommitDate: 2026-08-17 17:44:41 +0000 snd_hdspe: Avoid allocation in the interrupt handler Cache PCM children and drain interrupt callbacks before detach. Allocate the parent softc by its actual size. Reviewed by: br MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D58370 --- sys/dev/sound/pci/hdspe-pcm.c | 96 ++++++++++++++++++++++++++++++++----------- sys/dev/sound/pci/hdspe.c | 26 ++++++------ sys/dev/sound/pci/hdspe.h | 9 ++++ 3 files changed, 94 insertions(+), 37 deletions(-) diff --git a/sys/dev/sound/pci/hdspe-pcm.c b/sys/dev/sound/pci/hdspe-pcm.c index 0daa8fa8bb92..e0b6168efcba 100644 --- a/sys/dev/sound/pci/hdspe-pcm.c +++ b/sys/dev/sound/pci/hdspe-pcm.c @@ -391,35 +391,21 @@ hdspe_running(struct sc_info *sc) { struct sc_pcminfo *scp; struct sc_chinfo *ch; - device_t *devlist; - int devcount; - int i, j; - int err; - - if ((err = device_get_children(sc->dev, &devlist, &devcount)) != 0) - goto bad; + unsigned int i; + int j; - for (i = 0; i < devcount; i++) { - scp = device_get_ivars(devlist[i]); + for (i = 0; i < HDSPE_MAX_PCMDEV; i++) { + scp = sc->pcms[i]; + if (scp == NULL) + continue; for (j = 0; j < scp->chnum; j++) { ch = &scp->chan[j]; if (ch->run) - goto bad; + return (1); } } - free(devlist, M_TEMP); - return (0); -bad: - -#if 0 - device_printf(sc->dev, "hdspe is running\n"); -#endif - - free(devlist, M_TEMP); - - return (1); } static void @@ -1034,12 +1020,15 @@ hdspe_pcm_attach(device_t dev) { char status[SND_STATUSLEN]; struct sc_pcminfo *scp; + struct sc_info *sc; const char *buf; uint32_t pcm_flags; int err; int play, rec; + int i; scp = device_get_ivars(dev); + sc = scp->sc; scp->ih = &hdspe_pcm_intr; if (scp->hc->ports & HDSPE_CHAN_AIO_ALL) @@ -1077,8 +1066,8 @@ hdspe_pcm_attach(device_t dev) } snprintf(status, SND_STATUSLEN, "port 0x%jx irq %jd on %s", - rman_get_start(scp->sc->cs), - rman_get_start(scp->sc->irq), + rman_get_start(sc->cs), + rman_get_start(sc->irq), device_get_nameunit(device_get_parent(dev))); err = pcm_register(dev, status); if (err) { @@ -1088,19 +1077,78 @@ hdspe_pcm_attach(device_t dev) mixer_init(dev, &hdspemixer_class, scp); + /* Register the PCM child for interrupt dispatch. */ + mtx_lock(&sc->lock); + for (i = 0; i < HDSPE_MAX_PCMDEV; i++) { + if (sc->pcms[i] == NULL) { + sc->pcms[i] = scp; + break; + } + } + mtx_unlock(&sc->lock); + if (i == HDSPE_MAX_PCMDEV) + device_printf(dev, "Too many PCM children.\n"); + return (0); } +static int +hdspe_pcm_quiesce(struct sc_pcminfo *scp) +{ + struct sc_info *sc; + unsigned int i; + int slot; + + sc = scp->sc; + slot = -1; + mtx_lock(&sc->lock); + for (i = 0; i < HDSPE_MAX_PCMDEV; i++) { + if (sc->pcms[i] == scp) { + sc->pcm_detaching[i] = true; + while (sc->pcm_refs[i] != 0) + cv_wait(&sc->pcm_cv, &sc->lock); + slot = (int)i; + break; + } + } + mtx_unlock(&sc->lock); + return (slot); +} + +static void +hdspe_pcm_unquiesce(struct sc_pcminfo *scp, int slot, bool detach) +{ + struct sc_info *sc; + + sc = scp->sc; + mtx_lock(&sc->lock); + KASSERT(slot >= 0 && slot < HDSPE_MAX_PCMDEV && + sc->pcms[slot] == scp && sc->pcm_detaching[slot], + ("invalid PCM slot %d", slot)); + if (detach) + sc->pcms[slot] = NULL; + sc->pcm_detaching[slot] = false; + mtx_unlock(&sc->lock); +} + static int hdspe_pcm_detach(device_t dev) { - int err; + struct sc_pcminfo *scp; + int err, slot; + + scp = device_get_ivars(dev); + slot = hdspe_pcm_quiesce(scp); err = pcm_unregister(dev); if (err) { device_printf(dev, "Can't unregister device.\n"); + if (slot >= 0) + hdspe_pcm_unquiesce(scp, slot, false); return (err); } + if (slot >= 0) + hdspe_pcm_unquiesce(scp, slot, true); return (0); } diff --git a/sys/dev/sound/pci/hdspe.c b/sys/dev/sound/pci/hdspe.c index d08b42df0d82..d5a092a2e5f8 100644 --- a/sys/dev/sound/pci/hdspe.c +++ b/sys/dev/sound/pci/hdspe.c @@ -111,11 +111,8 @@ hdspe_intr(void *p) { struct sc_pcminfo *scp; struct sc_info *sc; - device_t *devlist; - int devcount; + unsigned int i; int status; - int err; - int i; sc = (struct sc_info *)p; @@ -123,17 +120,18 @@ hdspe_intr(void *p) status = hdspe_read_1(sc, HDSPE_STATUS_REG); if (status & HDSPE_AUDIO_IRQ_PENDING) { - if ((err = device_get_children(sc->dev, &devlist, &devcount)) != 0) - return; - - for (i = 0; i < devcount; i++) { - scp = device_get_ivars(devlist[i]); - if (scp->ih != NULL) - scp->ih(scp); + for (i = 0; i < HDSPE_MAX_PCMDEV; i++) { + scp = sc->pcms[i]; + if (scp == NULL || sc->pcm_detaching[i] || + scp->ih == NULL) + continue; + sc->pcm_refs[i]++; + scp->ih(scp); + if (--sc->pcm_refs[i] == 0 && sc->pcm_detaching[i]) + cv_broadcast(&sc->pcm_cv); } hdspe_write_1(sc, HDSPE_INTERRUPT_ACK, 0); - free(devlist, M_TEMP); } mtx_unlock(&sc->lock); @@ -844,6 +842,7 @@ hdspe_attach(device_t dev) "Analog input level ('LowGain', '+4dBU', '-10dBV')"); } + cv_init(&sc->pcm_cv, "snd_hdspe pcm"); bus_attach_children(dev); return (0); } @@ -891,6 +890,7 @@ hdspe_detach(device_t dev) bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); if (sc->cs) bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), sc->cs); + cv_destroy(&sc->pcm_cv); mtx_destroy(&sc->lock); return (0); @@ -907,7 +907,7 @@ static device_method_t hdspe_methods[] = { static driver_t hdspe_driver = { "hdspe", hdspe_methods, - PCM_SOFTC_SIZE, + sizeof(struct sc_info), }; DRIVER_MODULE(snd_hdspe, pci, hdspe_driver, 0, 0); diff --git a/sys/dev/sound/pci/hdspe.h b/sys/dev/sound/pci/hdspe.h index 85acbe9f7374..2ad955eb1784 100644 --- a/sys/dev/sound/pci/hdspe.h +++ b/sys/dev/sound/pci/hdspe.h @@ -211,6 +211,9 @@ struct sc_pcminfo { struct hdspe_channel *hc; }; +/* Maximum number of PCM children. */ +#define HDSPE_MAX_PCMDEV 8 + /* HDSPe device private data */ struct sc_info { device_t dev; @@ -241,6 +244,12 @@ struct sc_info { uint32_t speed; uint32_t force_period; uint32_t force_speed; + + /* PCM children used for interrupt dispatch. */ + struct sc_pcminfo *pcms[HDSPE_MAX_PCMDEV]; + unsigned int pcm_refs[HDSPE_MAX_PCMDEV]; + bool pcm_detaching[HDSPE_MAX_PCMDEV]; + struct cv pcm_cv; }; #define hdspe_read_1(sc, regno) \