> On 3 Jan 2015, at 9:35 am, David Gwynne <da...@gwynne.id.au> wrote: > >> >> On 2 Jan 2015, at 9:55 pm, Mark Kettenis <mark.kette...@xs4all.nl> wrote: >> >>> Date: Fri, 2 Jan 2015 16:15:07 +1000 >>> From: David Gwynne <da...@gwynne.id.au> >>> >>> can someone test this? >>> >>> it allocates storage for the volume change details rather than cast >>> arguments to a single global task. >>> >>> adds some safety while there if audio0 is a hotplug device. >>> >>> ok? >> >> The problem with this approach is that things silently fail when >> memory allocation fails. Exactly the problem that workq_add_task() >> had. Perhaps the best thing is to store the "event" in the softc, >> although then you'd probably need some locking to make sure the task >> sees a consistent dir/out pair. > > is "silently fail" a pun here? > > you can lose events either way. if you get more than one keypress before the > task runs, you'll lose. if you are in a situation where you cant allocate > memory, you lose. > > i think the code generally is bogus so im trying to do as little as possible > to it. the more i look at it the more i want to just remove it. > > its been unreliable in all incarnations.
did anyone try this diff? dlg > >> >>> Index: audio.c >>> =================================================================== >>> RCS file: /cvs/src/sys/dev/audio.c,v >>> retrieving revision 1.125 >>> diff -u -p -r1.125 audio.c >>> --- audio.c 19 Dec 2014 22:44:58 -0000 1.125 >>> +++ audio.c 2 Jan 2015 06:08:39 -0000 >>> @@ -465,11 +465,6 @@ audioattach(struct device *parent, struc >>> } >>> DPRINTF(("audio_attach: inputs ports=0x%x, output ports=0x%x\n", >>> sc->sc_inports.allports, sc->sc_outports.allports)); >>> - >>> -#if NWSKBD > 0 >>> - task_set(&sc->sc_mixer_task, wskbd_set_mixervolume_callback, NULL, >>> - NULL); >>> -#endif /* NWSKBD > 0 */ >>> } >>> >>> int >>> @@ -3432,27 +3427,39 @@ filt_audiowrite(struct knote *kn, long h >>> } >>> >>> #if NWSKBD > 0 >>> +struct wskbd_vol_change { >>> + struct task t; >>> + long dir; >>> + long out; >>> +}; >>> + >>> int >>> wskbd_set_mixervolume(long dir, long out) >>> { >>> struct audio_softc *sc; >>> + struct wskbd_vol_change *ch; >>> >>> if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { >>> DPRINTF(("wskbd_set_mixervolume: audio_cd\n")); >>> return (ENXIO); >>> } >>> >>> - task_del(systq, &sc->sc_mixer_task); >>> - task_set(&sc->sc_mixer_task, wskbd_set_mixervolume_callback, >>> - (void *)dir, (void *)out); >>> - task_add(systq, &sc->sc_mixer_task); >>> + ch = malloc(sizeof(*ch), M_TEMP, M_NOWAIT); >>> + if (ch == NULL) >>> + return (ENOMEM); >>> + >>> + task_set(&ch->t, wskbd_set_mixervolume_callback, ch, NULL); >>> + ch->dir = dir; >>> + ch->out = out; >>> + task_add(systq, &ch->t); >>> >>> return (0); >>> } >>> >>> void >>> -wskbd_set_mixervolume_callback(void *arg1, void *arg2) >>> +wskbd_set_mixervolume_callback(void *xch, void *null) >>> { >>> + struct wskbd_vol_change *ch = xch; >>> struct audio_softc *sc; >>> struct au_mixer_ports *ports; >>> mixer_devinfo_t mi; >>> @@ -3461,19 +3468,19 @@ wskbd_set_mixervolume_callback(void *arg >>> u_int gain; >>> int error; >>> >>> - if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { >>> - DPRINTF(("%s: audio_cd\n", __func__)); >>> - return; >>> - } >>> + dir = ch->dir; >>> + out = ch->out; >>> + free(ch, M_TEMP, sizeof(*ch)); >>> >>> - dir = (long)arg1; >>> - out = (long)arg2; >>> + sc = (struct audio_softc *)device_lookup(&audio_cd, 0); >>> + if (sc == NULL) >>> + return; >>> >>> ports = out ? &sc->sc_outports : &sc->sc_inports; >>> >>> if (ports->master == -1) { >>> DPRINTF(("%s: master == -1\n", __func__)); >>> - return; >>> + goto done; >>> } >>> >>> if (dir == 0) { >>> @@ -3482,7 +3489,7 @@ wskbd_set_mixervolume_callback(void *arg >>> error = au_get_mute(sc, ports, &mute); >>> if (error != 0) { >>> DPRINTF(("%s: au_get_mute: %d\n", __func__, error)); >>> - return; >>> + goto done; >>> } >>> >>> mute = !mute; >>> @@ -3490,7 +3497,7 @@ wskbd_set_mixervolume_callback(void *arg >>> error = au_set_mute(sc, ports, mute); >>> if (error != 0) { >>> DPRINTF(("%s: au_set_mute: %d\n", __func__, error)); >>> - return; >>> + goto done; >>> } >>> } else { >>> /* Raise or lower volume */ >>> @@ -3499,7 +3506,7 @@ wskbd_set_mixervolume_callback(void *arg >>> error = sc->hw_if->query_devinfo(sc->hw_hdl, &mi); >>> if (error != 0) { >>> DPRINTF(("%s: query_devinfo: %d\n", __func__, error)); >>> - return; >>> + goto done; >>> } >>> >>> au_get_gain(sc, ports, &gain, &balance); >>> @@ -3512,8 +3519,11 @@ wskbd_set_mixervolume_callback(void *arg >>> error = au_set_gain(sc, ports, gain, balance); >>> if (error != 0) { >>> DPRINTF(("%s: au_set_gain: %d\n", __func__, error)); >>> - return; >>> + goto done; >>> } >>> } >>> + >>> +done: >>> + device_unref(&sc->dev); >>> } >>> #endif /* NWSKBD > 0 */