All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: alsa-devel@alsa-project.org
Subject: [PATCH 02/51] ALSA: core: Add managed card creation
Date: Tue, 13 Jul 2021 16:28:08 +0200	[thread overview]
Message-ID: <20210713142857.19654-3-tiwai@suse.de> (raw)
In-Reply-To: <20210713142857.19654-1-tiwai@suse.de>

As a second step for preliminary to widen the devres usages among
sound drivers, this patch adds a new ALSA core API function,
snd_devm_card_new(), to create a snd_card object via devres.
When a card object is created by this new function, snd_card_free() is
called automatically and the card object resource gets released at the
device unbinding time.

However, the story isn't that simple.  A caveat is that we have to
call snd_card_free() at the very first of the whole resource release
procedure, in order to assure that the all exposed devices on
user-space are deleted and sync with processes accessing those devices
before releasing resources.

For achieving it, snd_card_register() adds a new devres action to
trigger snd_card_free() automatically when the given card object is a
"managed" one.  Since usually snd_card_register() is the last step of
the initialization, this should work in most cases.

With all these tricks, some drivers can get rid of the whole driver
remove callback code.

About a bit of implementation details: the patch adds two new flags to
snd_card object: managed and releasing.  The former indicates that the
object was created via snd_devm_card_new(), and the latter is used for
avoiding the double-free of snd_card_free() calls.  Both flags are
fairly internal and likely uninteresting to normal users.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/core.h |   5 +++
 sound/core/init.c    | 101 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 98 insertions(+), 8 deletions(-)

diff --git a/include/sound/core.h b/include/sound/core.h
index c4ade121727d..331195b51237 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -117,6 +117,8 @@ struct snd_card {
 	struct device card_dev;		/* cardX object for sysfs */
 	const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */
 	bool registered;		/* card_dev is registered? */
+	bool managed;			/* managed via devres */
+	bool releasing;			/* during card free process */
 	int sync_irq;			/* assigned irq, used for PCM sync */
 	wait_queue_head_t remove_sleep;
 
@@ -274,6 +276,9 @@ extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd);
 int snd_card_new(struct device *parent, int idx, const char *xid,
 		 struct module *module, int extra_size,
 		 struct snd_card **card_ret);
+int snd_devm_card_new(struct device *parent, int idx, const char *xid,
+		      struct module *module, int extra_size,
+		      struct snd_card **card_ret);
 
 int snd_card_disconnect(struct snd_card *card);
 void snd_card_disconnect_sync(struct snd_card *card);
diff --git a/sound/core/init.c b/sound/core/init.c
index 1490568efdb0..7a507e8d24c1 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -134,6 +134,9 @@ void snd_device_initialize(struct device *dev, struct snd_card *card)
 }
 EXPORT_SYMBOL_GPL(snd_device_initialize);
 
+static int snd_card_init(struct snd_card *card, struct device *parent,
+			 int idx, const char *xid, struct module *module,
+			 int extra_size);
 static int snd_card_do_free(struct snd_card *card);
 static const struct attribute_group card_dev_attr_group;
 
