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