All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/6] ALSA: Prep work for PCI rescan support
@ 2021-05-23  9:09 Takashi Iwai
  2021-05-23  9:09 ` [PATCH v2 1/6] ALSA: core: Use READ_ONCE() / WRITE_ONCE() for power state change Takashi Iwai
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: Takashi Iwai @ 2021-05-23  9:09 UTC (permalink / raw)
  To: alsa-devel; +Cc: Mark Brown

Hi,

this is a revised 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.

v1->v2:
* Move / drop unnecessary snd_power_wait() calls
* Rephrase changelogs and comments, reorder patches


Takashi

(*) https://lore.kernel.org/alsa-devel/e25017c6-e5e4-7a24-e793-14a2e70a434e@amd.com/

===

Takashi Iwai (6):
  ALSA: core: Use READ_ONCE() / WRITE_ONCE() for power state change
  ALSA: control: Track in-flight control read/write/tlv accesses
  ALSA: control: Drop superfluous snd_power_wait() calls
  ALSA: control: Minor optimization for SNDRV_CTL_IOCTL_POWER_STATE
  ALSA: Drop superfluous argument from snd_power_wait()
  ALSA: pcm: Block the release until the system resume finishes

 include/sound/core.h        | 50 ++++++++++++++++++++++++++++++++++---
 sound/core/control.c        | 38 +++++++++++++---------------
 sound/core/control_compat.c | 14 +++--------
 sound/core/init.c           | 46 ++++++++++++++++++++++++++++------
 sound/core/pcm_native.c     |  6 ++++-
 sound/soc/soc-core.c        |  2 +-
 sound/usb/usx2y/us122l.c    |  2 +-
 7 files changed, 113 insertions(+), 45 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 1/6] ALSA: core: Use READ_ONCE() / WRITE_ONCE() for power state change
  2021-05-23  9:09 [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Takashi Iwai
@ 2021-05-23  9:09 ` Takashi Iwai
  2021-05-23  9:09 ` [PATCH v2 2/6] ALSA: control: Track in-flight control read/write/tlv accesses Takashi Iwai
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Takashi Iwai @ 2021-05-23  9:09 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

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);
 }
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 2/6] ALSA: control: Track in-flight control read/write/tlv accesses
  2021-05-23  9:09 [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Takashi Iwai
  2021-05-23  9:09 ` [PATCH v2 1/6] ALSA: core: Use READ_ONCE() / WRITE_ONCE() for power state change Takashi Iwai
@ 2021-05-23  9:09 ` Takashi Iwai
  2021-05-23  9:09 ` [PATCH v2 3/6] ALSA: control: Drop superfluous snd_power_wait() calls Takashi Iwai
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Takashi Iwai @ 2021-05-23  9:09 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

Although the power state check is performed in various places (e.g. at
the entrance of quite a few ioctls), there can be still some pending
tasks that already went into the ioctl handler or other ops, and those
may access the hardware even after the power state check.  For
example, kcontrol access ioctl paths that call info/get/put callbacks
may update the hardware registers.  If a system wants to assure the
free from such hw access (like the case of 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 beforehand.

For that purpose, this patch introduces a few new things in core code:
- 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 with the newly introduced snd_power_ref_and_wait().  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 in return.  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; refcount_t
cannot be zero-based, and it cannot do dec_and_test() call for
multiple times, hence it's not suitable for our purpose.

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

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/core.h        | 42 +++++++++++++++++++++++++++++++
 sound/core/control.c        | 23 +++++++++++++----
 sound/core/control_compat.c |  5 +++-
 sound/core/init.c           | 50 +++++++++++++++++++++++++++++++------
 4 files changed, 106 insertions(+), 14 deletions(-)

diff --git a/include/sound/core.h b/include/sound/core.h
index d69dfc6c4953..3acb754108b1 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,52 @@ 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);
+}
+
+/**
+ * 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_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 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 498e3701514a..638da34605ba 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);
@@ -1088,7 +1091,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) &&
@@ -1154,7 +1160,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;
@@ -1669,7 +1678,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) {
@@ -1687,7 +1696,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 1d708aab9c98..19133ee076c5 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -187,7 +187,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..2c62e035bc62 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
  *
- *  Waits until the power-state is changed.
+ * 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.
  *
- *  Return: Zero if successful, or a negative error code.
+ * 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.
  */
