At Wed, 31 May 2006 23:59:24 +0200, Giuliano Pochini wrote: > > > Does this patch make sense ? > > It adds two functions to rawmidi.c: snd_rawmidi_suspend() and > snd_rawmidi_resume() and it adds a new ops callback. Those functions > pause or restart the tasklet respectively and call the driver's > ops->power(down/up) function. This patch also prevents driver's ops-> > functions from being called while the card is supended. > > (tested ok with the Gina 3G) Well, snd_power_lock() uses mutex, and this isn't allowed in the trigger callbacks that may be called in the (soft)irq context. Maybe we should use a simple flag and simply ignore/fail trigger operations during suspend. Takashi > > > > diff -dupr alsa-kernel__orig/core/rawmidi.c alsa-kernel/core/rawmidi.c > --- alsa-kernel__orig/core/rawmidi.c 2006-05-17 23:17:58.000000000 +0200 > +++ alsa-kernel/core/rawmidi.c 2006-05-31 23:47:16.000000000 +0200 > @@ -155,17 +155,28 @@ static int snd_rawmidi_runtime_free(stru > > static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream,int up) > { > - if (up) { > - tasklet_hi_schedule(&substream->runtime->tasklet); > - } else { > - tasklet_kill(&substream->runtime->tasklet); > - substream->ops->trigger(substream, 0); > + struct snd_card *card = substream->rmidi->card; > + > + snd_power_lock(card); > + if (snd_power_wait(card, SNDRV_CTL_POWER_D0) >= 0) { > + if (up) { > + tasklet_hi_schedule(&substream->runtime->tasklet); > + } else { > + tasklet_kill(&substream->runtime->tasklet); > + substream->ops->trigger(substream, 0); > + } > } > + snd_power_unlock(card); > } > > static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) > { > - substream->ops->trigger(substream, up); > + struct snd_card *card = substream->rmidi->card; > + > + snd_power_lock(card); > + if (snd_power_wait(card, SNDRV_CTL_POWER_D0) >= 0) > + substream->ops->trigger(substream, up); > + snd_power_unlock(card); > if (!up && substream->runtime->event) > tasklet_kill(&substream->runtime->tasklet); > } > @@ -204,9 +215,14 @@ int snd_rawmidi_drain_output(struct snd_ > runtime->drain = 0; > if (err != -ERESTARTSYS) { > /* we need wait a while to make sure that Tx FIFOs are empty */ > - if (substream->ops->drain) > - substream->ops->drain(substream); > - else > + if (substream->ops->drain) { > + struct snd_card *card = substream->rmidi->card; > + > + snd_power_lock(card); > + if (snd_power_wait(card, SNDRV_CTL_POWER_D0) >= 0) > + substream->ops->drain(substream); > + snd_power_unlock(card); > + } else > msleep(50); > snd_rawmidi_drop_output(substream); > } > @@ -1648,6 +1664,59 @@ void snd_rawmidi_set_ops(struct snd_rawm > } > } > > + > +#ifdef CONFIG_PM > + > +/** > + * snd_rawmidi_suspend > + * @substream: the rawmidi substream > + * > + * Suspend the given substream. > + */ > +int snd_rawmidi_suspend(struct snd_rawmidi_substream *substream) > +{ > + int err; > + struct snd_card *card = substream->rmidi->card; > + > +snd_printk("snd_rawmidi_suspend\n"); > + err = 0; > + snd_power_lock(card); > + tasklet_disable(&substream->runtime->tasklet); > + if (substream->ops->power) > + err = substream->ops->power(substream, 0); > + snd_power_unlock(card); > + return err; > +} > + > +EXPORT_SYMBOL(snd_rawmidi_suspend); > + > + > +/** > + * snd_rawmidi_resume > + * @substream: the rawmidi substream > + * > + * Resume the given substream. > + */ > +int snd_rawmidi_resume(struct snd_rawmidi_substream *substream) > +{ > + int err; > + struct snd_card *card = substream->rmidi->card; > + > +snd_printk("snd_rawmidi_resume\n"); > + err = 0; > + snd_power_lock(card); > + if (substream->ops->power) > + err = substream->ops->power(substream, 1); > + tasklet_enable(&substream->runtime->tasklet); > + snd_power_unlock(card); > + return err; > +} > + > +EXPORT_SYMBOL(snd_rawmidi_resume); > + > +#endif /* CONFIG_PM */ > + > + > /* > * ENTRY functions > */ > diff -dupr alsa-kernel__orig/include/rawmidi.h alsa-kernel/include/rawmidi.h > --- alsa-kernel__orig/include/rawmidi.h 2006-05-17 23:17:58.000000000 +0200 > +++ alsa-kernel/include/rawmidi.h 2006-05-28 19:57:49.000000000 +0200 > @@ -53,6 +53,7 @@ struct snd_rawmidi_ops { > int (*close) (struct snd_rawmidi_substream * substream); > void (*trigger) (struct snd_rawmidi_substream * substream, int up); > void (*drain) (struct snd_rawmidi_substream * substream); > + int (*power) (struct snd_rawmidi_substream * substream, int state); > }; > > struct snd_rawmidi_global_ops { > @@ -182,5 +183,7 @@ long snd_rawmidi_kernel_read(struct snd_ > unsigned char *buf, long count); > long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream, > const unsigned char *buf, long count); > +int snd_rawmidi_suspend(struct snd_rawmidi_substream *substream); > +int snd_rawmidi_resume(struct snd_rawmidi_substream *substream); > > #endif /* __SOUND_RAWMIDI_H */ > > > > > > -- > Giuliano. > > > _______________________________________________ > Alsa-devel mailing list > Alsa-devel@xxxxxxxxxxxxxxxxxxxxx > https://lists.sourceforge.net/lists/listinfo/alsa-devel > _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.sourceforge.net/lists/listinfo/alsa-devel