mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	ALSA: core: Remove child proc file elements recursively
This patch changes the way to manage the resource release of proc files: namely, let snd_info_free_entry() freeing the whole children. This makes it us possible to drop the snd_device_*() management. Then snd_card_proc_new() becomes merely a wrapper to snd_info_create_card_entry(). Together with this change, now you need to call snd_info_free_entry() for a proc entry created via snd_card_proc_new(), while it was freed via snd_device_free() beforehand. Acked-by: Jaroslav Kysela <perex@perex.cz> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									886364f679
								
							
						
					
					
						commit
						c560a6797e
					
				
					 3 changed files with 21 additions and 69 deletions
				
			
		| 
						 | 
				
			
			@ -24,6 +24,7 @@
 | 
			
		|||
 | 
			
		||||
#include <linux/poll.h>
 | 
			
		||||
#include <linux/seq_file.h>
 | 
			
		||||
#include <sound/core.h>
 | 
			
		||||
 | 
			
		||||
/* buffer for information */
 | 
			
		||||
struct snd_info_buffer {
 | 
			
		||||
| 
						 | 
				
			
			@ -146,8 +147,12 @@ void snd_info_card_id_change(struct snd_card *card);
 | 
			
		|||
int snd_info_register(struct snd_info_entry *entry);
 | 
			
		||||
 | 
			
		||||
/* for card drivers */
 | 
			
		||||
int snd_card_proc_new(struct snd_card *card, const char *name,
 | 
			
		||||
		      struct snd_info_entry **entryp);
 | 
			
		||||
static inline int snd_card_proc_new(struct snd_card *card, const char *name,
 | 
			
		||||
				    struct snd_info_entry **entryp)
 | 
			
		||||
{
 | 
			
		||||
	*entryp = snd_info_create_card_entry(card, name, card->proc_root);
 | 
			
		||||
	return *entryp ? 0 : -ENOMEM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void snd_info_set_text_ops(struct snd_info_entry *entry, 
 | 
			
		||||
	void *private_data,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -760,92 +760,39 @@ EXPORT_SYMBOL(snd_info_create_card_entry);
 | 
			
		|||
 | 
			
		||||
static void snd_info_disconnect(struct snd_info_entry *entry)
 | 
			
		||||
{
 | 
			
		||||
	struct list_head *p, *n;
 | 
			
		||||
	struct snd_info_entry *p, *n;
 | 
			
		||||
 | 
			
		||||
	list_for_each_safe(p, n, &entry->children) {
 | 
			
		||||
		snd_info_disconnect(list_entry(p, struct snd_info_entry, list));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (! entry->p)
 | 
			
		||||
	if (!entry->p)
 | 
			
		||||
		return;
 | 
			
		||||
	list_for_each_entry_safe(p, n, &entry->children, list)
 | 
			
		||||
		snd_info_disconnect(p);
 | 
			
		||||
	list_del_init(&entry->list);
 | 
			
		||||
	proc_remove(entry->p);
 | 
			
		||||
	entry->p = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int snd_info_dev_free_entry(struct snd_device *device)
 | 
			
		||||
{
 | 
			
		||||
	struct snd_info_entry *entry = device->device_data;
 | 
			
		||||
	snd_info_free_entry(entry);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int snd_info_dev_register_entry(struct snd_device *device)
 | 
			
		||||
{
 | 
			
		||||
	struct snd_info_entry *entry = device->device_data;
 | 
			
		||||
	return snd_info_register(entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * snd_card_proc_new - create an info entry for the given card
 | 
			
		||||
 * @card: the card instance
 | 
			
		||||
 * @name: the file name
 | 
			
		||||
 * @entryp: the pointer to store the new info entry
 | 
			
		||||
 *
 | 
			
		||||
 * Creates a new info entry and assigns it to the given card.
 | 
			
		||||
 * Unlike snd_info_create_card_entry(), this function registers the
 | 
			
		||||
 * info entry as an ALSA device component, so that it can be
 | 
			
		||||
 * unregistered/released without explicit call.
 | 
			
		||||
 * Also, you don't have to register this entry via snd_info_register(),
 | 
			
		||||
 * since this will be registered by snd_card_register() automatically.
 | 
			
		||||
 *
 | 
			
		||||
 * The parent is assumed as card->proc_root.
 | 
			
		||||
 *
 | 
			
		||||
 * For releasing this entry, use snd_device_free() instead of
 | 
			
		||||
 * snd_info_free_entry(). 
 | 
			
		||||
 *
 | 
			
		||||
 * Return: Zero if successful, or a negative error code on failure.
 | 
			
		||||
 */
 | 
			
		||||
int snd_card_proc_new(struct snd_card *card, const char *name,
 | 
			
		||||
		      struct snd_info_entry **entryp)
 | 
			
		||||
{
 | 
			
		||||
	static struct snd_device_ops ops = {
 | 
			
		||||
		.dev_free = snd_info_dev_free_entry,
 | 
			
		||||
		.dev_register =	snd_info_dev_register_entry,
 | 
			
		||||
		/* disconnect is done via snd_info_card_disconnect() */
 | 
			
		||||
	};
 | 
			
		||||
	struct snd_info_entry *entry;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	entry = snd_info_create_card_entry(card, name, card->proc_root);
 | 
			
		||||
	if (! entry)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	if ((err = snd_device_new(card, SNDRV_DEV_INFO, entry, &ops)) < 0) {
 | 
			
		||||
		snd_info_free_entry(entry);
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	if (entryp)
 | 
			
		||||
		*entryp = entry;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EXPORT_SYMBOL(snd_card_proc_new);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * snd_info_free_entry - release the info entry
 | 
			
		||||
 * @entry: the info entry
 | 
			
		||||
 *
 | 
			
		||||
 * Releases the info entry.  Don't call this after registered.
 | 
			
		||||
 * Releases the info entry.
 | 
			
		||||
 */
 | 
			
		||||
void snd_info_free_entry(struct snd_info_entry * entry)
 | 
			
		||||
{
 | 
			
		||||
	if (entry == NULL)
 | 
			
		||||
	struct snd_info_entry *p, *n;
 | 
			
		||||
 | 
			
		||||
	if (!entry)
 | 
			
		||||
		return;
 | 
			
		||||
	if (entry->p) {
 | 
			
		||||
		mutex_lock(&info_mutex);
 | 
			
		||||
		snd_info_disconnect(entry);
 | 
			
		||||
		mutex_unlock(&info_mutex);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* free all children at first */
 | 
			
		||||
	list_for_each_entry_safe(p, n, &entry->children, list)
 | 
			
		||||
		snd_info_free_entry(p);
 | 
			
		||||
 | 
			
		||||
	kfree(entry->name);
 | 
			
		||||
	if (entry->private_free)
 | 
			
		||||
		entry->private_free(entry);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -592,7 +592,7 @@ static int eld_proc_new(struct hdmi_spec_per_pin *per_pin, int index)
 | 
			
		|||
static void eld_proc_free(struct hdmi_spec_per_pin *per_pin)
 | 
			
		||||
{
 | 
			
		||||
	if (!per_pin->codec->bus->shutdown && per_pin->proc_entry) {
 | 
			
		||||
		snd_device_free(per_pin->codec->card, per_pin->proc_entry);
 | 
			
		||||
		snd_info_free_entry(per_pin->proc_entry);
 | 
			
		||||
		per_pin->proc_entry = NULL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue