From nobody Tue Aug 25 00:33:12 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 4hTTK94r9pz6pNKL for ; Tue, 25 Aug 2026 00:33:17 +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 4hTTK91jvlz4FnV for ; Tue, 25 Aug 2026 00:33:17 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787617997; 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=ssedx/SEmoJNYYcmmtxBaZefcJoJ/az0jpqnDjbcmOQ=; b=kiJWzJc2ha+EI502ixDL52UFlndKTEuFiw0Bpr4x3qyyZpI7Q9+zWGqnlTzESVVwtNkX4+ aGTfdxEU3Oel9qfMKXIDjQqZ0Qdgdfd5o34yPpy7p3Ba7LWLbWAvghux+zV+/08IiyFjTE g+wcXbeb7N21pQVG5MpUVPrMFl9W+wDm1LElFmAvQx572s56NdlJ/AC7DgQmCTpR5//QJy mvDzJq5fSxgT87Loi/G951O3/a+Mk2pWNcG5f/ACPOxQcKpRSBNxXKkhPSUTHhABFCV+9c 4XmS/Oaa7f2Jt2tj1dInHLuh9Y09U41I3l2Nl3ytNCIha/adqhemjFKGHPzjaA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1787617997; a=rsa-sha256; cv=none; b=m7QwuFs2ac6r+Uzxu9Uz4qxnXbB9uOH1ExQ8VIwVF1iRrUYWqhVPi64H7Dz+/PeWOg2XFr 2ccL5TAMfPEs8lc15fU+g22bOCS06g0CbgL2GqzxC1zxCXhXpHdnVKi+/gN/lXF4shQaeq GnZN0KLnCauGE+XgNV5dfov7SEC2EY7gh5Wq/jtZkoKcwsyanPkH5QQV0yeOj+dsT21TXt PjyYRZvH+uAFhDNr8JQphUkN8MnOUrzNbjVLc9dZzkGDpivBax8CQls44Dk64JTr/8jtjJ ZOcEWUt3ocSwdHU/U6dzNUQaeyP70Cw+eZTgJuvWGcra7vwBTiJ+bM/cK4q0yA== 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=1787617997; 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=ssedx/SEmoJNYYcmmtxBaZefcJoJ/az0jpqnDjbcmOQ=; b=Csl4VX2WwzLVsQSWQgS2JVwOnn98jUMBHQehR2SdkOOORW8Uq/m24Ny1PCvNWIqWGHRkI+ J4fkg7NAdW7WMVXwQik48Qx/HUr4JZTmsdyvfFtEDS7CWME2wcvhc7fmZ06l4UDj7TYT/K Ik+x7dIlPqi3e5fQS3O6P2VE7PTU7nzFTBUhkNJNWlehWrb/4rMScqQLfTikw1u7r1EmV7 fsaA3bMWYjt3AhCzOcMxEQSMqSJfwPbTXur39qRwNJcsGTB7ThyWuy84DJCVNmOSm6TBCB 90M6UfPvt8a+MKvabRN9vgDVDjMUHAAaAeo87U551pSU/KycUlmwVY7EoHCsdg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hTTK90N3zzC0N for ; Tue, 25 Aug 2026 00:33:17 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3dcde by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 25 Aug 2026 00:33:12 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: 0bc69050e40e - stable/15 - 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/stable/15 X-Git-Reftype: branch X-Git-Commit: 0bc69050e40ea18c00a59687e5be14adb4d8b920 Auto-Submitted: auto-generated Date: Tue, 25 Aug 2026 00:33:12 +0000 Message-Id: <6a8ce2c8.3dcde.a386a69@gitrepo.freebsd.org> The branch stable/15 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=0bc69050e40ea18c00a59687e5be14adb4d8b920 commit 0bc69050e40ea18c00a59687e5be14adb4d8b920 Author: Kevin Bowling AuthorDate: 2026-07-21 03:31:57 +0000 Commit: Kevin Bowling CommitDate: 2026-08-25 00:33:01 +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 Differential Revision: https://reviews.freebsd.org/D58370 (cherry picked from commit 4c1004c00ff250f2a9e5bff5ae90c25d6b70feb3) --- 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) \