sound: Fix hot-unload panics
This patch fixes multiple different panic scenarios occuring during
hot-unload:
- The channel is unlocked in chn_read()/chn_write() for uiomove(9) and in the meantime we enter pcm_killchans() and free it. By the time we have returned from userland and try to lock it back, the channel will have been freed.
- The parent channel has been freed in pcm_killchans(), but at the same time, some yet-unstopped vchan's chn_read()/chn_write() calls chn_start(), which eventually calls vchan_trigger(), which references the freed parent.
- PCM_WAIT() panics because it references a freed PCM lock.
For scenarios 1 and 2, refactor pcm_killchans() to first make sure all
channels have been stopped, and then proceed to free them one by one, as
opposed to freeing the first free channel until all channels have been
freed. This change makes the code more robust, but might introduce some
performance overhead when many channels are allocated, since we
continuously loop through the channel list until all of them are
stopped, and then we loop one last time to free them.
For scenario 3, restructure the code so that we can use destroy_dev(9)
instead of destroy_dev_sched(9) in dsp_destroy_dev(). Because
destroy_dev(9) blocks until all references to the device have went away,
we ensure that the PCM cv and lock will be freed safely.
While here, move the delete_unrhdr(9) calls to pcm_killchans() and
re-order some lines.
Sponsored by: The FreeBSD Foundation
MFC after: 2 days
Reviewed by: dev_submerge.ch
Differential Revision: https://reviews.freebsd.org/D47462