Re: [RFC] rawmidi suspend/resume support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux