ALSA: Embed card device into struct snd_card

As prepared in the previous patch, we are ready to create a device
struct for the card object in snd_card_create() now.  This patch
changes the scheme from the old style to:

- embed a device struct for the card object into snd_card struct,
- initialize the card device in snd_card_create() (but not register),
- registration is done in snd_card_register() via device_add()

The actual card device is stored in card->card_dev.  The card->dev
pointer is kept unchanged and pointing to the parent device as before
for compatibility reason.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
diff --git a/sound/core/init.c b/sound/core/init.c
index f4d3ac6..f787504 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -156,6 +156,13 @@
 	return mask; /* unchanged */
 }
 
+static int snd_card_do_free(struct snd_card *card);
+
+static void release_card_device(struct device *dev)
+{
+	snd_card_do_free(dev_to_snd_card(dev));
+}
+
 /**
  *  snd_card_new - create and initialize a soundcard structure
  *  @parent: the parent device object
@@ -189,6 +196,8 @@
 	card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
 	if (!card)
 		return -ENOMEM;
+	if (extra_size > 0)
+		card->private_data = (char *)card + sizeof(struct snd_card);
 	if (xid)
 		strlcpy(card->id, xid, sizeof(card->id));
 	err = 0;
@@ -208,7 +217,8 @@
 		mutex_unlock(&snd_card_mutex);
 		snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",
 			 idx, snd_ecards_limit - 1, err);
-		goto __error;
+		kfree(card);
+		return err;
 	}
 	set_bit(idx, snd_cards_lock);		/* lock it */
 	if (idx >= snd_ecards_limit)
@@ -230,6 +240,15 @@
 	mutex_init(&card->power_lock);
 	init_waitqueue_head(&card->power_sleep);
 #endif
+
+	device_initialize(&card->card_dev);
+	card->card_dev.parent = parent;
+	card->card_dev.class = sound_class;
+	card->card_dev.release = release_card_device;
+	err = kobject_set_name(&card->card_dev.kobj, "card%d", idx);
+	if (err < 0)
+		goto __error;
+
 	/* the control interface cannot be accessed from the user space until */
 	/* snd_cards_bitmask and snd_cards are set with snd_card_register */
 	err = snd_ctl_create(card);
@@ -242,15 +261,13 @@
 		snd_printk(KERN_ERR "unable to create card info\n");
 		goto __error_ctl;
 	}
-	if (extra_size > 0)
-		card->private_data = (char *)card + sizeof(struct snd_card);
 	*card_ret = card;
 	return 0;
 
       __error_ctl:
 	snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
       __error:
-	kfree(card);
+	put_device(&card->card_dev);
   	return err;
 }
 EXPORT_SYMBOL(snd_card_new);
@@ -407,9 +424,9 @@
 		snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
 
 	snd_info_card_disconnect(card);
-	if (card->card_dev) {
-		device_unregister(card->card_dev);
-		card->card_dev = NULL;
+	if (card->registered) {
+		device_del(&card->card_dev);
+		card->registered = false;
 	}
 #ifdef CONFIG_PM
 	wake_up(&card->power_sleep);
@@ -471,7 +488,7 @@
 	if (atomic_dec_and_test(&card->refcount)) {
 		wake_up(&card->shutdown_sleep);
 		if (card->free_on_last_close)
-			snd_card_do_free(card);
+			put_device(&card->card_dev);
 	}
 }
 EXPORT_SYMBOL(snd_card_unref);
@@ -489,7 +506,7 @@
 
 	card->free_on_last_close = 1;
 	if (atomic_dec_and_test(&card->refcount))
-		snd_card_do_free(card);
+		put_device(&card->card_dev);
 	return 0;
 }
 
@@ -503,7 +520,7 @@
 
 	/* wait, until all devices are ready for the free operation */
 	wait_event(card->shutdown_sleep, !atomic_read(&card->refcount));
-	snd_card_do_free(card);
+	put_device(&card->card_dev);
 	return 0;
 }
 
@@ -694,12 +711,11 @@
 	if (snd_BUG_ON(!card))
 		return -EINVAL;
 
-	if (!card->card_dev) {
-		card->card_dev = device_create(sound_class, card->dev,
-					       MKDEV(0, 0), card,
-					       "card%i", card->number);
-		if (IS_ERR(card->card_dev))
-			card->card_dev = NULL;
+	if (!card->registered) {
+		err = device_add(&card->card_dev);
+		if (err < 0)
+			return err;
+		card->registered = true;
 	}
 
 	if ((err = snd_device_register_all(card)) < 0)
@@ -729,11 +745,11 @@
 	if (snd_mixer_oss_notify_callback)
 		snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
 #endif
-	if (card->card_dev) {
-		err = device_create_file(card->card_dev, &card_id_attrs);
+	if (card->registered) {
+		err = device_create_file(&card->card_dev, &card_id_attrs);
 		if (err < 0)
 			return err;
-		err = device_create_file(card->card_dev, &card_number_attrs);
+		err = device_create_file(&card->card_dev, &card_number_attrs);
 		if (err < 0)
 			return err;
 	}