diff options
author | Takashi Iwai <tiwai@suse.de> | 2021-07-01 08:34:15 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2021-07-01 08:34:15 +0200 |
commit | 498386d1c4d98a72db7a2f51473593ad563b45ae (patch) | |
tree | f94e6b211b9a50106e6e047cd992ae3e209ef007 /include/sound/core.h | |
parent | 5c6d4f97267f02f47acea8a652265348ec12de51 (diff) | |
parent | dfc2e8ae4066a95c7f9c2bb2dfa26651feaa6b83 (diff) | |
download | lwn-498386d1c4d98a72db7a2f51473593ad563b45ae.tar.gz lwn-498386d1c4d98a72db7a2f51473593ad563b45ae.zip |
Merge branch 'for-next' into for-linus
Diffstat (limited to 'include/sound/core.h')
-rw-r--r-- | include/sound/core.h | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/include/sound/core.h b/include/sound/core.h index 1f9aef0adbc9..c4ade121727d 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -128,7 +128,9 @@ struct snd_card { #ifdef CONFIG_PM unsigned int power_state; /* power state */ + atomic_t power_ref; wait_queue_head_t power_sleep; + wait_queue_head_t power_ref_sleep; #endif #if IS_ENABLED(CONFIG_SND_MIXER_OSS) @@ -142,21 +144,61 @@ struct snd_card { #ifdef CONFIG_PM static inline unsigned int snd_power_get_state(struct snd_card *card) { - return card->power_state; + return READ_ONCE(card->power_state); } static inline void snd_power_change_state(struct snd_card *card, unsigned int state) { - card->power_state = state; + WRITE_ONCE(card->power_state, state); wake_up(&card->power_sleep); } +/** + * snd_power_ref - Take the reference count for power control + * @card: sound card object + * + * The power_ref reference of the card is used for managing to block + * the snd_power_sync_ref() operation. This function increments the reference. + * The counterpart snd_power_unref() has to be called appropriately later. + */ +static inline void snd_power_ref(struct snd_card *card) +{ + atomic_inc(&card->power_ref); +} + +/** + * snd_power_unref - Release the reference count for power control + * @card: sound card object + */ +static inline void snd_power_unref(struct snd_card *card) +{ + if (atomic_dec_and_test(&card->power_ref)) + wake_up(&card->power_ref_sleep); +} + +/** + * snd_power_sync_ref - wait until the card power_ref is freed + * @card: sound card object + * + * This function is used to synchronize with the pending power_ref being + * released. + */ +static inline void snd_power_sync_ref(struct snd_card *card) +{ + wait_event(card->power_ref_sleep, !atomic_read(&card->power_ref)); +} + /* init.c */ -int snd_power_wait(struct snd_card *card, unsigned int power_state); +int snd_power_wait(struct snd_card *card); +int snd_power_ref_and_wait(struct snd_card *card); #else /* ! CONFIG_PM */ -static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; } +static inline int snd_power_wait(struct snd_card *card) { return 0; } +static inline void snd_power_ref(struct snd_card *card) {} +static inline void snd_power_unref(struct snd_card *card) {} +static inline int snd_power_ref_and_wait(struct snd_card *card) { return 0; } +static inline void snd_power_sync_ref(struct snd_card *card) {} #define snd_power_get_state(card) ({ (void)(card); SNDRV_CTL_POWER_D0; }) #define snd_power_change_state(card, state) do { (void)(card); } while (0) |