-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,37 @@ 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);
 #endif /* CONFIG_PM */
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 3/6] ALSA: control: Drop superfluous snd_power_wait() calls
  2021-05-23  9:09 [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Takashi Iwai
  2021-05-23  9:09 ` [PATCH v2 1/6] ALSA: core: Use READ_ONCE() / WRITE_ONCE() for power state change Takashi Iwai
  2021-05-23  9:09 ` [PATCH v2 2/6] ALSA: control: Track in-flight control read/write/tlv accesses Takashi Iwai
@ 2021-05-23  9:09 ` Takashi Iwai
  2021-05-23  9:09 ` [PATCH v2 4/6] ALSA: control: Minor optimization for SNDRV_CTL_IOCTL_POWER_STATE Takashi Iwai
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Takashi Iwai @ 2021-05-23  9:09 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

Now we have more fine-grained power controls in each kcontrol ops, the
coarse checks of snd_power_wait() in a few control ioctls became
superfluous.  Let's drop them.

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 638da34605ba..7fe901384c9c 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1045,9 +1045,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;
@@ -1119,10 +1116,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);
@@ -1192,10 +1185,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 19133ee076c5..470dabc60aa0 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;
@@ -301,9 +298,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;
@@ -329,9 +323,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;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 4/6] ALSA: control: Minor optimization for SNDRV_CTL_IOCTL_POWER_STATE
  2021-05-23  9:09 [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Takashi Iwai
                   ` (2 preceding siblings ...)
  2021-05-23  9:09 ` [PATCH v2 3/6] ALSA: control: Drop superfluous snd_power_wait() calls Takashi Iwai
@ 2021-05-23  9:09 ` Takashi Iwai
  2021-05-23  9:09 ` [PATCH v2 5/6] ALSA: Drop superfluous argument from snd_power_wait() Takashi Iwai
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Takashi Iwai @ 2021-05-23  9:09 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

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.  Now the read part,
SNDRV_IOCTL_POWER_STATE ioctl, returns practically always D0, and we
can do some minor optimization there.

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 7fe901384c9c..a25c0d64d104 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1817,11 +1817,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) {
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 5/6] ALSA: Drop superfluous argument from snd_power_wait()
  2021-05-23  9:09 [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Takashi Iwai
                   ` (3 preceding siblings ...)
  2021-05-23  9:09 ` [PATCH v2 4/6] ALSA: control: Minor optimization for SNDRV_CTL_IOCTL_POWER_STATE Takashi Iwai
@ 2021-05-23  9:09 ` Takashi Iwai
  2021-05-24  8:39   ` Mark Brown
  2021-05-23  9:09 ` [PATCH v2 6/6] ALSA: pcm: Block the release until the system resume finishes Takashi Iwai
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 10+ messages in thread
From: Takashi Iwai @ 2021-05-23  9:09 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai, Mark Brown

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.

Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/core.h     | 4 ++--
 sound/core/init.c        | 6 +-----
 sound/core/pcm_native.c  | 2 +-
 sound/soc/soc-core.c     | 2 +-
 sound/usb/usx2y/us122l.c | 2 +-
 5 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/include/sound/core.h b/include/sound/core.h
index 3acb754108b1..c4ade121727d 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -189,12 +189,12 @@ static inline void snd_power_sync_ref(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);
 
 #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/init.c b/sound/core/init.c
index 2c62e035bc62..70114fd26956 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 8dbe86cf2e4f..82f80d0c068b 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3193,7 +3193,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;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 6/6] ALSA: pcm: Block the release until the system resume finishes
  2021-05-23  9:09 [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Takashi Iwai
                   ` (4 preceding siblings ...)
  2021-05-23  9:09 ` [PATCH v2 5/6] ALSA: Drop superfluous argument from snd_power_wait() Takashi Iwai
@ 2021-05-23  9:09 ` Takashi Iwai
  2021-05-24  9:32 ` [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Jaroslav Kysela
  2021-05-25  6:56 ` Takashi Iwai
  7 siblings, 0 replies; 10+ messages in thread
From: Takashi Iwai @ 2021-05-23  9:09 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

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 82f80d0c068b..11acea02bc74 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);
+
 	mutex_lock(&pcm->open_mutex);
 	snd_pcm_release_substream(substream);
 	kfree(pcm_file);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 5/6] ALSA: Drop superfluous argument from snd_power_wait()
  2021-05-23  9:09 ` [PATCH v2 5/6] ALSA: Drop superfluous argument from snd_power_wait() Takashi Iwai
@ 2021-05-24  8:39   ` Mark Brown
  0 siblings, 0 replies; 10+ messages in thread
From: Mark Brown @ 2021-05-24  8:39 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

