Module Name: src
Committed By: nat
Date: Sun Dec 25 22:44:24 UTC 2016
Modified Files:
src/sys/dev: audio.c
Log Message:
Fix suspend/resume logic.
To generate a diff of this commit:
cvs rdiff -u -r1.286 -r1.287 src/sys/dev/audio.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/audio.c
diff -u src/sys/dev/audio.c:1.286 src/sys/dev/audio.c:1.287
--- src/sys/dev/audio.c:1.286 Fri Dec 23 21:01:00 2016
+++ src/sys/dev/audio.c Sun Dec 25 22:44:24 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: audio.c,v 1.286 2016/12/23 21:01:00 nat Exp $ */
+/* $NetBSD: audio.c,v 1.287 2016/12/25 22:44:24 nat Exp $ */
/*-
* Copyright (c) 2016 Nathanial Sloss <[email protected]>
@@ -87,7 +87,7 @@
*/
/*
- * Locking: there are three locks.
+ * Locking: there are two locks.
*
* - sc_lock, provided by the underlying driver. This is an adaptive lock,
* returned in the second parameter to hw_if->get_locks(). It is known
@@ -148,7 +148,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.286 2016/12/23 21:01:00 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.287 2016/12/25 22:44:24 nat Exp $");
#include "audio.h"
#if NAUDIO > 0
@@ -480,6 +480,7 @@ audioattach(device_t parent, device_t se
sc->sc_trigger_started = false;
sc->sc_rec_started = false;
+ sc->sc_dying = false;
sc->sc_vchan[0] = kmem_zalloc(sizeof(struct virtual_channel), KM_SLEEP);
vc = sc->sc_vchan[0];
memset(sc->sc_audiopid, -1, sizeof(sc->sc_audiopid));
@@ -853,6 +854,7 @@ audioactivate(device_t self, enum devact
case DVACT_DEACTIVATE:
mutex_enter(sc->sc_lock);
sc->sc_dying = true;
+ cv_broadcast(&sc->sc_condvar);
mutex_exit(sc->sc_lock);
return 0;
default:
@@ -5018,23 +5020,27 @@ audio_suspend(device_t dv, const pmf_qua
{
struct audio_softc *sc = device_private(dv);
const struct audio_hw_if *hwp = sc->hw_if;
+ struct virtual_channel *vc;
int n;
+ bool pbus, rbus;
+ pbus = rbus = false;
mutex_enter(sc->sc_lock);
+ audio_mixer_capture(sc);
for (n = 1; n < VAUDIOCHANS; n++) {
- if (sc->sc_audiopid[n].pid == curproc->p_pid)
- break;
- }
- if (n == VAUDIOCHANS) {
- mutex_exit(sc->sc_lock);
- return false;
- }
+ if (sc->sc_audiopid[n].pid == -1)
+ continue;
- audio_mixer_capture(sc);
+ vc = sc->sc_vchan[n];
+ if (vc->sc_pbus && !pbus)
+ pbus = true;
+ if (vc->sc_rbus && !rbus)
+ rbus = true;
+ }
mutex_enter(sc->sc_intr_lock);
- if (sc->sc_vchan[n]->sc_pbus == true)
+ if (pbus == true)
hwp->halt_output(sc->hw_hdl);
- if (sc->sc_recopens == 1 && sc->sc_vchan[n]->sc_rbus == true)
+ if (rbus == true)
hwp->halt_input(sc->hw_hdl);
mutex_exit(sc->sc_intr_lock);
#ifdef AUDIO_PM_IDLE
@@ -5052,25 +5058,28 @@ audio_resume(device_t dv, const pmf_qual
struct virtual_channel *vc;
int n;
- for (n = 1; n < VAUDIOCHANS; n++) {
- if (sc->sc_audiopid[n].pid == curproc->p_pid)
- break;
- }
-
- if (n == VAUDIOCHANS)
- return false;
- vc = sc->sc_vchan[n];
-
mutex_enter(sc->sc_lock);
- if (vc->sc_lastinfovalid)
- audiosetinfo(sc, &vc->sc_lastinfo, true, n);
+ sc->sc_trigger_started = false;
+ sc->sc_rec_started = false;
+
+ audio_set_vchan_defaults(sc, AUMODE_PLAY | AUMODE_PLAY_ALL |
+ AUMODE_RECORD, &vaudio_formats[0], 0);
+
audio_mixer_restore(sc);
- mutex_enter(sc->sc_intr_lock);
- if ((vc->sc_pbus == true) && !vc->sc_mpr.pause)
- audiostartp(sc, n);
- if ((vc->sc_rbus == true) && !vc->sc_mrr.pause)
- audiostartr(sc, n);
- mutex_exit(sc->sc_intr_lock);
+ for (n = 1; n < VAUDIOCHANS; n++) {
+ if (sc->sc_audiopid[n].pid == -1)
+ continue;
+ vc = sc->sc_vchan[n];
+
+ if (vc->sc_lastinfovalid == true)
+ audiosetinfo(sc, &vc->sc_lastinfo, true, n);
+ mutex_enter(sc->sc_intr_lock);
+ if (vc->sc_pbus == true && !vc->sc_mpr.pause)
+ audiostartp(sc, n);
+ if (vc->sc_rbus == true && !vc->sc_mrr.pause)
+ audiostartr(sc, n);
+ mutex_exit(sc->sc_intr_lock);
+ }
mutex_exit(sc->sc_lock);
return true;
@@ -5248,6 +5257,7 @@ mix_write(void *arg)
vc = sc->sc_vchan[0];
blksize = vc->sc_mpr.blksize;
cc = blksize;
+ error = 0;
cc1 = cc;
if (vc->sc_pustream->inp + cc > vc->sc_pustream->end)
@@ -5280,13 +5290,15 @@ mix_write(void *arg)
error = sc->hw_if->start_output(sc->hw_hdl,
__UNCONST(vc->sc_mpr.s.outp), blksize,
audio_pint, (void *)sc);
- if (error) {
- /* XXX does this really help? */
- DPRINTF(("audio_mix restart failed: %d\n", error));
- audio_clear(sc, 0);
- }
}
sc->sc_trigger_started = true;
+
+ if (error) {
+ /* XXX does this really help? */
+ DPRINTF(("audio_mix restart failed: %d\n", error));
+ audio_clear(sc, 0);
+ sc->sc_trigger_started = false;
+ }
}
void