Commit 7d2aae1e authored by Takashi Iwai's avatar Takashi Iwai Committed by Greg Kroah-Hartman

[PATCH] ALSA: Fix sysfs breakage

The recent change for a new sysfs tree with card* object breaks the
/sys/class/sound tree if CONFIG_SYSFS_DEPRECATED is enabled.
The device in each entry doesn't point the correct device object:

  /sys/class/sound
  ...
  |-- pcmC0D0c
  |   |-- dev
  |   |-- device -> ../../../class/sound/card0
  |   |-- pcm_class
  |   |-- power
  |   |   `-- wakeup
  |   |-- subsystem -> ../../../class/sound
  |   `-- uevent

Also, this change breaks some drivers (like sound/arm/*) referring
card->dev directly to obtain the device object for memory handling.

This patch reverts the semantics of card->dev to the former version,
which points to a real device object.  The card* object is stored in a
new card->card_dev field, instead.  The device parent is chosen either
card->dev or card->card_dev according to CONFIG_SYSFS_DEPRECATED to
keep the tree compatibility.
Also, card* isn't created if CONFIG_SYSFS_DEPRECATED is enabled.  The
reason of card* object is a root of all beloing devices, and it makes
little sense if each sound device points to the real device object
directly.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Acked-by: default avatarMonty Montgomery <xiphmont@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 5263bf65
...@@ -132,8 +132,10 @@ struct snd_card { ...@@ -132,8 +132,10 @@ struct snd_card {
int shutdown; /* this card is going down */ int shutdown; /* this card is going down */
int free_on_last_close; /* free in context of file_release */ int free_on_last_close; /* free in context of file_release */
wait_queue_head_t shutdown_sleep; wait_queue_head_t shutdown_sleep;
struct device *parent; struct device *dev; /* device assigned to this card */
struct device *dev; #ifndef CONFIG_SYSFS_DEPRECATED
struct device *card_dev; /* cardX object for sysfs */
#endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
unsigned int power_state; /* power state */ unsigned int power_state; /* power state */
...@@ -191,6 +193,16 @@ struct snd_minor { ...@@ -191,6 +193,16 @@ struct snd_minor {
struct device *dev; /* device for sysfs */ struct device *dev; /* device for sysfs */
}; };
/* 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)
{
#ifdef CONFIG_SYSFS_DEPRECATED
return card ? card->dev : NULL;
#else
return card ? card->card_dev : NULL;
#endif
}
/* sound.c */ /* sound.c */
extern int snd_major; extern int snd_major;
...@@ -257,7 +269,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file); ...@@ -257,7 +269,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file);
int snd_card_file_remove(struct snd_card *card, struct file *file); int snd_card_file_remove(struct snd_card *card, struct file *file);
#ifndef snd_card_set_dev #ifndef snd_card_set_dev
#define snd_card_set_dev(card,devptr) ((card)->parent = (devptr)) #define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
#endif #endif
/* device.c */ /* device.c */
......
...@@ -361,8 +361,10 @@ static int snd_card_do_free(struct snd_card *card) ...@@ -361,8 +361,10 @@ static int snd_card_do_free(struct snd_card *card)
snd_printk(KERN_WARNING "unable to free card info\n"); snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */ /* Not fatal error */
} }
if (card->dev) #ifndef CONFIG_SYSFS_DEPRECATED
device_unregister(card->dev); if (card->card_dev)
device_unregister(card->card_dev);
#endif
kfree(card); kfree(card);
return 0; return 0;
} }
...@@ -497,12 +499,14 @@ int snd_card_register(struct snd_card *card) ...@@ -497,12 +499,14 @@ int snd_card_register(struct snd_card *card)
int err; int err;
snd_assert(card != NULL, return -EINVAL); snd_assert(card != NULL, return -EINVAL);
if (!card->dev) { #ifndef CONFIG_SYSFS_DEPRECATED
card->dev = device_create(sound_class, card->parent, 0, if (!card->card_dev) {
card->card_dev = device_create(sound_class, card->dev, 0,
"card%i", card->number); "card%i", card->number);
if (IS_ERR(card->dev)) if (IS_ERR(card->card_dev))
card->dev = NULL; card->card_dev = NULL;
} }
#endif
if ((err = snd_device_register_all(card)) < 0) if ((err = snd_device_register_all(card)) < 0)
return err; return err;
mutex_lock(&snd_card_mutex); mutex_lock(&snd_card_mutex);
......
...@@ -238,7 +238,7 @@ int snd_register_device(int type, struct snd_card *card, int dev, ...@@ -238,7 +238,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
{ {
int minor; int minor;
struct snd_minor *preg; struct snd_minor *preg;
struct device *device = NULL; struct device *device = snd_card_get_device_link(card);
snd_assert(name, return -EINVAL); snd_assert(name, return -EINVAL);
preg = kmalloc(sizeof *preg, GFP_KERNEL); preg = kmalloc(sizeof *preg, GFP_KERNEL);
...@@ -263,8 +263,6 @@ int snd_register_device(int type, struct snd_card *card, int dev, ...@@ -263,8 +263,6 @@ int snd_register_device(int type, struct snd_card *card, int dev,
return minor; return minor;
} }
snd_minors[minor] = preg; snd_minors[minor] = preg;
if (card)
device = card->dev;
preg->dev = device_create(sound_class, device, MKDEV(major, minor), preg->dev = device_create(sound_class, device, MKDEV(major, minor),
"%s", name); "%s", name);
if (preg->dev) if (preg->dev)
......
...@@ -106,7 +106,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, ...@@ -106,7 +106,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
int cidx = SNDRV_MINOR_OSS_CARD(minor); int cidx = SNDRV_MINOR_OSS_CARD(minor);
int track2 = -1; int track2 = -1;
int register1 = -1, register2 = -1; int register1 = -1, register2 = -1;
struct device *carddev = NULL; struct device *carddev = snd_card_get_device_link(card);
if (card && card->number >= 8) if (card && card->number >= 8)
return 0; /* ignore silently */ return 0; /* ignore silently */
...@@ -134,8 +134,6 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, ...@@ -134,8 +134,6 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1); track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
break; break;
} }
if (card)
carddev = card->dev;
register1 = register_sound_special_device(f_ops, minor, carddev); register1 = register_sound_special_device(f_ops, minor, carddev);
if (register1 != minor) if (register1 != minor)
goto __end; goto __end;
......
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