[PATCH 0/7] ALSA: Prep work for PCI rescan support
Hi,
this is a patch set as a prep work for the future-planned PCI rescan support(*). The essential part is the patch to track in-flight tasks, and the rest are cleanups and fixes in the core code. With those changes, the driver can perform a sort of software suspend on the device without the hardware intervention, which is required during the PCI BAR movement, for example.
Takashi
(*) https://lore.kernel.org/alsa-devel/e25017c6-e5e4-7a24-e793-14a2e70a434e@amd....
===
Takashi Iwai (7): ALSA: core: Use READ_ONCE() / WRITE_ONCE() for power state change ALSA: control: Add power state check commonly for ioctl handlers ALSA: control: Drop superfluous snd_power_wait() calls ALSA: control: Minor optimization for SNDRV_CTL_IOCTL_POWER_STATE ALSA: control: Track in-flight control read/write/tlv accesses ALSA: pcm: Block the release until the system resume finishes ALSA: Drop superfluous argument from snd_power_wait()
include/sound/core.h | 39 +++++++++++++++++++++--- sound/core/control.c | 41 +++++++++++++------------- sound/core/control_compat.c | 17 +++++------ sound/core/init.c | 59 ++++++++++++++++++++++++++++++++----- sound/core/pcm_native.c | 6 +++- sound/soc/soc-core.c | 2 +- sound/usb/usx2y/us122l.c | 2 +- 7 files changed, 121 insertions(+), 45 deletions(-)
We need proper barriers to handle the power state change of the card from different CPUs.
Signed-off-by: Takashi Iwai tiwai@suse.de --- include/sound/core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/sound/core.h b/include/sound/core.h index 1f9aef0adbc9..d69dfc6c4953 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -142,12 +142,12 @@ 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); }
The card power state check can be better put in the common ioctl handler, as basically we want to prevent ioctls during the power off state. Although this situation won't happen normally any longer (*), it'll be helpful for catching this for the future implementation like the faked suspend that is needed for PCI rescan.
(*) Long long time ago, before the proper PM framework was introduced, it was still possible to reach SNDRV_CTL_IOCTL_POWER ioctl during the power off state. This ioctl existed as a main control for the suspend resume state in the past, but the feature was already dropped along with the standard PM framework.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/core/control.c | 3 +++ sound/core/control_compat.c | 3 +++ 2 files changed, 6 insertions(+)
diff --git a/sound/core/control.c b/sound/core/control.c index 498e3701514a..c22c3fad0c64 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1772,6 +1772,9 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg card = ctl->card; if (snd_BUG_ON(!card)) return -ENXIO; + err = snd_power_wait(card, SNDRV_CTL_POWER_D0); + if (err < 0) + return err; switch (cmd) { case SNDRV_CTL_IOCTL_PVERSION: return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0; diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 1d708aab9c98..d5b562ff237b 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -438,6 +438,9 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns if (snd_BUG_ON(!ctl || !ctl->card)) return -ENXIO;
+ err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); + if (err < 0) + return err; switch (cmd) { case SNDRV_CTL_IOCTL_PVERSION: case SNDRV_CTL_IOCTL_CARD_INFO:
Dne 18. 05. 21 v 18:51 Takashi Iwai napsal(a):
The card power state check can be better put in the common ioctl handler, as basically we want to prevent ioctls during the power off state. Although this situation won't happen normally any longer (*), it'll be helpful for catching this for the future implementation like the faked suspend that is needed for PCI rescan.
(*) Long long time ago, before the proper PM framework was introduced, it was still possible to reach SNDRV_CTL_IOCTL_POWER ioctl during the power off state. This ioctl existed as a main control for the suspend resume state in the past, but the feature was already dropped along with the standard PM framework.
It seems like a function dup for the 5th patch which tracks in flight the power state. I think that we should drop this (and reshuffle patches) or remove this in or after the 5th patch.
Jaroslav
Signed-off-by: Takashi Iwai tiwai@suse.de
sound/core/control.c | 3 +++ sound/core/control_compat.c | 3 +++ 2 files changed, 6 insertions(+)
diff --git a/sound/core/control.c b/sound/core/control.c index 498e3701514a..c22c3fad0c64 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1772,6 +1772,9 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg card = ctl->card; if (snd_BUG_ON(!card)) return -ENXIO;
- err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (err < 0)
switch (cmd) { case SNDRV_CTL_IOCTL_PVERSION: return put_user(SNDRV_CTL_VERSION, ip) ? -EFAULT : 0;return err;
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 1d708aab9c98..d5b562ff237b 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -438,6 +438,9 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns if (snd_BUG_ON(!ctl || !ctl->card)) return -ENXIO;
- err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
- if (err < 0)
switch (cmd) { case SNDRV_CTL_IOCTL_PVERSION: case SNDRV_CTL_IOCTL_CARD_INFO:return err;
On Tue, 18 May 2021 20:00:46 +0200, Jaroslav Kysela wrote:
Dne 18. 05. 21 v 18:51 Takashi Iwai napsal(a):
The card power state check can be better put in the common ioctl handler, as basically we want to prevent ioctls during the power off state. Although this situation won't happen normally any longer (*), it'll be helpful for catching this for the future implementation like the faked suspend that is needed for PCI rescan.
(*) Long long time ago, before the proper PM framework was introduced, it was still possible to reach SNDRV_CTL_IOCTL_POWER ioctl during the power off state. This ioctl existed as a main control for the suspend resume state in the past, but the feature was already dropped along with the standard PM framework.
It seems like a function dup for the 5th patch which tracks in flight the power state. I think that we should drop this (and reshuffle patches) or remove this in or after the 5th patch.
A good point. With snd_power_ref_and_wait(), we achieve more fine-grained protection, so those checks could be indeed dropped. Will clean up later in the v2 patch.
thanks,
Takashi
Now the card power state is checked in the common ioctl handler, drop the same redundant checks in each ioctl.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/core/control.c | 11 ----------- sound/core/control_compat.c | 9 --------- 2 files changed, 20 deletions(-)
diff --git a/sound/core/control.c b/sound/core/control.c index c22c3fad0c64..799d91ddccb0 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1042,9 +1042,6 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
if (copy_from_user(&info, _info, sizeof(info))) return -EFAULT; - result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); - if (result < 0) - return result; result = snd_ctl_elem_info(ctl, &info); if (result < 0) return result; @@ -1113,10 +1110,6 @@ static int snd_ctl_elem_read_user(struct snd_card *card, if (IS_ERR(control)) return PTR_ERR(control);
- result = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (result < 0) - goto error; - down_read(&card->controls_rwsem); result = snd_ctl_elem_read(card, control); up_read(&card->controls_rwsem); @@ -1183,10 +1176,6 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file, return PTR_ERR(control);
card = file->card; - result = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (result < 0) - goto error; - result = snd_ctl_elem_write(card, file, control); if (result < 0) goto error; diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index d5b562ff237b..57b73ab57506 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -96,9 +96,6 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl, if (get_user(data->value.enumerated.item, &data32->value.enumerated.item)) goto error;
- err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); - if (err < 0) - goto error; err = snd_ctl_elem_info(ctl, data); if (err < 0) goto error; @@ -298,9 +295,6 @@ static int ctl_elem_read_user(struct snd_card *card, if (err < 0) goto error;
- err = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (err < 0) - goto error; err = snd_ctl_elem_read(card, data); if (err < 0) goto error; @@ -326,9 +320,6 @@ static int ctl_elem_write_user(struct snd_ctl_file *file, if (err < 0) goto error;
- err = snd_power_wait(card, SNDRV_CTL_POWER_D0); - if (err < 0) - goto error; err = snd_ctl_elem_write(card, file, data); if (err < 0) goto error;
The SNDRV_CTL_IOCTL_POWER_STATE is an obsoleted ioctl and now practically it returns always D0. Do some minor optimization.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/core/control.c | 4 ---- 1 file changed, 4 deletions(-)
diff --git a/sound/core/control.c b/sound/core/control.c index 799d91ddccb0..5e8b77855e5d 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1807,11 +1807,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg case SNDRV_CTL_IOCTL_POWER: return -ENOPROTOOPT; case SNDRV_CTL_IOCTL_POWER_STATE: -#ifdef CONFIG_PM - return put_user(card->power_state, ip) ? -EFAULT : 0; -#else return put_user(SNDRV_CTL_POWER_D0, ip) ? -EFAULT : 0; -#endif } down_read(&snd_ioctl_rwsem); list_for_each_entry(p, &snd_control_ioctls, list) {
Although we introduced the power state check at the entrance of the common handler for control API (and other interfaces), there can be still some pending tasks that already went into the ioctl handler, and those may access the hardware even after the power state check; currently the problem is seen typically for the kcontrol access paths. If a system wants to assure the free from hw access (like the PCI rescan feature we're going to implement in future), this situation must be avoided, and we have to sync such in-flight tasks finishing.
For that purpose, this patch introduces a few new things: - A refcount, power_ref, and a wait queue, power_ref_sleep, to the card object - A few new helpers, snd_power_ref(), snd_power_unref(), snd_power_ref_and_wait(), and snd_power_sync_ref()
In the code paths that call kctl info/read/write/tlv ops, we check the power state again but at this time with the newly introduced snd_power_ref_and_wait() instead. This function also takes the card.power_ref refcount for tracking this in-flight task. Once after the access finishes, snd_power_unref() is called to released the refcount. So the driver can sync via snd_power_sync_ref() assuring that all in-flight tasks have been finished.
As of this patch, snd_power_sync_ref() is called only at snd_card_disconnect(), but it'll be used in other places in future.
Note that atomic_t is used for power_ref intentionally instead of refcount_t. It's because of the design of refcount_t type; it cannot be zero-based, and it cannot do dec_and_test() call for multiple times.
Also, this patch changes snd_power_wait() to accept only SNDRV_CTL_POWER_D0, which is the only value that makes sense. In later patch, the snd_power_wait() calls will be simplified.
Signed-off-by: Takashi Iwai tiwai@suse.de --- include/sound/core.h | 31 ++++++++++++++++++ sound/core/control.c | 23 +++++++++++--- sound/core/control_compat.c | 5 ++- sound/core/init.c | 63 ++++++++++++++++++++++++++++++++----- 4 files changed, 108 insertions(+), 14 deletions(-)
diff --git a/include/sound/core.h b/include/sound/core.h index d69dfc6c4953..430d775b3c0e 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) @@ -151,12 +153,41 @@ static inline void snd_power_change_state(struct snd_card *card, unsigned int st 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); +} + /* init.c */ int snd_power_wait(struct snd_card *card, unsigned int power_state); +int snd_power_ref_and_wait(struct snd_card *card); +void snd_power_sync_ref(struct snd_card *card);
#else /* ! CONFIG_PM */
static inline int snd_power_wait(struct snd_card *card, unsigned int state) { 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)
diff --git a/sound/core/control.c b/sound/core/control.c index 5e8b77855e5d..37f6f2ca0543 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -995,7 +995,10 @@ static int __snd_ctl_elem_info(struct snd_card *card, #ifdef CONFIG_SND_DEBUG info->access = 0; #endif - result = kctl->info(kctl, info); + result = snd_power_ref_and_wait(card); + if (!result) + result = kctl->info(kctl, info); + snd_power_unref(card); if (result >= 0) { snd_BUG_ON(info->access); index_offset = snd_ctl_get_ioff(kctl, &info->id); @@ -1085,7 +1088,10 @@ static int snd_ctl_elem_read(struct snd_card *card,
if (!snd_ctl_skip_validation(&info)) fill_remaining_elem_value(control, &info, pattern); - ret = kctl->get(kctl, control); + ret = snd_power_ref_and_wait(card); + if (!ret) + ret = kctl->get(kctl, control); + snd_power_unref(card); if (ret < 0) return ret; if (!snd_ctl_skip_validation(&info) && @@ -1147,7 +1153,10 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, }
snd_ctl_build_ioff(&control->id, kctl, index_offset); - result = kctl->put(kctl, control); + result = snd_power_ref_and_wait(card); + if (!result) + result = kctl->put(kctl, control); + snd_power_unref(card); if (result < 0) { up_write(&card->controls_rwsem); return result; @@ -1658,7 +1667,7 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag, {SNDRV_CTL_TLV_OP_CMD, SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND}, }; struct snd_kcontrol_volatile *vd = &kctl->vd[snd_ctl_get_ioff(kctl, id)]; - int i; + int i, ret;
/* Check support of the request for this element. */ for (i = 0; i < ARRAY_SIZE(pairs); ++i) { @@ -1676,7 +1685,11 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag, vd->owner != NULL && vd->owner != file) return -EPERM;
- return kctl->tlv.c(kctl, op_flag, size, buf); + ret = snd_power_ref_and_wait(file->card); + if (!ret) + ret = kctl->tlv.c(kctl, op_flag, size, buf); + snd_power_unref(file->card); + return ret; }
static int read_tlv_buf(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id, diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 57b73ab57506..b9fe1ead435b 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -184,7 +184,10 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, return -ENOMEM; } info->id = *id; - err = kctl->info(kctl, info); + err = snd_power_ref_and_wait(card); + if (!err) + err = kctl->info(kctl, info); + snd_power_unref(card); up_read(&card->controls_rwsem); if (err >= 0) { err = info->type; diff --git a/sound/core/init.c b/sound/core/init.c index ef41f5b3a240..d11636fac608 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -220,6 +220,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid, mutex_init(&card->memory_mutex); #ifdef CONFIG_PM init_waitqueue_head(&card->power_sleep); + init_waitqueue_head(&card->power_ref_sleep); + atomic_set(&card->power_ref, 0); #endif init_waitqueue_head(&card->remove_sleep); card->sync_irq = -1; @@ -442,6 +444,7 @@ int snd_card_disconnect(struct snd_card *card)
#ifdef CONFIG_PM wake_up(&card->power_sleep); + snd_power_sync_ref(card); #endif return 0; } @@ -1002,21 +1005,28 @@ EXPORT_SYMBOL(snd_card_file_remove);
#ifdef CONFIG_PM /** - * snd_power_wait - wait until the power-state is changed. - * @card: soundcard structure - * @power_state: expected power state + * snd_power_ref_and_wait - wait until the card gets powered up + * @card: soundcard structure + * + * Take the power_ref reference count of the given card, and + * wait until the card gets powered up to SNDRV_CTL_POWER_D0 state. + * The refcount is down again while sleeping until power-up, hence this + * function can be used for syncing the floating control ops accesses, + * typically around calling control ops. * - * Waits until the power-state is changed. + * The caller needs to pull down the refcount via snd_power_unref() later + * no matter whether the error is returned from this function or not. * - * Return: Zero if successful, or a negative error code. + * Return: Zero if successful, or a negative error code. */ -int snd_power_wait(struct snd_card *card, unsigned int power_state) +int snd_power_ref_and_wait(struct snd_card *card) { wait_queue_entry_t wait; int result = 0;
+ snd_power_ref(card); /* fastpath */ - if (snd_power_get_state(card) == power_state) + if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0) return 0; init_waitqueue_entry(&wait, current); add_wait_queue(&card->power_sleep, &wait); @@ -1025,13 +1035,50 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state) result = -ENODEV; break; } - if (snd_power_get_state(card) == power_state) + if (snd_power_get_state(card) == SNDRV_CTL_POWER_D0) break; + snd_power_unref(card); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(30 * HZ); + snd_power_ref(card); } remove_wait_queue(&card->power_sleep, &wait); return result; } +EXPORT_SYMBOL_GPL(snd_power_ref_and_wait); + +/** + * snd_power_wait - wait until the card gets powered up (old form) + * @card: soundcard structure + * @power_state: expected power state + * + * Wait until the card gets powered up to SNDRV_CTL_POWER_D0 state. + * @power_state must be SNDRV_CTL_POWER_D0. + * + * Return: Zero if successful, or a negative error code. + */ +int snd_power_wait(struct snd_card *card, unsigned int power_state) +{ + int ret; + + if (WARN_ON(power_state != SNDRV_CTL_POWER_D0)) + return 0; + ret = snd_power_ref_and_wait(card); + snd_power_unref(card); + return ret; +} EXPORT_SYMBOL(snd_power_wait); + +/** + * 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. + */ +void snd_power_sync_ref(struct snd_card *card) +{ + wait_event(card->power_ref_sleep, !atomic_read(&card->power_ref)); +} +EXPORT_SYMBOL_GPL(snd_power_sync_ref); #endif /* CONFIG_PM */
Dne 18. 05. 21 v 18:51 Takashi Iwai napsal(a):
+/**
- 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.
- */
+void snd_power_sync_ref(struct snd_card *card) +{
- wait_event(card->power_ref_sleep, !atomic_read(&card->power_ref));
+} +EXPORT_SYMBOL_GPL(snd_power_sync_ref);
Perhaps, this function can be inline, too?
Jaroslav
On Tue, 18 May 2021 20:01:33 +0200, Jaroslav Kysela wrote:
Dne 18. 05. 21 v 18:51 Takashi Iwai napsal(a):
+/**
- 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.
- */
+void snd_power_sync_ref(struct snd_card *card) +{
- wait_event(card->power_ref_sleep, !atomic_read(&card->power_ref));
+} +EXPORT_SYMBOL_GPL(snd_power_sync_ref);
Perhaps, this function can be inline, too?
I thought of that, too. Then maybe core.h needs more inclusion, but it might be worth, yeah.
thanks,
Takashi
The normal PCM operations are already blocked during the card power off state in the PCM common ioctl handler, but the release isn't covered. As the PCM stream release may also access the hardware, let's block the release until the card power turns on.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/core/pcm_native.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 8dbe86cf2e4f..3c6ba0dc2970 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2799,6 +2799,10 @@ static int snd_pcm_release(struct inode *inode, struct file *file) if (snd_BUG_ON(!substream)) return -ENXIO; pcm = substream->pcm; + + /* block until the device gets woken up as it may touch the hardware */ + snd_power_wait(pcm->card, SNDRV_CTL_POWER_D0); + mutex_lock(&pcm->open_mutex); snd_pcm_release_substream(substream); kfree(pcm_file);
The power_state argument of snd_power_wait() is superfluous, receiving only SNDRV_POWER_STATE_D0. Let's drop it in all callers for simplicity.
Signed-off-by: Takashi Iwai tiwai@suse.de --- include/sound/core.h | 4 ++-- sound/core/control.c | 2 +- sound/core/control_compat.c | 2 +- sound/core/init.c | 6 +----- sound/core/pcm_native.c | 4 ++-- sound/soc/soc-core.c | 2 +- sound/usb/usx2y/us122l.c | 2 +- 7 files changed, 9 insertions(+), 13 deletions(-)
diff --git a/include/sound/core.h b/include/sound/core.h index 430d775b3c0e..e1192a337582 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -177,13 +177,13 @@ static inline void snd_power_unref(struct snd_card *card) }
/* 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); void snd_power_sync_ref(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; } diff --git a/sound/core/control.c b/sound/core/control.c index 37f6f2ca0543..c145c6011878 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1774,7 +1774,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg card = ctl->card; if (snd_BUG_ON(!card)) return -ENXIO; - err = snd_power_wait(card, SNDRV_CTL_POWER_D0); + err = snd_power_wait(card); if (err < 0) return err; switch (cmd) { diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index b9fe1ead435b..b4554ae21e33 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -432,7 +432,7 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns if (snd_BUG_ON(!ctl || !ctl->card)) return -ENXIO;
- err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); + err = snd_power_wait(ctl->card); if (err < 0) return err; switch (cmd) { diff --git a/sound/core/init.c b/sound/core/init.c index d11636fac608..7942da1085d2 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -1050,19 +1050,15 @@ EXPORT_SYMBOL_GPL(snd_power_ref_and_wait); /** * snd_power_wait - wait until the card gets powered up (old form) * @card: soundcard structure - * @power_state: expected power state * * Wait until the card gets powered up to SNDRV_CTL_POWER_D0 state. - * @power_state must be SNDRV_CTL_POWER_D0. * * Return: Zero if successful, or a negative error code. */ -int snd_power_wait(struct snd_card *card, unsigned int power_state) +int snd_power_wait(struct snd_card *card) { int ret;
- if (WARN_ON(power_state != SNDRV_CTL_POWER_D0)) - return 0; ret = snd_power_ref_and_wait(card); snd_power_unref(card); return ret; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 3c6ba0dc2970..11acea02bc74 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2801,7 +2801,7 @@ static int snd_pcm_release(struct inode *inode, struct file *file) pcm = substream->pcm;
/* block until the device gets woken up as it may touch the hardware */ - snd_power_wait(pcm->card, SNDRV_CTL_POWER_D0); + snd_power_wait(pcm->card);
mutex_lock(&pcm->open_mutex); snd_pcm_release_substream(substream); @@ -3197,7 +3197,7 @@ static int snd_pcm_common_ioctl(struct file *file, if (PCM_RUNTIME_CHECK(substream)) return -ENXIO;
- res = snd_power_wait(substream->pcm->card, SNDRV_CTL_POWER_D0); + res = snd_power_wait(substream->pcm->card); if (res < 0) return res;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 1c0904acb935..ddc65c12f6f4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -580,7 +580,7 @@ int snd_soc_suspend(struct device *dev) * Due to the resume being scheduled into a workqueue we could * suspend before that's finished - wait for it to complete. */ - snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0); + snd_power_wait(card->snd_card);
/* we're going to block userspace touching us until resume completes */ snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c index 6e1bfe894dd5..596a1a1fea49 100644 --- a/sound/usb/usx2y/us122l.c +++ b/sound/usb/usx2y/us122l.c @@ -379,7 +379,7 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, if (cfg.period_frames < min_period_frames) return -EINVAL;
- snd_power_wait(hw->card, SNDRV_CTL_POWER_D0); + snd_power_wait(hw->card);
mutex_lock(&us122l->mutex); s = us122l->sk.s;
participants (2)
-
Jaroslav Kysela
-
Takashi Iwai