Commit 8bfb181c authored by Takashi Iwai's avatar Takashi Iwai

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: default avatarTakashi Iwai <tiwai@suse.de>
parent 13345095
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* *
*/ */
#include <linux/device.h>
#include <linux/sched.h> /* wake_up() */ #include <linux/sched.h> /* wake_up() */
#include <linux/mutex.h> /* struct mutex */ #include <linux/mutex.h> /* struct mutex */
#include <linux/rwsem.h> /* struct rw_semaphore */ #include <linux/rwsem.h> /* struct rw_semaphore */
...@@ -41,8 +42,6 @@ ...@@ -41,8 +42,6 @@
/* forward declarations */ /* forward declarations */
struct pci_dev; struct pci_dev;
struct module; struct module;
struct device;
struct device_attribute;
/* device allocation stuff */ /* device allocation stuff */
...@@ -135,7 +134,8 @@ struct snd_card { ...@@ -135,7 +134,8 @@ struct snd_card {
wait_queue_head_t shutdown_sleep; wait_queue_head_t shutdown_sleep;
atomic_t refcount; /* refcount for disconnection */ atomic_t refcount; /* refcount for disconnection */
struct device *dev; /* device assigned to this card */ struct device *dev; /* device assigned to this card */
struct device *card_dev; /* cardX object for sysfs */ struct device card_dev; /* cardX object for sysfs */
bool registered; /* card_dev is registered? */
#ifdef CONFIG_PM #ifdef CONFIG_PM
unsigned int power_state; /* power state */ unsigned int power_state; /* power state */
...@@ -149,6 +149,8 @@ struct snd_card { ...@@ -149,6 +149,8 @@ struct snd_card {
#endif #endif
}; };
#define dev_to_snd_card(p) container_of(p, struct snd_card, card_dev)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static inline void snd_power_lock(struct snd_card *card) static inline void snd_power_lock(struct snd_card *card)
{ {
...@@ -197,7 +199,7 @@ struct snd_minor { ...@@ -197,7 +199,7 @@ struct snd_minor {
/* return a device pointer linked to each sound device as a parent */ /* return a device pointer linked to each sound device as a parent */
static inline struct device *snd_card_get_device_link(struct snd_card *card) static inline struct device *snd_card_get_device_link(struct snd_card *card)
{ {
return card ? card->card_dev : NULL; return card ? &card->card_dev : NULL;
} }
/* sound.c */ /* sound.c */
......
...@@ -156,6 +156,13 @@ static int get_slot_from_bitmask(int mask, int (*check)(struct module *, int), ...@@ -156,6 +156,13 @@ static int get_slot_from_bitmask(int mask, int (*check)(struct module *, int),
return mask; /* unchanged */ 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 * snd_card_new - create and initialize a soundcard structure
* @parent: the parent device object * @parent: the parent device object
...@@ -189,6 +196,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid, ...@@ -189,6 +196,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
if (!card) if (!card)
return -ENOMEM; return -ENOMEM;
if (extra_size > 0)
card->private_data = (char *)card + sizeof(struct snd_card);
if (xid) if (xid)
strlcpy(card->id, xid, sizeof(card->id)); strlcpy(card->id, xid, sizeof(card->id));
err = 0; err = 0;
...@@ -208,7 +217,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid, ...@@ -208,7 +217,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
mutex_unlock(&snd_card_mutex); mutex_unlock(&snd_card_mutex);
snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n", snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",
idx, snd_ecards_limit - 1, err); idx, snd_ecards_limit - 1, err);
goto __error; kfree(card);
return err;
} }
set_bit(idx, snd_cards_lock); /* lock it */ set_bit(idx, snd_cards_lock); /* lock it */
if (idx >= snd_ecards_limit) if (idx >= snd_ecards_limit)
...@@ -230,6 +240,15 @@ int snd_card_new(struct device *parent, int idx, const char *xid, ...@@ -230,6 +240,15 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
mutex_init(&card->power_lock); mutex_init(&card->power_lock);
init_waitqueue_head(&card->power_sleep); init_waitqueue_head(&card->power_sleep);
#endif #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 */ /* the control interface cannot be accessed from the user space until */
/* snd_cards_bitmask and snd_cards are set with snd_card_register */ /* snd_cards_bitmask and snd_cards are set with snd_card_register */
err = snd_ctl_create(card); err = snd_ctl_create(card);
...@@ -242,15 +261,13 @@ int snd_card_new(struct device *parent, int idx, const char *xid, ...@@ -242,15 +261,13 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
snd_printk(KERN_ERR "unable to create card info\n"); snd_printk(KERN_ERR "unable to create card info\n");
goto __error_ctl; goto __error_ctl;
} }
if (extra_size > 0)
card->private_data = (char *)card + sizeof(struct snd_card);
*card_ret = card; *card_ret = card;
return 0; return 0;
__error_ctl: __error_ctl:
snd_device_free_all(card, SNDRV_DEV_CMD_PRE); snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
__error: __error:
kfree(card); put_device(&card->card_dev);
return err; return err;
} }
EXPORT_SYMBOL(snd_card_new); EXPORT_SYMBOL(snd_card_new);
...@@ -407,9 +424,9 @@ int snd_card_disconnect(struct snd_card *card) ...@@ -407,9 +424,9 @@ int snd_card_disconnect(struct snd_card *card)
snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number); snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number);
snd_info_card_disconnect(card); snd_info_card_disconnect(card);
if (card->card_dev) { if (card->registered) {
device_unregister(card->card_dev); device_del(&card->card_dev);
card->card_dev = NULL; card->registered = false;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
wake_up(&card->power_sleep); wake_up(&card->power_sleep);
...@@ -471,7 +488,7 @@ void snd_card_unref(struct snd_card *card) ...@@ -471,7 +488,7 @@ void snd_card_unref(struct snd_card *card)
if (atomic_dec_and_test(&card->refcount)) { if (atomic_dec_and_test(&card->refcount)) {
wake_up(&card->shutdown_sleep); wake_up(&card->shutdown_sleep);
if (card->free_on_last_close) if (card->free_on_last_close)
snd_card_do_free(card); put_device(&card->card_dev);
} }
} }
EXPORT_SYMBOL(snd_card_unref); EXPORT_SYMBOL(snd_card_unref);
...@@ -489,7 +506,7 @@ int snd_card_free_when_closed(struct snd_card *card) ...@@ -489,7 +506,7 @@ int snd_card_free_when_closed(struct snd_card *card)
card->free_on_last_close = 1; card->free_on_last_close = 1;
if (atomic_dec_and_test(&card->refcount)) if (atomic_dec_and_test(&card->refcount))
snd_card_do_free(card); put_device(&card->card_dev);
return 0; return 0;
} }
...@@ -503,7 +520,7 @@ int snd_card_free(struct snd_card *card) ...@@ -503,7 +520,7 @@ int snd_card_free(struct snd_card *card)
/* wait, until all devices are ready for the free operation */ /* wait, until all devices are ready for the free operation */
wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); wait_event(card->shutdown_sleep, !atomic_read(&card->refcount));
snd_card_do_free(card); put_device(&card->card_dev);
return 0; return 0;
} }
...@@ -694,12 +711,11 @@ int snd_card_register(struct snd_card *card) ...@@ -694,12 +711,11 @@ int snd_card_register(struct snd_card *card)
if (snd_BUG_ON(!card)) if (snd_BUG_ON(!card))
return -EINVAL; return -EINVAL;
if (!card->card_dev) { if (!card->registered) {
card->card_dev = device_create(sound_class, card->dev, err = device_add(&card->card_dev);
MKDEV(0, 0), card, if (err < 0)
"card%i", card->number); return err;
if (IS_ERR(card->card_dev)) card->registered = true;
card->card_dev = NULL;
} }
if ((err = snd_device_register_all(card)) < 0) if ((err = snd_device_register_all(card)) < 0)
...@@ -729,11 +745,11 @@ int snd_card_register(struct snd_card *card) ...@@ -729,11 +745,11 @@ int snd_card_register(struct snd_card *card)
if (snd_mixer_oss_notify_callback) if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER); snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
#endif #endif
if (card->card_dev) { if (card->registered) {
err = device_create_file(card->card_dev, &card_id_attrs); err = device_create_file(&card->card_dev, &card_id_attrs);
if (err < 0) if (err < 0)
return err; 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) if (err < 0)
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment