aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/sound/pcm/channel.c
Commit message (Collapse)AuthorAgeFilesLines
* Revert "sound: Merge chn_intr() with chn_intr_locked()"Christos Margiolis2025-11-231-2/+18
| | | | | | | | | It turns out that snd_uaudio(4) uses sound(4)'s channel lock for its USB transfer callbacks. I will try to address this at some point, because this is layering violation, but for now we need to revert the commit, as it causes a lock recursion panic with USB audio devices. This reverts commit e254ef87a30bfcaabc6e4d8e0ecf05f6949a4f06.
* sound: Retire snd_mtx* wrappersChristos Margiolis2025-11-211-7/+9
| | | | | | | | | | | | Do not create mutexes with snd_mtxcreate(). It doesn't provide any value, plus it first allocates the mutex with malloc(9). Allocate mutexes in the stack and use mtx_* functions directly instead of the snd_mtx* wrappers. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: kib, markj Differential Revision: https://reviews.freebsd.org/D53855
* sound: Merge chn_intr() with chn_intr_locked()Christos Margiolis2025-11-211-18/+2
| | | | | | | | | | | | There is no scenario where chn_intr() is called with the channel lock already held. No functional change intended. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: kib, markj Differential Revision: https://reviews.freebsd.org/D53854
* sound: Fix KASSERT panics in chn_read() and chn_write()Christos Margiolis2025-11-201-48/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | INVARIANTS kernels may trigger a KASSERT panic from sndbuf_acquire(), when fuzzing write(2) using stress2, because of a race in chn_write(). In the case of chn_write(), what sndbuf_acquire() does is extend the ready-to-read area of the buffer by a specified amount of bytes. The KASSERT in question makes sure the number of bytes we want to extend the ready area by, is less than or equal to the number of free bytes in the buffer. This makes sense, because we cannot extend the ready area to something larger than what is available (i.e., free) in the first place. What chn_write() currently does for every write is; calculate the appropriate write size, let's say X, unlock the channel, uiomove() X bytes to the channel's buffer, lock the channel, and call sndbuf_acquire() to extend the ready area by X bytes. The problem with this approach, however, is the following. Suppose an empty channel buffer with a length of 1024 bytes, and 2 threads, (A) and (B), where (B) is a higher-priority one. Suppose thread (A) wants to write 1024 bytes. It unlocks the channel and uiomove()s 1024 bytes to the channel buffer. At the same time, thread (B) picks up the lock, and because it is higher priority, it keeps dominating the lock for a few iterations. By the time thread (A) picks up the lock again, it tries to call sndbuf_acquire() with a size of 1024 bytes, which was calculated before it performed the uiomove(). In this case, there is a very high chance that the buffer will not be empty, that is, have a free area of 1024 bytes, as was the case when thread (A) started executing, and so the KASSERT will trigger a panic because the condition (bytes <= free) is not met. Another scenario that can trigger a panic is the following: suppose a buffer with a size of 4 bytes, and two threads: (A) and (B). In the first iteration, thread (A) wants to write 2 bytes, while the buffer is empty, BUT the pointer (sndbuf_getfreeptr()) is at the end (i.e., buf[3]). In the first iteration of the loop, because of the way we calculate t, we'll end up writing only 1 byte, so after sz -= t, sz will be 1, and so we'll need one more iteration in the inner loop, to write the remaining 1 byte. Now we're at the end of the first loop, thread (A) unlocks the channel, it has written 1 byte, it needs to write 1 more, and the buffer is left with 3 empty slots. Now thread (B) picks up the lock, and it wants to write 3 (or more) bytes. Eventually it writes the 3 bytes, and it leaves the buffer with 0 free slots. By the time thread (A) picks up the lock again, and continues with the second iteration of the inner loop, it will try to write the last byte, but sndbuf_acquire() will panic because there is no free space anymore. To fix this, get rid of the inner loop and calculate the write size on each iteration. Also, call sndbuf_acquire() before unlocking the channel. In the scenarios explained above, we'll end up entering the chn_sleep() case. Modify it as well, so that we do not kill the channel if we need to sleep more. Do the same for chn_read() to avoid possible similar panics from sndbuf_dispose(). Reported by: pho Tested by: christos, pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: pho, kib Differential Revision: https://reviews.freebsd.org/D53666
* sound: Simplify feeder_getclass()Christos Margiolis2025-11-111-1/+1
| | | | | | | | | | | | | With the parameters we provide feeder_getclass(), the only thing we really care about is the feeder's class type. We can simplify (and make the code more readable) that by simply passing the type to feeder_getclass(). Apart from being simpler, we can now also retire feedertab_entry->desc and cmpdesc(). Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D53553
* sound: Get rid of useless sndbuf getters and settersChristos Margiolis2025-11-111-69/+64
| | | | | | | | No functional change intended. Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D53528
* sound: Remove redundant sndbuf_free() in chn_kill()Christos Margiolis2025-11-111-2/+2
| | | | | | | | | | If b exists, it will get destroyed by sndbuf_destroy() (which calls sndbuf_free()) a few lines below, so the additional sndbuf_free() here is redundant. Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D53527
* sound: Re-arrange sndbuf_create() argumentsChristos Margiolis2025-11-111-2/+2
| | | | | | | | | | | | | Since we always use the channel name as the "drv" argument, we can just get rid of it and fetch it in sndbuf_create(). Also, put the "channel" argument first, as it is more intuitive. No functional change intended. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D53520
* sound: Retire snd_dbuf->devChristos Margiolis2025-11-111-2/+2
| | | | | | | | | | Redundant, and if we at some point really need this, we can fetch it from snd_dbuf->channel->dev. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D53519
* sound: Add kqueue supportChristos Margiolis2025-11-111-2/+7
| | | | | | | | Co-authored by: meka@tilda.center Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D53029
* sound: Use bus_topo_lock() where appropriateChristos Margiolis2025-03-301-2/+4
| | | | | | | | | | Lock around uses of devclass_*() and replace leftover CTLFLAG_NEEDGIANTs with CTLFLAG_MPSAFE. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: imp, jhb Differential Revision: https://reviews.freebsd.org/D46700
* sound: Improve afmt_tabChristos Margiolis2025-03-301-13/+18
| | | | | | | | | Reduce ifdefs, and add aliases for the unsigned formats. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D48009
* sound: Implement AFMT_FLOAT supportChristos Margiolis2025-03-301-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Even though the OSS manual [1] advises against using AFMT_FLOAT, there are applications that expect the sound driver to support it, and might not work properly without it. This patch adds AFMT_F32_LE|BE (as well as AFMT_FLOAT for OSS compatibility) in sys/soundcard.h and implements AFMT_F32_LE|BE <-> AFMT_S32_LE|BE conversion functions. As a result, applications can write/read floats to/from sound(4), but internally, because sound(4) works with integers, we convert floating point samples to integer ones, before doing any processing. The reason for encoding/decoding IEEE754s manually, instead of using fpu_kern(9), is that fpu_kern(9) is not supported by all architectures, and also introduces significant overhead. The IEEE754 encoding/decoding implementation has been written by Ariff Abdullah [2]. [1] http://manuals.opensound.com/developer/AFMT_FLOAT.html [2] https://people.freebsd.org/~ariff/utils/ieee754.c PR: 157050, 184380, 264973, 280612, 281390 Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: emaste Differential Revision: https://reviews.freebsd.org/D47638
* sound: Fix vchanrate and vchanformatChristos Margiolis2025-03-301-2/+10
| | | | | | | | | | | | | | | | | | | Make vchanrate and vchanformat reflect the primary channel's software buffer's rate and format respectively. Fix previous inconsistencies. Get rid of the initializations in vchan_create() and move them to chn_init(). Without the feeder_rate_round check in sysctl_dev_pcm_vchanrate(), we can set the software rate to anything between feeder_rate_min and feeder_rate_max. If we keep the check, however, the rate is limited to whatever the driver's min/max is, which can be a problem if, for example, the driver supports only a single rate, in which case we won't be able to set anything other than the driver rate. Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D48961
* sound: Update COPYRIGHT noticesChristos Margiolis2025-03-101-0/+4
| | | | | | | Only to files I've currently made significant contributions to. Sponsored by: The FreeBSD Foundation MFC after: 1 week
* sound: Call chn_kill() in chn_init() failureChristos Margiolis2025-02-251-35/+15
| | | | | | Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D48966
* sound: Return if the new speed/format is the same as the current oneChristos Margiolis2025-02-251-0/+6
| | | | | | | | | | This gives us a slight performance boost since we do not have to go through chn_setparam() and the driver functions. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: dev_submerge.ch, emaste Differential Revision: https://reviews.freebsd.org/D48012
* sound: Get rid of redundant variables in chn_setspeed() and chn_setformat()Christos Margiolis2025-02-251-7/+5
| | | | | | | Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: dev_submerge.ch, emaste Differential Revision: https://reviews.freebsd.org/D48011
* sound: Allocate vchans on-demandChristos Margiolis2025-02-251-1/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Refactor pcm_chnalloc() and merge with parts of vchan_setnew() (now removed) and dsp_open()’s channel creation into a new dsp_chn_alloc() function. The function is responsible for either using a free HW channel (if vchans are disabled), or allocating a new vchan. Clean up allocated vchans associated with a given dsp_cdevpriv on dsp_close() instead of leaving them unused. hw.snd.vchans_enable (previously hw.snd.maxautovchans) and dev.pcm.X.{play|rec}.vchans now work as tunables to only enable/disable vchans, as opposed to setting their number and/or (de-)allocating vchans. Since these sysctls do not trigger any (de-)allocations anymore, their effect is instantaneous, whereas before we could have frozen the machine (when trying to allocate new vchans) when setting dev.pcm.X.{play|rec}.vchans to a very large value. Create a new "primary" channel sublist so that we do not waste time looping through all channels in dsp_chn_alloc(), since we are only looking for a parent channel to either use, or add a new vchan to. This guarantees a steady traversal speed, as the parent channels are most likely going to be just a handful (2). What was currently in place was a loop through the whole channel list, which meant that the traversal would take longer the more channels were added to that list. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D47917
* sound: Initialize channels with sane default rate and formatChristos Margiolis2025-02-251-2/+2
| | | | | | | | | There is no good reason to initialize with AFMT_U8 at 8000Hz. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D48434
* sound: Do not return an error from chn_notify() if the children list is emptyChristos Margiolis2025-02-251-1/+1
| | | | | | | | | | An empty children list does not mean that there is an error. Reported by: Florian Walpen <dev@submerge.ch> Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D48156
* sound: Make CHN_REMOVE_SAFE() the defaultChristos Margiolis2025-01-211-1/+1
| | | | | | | | | | | | Commit 27b932e32fab ("sound: Safely remove channel from list in one pass") optimized CHN_REMOVE_SAFE() to perform almost equally to CHN_REMOVE(), so we can turn CHN_REMOVE_SAFE() into CHN_REMOVE() without fears of performance regressions, while also being more robust. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D48249
* sound: Do not access cv_waitersChristos Margiolis2024-12-021-0/+2
| | | | | | | | | | | | | | | Remove uses of cv_waiters in PCM_RELEASE and CHN_BROADCAST, and also use a counter around cv_timedwait_sig() in chn_sleep(), which is checked in pcm_killchans(), as opposed to reading cv_waiters directly, which is a layering violation. While here, move CHN_BROADCAST below the channel lock operations. Reported by: avg, jhb, markj Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch, avg Differential Revision: https://reviews.freebsd.org/D47780
* sound: Remove dead code from pcm/Christos Margiolis2024-12-021-53/+0
| | | | | | | | | No functional change intended. Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch, markj Differential Revision: https://reviews.freebsd.org/D47733
* sound: Remove CHN_F_SLEEPINGChristos Margiolis2024-11-261-12/+1
| | | | | | | | | | | | | | | | | | | | | The KASSERT in chn_sleep() can be triggered if more than one thread wants to sleep on a given channel at the same time. While this is not really a common scenario, tools such as stress2, which use fork() and the child process(es) inherit the parent's FDs as a result, we can end up triggering such scenarios. Fix this by removing CHN_F_SLEEPING altogether, which is not very useful in the first place: - CHN_BROADCAST() checks cv_waiters already, so there is no need to check CHN_F_SLEEPING as well. - We can check whether cv_waiters is 0 in pcm_killchans(), instead of whether CHN_F_SLEEPING is not set. Reported by: dougm, pho (stress2) Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch, markj Differential Revision: https://reviews.freebsd.org/D47559
* sound: Fix chn_trigger() and vchan_trigger() racesChristos Margiolis2024-11-261-27/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Consider the following scenario: 1. CHN currently has its trigger set to PCMTRIG_STOP. 2. Thread A locks CHN, calls CHANNEL_TRIGGER(PCMTRIG_START), sets the trigger to PCMTRIG_START and unlocks. 3. Thread B picks up the lock, calls CHANNEL_TRIGGER(PCMTRIG_ABORT) and returns a non-zero value, so it returns from chn_trigger() as well. 4. Thread A picks up the lock and adds CHN to the list, which is _wrong_, because the last call to CHANNEL_TRIGGER() was with PCMTRIG_ABORT, meaning the channel is stopped, yet we are adding it to the list and marking it as started. Another problematic scenario: 1. Thread A locks CHN, sets the trigger to PCMTRIG_ABORT, and unlocks CHN. It then locks PCM and _removes_ CHN from the list. 2. In the meantime, since thread A unlocked CHN, thread B has locked it, set the trigger to PCMTRIG_START, unlocked it, and is now blocking on PCM held by thread A. 3. At the same time, thread C locks CHN, sets the trigger back to PCMTRIG_ABORT, unlocks CHN, and is also blocking on PCM. However, once thread A unlocks PCM, because thread C is higher-priority than thread B, it picks up the PCM lock instead of thread B, and because CHN is already removed from the list, and thread B hasn't added it back yet, we take a page fault in CHN_REMOVE() by trying to remove a non-existent element. To fix the former scenario, set the channel trigger before the call to CHANNEL_TRIGGER() (could also come after, doesn't really matter) and check if anything changed one we lock CHN back. To fix the latter scenario, use the SAFE variants of CHN_INSERT_HEAD() and CHN_REMOVE(). A similar scenario can occur in vchan_trigger(), so do the trigger setting after we've locked the parent channel. Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D47461
* sound: Retire channel refcountChristos Margiolis2024-10-251-13/+0
| | | | | | | | | No longer used. Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D47269
* sound: Fix build error in chm_mkname() KASSERTChristos Margiolis2024-10-241-1/+1
| | | | | Sponsored by: The FreeBSD Foundation MFC after: 2 days
* sound: Untangle dsp_cdevs[] and dsp_unit2name() confusionChristos Margiolis2024-10-241-24/+46
| | | | | | | | | | | | | | | | | | | | | | | | | | | Before de8c0d15a64fa ("sound: Get rid of snd_clone and use DEVFS_CDEVPRIV(9)"), sound(4) would create one device for each allocated channel. The device names would be chosen from dsp_cdevs[], and created with dsp_unit2name(). Additionally, dsp_cdevs[] was also used to match these devices names, as well as OSSv4 aliases in dsp_clone(). Since sound(4) does not create separate devices for each channel anymore, the meaning and use dsp_cdevs[] has changed. Part of it no longer corresponds to devices at all, but instead is used to create channel names, and another part is used to match only OSSv4 aliases in dsp_clone(). To address this confusion, separate dsp_cdevs[] into a dsp_aliases[] array, and move dsp_unit2name() to pcm/channel.c and rename it to chn_mkname(). While here, get rid of the SND_DEV_DSPHW_* channel types, and simply use the existing PCMDIR_* constants as the channel types. There is no need to duplicate the same meaning twice. Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D47199
* sound: Use M_WAITOK where possibleChristos Margiolis2024-10-181-6/+1
| | | | | | | | | These malloc(9) calls are in contexts where sleeping is permitted. Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch, zlei, markj, emaste Differential Revision: https://reviews.freebsd.org/D46845
* sound: Shorten channel namesChristos Margiolis2024-10-181-8/+2
| | | | | | | | | | | | | | | | The current channel naming convention is: pcmX:[virtual_]play|record:dspX.[v]p|rY - pcmX and dspX share the same unit numbers - "[v]p|r" gives us the same information as "[virtual_]play|record" Remove the redundant information, so that the channel names become more readable: dspX.[virtual_]play|record.Y Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D46836
* sound: Simplify channel creation and deletion processChristos Margiolis2024-10-181-0/+40
| | | | | | | | | | | | | | | | | | | Currently we create and destroy channels with the following consistent pattern: - chn_init() -> pcm_chn_add() - pcm_chn_remove() -> chn_kill() Instead of calling two separate functions, merge pcm_chn_add() with chn_init(), and pcm_chn_remove() with chn_kill(). Another benefit of this change is that we avoid the confusion caused by having pcm_chn_add(), as well as pcm_addchan(). Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch, markj Differential Revision: https://reviews.freebsd.org/D46835
* sound: Use unr(9) to produce unique channel unit numbersChristos Margiolis2024-10-181-9/+22
| | | | | | | | | | | | | | | | | | | | | | | | Currently it is possible to assign a unit number that already exists. Suppose the following channel list: [vp2] If we create 3 channels, we'll end up with the following list: [vp0, vp1, vp2, vp2] This happens because chn_init() does not check if the unit number we are assigning already exists. While fixing this is trivial when the channel list is sorted in ascending order, it is way more involved when sorted in descending order. Even though sorting the list in descending order would require deliberately modifying pcm_chn_add(), and is most likely not going to happen, make the mechanism more robust by using a unr(9) allocator for each channel type. Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D46680
* sound: Get rid of pnum and max variables in chn_init()Christos Margiolis2024-10-181-21/+1
| | | | | | | | | | | | The VCHAN count is checked in vchan_setnew(), and there is no reason to cap the hardware channels in the first place. This is part of a series of follow-up patches. Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D46521
* sound: Simplify feeder_remove()Christos Margiolis2024-07-271-4/+2
| | | | | | | Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch, markj, emaste Differential Revision: https://reviews.freebsd.org/D46100
* sound: Simplify chn_init()Christos Margiolis2024-07-271-114/+63
| | | | | | | | | | | | | | | | | - Remove unnecessary CHN_[UN]LOCKs. - Improve device_printf() messages. - Remove redundant checks. - Remove 0 assignments, since the channel is allocated with M_ZERO. - Re-organize sections in a more coherent way. - Remove "out1" label, just return NULL directly. - Rename "out2" to "fail" and simplify logic. - Do not check the return value of dsp_unit2name(), as it is guaranteed not to fail (we pass a valid channel type). Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D45985
* sound: Rename chn_* feeder functions to feeder_*Christos Margiolis2024-07-271-4/+4
| | | | | | | | | Avoid layering violation. No functional change intended. Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D45983
* sound: Fix memory leak in chn_init()Christos Margiolis2024-07-271-0/+2
| | | | | | | | | | In case chn_init() fails, we are leaking memory by not freeing the feeder. Sponsored by: The FreeBSD Foundation MFC after: 2 days Reviewed by: dev_submerge.ch, markj Differential Revision: https://reviews.freebsd.org/D45979
* sound: Prevent uninitialized variable destruction in chn_init()Christos Margiolis2024-05-201-2/+2
| | | | | | | | | | | | | | If dsp_unit2name() fails, we'll get to out2 with b, bs and devinfo uninitialized, which will result in a panic. Reported by: Pierre Pronchery <pierre@freebsdfoundation.org> Reported by: Coverity Scan CID: 1545029, 1545025 Pull-request: https://github.com/freebsd/freebsd-src/pull/1240 Sponsored by: The FreeBSD Foundation MFC after: 1 day Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D45272
* sound: Get rid of redundant assignments in chn_init()Christos Margiolis2024-05-201-2/+0
| | | | | | | | | | c is allocated with M_ZERO. Reported by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 day Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D45273
* sound: Remove unused "num" argument from chn_init() and related callersChristos Margiolis2024-05-061-9/+2
| | | | | | | | | It is always -1 (i.e unused). Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D45095
* sound: Merge pcm_chn_create() and chn_init()Christos Margiolis2024-05-061-21/+146
| | | | | | | | | | | | | | Follow-up of b3ea087c05d8c75978a302cbb3fa92ce1afa3e49 ("sound: Merge pcm_chn_destroy() and chn_kill()") While here, add device_printf()'s to all failure points. Also fix an existing bug where we'd unlock an already unlocked channel, in case we went to "out" (now "out2") before locking the channel. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D44993
* sound: Remove chn_timeout check from chn_init()Christos Margiolis2024-04-281-3/+0
| | | | | | | | | | | This check is not related to channel initializion, but is also unnecessary, since sysctl_hw_snd_timeout() takes care of checking if chn_timeout is within bounds. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D44992
* sound: Move pcm_chnref() and pcm_chnrelease() to pcm/channel.cChristos Margiolis2024-04-281-0/+28
| | | | | | | | | | | | Improve code layering. These are channel functions, and so they do not belong in pcm/sound.c. While here, assert in chn_ref() that new refcount won't be negative. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D44985
* sound: Merge pcm_chn_destroy() and chn_kill()Christos Margiolis2024-04-281-5/+7
| | | | | | | | | | | | | | pcm_chn_destroy() acts like a wrapper around chn_kill(), and additionally calls a few more functions that should in fact be part of chn_kill()'s logic. Merge pcm_chn_destroy()'s functionality in chn_kill() to improve readability, as well as code layering. While here, convert chn_kill() to void as it currently always returns 0. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D44984
* sound: Assert that we do not enter chn_sleep() with CHN_F_SLEEPINGChristos Margiolis2024-04-281-0/+2
| | | | | | | Sponsored by: The FreeBSD Foundation MFC after: 1 day Reviewed by: markj, emaste Differential Revision: https://reviews.freebsd.org/D44959
* sound: Fix panic caused by sleeping-channel destruction during asynchronous ↵Christos Margiolis2024-04-281-0/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | detach Currently we are force-destroying all channels unconditionally in pcm_killchan(). However, since asynchronous audio device detach is possible as of 44e128fe9d92, if we do not check whether the channel is sleeping or not and forcefully kill it, we will get a panic from cv_timedwait_sig() (called from chn_sleep()), because it will try to use a freed lock/cv. Modify pcm_killchan() (renamed to pcm_killchans() since that's a more appropriate name now) to loop through the channel list and destroy only the channels that are awake, otherwise wake up the sleeping thread and try again. This loop is repeated until all channels are awakened and destroyed. To reduce code duplication, implement chn_shutdown() which wakes up the channel and sets CHN_F_DEAD, and use it in pcm_unregister() and pcm_killchans(). Reported by: KASAN Fixes: 44e128fe9d92 ("sound: Implement asynchronous device detach") Sponsored by: The FreeBSD Foundation MFC after: 1 day Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D44923
* sound: Remove obsolete chn_setvolume()Christos Margiolis2024-04-181-13/+0
| | | | | | | | | It is marked as obsolete and there are no consumers of it anymore. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: markj, emaste Differential Revision: https://reviews.freebsd.org/D44853
* sys: Remove SND_DECLARE_FILEJohn Baldwin2023-08-181-2/+0
| | | | | Reviewed by: kbowling, imp, emaste Differential Revision: https://reviews.freebsd.org/D41499
* sys: Remove $FreeBSD$: sound driver versionWarner Losh2023-08-161-1/+1
| | | | Remove /SND_DECLARE_FILE\("\$FreeBSD\$"\);/