@@ -163,9 +166,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
 {
 	struct snd_card *card;
 	int err;
-#ifdef CONFIG_SND_DEBUG
-	char name[8];
-#endif
 
 	if (snd_BUG_ON(!card_ret))
 		return -EINVAL;
@@ -176,6 +176,76 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
 	card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
 	if (!card)
 		return -ENOMEM;
+
+	err = snd_card_init(card, parent, idx, xid, module, extra_size);
+	if (err < 0) {
+		kfree(card);
+		return err;
+	}
+
+	*card_ret = card;
+	return 0;
+}
+EXPORT_SYMBOL(snd_card_new);
+
+static void __snd_card_release(struct device *dev, void *data)
+{
+	snd_card_free(data);
+}
+
+/**
+ * snd_devm_card_new - managed snd_card object creation
+ * @parent: the parent device object
+ * @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
+ * @xid: card identification (ASCII string)
+ * @module: top level module for locking
+ * @extra_size: allocate this extra size after the main soundcard structure
+ * @card_ret: the pointer to store the created card instance
+ *
+ * This function works like snd_card_new() but manages the allocated resource
+ * via devres, i.e. you don't need to free explicitly.
+ *
+ * When a snd_card object is created with this function and registered via
+ * snd_card_register(), the very first devres action to call snd_card_free()
+ * is added automatically.  In that way, the resource disconnection is assured
+ * at first, then released in the expected order.
+ */
+int snd_devm_card_new(struct device *parent, int idx, const char *xid,
+		      struct module *module, int extra_size,
+		      struct snd_card **card_ret)
+{
+	struct snd_card *card;
+	int err;
+
+	*card_ret = NULL;
+	if (extra_size < 0)
+		extra_size = 0;
+	card = devres_alloc(__snd_card_release, sizeof(*card) + extra_size,
+			    GFP_KERNEL);
+	if (!card)
+		return -ENOMEM;
+	card->managed = true;
+	err = snd_card_init(card, parent, idx, xid, module, extra_size);
+	if (err < 0) {
+		devres_free(card);
+		return err;
+	}
+
+	devres_add(parent, card);
+	*card_ret = card;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_devm_card_new);
+
+static int snd_card_init(struct snd_card *card, struct device *parent,
+			 int idx, const char *xid, struct module *module,
+			 int extra_size)
+{
+	int err;
+#ifdef CONFIG_SND_DEBUG
+	char name[8];
+#endif
+
 	if (extra_size > 0)
 		card->private_data = (char *)card + sizeof(struct snd_card);
 	if (xid)
@@ -197,7 +267,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
 		mutex_unlock(&snd_card_mutex);
 		dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n",
 			 idx, snd_ecards_limit - 1, err);
-		kfree(card);
 		return err;
 	}
 	set_bit(idx, snd_cards_lock);		/* lock it */
@@ -256,8 +325,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
 	sprintf(name, "card%d", idx);
 	card->debugfs_root = debugfs_create_dir(name, sound_debugfs_root);
 #endif
-
-	*card_ret = card;
 	return 0;
 
       __error_ctl:
@@ -266,7 +333,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
 	put_device(&card->card_dev);
   	return err;
 }