[-- Attachment #1: Type: text/plain, Size: 255 bytes --]

On Sun, May 23, 2021 at 11:09:19AM +0200, Takashi Iwai wrote:
> 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.

Acked-by: Mark Brown <broonie@kernel.org>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 0/6] ALSA: Prep work for PCI rescan support
  2021-05-23  9:09 [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Takashi Iwai
                   ` (5 preceding siblings ...)
  2021-05-23  9:09 ` [PATCH v2 6/6] ALSA: pcm: Block the release until the system resume finishes Takashi Iwai
@ 2021-05-24  9:32 ` Jaroslav Kysela
  2021-05-25  6:56 ` Takashi Iwai
  7 siblings, 0 replies; 10+ messages in thread
From: Jaroslav Kysela @ 2021-05-24  9:32 UTC (permalink / raw)
  To: Takashi Iwai, alsa-devel; +Cc: Mark Brown

Dne 23. 05. 21 v 11:09 Takashi Iwai napsal(a):
> Hi,
> 
> this is a revised 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.
> 
> v1->v2:
> * Move / drop unnecessary snd_power_wait() calls
> * Rephrase changelogs and comments, reorder patches

Reviewed-by: Jaroslav Kysela <perex@perex.cz>

> 
> 
> Takashi
> 
> (*) https://lore.kernel.org/alsa-devel/e25017c6-e5e4-7a24-e793-14a2e70a434e@amd.com/
> 
> ===
> 
> Takashi Iwai (6):
>   ALSA: core: Use READ_ONCE() / WRITE_ONCE() for power state change
>   ALSA: control: Track in-flight control read/write/tlv accesses
>   ALSA: control: Drop superfluous snd_power_wait() calls
>   ALSA: control: Minor optimization for SNDRV_CTL_IOCTL_POWER_STATE
>   ALSA: Drop superfluous argument from snd_power_wait()
>   ALSA: pcm: Block the release until the system resume finishes
> 
>  include/sound/core.h        | 50 ++++++++++++++++++++++++++++++++++---
>  sound/core/control.c        | 38 +++++++++++++---------------
>  sound/core/control_compat.c | 14 +++--------
>  sound/core/init.c           | 46 ++++++++++++++++++++++++++++------
>  sound/core/pcm_native.c     |  6 ++++-
>  sound/soc/soc-core.c        |  2 +-
>  sound/usb/usx2y/us122l.c    |  2 +-
>  7 files changed, 113 insertions(+), 45 deletions(-)
> 


-- 
Jaroslav Kysela <perex@perex.cz>
Linux Sound Maintainer; ALSA Project; Red Hat, Inc.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 0/6] ALSA: Prep work for PCI rescan support
  2021-05-23  9:09 [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Takashi Iwai
                   ` (6 preceding siblings ...)
  2021-05-24  9:32 ` [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Jaroslav Kysela
@ 2021-05-25  6:56 ` Takashi Iwai
  7 siblings, 0 replies; 10+ messages in thread
From: Takashi Iwai @ 2021-05-25  6:56 UTC (permalink / raw)
  To: alsa-devel; +Cc: Mark Brown

On Sun, 23 May 2021 11:09:14 +0200,
Takashi Iwai wrote:
> 
> Hi,
> 
> this is a revised 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.
> 
> v1->v2:
> * Move / drop unnecessary snd_power_wait() calls
> * Rephrase changelogs and comments, reorder patches
> 
> 
> Takashi
> 
> (*) https://lore.kernel.org/alsa-devel/e25017c6-e5e4-7a24-e793-14a2e70a434e@amd.com/
> 
> ===
> 
> Takashi Iwai (6):
>   ALSA: core: Use READ_ONCE() / WRITE_ONCE() for power state change
>   ALSA: control: Track in-flight control read/write/tlv accesses
>   ALSA: control: Drop superfluous snd_power_wait() calls
>   ALSA: control: Minor optimization for SNDRV_CTL_IOCTL_POWER_STATE
>   ALSA: Drop superfluous argument from snd_power_wait()
>   ALSA: pcm: Block the release until the system resume finishes

Now all patches merged to topic/pci-rescan-v2 branch, and into
for-next branch.  The former is a branch freshly based on 5.13-rc1, so
that other trees may pull cleanly.


Takashi

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-05-25  6:57 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-23  9:09 [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Takashi Iwai
2021-05-23  9:09 ` [PATCH v2 1/6] ALSA: core: Use READ_ONCE() / WRITE_ONCE() for power state change Takashi Iwai
2021-05-23  9:09 ` [PATCH v2 2/6] ALSA: control: Track in-flight control read/write/tlv accesses Takashi Iwai
2021-05-23  9:09 ` [PATCH v2 3/6] ALSA: control: Drop superfluous snd_power_wait() calls Takashi Iwai
2021-05-23  9:09 ` [PATCH v2 4/6] ALSA: control: Minor optimization for SNDRV_CTL_IOCTL_POWER_STATE Takashi Iwai
2021-05-23  9:09 ` [PATCH v2 5/6] ALSA: Drop superfluous argument from snd_power_wait() Takashi Iwai
2021-05-24  8:39   ` Mark Brown
2021-05-23  9:09 ` [PATCH v2 6/6] ALSA: pcm: Block the release until the system resume finishes Takashi Iwai
2021-05-24  9:32 ` [PATCH v2 0/6] ALSA: Prep work for PCI rescan support Jaroslav Kysela
2021-05-25  6:56 ` Takashi Iwai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.