All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Jaroslav Kysela <perex@suse.cz>
Cc: Clemens Ladisch <clemens@ladisch.de>,
	"alsa-devel@lists.sourceforge.net"
	<alsa-devel@lists.sourceforge.net>
Subject: Re: trying out usb hotplugs
Date: Fri, 29 Nov 2002 13:12:30 +0100	[thread overview]
Message-ID: <s5hof88bmmp.wl@alsa2.suse.de> (raw)
In-Reply-To: <Pine.LNX.4.33.0211291150340.532-100000@pnote.perex-int.cz>

[-- Attachment #1: Type: text/plain, Size: 77 bytes --]

Hi,

the attached is my latest patch.
could you check it?


thanks,

Takashi

[-- Attachment #2: disconnect-fix.dif --]
[-- Type: application/octet-stream, Size: 13942 bytes --]

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(&register_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 */

  parent reply	other threads:[~2002-11-29 12:12 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-11-28  0:27 trying out usb hotplugs Martin Langer
2002-11-28 12:11 ` Takashi Iwai
2002-11-29  7:52   ` Clemens Ladisch
2002-11-29  9:06     ` Takashi Iwai
2002-11-29  9:39       ` Jaroslav Kysela
2002-11-29 10:07         ` Takashi Iwai
2002-11-29 11:24           ` Jaroslav Kysela
2002-11-29 11:42             ` Takashi Iwai
2002-11-29 12:12             ` Takashi Iwai [this message]
2002-11-29 14:05               ` Jaroslav Kysela
2002-11-29 14:14                 ` Takashi Iwai
2002-11-29 14:52                   ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=s5hof88bmmp.wl@alsa2.suse.de \
    --to=tiwai@suse.de \
    --cc=alsa-devel@lists.sourceforge.net \
    --cc=clemens@ladisch.de \
    --cc=perex@suse.cz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.