Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c461482c authored by Takashi Iwai's avatar Takashi Iwai Committed by Jaroslav Kysela
Browse files

[ALSA] Unregister device files at disconnection



Orignally proposed by Sam Revitch <sam.revitch@gmail.com>.
Unregister device files at disconnection to avoid the futher accesses.
Also, the dev_unregister callback is removed and replaced with the
combination of disconnect + free.
A new function snd_card_free_when_closed() is introduced, which is
used in USB disconnect callback.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent 746d4a02
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -71,7 +71,6 @@ struct snd_device_ops {
	int (*dev_free)(struct snd_device *dev);
	int (*dev_register)(struct snd_device *dev);
	int (*dev_disconnect)(struct snd_device *dev);
	int (*dev_unregister)(struct snd_device *dev);
};

struct snd_device {
@@ -131,6 +130,7 @@ struct snd_card {
								state */
	spinlock_t files_lock;		/* lock the files for this card */
	int shutdown;			/* this card is going down */
	int free_on_last_close;		/* free in context of file_release */
	wait_queue_head_t shutdown_sleep;
	struct work_struct free_workq;	/* for free in workqueue */
	struct device *dev;
@@ -244,6 +244,7 @@ struct snd_card *snd_card_new(int idx, const char *id,
			 struct module *module, int extra_size);
int snd_card_disconnect(struct snd_card *card);
int snd_card_free(struct snd_card *card);
int snd_card_free_when_closed(struct snd_card *card);
int snd_card_free_in_thread(struct snd_card *card);
int snd_card_register(struct snd_card *card);
int snd_card_info_init(void);
+0 −1
Original line number Diff line number Diff line
@@ -129,7 +129,6 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer);
int snd_timer_global_free(struct snd_timer *timer);
int snd_timer_global_register(struct snd_timer *timer);
int snd_timer_global_unregister(struct snd_timer *timer);

int snd_timer_open(struct snd_timer_instance **ti, char *owner, struct snd_timer_id *tid, unsigned int slave_id);
int snd_timer_close(struct snd_timer_instance *timeri);
+9 −18
Original line number Diff line number Diff line
@@ -1375,6 +1375,11 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
	struct snd_card *card = device->device_data;
	struct list_head *flist;
	struct snd_ctl_file *ctl;
	int err, cardnum;

	snd_assert(card != NULL, return -ENXIO);
	cardnum = card->number;
	snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);

	down_read(&card->controls_rwsem);
	list_for_each(flist, &card->ctl_files) {
@@ -1383,6 +1388,10 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
		kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
	}
	up_read(&card->controls_rwsem);

	if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL,
					 card, -1)) < 0)
		return err;
	return 0;
}

@@ -1403,23 +1412,6 @@ static int snd_ctl_dev_free(struct snd_device *device)
	return 0;
}

/*
 * de-registration of the control device
 */
static int snd_ctl_dev_unregister(struct snd_device *device)
{
	struct snd_card *card = device->device_data;
	int err, cardnum;

	snd_assert(card != NULL, return -ENXIO);
	cardnum = card->number;
	snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
	if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL,
					 card, -1)) < 0)
		return err;
	return snd_ctl_dev_free(device);
}

/*
 * create control core:
 * called from init.c
@@ -1430,7 +1422,6 @@ int snd_ctl_create(struct snd_card *card)
		.dev_free = snd_ctl_dev_free,
		.dev_register =	snd_ctl_dev_register,
		.dev_disconnect = snd_ctl_dev_disconnect,
		.dev_unregister = snd_ctl_dev_unregister
	};

	snd_assert(card != NULL, return -ENXIO);
+9 −11
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ EXPORT_SYMBOL(snd_device_new);
 * @device_data: the data pointer to release
 *
 * Removes the device from the list on the card and invokes the
 * callback, dev_unregister or dev_free, corresponding to the state.
 * callbacks, dev_disconnect and dev_free, corresponding to the state.
 * Then release the device.
 *
 * Returns zero if successful, or a negative error code on failure or if the
@@ -90,17 +90,15 @@ int snd_device_free(struct snd_card *card, void *device_data)
			continue;
		/* unlink */
		list_del(&dev->list);
		if ((dev->state == SNDRV_DEV_REGISTERED ||
		     dev->state == SNDRV_DEV_DISCONNECTED) &&
		    dev->ops->dev_unregister) {
			if (dev->ops->dev_unregister(dev))
				snd_printk(KERN_ERR "device unregister failure\n");
		} else {
		if (dev->state == SNDRV_DEV_REGISTERED &&
		    dev->ops->dev_disconnect)
			if (dev->ops->dev_disconnect(dev))
				snd_printk(KERN_ERR
					   "device disconnect failure\n");
		if (dev->ops->dev_free) {
			if (dev->ops->dev_free(dev))
				snd_printk(KERN_ERR "device free failure\n");
		}
		}
		kfree(dev);
		return 0;
	}
+5 −5
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ static DEFINE_MUTEX(register_mutex);
static int snd_hwdep_free(struct snd_hwdep *hwdep);
static int snd_hwdep_dev_free(struct snd_device *device);
static int snd_hwdep_dev_register(struct snd_device *device);
static int snd_hwdep_dev_unregister(struct snd_device *device);
static int snd_hwdep_dev_disconnect(struct snd_device *device);


static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device)
@@ -353,7 +353,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,
	static struct snd_device_ops ops = {
		.dev_free = snd_hwdep_dev_free,
		.dev_register = snd_hwdep_dev_register,
		.dev_unregister = snd_hwdep_dev_unregister
		.dev_disconnect = snd_hwdep_dev_disconnect,
	};

	snd_assert(rhwdep != NULL, return -EINVAL);
@@ -439,7 +439,7 @@ static int snd_hwdep_dev_register(struct snd_device *device)
	return 0;
}

static int snd_hwdep_dev_unregister(struct snd_device *device)
static int snd_hwdep_dev_disconnect(struct snd_device *device)
{
	struct snd_hwdep *hwdep = device->device_data;

@@ -454,9 +454,9 @@ static int snd_hwdep_dev_unregister(struct snd_device *device)
		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(&hwdep->list);
	list_del_init(&hwdep->list);
	mutex_unlock(&register_mutex);
	return snd_hwdep_free(hwdep);
	return 0;
}

#ifdef CONFIG_PROC_FS
Loading