diff options
Diffstat (limited to 'sound/core/hwdep.c')
| -rw-r--r-- | sound/core/hwdep.c | 77 |
1 files changed, 59 insertions, 18 deletions
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index a70ee7f1ed9..69459e5f712 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -24,6 +24,7 @@ #include <linux/slab.h> #include <linux/time.h> #include <linux/mutex.h> +#include <linux/module.h> #include <sound/core.h> #include <sound/control.h> #include <sound/minors.h> @@ -99,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) if (hw == NULL) return -ENODEV; - if (!try_module_get(hw->card->module)) + if (!try_module_get(hw->card->module)) { + snd_card_unref(hw->card); return -EFAULT; + } init_waitqueue_entry(&wait, current); add_wait_queue(&hw->open_wait, &wait); @@ -128,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); schedule(); mutex_lock(&hw->open_mutex); + if (hw->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -147,6 +154,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); if (err < 0) module_put(hw->card->module); + snd_card_unref(hw->card); return err; } @@ -272,7 +280,14 @@ static int snd_hwdep_control_ioctl(struct snd_card *card, if (get_user(device, (int __user *)arg)) return -EFAULT; mutex_lock(®ister_mutex); - device = device < 0 ? 0 : device + 1; + + if (device < 0) + device = 0; + else if (device < SNDRV_MINOR_HWDEPS) + device++; + else + device = SNDRV_MINOR_HWDEPS; + while (device < SNDRV_MINOR_HWDEPS) { if (snd_hwdep_search(card, device)) break; @@ -341,7 +356,7 @@ static const struct file_operations snd_hwdep_f_ops = * The callbacks (hwdep->ops) must be set on the returned instance * after this call manually by the caller. * - * Returns zero if successful, or a negative error code on failure. + * Return: Zero if successful, or a negative error code on failure. */ int snd_hwdep_new(struct snd_card *card, char *id, int device, struct snd_hwdep **rhwdep) @@ -360,7 +375,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, *rhwdep = NULL; hwdep = kzalloc(sizeof(*hwdep), GFP_KERNEL); if (hwdep == NULL) { - snd_printk(KERN_ERR "hwdep: cannot allocate\n"); + dev_err(card->dev, "hwdep: cannot allocate\n"); return -ENOMEM; } hwdep->card = card; @@ -380,6 +395,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, *rhwdep = hwdep; return 0; } +EXPORT_SYMBOL(snd_hwdep_new); static int snd_hwdep_free(struct snd_hwdep *hwdep) { @@ -400,37 +416,61 @@ static int snd_hwdep_dev_free(struct snd_device *device) static int snd_hwdep_dev_register(struct snd_device *device) { struct snd_hwdep *hwdep = device->device_data; + struct snd_card *card = hwdep->card; + struct device *dev; int err; char name[32]; mutex_lock(®ister_mutex); - if (snd_hwdep_search(hwdep->card, hwdep->device)) { + if (snd_hwdep_search(card, hwdep->device)) { mutex_unlock(®ister_mutex); return -EBUSY; } list_add_tail(&hwdep->list, &snd_hwdep_devices); sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device); - if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP, - hwdep->card, hwdep->device, - &snd_hwdep_f_ops, hwdep, name)) < 0) { - snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n", - hwdep->card->number, hwdep->device); + dev = hwdep->dev; + if (!dev) + dev = snd_card_get_device_link(hwdep->card); + err = snd_register_device_for_dev(SNDRV_DEVICE_TYPE_HWDEP, + hwdep->card, hwdep->device, + &snd_hwdep_f_ops, hwdep, name, dev); + if (err < 0) { + dev_err(dev, + "unable to register hardware dependent device %i:%i\n", + card->number, hwdep->device); list_del(&hwdep->list); mutex_unlock(®ister_mutex); return err; } + + if (hwdep->groups) { + struct device *d = snd_get_device(SNDRV_DEVICE_TYPE_HWDEP, + hwdep->card, hwdep->device); + if (d) { + if (hwdep->private_data) + dev_set_drvdata(d, hwdep->private_data); + err = sysfs_create_groups(&d->kobj, hwdep->groups); + if (err < 0) + dev_warn(dev, + "hwdep %d:%d: cannot create sysfs groups\n", + card->number, hwdep->device); + put_device(d); + } + } + #ifdef CONFIG_SND_OSSEMUL hwdep->ossreg = 0; if (hwdep->oss_type >= 0) { if ((hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM) && (hwdep->device != 0)) { - snd_printk (KERN_WARNING "only hwdep device 0 can be registered as OSS direct FM device!\n"); + dev_warn(dev, + "only hwdep device 0 can be registered as OSS direct FM device!\n"); } else { if (snd_register_oss_device(hwdep->oss_type, - hwdep->card, hwdep->device, - &snd_hwdep_f_ops, hwdep, - hwdep->oss_dev) < 0) { - snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n", - hwdep->card->number, hwdep->device); + card, hwdep->device, + &snd_hwdep_f_ops, hwdep) < 0) { + dev_err(dev, + "unable to register OSS compatibility device %i:%i\n", + card->number, hwdep->device); } else hwdep->ossreg = 1; } @@ -451,12 +491,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) mutex_unlock(®ister_mutex); return -EINVAL; } + mutex_lock(&hwdep->open_mutex); + wake_up(&hwdep->open_wait); #ifdef CONFIG_SND_OSSEMUL if (hwdep->ossreg) snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); #endif snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); list_del_init(&hwdep->list); + mutex_unlock(&hwdep->open_mutex); mutex_unlock(®ister_mutex); return 0; } @@ -525,5 +568,3 @@ static void __exit alsa_hwdep_exit(void) module_init(alsa_hwdep_init) module_exit(alsa_hwdep_exit) - -EXPORT_SYMBOL(snd_hwdep_new); |
