> 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.

> 
>> 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 */
>> 
>> 


Reply via email to