From mboxrd@z Thu Jan 1 00:00:00 1970 From: Takashi Iwai Subject: Re: trying out usb hotplugs Date: Fri, 29 Nov 2002 13:12:30 +0100 Sender: alsa-devel-admin@lists.sourceforge.net Message-ID: References: Mime-Version: 1.0 (generated by SEMI 1.14.4 - "Hosorogi") Content-Type: multipart/mixed; boundary="Multipart_Fri_Nov_29_13:12:29_2002-1" Return-path: In-Reply-To: Errors-To: alsa-devel-admin@lists.sourceforge.net List-Help: List-Post: List-Subscribe: , List-Unsubscribe: , List-Archive: To: Jaroslav Kysela Cc: Clemens Ladisch , "alsa-devel@lists.sourceforge.net" List-Id: alsa-devel@alsa-project.org --Multipart_Fri_Nov_29_13:12:29_2002-1 Content-Type: text/plain; charset=US-ASCII Hi, the attached is my latest patch. could you check it? thanks, Takashi --Multipart_Fri_Nov_29_13:12:29_2002-1 Content-Type: application/octet-stream Content-Disposition: attachment; filename="disconnect-fix.dif" Content-Transfer-Encoding: 7bit Index: alsa-kernel/core/control.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/control.c,v retrieving revision 1.15 diff -u -r1.15 control.c --- alsa-kernel/core/control.c 28 Nov 2002 09:31:13 -0000 1.15 +++ alsa-kernel/core/control.c 29 Nov 2002 11:52:05 -0000 @@ -78,6 +78,7 @@ ctl->pid = current->pid; file->private_data = ctl; write_lock_irqsave(&card->control_rwlock, flags); + atomic_inc(&card->ctl_use_count); list_add_tail(&ctl->list, &card->ctl_files); write_unlock_irqrestore(&card->control_rwlock, flags); return 0; @@ -118,10 +119,8 @@ card = ctl->card; write_lock_irqsave(&card->control_rwlock, flags); list_del(&ctl->list); - write_unlock_irqrestore(&card->control_rwlock, flags); - if (snd_ctl_can_unregister(card) == 0) + if (atomic_dec_and_test(&card->ctl_use_count)) wake_up(&card->shutdown_sleep); - write_lock(&card->control_owner_lock); list_for_each(list, &card->controls) { control = snd_kcontrol(list); if (control->owner == ctl) @@ -602,6 +601,9 @@ ctl = snd_magic_cast(snd_ctl_file_t, file->private_data, return -ENXIO); card = ctl->card; snd_assert(card != NULL, return -ENXIO); + if (card->ctl_shutdown) + return -ENODEV; + switch (cmd) { case SNDRV_CTL_IOCTL_PVERSION: return put_user(SNDRV_CTL_VERSION, (int *)arg) ? -EFAULT : 0; @@ -832,12 +834,7 @@ int snd_ctl_can_unregister(snd_card_t *card) { - int res; - - write_lock_irq(&card->control_rwlock); - res = !list_empty(&card->ctl_files); - write_unlock_irq(&card->control_rwlock); - return res; + return atomic_read(&card->ctl_use_count) != 0; } int snd_ctl_unregister(snd_card_t *card) Index: alsa-kernel/core/init.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/init.c,v retrieving revision 1.14 diff -u -r1.14 init.c --- alsa-kernel/core/init.c 28 Nov 2002 09:31:13 -0000 1.14 +++ alsa-kernel/core/init.c 29 Nov 2002 11:54:31 -0000 @@ -96,6 +96,7 @@ INIT_LIST_HEAD(&card->controls); INIT_LIST_HEAD(&card->ctl_files); init_waitqueue_head(&card->shutdown_sleep); + atomic_set(&card->ctl_use_count, 0); #ifdef CONFIG_PM init_MUTEX(&card->power_lock); init_waitqueue_head(&card->power_sleep); @@ -138,7 +139,7 @@ #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) if (snd_mixer_oss_notify_callback) - snd_mixer_oss_notify_callback(card, 1); + snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT); #endif /* notify all devices that we are disconnected */ @@ -174,7 +175,7 @@ #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) if (snd_mixer_oss_notify_callback) - snd_mixer_oss_notify_callback(card, 2); + snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE); #endif if (snd_device_free_all(card, SNDRV_DEV_CMD_PRE) < 0) { snd_printk(KERN_ERR "unable to free all devices (pre)\n"); @@ -300,7 +301,7 @@ __skip_info: #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) if (snd_mixer_oss_notify_callback) - snd_mixer_oss_notify_callback(card, 0); + snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER); #endif return 0; } Index: alsa-kernel/core/rawmidi.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/rawmidi.c,v retrieving revision 1.21 diff -u -r1.21 rawmidi.c --- alsa-kernel/core/rawmidi.c 28 Nov 2002 09:31:13 -0000 1.21 +++ alsa-kernel/core/rawmidi.c 29 Nov 2002 09:04:56 -0000 @@ -136,6 +136,8 @@ long timeout; snd_rawmidi_runtime_t *runtime = substream->runtime; + if (substream->rmidi->disconnected) + return 0; err = 0; runtime->drain = 1; while (runtime->avail < runtime->buffer_size) { @@ -144,6 +146,8 @@ err = -ERESTARTSYS; break; } + if (substream->rmidi->disconnected) + return 0; if (runtime->avail < runtime->buffer_size && !timeout) { snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size); err = -EIO; @@ -1070,6 +1074,9 @@ snd_assert(buf != NULL, return -EINVAL); snd_assert(runtime->buffer != NULL, return -EINVAL); + if (substream->rmidi->disconnected) + return -ENODEV; + result = 0; spin_lock_irqsave(&runtime->lock, flags); if (substream->append) { @@ -1480,6 +1487,7 @@ snd_rawmidi_t *rmidi = snd_magic_cast(snd_rawmidi_t, device->device_data, return -ENXIO); int idx; + rmidi->disconnected = 1; down(®ister_mutex); idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device; snd_rawmidi_devices[idx] = NULL; Index: alsa-kernel/core/oss/mixer_oss.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/oss/mixer_oss.c,v retrieving revision 1.12 diff -u -r1.12 mixer_oss.c --- alsa-kernel/core/oss/mixer_oss.c 28 Nov 2002 09:31:13 -0000 1.12 +++ alsa-kernel/core/oss/mixer_oss.c 29 Nov 2002 12:08:01 -0000 @@ -53,6 +53,7 @@ fmixer = (snd_mixer_oss_file_t *)snd_kcalloc(sizeof(*fmixer), GFP_KERNEL); if (fmixer == NULL) return -ENOMEM; + atomic_inc(&card->ctl_use_count); fmixer->card = card; fmixer->mixer = card->mixer_oss; file->private_data = fmixer; @@ -64,6 +65,8 @@ #ifdef LINUX_2_2 MOD_DEC_USE_COUNT; #endif + if (atomic_dec_and_test(&card->ctl_use_count)) + wake_up(&card->shutdown_sleep); return -EFAULT; } return 0; @@ -79,6 +82,8 @@ #ifdef LINUX_2_2 MOD_DEC_USE_COUNT; #endif + if (atomic_dec_and_test(&fmixer->card->ctl_use_count)) + wake_up(&fmixer->card->shutdown_sleep); kfree(fmixer); } return 0; @@ -498,6 +503,10 @@ snd_ctl_elem_info_t *uinfo; snd_ctl_elem_value_t *uctl; + /* FIXME: needs lock? */ + if (fmixer->mixer->disconnected) + return; + snd_runtime_check(kctl != NULL, return); uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC); uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC); @@ -525,6 +534,10 @@ snd_ctl_elem_info_t *uinfo; snd_ctl_elem_value_t *uctl; + /* FIXME: needs lock? */ + if (fmixer->mixer->disconnected) + return; + snd_runtime_check(kctl != NULL, return); uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC); uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC); @@ -584,6 +597,10 @@ snd_ctl_elem_value_t *uctl; int res; + /* FIXME: needs lock? */ + if (fmixer->mixer->disconnected) + return; + snd_runtime_check(kctl != NULL, return); uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC); uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC); @@ -614,6 +631,10 @@ snd_ctl_elem_value_t *uctl; int res; + /* FIXME: needs lock? */ + if (fmixer->mixer->disconnected) + return; + snd_runtime_check(kctl != NULL, return); uinfo = snd_kcalloc(sizeof(*uinfo), GFP_ATOMIC); uctl = snd_kcalloc(sizeof(*uctl), GFP_ATOMIC); @@ -750,6 +771,10 @@ snd_ctl_elem_value_t *uctl; int err, idx; + /* FIXME: needs lock? */ + if (mixer->disconnected) + return -ENODEV; + uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL); uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) { @@ -765,7 +790,7 @@ for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) continue; - pslot = &fmixer->mixer->slots[idx]; + pslot = &mixer->slots[idx]; slot = (struct slot *)pslot->private_data; if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE) continue; @@ -799,6 +824,10 @@ snd_ctl_elem_value_t *uctl; int err, idx; + /* FIXME: needs lock? */ + if (mixer->disconnected) + return -ENODEV; + uinfo = snd_kcalloc(sizeof(*uinfo), GFP_KERNEL); uctl = snd_kcalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) { @@ -812,7 +841,7 @@ for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) continue; - pslot = &fmixer->mixer->slots[idx]; + pslot = &mixer->slots[idx]; slot = (struct slot *)pslot->private_data; if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE) continue; @@ -1204,7 +1233,7 @@ { snd_mixer_oss_t *mixer; - if (cmd == 0) { /* register */ + if (cmd == SND_MIXER_OSS_NOTIFY_REGISTER) { char name[128]; int idx, err; @@ -1238,10 +1267,11 @@ card->mixer_oss = mixer; snd_mixer_oss_build(mixer); snd_mixer_oss_proc_init(mixer); - } else if (cmd == 1) { /* disconnect */ + } else if (cmd == SND_MIXER_OSS_NOTIFY_DISCONNECT) { mixer = card->mixer_oss; if (mixer == NULL || !mixer->oss_dev_alloc) return 0; + mixer->disconnected = 1; snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0); mixer->oss_dev_alloc = 0; } else { /* free */ @@ -1266,7 +1296,7 @@ snd_mixer_oss_notify_callback = snd_mixer_oss_notify_handler; for (idx = 0; idx < SNDRV_CARDS; idx++) { if (snd_cards[idx]) - snd_mixer_oss_notify_handler(snd_cards[idx], 0); + snd_mixer_oss_notify_handler(snd_cards[idx], SND_MIXER_OSS_NOTIFY_REGISTER); } return 0; } @@ -1278,7 +1308,7 @@ snd_mixer_oss_notify_callback = NULL; for (idx = 0; idx < SNDRV_CARDS; idx++) { if (snd_cards[idx]) - snd_mixer_oss_notify_handler(snd_cards[idx], 1); + snd_mixer_oss_notify_handler(snd_cards[idx], SND_MIXER_OSS_NOTIFY_FREE); } } Index: alsa-kernel/core/oss/pcm_oss.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/oss/pcm_oss.c,v retrieving revision 1.20 diff -u -r1.20 pcm_oss.c --- alsa-kernel/core/oss/pcm_oss.c 28 Nov 2002 09:31:13 -0000 1.20 +++ alsa-kernel/core/oss/pcm_oss.c 29 Nov 2002 11:29:18 -0000 @@ -1554,13 +1554,15 @@ err = -ENODEV; goto __error1; } + atomic_inc(&pcm->use_count); if (!try_inc_mod_count(pcm->card->module)) { err = -EFAULT; + atomic_dec(&pcm->use_count); goto __error1; } if (snd_task_name(current, task_name, sizeof(task_name)) < 0) { err = -EFAULT; - goto __error1; + goto __error; } if (file->f_mode & FMODE_WRITE) psetup = snd_pcm_oss_look_for_setup(pcm, SNDRV_PCM_STREAM_PLAYBACK, task_name); @@ -1639,6 +1641,8 @@ up(&pcm->open_mutex); wake_up(&pcm->open_wait); dec_mod_count(pcm->card->module); + if (atomic_dec_and_test(&pcm->use_count)) + wake_up(&pcm->card->shutdown_sleep); #ifdef LINUX_2_2 MOD_DEC_USE_COUNT; #endif Index: alsa-kernel/core/seq/seq_device.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/core/seq/seq_device.c,v retrieving revision 1.6 diff -u -r1.6 seq_device.c --- alsa-kernel/core/seq/seq_device.c 13 Aug 2002 16:17:06 -0000 1.6 +++ alsa-kernel/core/seq/seq_device.c 29 Nov 2002 08:45:48 -0000 @@ -92,6 +92,7 @@ static int snd_seq_device_free(snd_seq_device_t *dev); static int snd_seq_device_dev_free(snd_device_t *device); static int snd_seq_device_dev_register(snd_device_t *device); +static int snd_seq_device_dev_disconnect(snd_device_t *device); static int snd_seq_device_dev_unregister(snd_device_t *device); static int init_device(snd_seq_device_t *dev, ops_list_t *ops); @@ -166,6 +167,7 @@ static snd_device_ops_t dops = { .dev_free = snd_seq_device_dev_free, .dev_register = snd_seq_device_dev_register, + .dev_disconnect = snd_seq_device_dev_disconnect, .dev_unregister = snd_seq_device_dev_unregister }; @@ -265,6 +267,22 @@ init_device(dev, ops); unlock_driver(ops); + return 0; +} + +/* + * disconnect the device + */ +static int snd_seq_device_dev_disconnect(snd_device_t *device) +{ + snd_seq_device_t *dev = snd_magic_cast(snd_seq_device_t, device->device_data, return -ENXIO); + ops_list_t *ops; + + ops = find_driver(dev->id, 0); + if (ops == NULL) + return -ENOENT; + + free_device(dev, ops); return 0; } Index: alsa-kernel/include/core.h =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/core.h,v retrieving revision 1.24 diff -u -r1.24 core.h --- alsa-kernel/include/core.h 28 Nov 2002 09:31:13 -0000 1.24 +++ alsa-kernel/include/core.h 29 Nov 2002 11:53:54 -0000 @@ -140,6 +140,7 @@ struct list_head controls; /* all controls for this card */ struct list_head ctl_files; /* active control files */ int ctl_shutdown; /* control interface is going down */ + atomic_t ctl_use_count; /* reference counter for control files */ snd_info_entry_t *proc_root; /* root for soundcard specific files */ snd_info_entry_t *proc_id; /* the card id */ @@ -297,6 +298,9 @@ extern snd_card_t *snd_cards[SNDRV_CARDS]; extern rwlock_t snd_card_rwlock; #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) +#define SND_MIXER_OSS_NOTIFY_REGISTER 0 +#define SND_MIXER_OSS_NOTIFY_DISCONNECT 1 +#define SND_MIXER_OSS_NOTIFY_FREE 2 extern int (*snd_mixer_oss_notify_callback)(snd_card_t *card, int cmd); #endif Index: alsa-kernel/include/mixer_oss.h =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/mixer_oss.h,v retrieving revision 1.6 diff -u -r1.6 mixer_oss.h --- alsa-kernel/include/mixer_oss.h 28 Nov 2002 09:31:13 -0000 1.6 +++ alsa-kernel/include/mixer_oss.h 29 Nov 2002 11:53:16 -0000 @@ -61,7 +61,8 @@ void (*private_free_recsrc)(snd_mixer_oss_t *mixer); struct semaphore reg_mutex; snd_info_entry_t *proc_entry; - int oss_dev_alloc; + unsigned int oss_dev_alloc: 1; + unsigned int disconnected: 1; /* --- */ int oss_recsrc; }; Index: alsa-kernel/include/rawmidi.h =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/rawmidi.h,v retrieving revision 1.10 diff -u -r1.10 rawmidi.h --- alsa-kernel/include/rawmidi.h 28 Nov 2002 09:31:13 -0000 1.10 +++ alsa-kernel/include/rawmidi.h 29 Nov 2002 09:05:31 -0000 @@ -118,6 +118,7 @@ snd_card_t *card; atomic_t use_count; + unsigned int disconnected: 1; unsigned int device; /* device number */ unsigned int info_flags; /* SNDRV_RAWMIDI_INFO_XXXX */ --Multipart_Fri_Nov_29_13:12:29_2002-1-- ------------------------------------------------------- This SF.net email is sponsored by: Get the new Palm Tungsten T handheld. Power & Color in a compact size! http://ads.sourceforge.net/cgi-bin/redirect.pl?palm0002en