Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-9]: src/sys/dev/audio Pull up following revision(s) (requested by...
details: https://anonhg.NetBSD.org/src/rev/3bc1205bea20
branches: netbsd-9
changeset: 963846:3bc1205bea20
user: martin <martin%NetBSD.org@localhost>
date: Thu Apr 30 16:05:18 2020 +0000
description:
Pull up following revision(s) (requested by isaki in ticket #877):
sys/dev/audio/audio.c: revision 1.55
sys/dev/audio/audio.c: revision 1.41
sys/dev/audio/audio.c: revision 1.48
sys/dev/audio/audiovar.h: revision 1.7
sys/dev/audio/audio.c: revision 1.63 (via patch)
sys/dev/audio/audiovar.h: revision 1.11
sys/dev/audio/audio.c: revision 1.64
Simplify async_mixer handling.
- It makes FIOASYNC code in mixer_ioctl() symmetric.
- For readability, mixer_async_{add,remove}() should take pid argument
though pid is always curproc.
hw_if->query_format is already mandatory method. Drop null checks.
Improve error handling around audio_hw_probe().
It was difficult to return multiple errors.
Split sc_lock and sc_exlock.
Most (probably all) malloc/free (or routines which may sleep) now can be
called without holding mutex.
Pointed out by riastradh@.
Fix/Update comments about allocm/freem.
diffstat:
sys/dev/audio/audio.c | 615 +++++++++++++++++++++++++---------------------
sys/dev/audio/audiovar.h | 29 +-
2 files changed, 350 insertions(+), 294 deletions(-)
diffs (truncated from 1656 to 300 lines):
diff -r 81b88c3a26de -r 3bc1205bea20 sys/dev/audio/audio.c
--- a/sys/dev/audio/audio.c Thu Apr 30 15:43:30 2020 +0000
+++ b/sys/dev/audio/audio.c Thu Apr 30 16:05:18 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: audio.c,v 1.28.2.11 2020/04/30 15:43:30 martin Exp $ */
+/* $NetBSD: audio.c,v 1.28.2.12 2020/04/30 16:05:18 martin Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -118,8 +118,8 @@
* set_port - x +
* get_port - x +
* query_devinfo - x
- * allocm - - + (*1)
- * freem - - + (*1)
+ * allocm - - +
+ * freem - - +
* round_buffersize - x
* get_props - x Called at attach time
* trigger_output x x +
@@ -127,10 +127,6 @@
* dev_ioctl - x
* get_locks - - Called at attach time
*
- * *1 Note: Before 8.0, since these have been called only at attach time,
- * neither lock were necessary. Currently, on the other hand, since
- * these may be also called after attach, the thread lock is required.
- *
* In addition, there is an additional lock.
*
* - track->lock. This is an atomic variable and is similar to the
@@ -142,7 +138,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.28.2.11 2020/04/30 15:43:30 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.28.2.12 2020/04/30 16:05:18 martin Exp $");
#ifdef _KERNEL_OPT
#include "audio.h"
@@ -466,6 +462,9 @@
int audio_idle_timeout = 30;
#endif
+/* Number of elements of async mixer's pid */
+#define AM_CAPACITY (4)
+
struct portname {
const char *name;
int mask;
@@ -497,8 +496,10 @@
static void audio_softintr_rd(void *);
static void audio_softintr_wr(void *);
-static int audio_enter_exclusive(struct audio_softc *);
-static void audio_exit_exclusive(struct audio_softc *);
+static int audio_exlock_mutex_enter(struct audio_softc *);
+static void audio_exlock_mutex_exit(struct audio_softc *);
+static int audio_exlock_enter(struct audio_softc *);
+static void audio_exlock_exit(struct audio_softc *);
static struct audio_softc *audio_file_enter(audio_file_t *, struct psref *);
static void audio_file_exit(struct audio_softc *, struct psref *);
static int audio_track_waitio(struct audio_softc *, audio_track_t *);
@@ -560,9 +561,7 @@
const audio_format2_t *, const audio_format2_t *,
const audio_filter_reg_t *, const audio_filter_reg_t *);
static int audio_select_freq(const struct audio_format *);
-static int audio_hw_probe(struct audio_softc *, int, int *,
- audio_format2_t *, audio_format2_t *);
-static int audio_hw_probe_fmt(struct audio_softc *, audio_format2_t *, int);
+static int audio_hw_probe(struct audio_softc *, audio_format2_t *, int);
static int audio_hw_validate_format(struct audio_softc *, int,
const audio_format2_t *);
static int audio_mixers_set_format(struct audio_softc *,
@@ -609,7 +608,8 @@
static int mixer_open(dev_t, struct audio_softc *, int, int, struct lwp *);
static int mixer_close(struct audio_softc *, audio_file_t *);
static int mixer_ioctl(struct audio_softc *, u_long, void *, int, struct lwp *);
-static void mixer_remove(struct audio_softc *);
+static void mixer_async_add(struct audio_softc *, pid_t);
+static void mixer_async_remove(struct audio_softc *, pid_t);
static void mixer_signal(struct audio_softc *);
static int au_portof(struct audio_softc *, char *, int);
@@ -882,9 +882,13 @@
sc->hw_hdl = hdlp;
sc->hw_dev = parent;
+ sc->sc_exlock = 1;
sc->sc_blk_ms = AUDIO_BLK_MS;
SLIST_INIT(&sc->sc_files);
cv_init(&sc->sc_exlockcv, "audiolk");
+ sc->sc_am_capacity = 0;
+ sc->sc_am_used = 0;
+ sc->sc_am = NULL;
mutex_enter(sc->sc_lock);
sc->sc_props = hw_if->get_props(sc->hw_hdl);
@@ -932,24 +936,47 @@
memset(&rhwfmt, 0, sizeof(rhwfmt));
memset(&pfil, 0, sizeof(pfil));
memset(&rfil, 0, sizeof(rfil));
- mutex_enter(sc->sc_lock);
- error = audio_hw_probe(sc, has_indep, &mode, &phwfmt, &rhwfmt);
- if (error) {
- mutex_exit(sc->sc_lock);
- aprint_error_dev(self, "audio_hw_probe failed, "
- "error = %d\n", error);
- goto bad;
- }
- if (mode == 0) {
- mutex_exit(sc->sc_lock);
- aprint_error_dev(self, "audio_hw_probe failed, no mode\n");
- goto bad;
- }
+ if (has_indep) {
+ int perror, rerror;
+
+ /* On independent devices, probe separately. */
+ perror = audio_hw_probe(sc, &phwfmt, AUMODE_PLAY);
+ rerror = audio_hw_probe(sc, &rhwfmt, AUMODE_RECORD);
+ if (perror && rerror) {
+ aprint_error_dev(self, "audio_hw_probe failed, "
+ "perror = %d, rerror = %d\n", perror, rerror);
+ goto bad;
+ }
+ if (perror) {
+ mode &= ~AUMODE_PLAY;
+ aprint_error_dev(self, "audio_hw_probe failed with "
+ "%d, playback disabled\n", perror);
+ }
+ if (rerror) {
+ mode &= ~AUMODE_RECORD;
+ aprint_error_dev(self, "audio_hw_probe failed with "
+ "%d, capture disabled\n", rerror);
+ }
+ } else {
+ /*
+ * On non independent devices or uni-directional devices,
+ * probe once (simultaneously).
+ */
+ audio_format2_t *fmt = has_playback ? &phwfmt : &rhwfmt;
+ error = audio_hw_probe(sc, fmt, mode);
+ if (error) {
+ aprint_error_dev(self, "audio_hw_probe failed, "
+ "error = %d\n", error);
+ goto bad;
+ }
+ if (has_playback && has_capture)
+ rhwfmt = phwfmt;
+ }
+
/* Init hardware. */
/* hw_probe() also validates [pr]hwfmt. */
error = audio_hw_set_format(sc, mode, &phwfmt, &rhwfmt, &pfil, &rfil);
if (error) {
- mutex_exit(sc->sc_lock);
aprint_error_dev(self, "audio_hw_set_format failed, "
"error = %d\n", error);
goto bad;
@@ -960,7 +987,6 @@
* attach time, we assume a success.
*/
error = audio_mixers_init(sc, mode, &phwfmt, &rhwfmt, &pfil, &rfil);
- mutex_exit(sc->sc_lock);
if (sc->sc_pmixer == NULL && sc->sc_rmixer == NULL) {
aprint_error_dev(self, "audio_mixers_init failed, "
"error = %d\n", error);
@@ -1052,11 +1078,13 @@
#endif
audiorescan(self, "audio", NULL);
+ sc->sc_exlock = 0;
return;
bad:
/* Clearing hw_if means that device is attached but disabled. */
sc->hw_if = NULL;
+ sc->sc_exlock = 0;
aprint_error_dev(sc->sc_dev, "disabled\n");
return;
}
@@ -1274,6 +1302,7 @@
* that hold sc, and any new calls with files that were for sc will
* fail. Thus, we now have exclusive access to the softc.
*/
+ sc->sc_exlock = 1;
/*
* Nuke all open instances.
@@ -1299,7 +1328,6 @@
pmf_device_deregister(self);
/* Free resources */
- mutex_enter(sc->sc_lock);
if (sc->sc_pmixer) {
audio_mixer_destroy(sc, sc->sc_pmixer);
kmem_free(sc->sc_pmixer, sizeof(*sc->sc_pmixer));
@@ -1308,7 +1336,8 @@
audio_mixer_destroy(sc, sc->sc_rmixer);
kmem_free(sc->sc_rmixer, sizeof(*sc->sc_rmixer));
}
- mutex_exit(sc->sc_lock);
+ if (sc->sc_am)
+ kern_free(sc->sc_am);
seldestroy(&sc->sc_wsel);
seldestroy(&sc->sc_rsel);
@@ -1378,12 +1407,12 @@
}
/*
- * Acquire sc_lock and enter exlock critical section.
- * If successful, it returns 0. Otherwise returns errno.
+ * Enter critical section and also keep sc_lock.
+ * If successful, returns 0 with sc_lock held. Otherwise returns errno.
* Must be called without sc_lock held.
*/
static int
-audio_enter_exclusive(struct audio_softc *sc)
+audio_exlock_mutex_enter(struct audio_softc *sc)
{
int error;
@@ -1409,23 +1438,51 @@
}
/*
- * Leave exlock critical section and release sc_lock.
+ * Exit critical section and exit sc_lock.
* Must be called with sc_lock held.
*/
static void
-audio_exit_exclusive(struct audio_softc *sc)
+audio_exlock_mutex_exit(struct audio_softc *sc)
{
KASSERT(mutex_owned(sc->sc_lock));
- KASSERT(sc->sc_exlock);
-
- /* Leave critical section */
+
sc->sc_exlock = 0;
cv_broadcast(&sc->sc_exlockcv);
mutex_exit(sc->sc_lock);
}
/*
+ * Enter critical section.
+ * If successful, it returns 0. Otherwise returns errno.
+ * Must be called without sc_lock held.
+ * This function returns without sc_lock held.
+ */
+static int
+audio_exlock_enter(struct audio_softc *sc)
+{
+ int error;
+
+ error = audio_exlock_mutex_enter(sc);
+ if (error)
+ return error;
+ mutex_exit(sc->sc_lock);
+ return 0;
+}
+
+/*
+ * Exit critical section.
+ * Must be called without sc_lock held.
+ */
+static void
+audio_exlock_exit(struct audio_softc *sc)
+{
+
+ mutex_enter(sc->sc_lock);
+ audio_exlock_mutex_exit(sc);
+}
+
+/*
* Acquire sc from file, and increment the psref count.
* If successful, returns sc. Otherwise returns NULL.
*/
@@ -1539,7 +1596,7 @@
if (sc == NULL || sc->hw_if == NULL)
return ENXIO;
- error = audio_enter_exclusive(sc);
+ error = audio_exlock_enter(sc);
if (error)
return error;
@@ -1559,7 +1616,7 @@
error = ENXIO;
break;
}
- audio_exit_exclusive(sc);
+ audio_exlock_exit(sc);
return error;
}
@@ -1893,14 +1950,14 @@
Home |
Main Index |
Thread Index |
Old Index