-EXPORT_SYMBOL(snd_card_new);
 
 /**
  * snd_card_ref - Get the card object from the index
@@ -481,6 +547,7 @@ EXPORT_SYMBOL_GPL(snd_card_disconnect_sync);
 
 static int snd_card_do_free(struct snd_card *card)
 {
+	card->releasing = true;
 #if IS_ENABLED(CONFIG_SND_MIXER_OSS)
 	if (snd_mixer_oss_notify_callback)
 		snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
@@ -498,7 +565,8 @@ static int snd_card_do_free(struct snd_card *card)
 #endif
 	if (card->release_completion)
 		complete(card->release_completion);
-	kfree(card);
+	if (!card->managed)
+		kfree(card);
 	return 0;
 }
 
@@ -539,6 +607,9 @@ int snd_card_free(struct snd_card *card)
 	DECLARE_COMPLETION_ONSTACK(released);
 	int ret;
 
+	if (card->releasing)
+		return 0;
+
 	card->release_completion = &released;
 	ret = snd_card_free_when_closed(card);
 	if (ret)
@@ -745,6 +816,11 @@ int snd_card_add_dev_attr(struct snd_card *card,
 }
 EXPORT_SYMBOL_GPL(snd_card_add_dev_attr);
 
+static void trigger_card_free(void *data)
+{
+	snd_card_free(data);
+}
+
 /**
  *  snd_card_register - register the soundcard
  *  @card: soundcard structure
@@ -768,6 +844,15 @@ int snd_card_register(struct snd_card *card)
 		if (err < 0)
 			return err;
 		card->registered = true;
+	} else {
+		if (card->managed)
+			devm_remove_action(card->dev, trigger_card_free, card);
+	}
+
+	if (card->managed) {
+		err = devm_add_action(card->dev, trigger_card_free, card);
+		if (err < 0)
+			return err;
 	}
 
 	err = snd_device_register_all(card);
-- 
2.26.2


  parent reply	other threads:[~2021-07-13 14:31 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-13 14:28 [PATCH resent 00/51] ALSA: More devres usages Takashi Iwai
2021-07-13 14:28 ` [PATCH 01/51] ALSA: core: Add device-managed page allocator helper Takashi Iwai
2021-07-13 14:28 ` Takashi Iwai [this message]
2021-07-13 15:23   ` [PATCH 02/51] ALSA: core: Add managed card creation Amadeusz Sławiński
2021-07-13 16:05     ` Takashi Iwai
2021-07-13 16:15       ` Takashi Iwai
2021-07-13 14:28 ` [PATCH 03/51] ALSA: intel8x0: Allocate resources with device-managed APIs Takashi Iwai
2021-07-13 14:28 ` [PATCH 04/51] ALSA: atiixp: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 05/51] ALSA: hda: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 06/51] ALSA: doc: Add device-managed resource section Takashi Iwai
2021-07-13 14:28 ` [PATCH 07/51] ALSA: ad1889: Allocate resources with device-managed APIs Takashi Iwai
2021-07-13 14:28 ` [PATCH 08/51] ALSA: als300: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 09/51] ALSA: als4000: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 10/51] ALSA: azt3328: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 11/51] ALSA: bt87x: " Takashi Iwai
2021-07-13 17:10   ` kernel test robot
2021-07-13 14:28 ` [PATCH 12/51] ALSA: cmipci: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 13/51] ALSA: cs4281: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 14/51] ALSA: cs5530: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 15/51] ALSA: ens137x: " Takashi Iwai
2021-07-13 15:23   ` Amadeusz Sławiński
2021-07-13 16:07     ` Takashi Iwai
2021-07-13 14:28 ` [PATCH 16/51] ALSA: es1938: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 17/51] ALSA: es1968: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 18/51] ALSA: fm801: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 19/51] ALSA: maestro3: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 20/51] ALSA: rme32: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 21/51] ALSA: rme96: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 22/51] ALSA: sis7019: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 23/51] ALSA: sonicvibes: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 24/51] ALSA: via82xx: " Takashi Iwai
2021-07-13 18:40   ` kernel test robot
2021-07-13 14:28 ` [PATCH 25/51] ALSA: ali5451: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 26/51] ALSA: au88x0: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 27/51] ALSA: aw2: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 28/51] ALSA: ca0106: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 29/51] ALSA: cs46xx: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 30/51] ALSA: cs5535audio: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 31/51] ALSA: echoaudio: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 32/51] ALSA: emu10k1: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 33/51] ALSA: emu10k1x: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 34/51] ALSA: ice1712: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 35/51] ALSA: ice1724: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 36/51] ALSA: korg1212: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 37/51] ALSA: lola: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 38/51] ALSA: oxygen: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 39/51] ALSA: riptide: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 40/51] ALSA: hdsp: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 41/51] ALSA: hdspm: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 42/51] ALSA: rme9652: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 43/51] ALSA: trident: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 44/51] ALSA: vx: Manage vx_core object with devres Takashi Iwai
2021-07-13 14:28 ` [PATCH 45/51] ALSA: vx222: Allocate resources with device-managed APIs Takashi Iwai
2021-07-13 14:28 ` [PATCH 46/51] ALSA: ymfpci: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 47/51] ALSA: x86: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 48/51] ALSA: virmidi: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 49/51] ALSA: mtpav: " Takashi Iwai
2021-07-13 14:28 ` [PATCH 50/51] ALSA: serial-u16550: " Takashi Iwai
2021-07-13 16:08   ` Takashi Iwai
2021-07-13 18:39   ` kernel test robot
2021-07-13 14:28 ` [PATCH 51/51] ALSA: mpu401: " Takashi Iwai
  -- strict thread matches above, loose matches on Subject: below --
2021-07-13 14:24 [PATCH 00/51] ALSA: More devres usages Takashi Iwai
2021-07-13 14:24 ` [PATCH 02/51] ALSA: core: Add managed card creation Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210713142857.19654-3-tiwai@suse.de \
    --to=tiwai@suse.de \
    --cc=alsa-devel@alsa-project.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.