Merge branch 'for-linus' into for-next
... for migrating the core changes for USB-audio disconnection fixes
This commit is contained in:
@@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f)
|
||||
|
||||
if (dirn != compr->direction) {
|
||||
pr_err("this device doesn't support this direction\n");
|
||||
snd_card_unref(compr->card);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
if (!data) {
|
||||
snd_card_unref(compr->card);
|
||||
return -ENOMEM;
|
||||
}
|
||||
data->stream.ops = compr->ops;
|
||||
data->stream.direction = dirn;
|
||||
data->stream.private_data = compr->private_data;
|
||||
@@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f)
|
||||
runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
|
||||
if (!runtime) {
|
||||
kfree(data);
|
||||
snd_card_unref(compr->card);
|
||||
return -ENOMEM;
|
||||
}
|
||||
runtime->state = SNDRV_PCM_STATE_OPEN;
|
||||
@@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f)
|
||||
kfree(runtime);
|
||||
kfree(data);
|
||||
}
|
||||
return ret;
|
||||
snd_card_unref(compr->card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int snd_compr_free(struct inode *inode, struct file *f)
|
||||
|
@@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
|
||||
write_lock_irqsave(&card->ctl_files_rwlock, flags);
|
||||
list_add_tail(&ctl->list, &card->ctl_files);
|
||||
write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
|
||||
snd_card_unref(card);
|
||||
return 0;
|
||||
|
||||
__error:
|
||||
@@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
|
||||
__error2:
|
||||
snd_card_file_remove(card, file);
|
||||
__error1:
|
||||
if (card)
|
||||
snd_card_unref(card);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1434,6 +1437,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
|
||||
spin_unlock_irq(&ctl->read_lock);
|
||||
schedule();
|
||||
remove_wait_queue(&ctl->change_sleep, &wait);
|
||||
if (ctl->card->shutdown)
|
||||
return -ENODEV;
|
||||
if (signal_pending(current))
|
||||
return -ERESTARTSYS;
|
||||
spin_lock_irq(&ctl->read_lock);
|
||||
|
@@ -100,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);
|
||||
@@ -129,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;
|
||||
@@ -148,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;
|
||||
}
|
||||
|
||||
@@ -459,12 +466,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;
|
||||
}
|
||||
|
@@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid,
|
||||
spin_lock_init(&card->files_lock);
|
||||
INIT_LIST_HEAD(&card->files_list);
|
||||
init_waitqueue_head(&card->shutdown_sleep);
|
||||
atomic_set(&card->refcount, 0);
|
||||
#ifdef CONFIG_PM
|
||||
mutex_init(&card->power_lock);
|
||||
init_waitqueue_head(&card->power_sleep);
|
||||
@@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* snd_card_unref - release the reference counter
|
||||
* @card: the card instance
|
||||
*
|
||||
* Decrements the reference counter. When it reaches to zero, wake up
|
||||
* the sleeper and call the destructor if needed.
|
||||
*/
|
||||
void snd_card_unref(struct snd_card *card)
|
||||
{
|
||||
if (atomic_dec_and_test(&card->refcount)) {
|
||||
wake_up(&card->shutdown_sleep);
|
||||
if (card->free_on_last_close)
|
||||
snd_card_do_free(card);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(snd_card_unref);
|
||||
|
||||
int snd_card_free_when_closed(struct snd_card *card)
|
||||
{
|
||||
int free_now = 0;
|
||||
int ret = snd_card_disconnect(card);
|
||||
if (ret)
|
||||
int ret;
|
||||
|
||||
atomic_inc(&card->refcount);
|
||||
ret = snd_card_disconnect(card);
|
||||
if (ret) {
|
||||
atomic_dec(&card->refcount);
|
||||
return ret;
|
||||
}
|
||||
|
||||
spin_lock(&card->files_lock);
|
||||
if (list_empty(&card->files_list))
|
||||
free_now = 1;
|
||||
else
|
||||
card->free_on_last_close = 1;
|
||||
spin_unlock(&card->files_lock);
|
||||
|
||||
if (free_now)
|
||||
card->free_on_last_close = 1;
|
||||
if (atomic_dec_and_test(&card->refcount))
|
||||
snd_card_do_free(card);
|
||||
return 0;
|
||||
}
|
||||
@@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card)
|
||||
return ret;
|
||||
|
||||
/* wait, until all devices are ready for the free operation */
|
||||
wait_event(card->shutdown_sleep, list_empty(&card->files_list));
|
||||
wait_event(card->shutdown_sleep, !atomic_read(&card->refcount));
|
||||
snd_card_do_free(card);
|
||||
return 0;
|
||||
}
|
||||
@@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
|
||||
return -ENODEV;
|
||||
}
|
||||
list_add(&mfile->list, &card->files_list);
|
||||
atomic_inc(&card->refcount);
|
||||
spin_unlock(&card->files_lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add);
|
||||
int snd_card_file_remove(struct snd_card *card, struct file *file)
|
||||
{
|
||||
struct snd_monitor_file *mfile, *found = NULL;
|
||||
int last_close = 0;
|
||||
|
||||
spin_lock(&card->files_lock);
|
||||
list_for_each_entry(mfile, &card->files_list, list) {
|
||||
@@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (list_empty(&card->files_list))
|
||||
last_close = 1;
|
||||
spin_unlock(&card->files_lock);
|
||||
if (last_close) {
|
||||
wake_up(&card->shutdown_sleep);
|
||||
if (card->free_on_last_close)
|
||||
snd_card_do_free(card);
|
||||
}
|
||||
if (!found) {
|
||||
snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
|
||||
return -ENOENT;
|
||||
}
|
||||
kfree(found);
|
||||
snd_card_unref(card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
|
||||
SNDRV_OSS_DEVICE_TYPE_MIXER);
|
||||
if (card == NULL)
|
||||
return -ENODEV;
|
||||
if (card->mixer_oss == NULL)
|
||||
if (card->mixer_oss == NULL) {
|
||||
snd_card_unref(card);
|
||||
return -ENODEV;
|
||||
}
|
||||
err = snd_card_file_add(card, file);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
snd_card_unref(card);
|
||||
return err;
|
||||
}
|
||||
fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);
|
||||
if (fmixer == NULL) {
|
||||
snd_card_file_remove(card, file);
|
||||
snd_card_unref(card);
|
||||
return -ENOMEM;
|
||||
}
|
||||
fmixer->card = card;
|
||||
@@ -68,6 +73,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
|
||||
if (!try_module_get(card->module)) {
|
||||
kfree(fmixer);
|
||||
snd_card_file_remove(card, file);
|
||||
snd_card_unref(card);
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
|
@@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
|
||||
mutex_unlock(&pcm->open_mutex);
|
||||
schedule();
|
||||
mutex_lock(&pcm->open_mutex);
|
||||
if (pcm->card->shutdown) {
|
||||
err = -ENODEV;
|
||||
break;
|
||||
}
|
||||
if (signal_pending(current)) {
|
||||
err = -ERESTARTSYS;
|
||||
break;
|
||||
@@ -2457,6 +2461,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
|
||||
__error2:
|
||||
snd_card_file_remove(pcm->card, file);
|
||||
__error1:
|
||||
if (pcm)
|
||||
snd_card_unref(pcm->card);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@@ -1086,11 +1086,19 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
|
||||
if (list_empty(&pcm->list))
|
||||
goto unlock;
|
||||
|
||||
mutex_lock(&pcm->open_mutex);
|
||||
wake_up(&pcm->open_wait);
|
||||
list_del_init(&pcm->list);
|
||||
for (cidx = 0; cidx < 2; cidx++)
|
||||
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
|
||||
if (substream->runtime)
|
||||
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
if (substream->runtime) {
|
||||
substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
|
||||
wake_up(&substream->runtime->sleep);
|
||||
wake_up(&substream->runtime->tsleep);
|
||||
}
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
}
|
||||
list_for_each_entry(notify, &snd_pcm_notify_list, list) {
|
||||
notify->n_disconnect(pcm);
|
||||
}
|
||||
@@ -1110,6 +1118,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
|
||||
pcm->streams[cidx].chmap_kctl = NULL;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&pcm->open_mutex);
|
||||
unlock:
|
||||
mutex_unlock(®ister_mutex);
|
||||
return 0;
|
||||
|
@@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
|
||||
return usecs;
|
||||
}
|
||||
|
||||
static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
|
||||
{
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
|
||||
substream->runtime->status->state = state;
|
||||
snd_pcm_stream_unlock_irq(substream);
|
||||
}
|
||||
|
||||
static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params)
|
||||
{
|
||||
@@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
runtime->boundary *= 2;
|
||||
|
||||
snd_pcm_timer_resolution_change(substream);
|
||||
runtime->status->state = SNDRV_PCM_STATE_SETUP;
|
||||
snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
|
||||
|
||||
if (pm_qos_request_active(&substream->latency_pm_qos_req))
|
||||
pm_qos_remove_request(&substream->latency_pm_qos_req);
|
||||
@@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
|
||||
/* hardware might be unusable from this time,
|
||||
so we force application to retry to set
|
||||
the correct hardware parameter settings */
|
||||
runtime->status->state = SNDRV_PCM_STATE_OPEN;
|
||||
snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
|
||||
if (substream->ops->hw_free != NULL)
|
||||
substream->ops->hw_free(substream);
|
||||
return err;
|
||||
@@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
|
||||
return -EBADFD;
|
||||
if (substream->ops->hw_free)
|
||||
result = substream->ops->hw_free(substream);
|
||||
runtime->status->state = SNDRV_PCM_STATE_OPEN;
|
||||
snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
|
||||
pm_qos_remove_request(&substream->latency_pm_qos_req);
|
||||
return result;
|
||||
}
|
||||
@@ -1322,7 +1330,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
runtime->control->appl_ptr = runtime->status->hw_ptr;
|
||||
runtime->status->state = SNDRV_PCM_STATE_PREPARED;
|
||||
snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
|
||||
}
|
||||
|
||||
static struct action_ops snd_pcm_action_prepare = {
|
||||
@@ -1512,6 +1520,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
|
||||
down_read(&snd_pcm_link_rwsem);
|
||||
snd_pcm_stream_lock_irq(substream);
|
||||
remove_wait_queue(&to_check->sleep, &wait);
|
||||
if (card->shutdown) {
|
||||
result = -ENODEV;
|
||||
break;
|
||||
}
|
||||
if (tout == 0) {
|
||||
if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
|
||||
result = -ESTRPIPE;
|
||||
@@ -1636,6 +1648,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
|
||||
write_unlock_irq(&snd_pcm_link_rwlock);
|
||||
up_write(&snd_pcm_link_rwsem);
|
||||
_nolock:
|
||||
snd_card_unref(substream1->pcm->card);
|
||||
fput_light(file, fput_needed);
|
||||
if (res < 0)
|
||||
kfree(group);
|
||||
@@ -2110,7 +2123,9 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)
|
||||
return err;
|
||||
pcm = snd_lookup_minor_data(iminor(inode),
|
||||
SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
|
||||
return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
|
||||
err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
|
||||
snd_card_unref(pcm->card);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_pcm_capture_open(struct inode *inode, struct file *file)
|
||||
@@ -2121,7 +2136,9 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file)
|
||||
return err;
|
||||
pcm = snd_lookup_minor_data(iminor(inode),
|
||||
SNDRV_DEVICE_TYPE_PCM_CAPTURE);
|
||||
return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
|
||||
err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
|
||||
snd_card_unref(pcm->card);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
|
||||
@@ -2158,6 +2175,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
|
||||
mutex_unlock(&pcm->open_mutex);
|
||||
schedule();
|
||||
mutex_lock(&pcm->open_mutex);
|
||||
if (pcm->card->shutdown) {
|
||||
err = -ENODEV;
|
||||
break;
|
||||
}
|
||||
if (signal_pending(current)) {
|
||||
err = -ERESTARTSYS;
|
||||
break;
|
||||
|
@@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
|
||||
if (rmidi == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (!try_module_get(rmidi->card->module))
|
||||
if (!try_module_get(rmidi->card->module)) {
|
||||
snd_card_unref(rmidi->card);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
mutex_lock(&rmidi->open_mutex);
|
||||
card = rmidi->card;
|
||||
@@ -422,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
|
||||
mutex_unlock(&rmidi->open_mutex);
|
||||
schedule();
|
||||
mutex_lock(&rmidi->open_mutex);
|
||||
if (rmidi->card->shutdown) {
|
||||
err = -ENODEV;
|
||||
break;
|
||||
}
|
||||
if (signal_pending(current)) {
|
||||
err = -ERESTARTSYS;
|
||||
break;
|
||||
@@ -440,6 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
|
||||
#endif
|
||||
file->private_data = rawmidi_file;
|
||||
mutex_unlock(&rmidi->open_mutex);
|
||||
snd_card_unref(rmidi->card);
|
||||
return 0;
|
||||
|
||||
__error:
|
||||
@@ -447,6 +454,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
|
||||
__error_card:
|
||||
mutex_unlock(&rmidi->open_mutex);
|
||||
module_put(rmidi->card->module);
|
||||
snd_card_unref(rmidi->card);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -991,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
|
||||
spin_unlock_irq(&runtime->lock);
|
||||
schedule();
|
||||
remove_wait_queue(&runtime->sleep, &wait);
|
||||
if (rfile->rmidi->card->shutdown)
|
||||
return -ENODEV;
|
||||
if (signal_pending(current))
|
||||
return result > 0 ? result : -ERESTARTSYS;
|
||||
if (!runtime->avail)
|
||||
@@ -1234,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
|
||||
spin_unlock_irq(&runtime->lock);
|
||||
timeout = schedule_timeout(30 * HZ);
|
||||
remove_wait_queue(&runtime->sleep, &wait);
|
||||
if (rfile->rmidi->card->shutdown)
|
||||
return -ENODEV;
|
||||
if (signal_pending(current))
|
||||
return result > 0 ? result : -ERESTARTSYS;
|
||||
if (!runtime->avail && !timeout)
|
||||
@@ -1609,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
|
||||
static int snd_rawmidi_dev_disconnect(struct snd_device *device)
|
||||
{
|
||||
struct snd_rawmidi *rmidi = device->device_data;
|
||||
int dir;
|
||||
|
||||
mutex_lock(®ister_mutex);
|
||||
mutex_lock(&rmidi->open_mutex);
|
||||
wake_up(&rmidi->open_wait);
|
||||
list_del_init(&rmidi->list);
|
||||
for (dir = 0; dir < 2; dir++) {
|
||||
struct snd_rawmidi_substream *s;
|
||||
list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
|
||||
if (s->runtime)
|
||||
wake_up(&s->runtime->sleep);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SND_OSSEMUL
|
||||
if (rmidi->ossreg) {
|
||||
if ((int)rmidi->device == midi_map[rmidi->card->number]) {
|
||||
@@ -1626,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
|
||||
}
|
||||
#endif /* CONFIG_SND_OSSEMUL */
|
||||
snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
|
||||
mutex_unlock(&rmidi->open_mutex);
|
||||
mutex_unlock(®ister_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -98,6 +98,10 @@ static void snd_request_other(int minor)
|
||||
*
|
||||
* Checks that a minor device with the specified type is registered, and returns
|
||||
* its user data pointer.
|
||||
*
|
||||
* This function increments the reference counter of the card instance
|
||||
* if an associated instance with the given minor number and type is found.
|
||||
* The caller must call snd_card_unref() appropriately later.
|
||||
*/
|
||||
void *snd_lookup_minor_data(unsigned int minor, int type)
|
||||
{
|
||||
@@ -108,9 +112,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
|
||||
return NULL;
|
||||
mutex_lock(&sound_mutex);
|
||||
mreg = snd_minors[minor];
|
||||
if (mreg && mreg->type == type)
|
||||
if (mreg && mreg->type == type) {
|
||||
private_data = mreg->private_data;
|
||||
else
|
||||
if (mreg->card_ptr)
|
||||
atomic_inc(&mreg->card_ptr->refcount);
|
||||
} else
|
||||
private_data = NULL;
|
||||
mutex_unlock(&sound_mutex);
|
||||
return private_data;
|
||||
@@ -275,6 +281,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
|
||||
preg->device = dev;
|
||||
preg->f_ops = f_ops;
|
||||
preg->private_data = private_data;
|
||||
preg->card_ptr = card;
|
||||
mutex_lock(&sound_mutex);
|
||||
#ifdef CONFIG_SND_DYNAMIC_MINORS
|
||||
minor = snd_find_free_minor(type);
|
||||
|
@@ -40,6 +40,9 @@
|
||||
static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
|
||||
static DEFINE_MUTEX(sound_oss_mutex);
|
||||
|
||||
/* NOTE: This function increments the refcount of the associated card like
|
||||
* snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately
|
||||
*/
|
||||
void *snd_lookup_oss_minor_data(unsigned int minor, int type)
|
||||
{
|
||||
struct snd_minor *mreg;
|
||||
@@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)
|
||||
return NULL;
|
||||
mutex_lock(&sound_oss_mutex);
|
||||
mreg = snd_oss_minors[minor];
|
||||
if (mreg && mreg->type == type)
|
||||
if (mreg && mreg->type == type) {
|
||||
private_data = mreg->private_data;
|
||||
else
|
||||
if (mreg->card_ptr)
|
||||
atomic_inc(&mreg->card_ptr->refcount);
|
||||
} else
|
||||
private_data = NULL;
|
||||
mutex_unlock(&sound_oss_mutex);
|
||||
return private_data;
|
||||
@@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
|
||||
preg->device = dev;
|
||||
preg->f_ops = f_ops;
|
||||
preg->private_data = private_data;
|
||||
preg->card_ptr = card;
|
||||
mutex_lock(&sound_oss_mutex);
|
||||
snd_oss_minors[minor] = preg;
|
||||
minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
|
||||
|
Reference in New Issue
Block a user