X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=sound%2Fcore%2Finfo.c;h=c67773ad9298076e701ea161b5f7c9ce3560da1e;hb=bacac545f10f2bf6e5ceff0d8e2b82dfc493602a;hp=10c1772bf3ea3dbe9ff06960f945d06457112a35;hpb=6581f4e74d8541dd7d579f64e94822622cbb1654;p=safe%2Fjmp%2Flinux-2.6 diff --git a/sound/core/info.c b/sound/core/info.c index 10c1772..c67773a 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -1,6 +1,6 @@ /* * Information interface for ALSA driver - * Copyright (c) by Jaroslav Kysela + * Copyright (c) by Jaroslav Kysela * * * This program is free software; you can redistribute it and/or modify @@ -19,9 +19,9 @@ * */ -#include #include #include +#include #include #include #include @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -79,6 +78,7 @@ struct snd_info_private_data { static int snd_info_version_init(void); static int snd_info_version_done(void); +static void snd_info_disconnect(struct snd_info_entry *entry); /* resize the proc r/w buffer */ @@ -120,7 +120,10 @@ int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...) len = buffer->len - buffer->size; va_start(args, fmt); for (;;) { - res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, args); + va_list ap; + va_copy(ap, args); + res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, ap); + va_end(ap); if (res < len) break; err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE); @@ -175,15 +178,15 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) switch (entry->content) { case SNDRV_INFO_CONTENT_TEXT: switch (orig) { - case 0: /* SEEK_SET */ + case SEEK_SET: file->f_pos = offset; ret = file->f_pos; goto out; - case 1: /* SEEK_CUR */ + case SEEK_CUR: file->f_pos += offset; ret = file->f_pos; goto out; - case 2: /* SEEK_END */ + case SEEK_END: default: ret = -EINVAL; goto out; @@ -305,7 +308,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) mutex_lock(&info_mutex); p = PDE(inode); entry = p == NULL ? NULL : (struct snd_info_entry *)p->data; - if (entry == NULL || entry->disconnected) { + if (entry == NULL || ! entry->p) { mutex_unlock(&info_mutex); return -ENODEV; } @@ -485,7 +488,7 @@ static long snd_info_entry_ioctl(struct file *file, unsigned int cmd, static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma) { - struct inode *inode = file->f_dentry->d_inode; + struct inode *inode = file->f_path.dentry->d_inode; struct snd_info_private_data *data; struct snd_info_entry *entry; @@ -504,7 +507,7 @@ static int snd_info_entry_mmap(struct file *file, struct vm_area_struct *vma) return -ENXIO; } -static struct file_operations snd_info_entry_operations = +static const struct file_operations snd_info_entry_operations = { .owner = THIS_MODULE, .llseek = snd_info_entry_llseek, @@ -542,7 +545,7 @@ int __init snd_info_init(void) { struct proc_dir_entry *p; - p = snd_create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, &proc_root); + p = snd_create_proc_entry("asound", S_IFDIR | S_IRUGO | S_IXUGO, NULL); if (p == NULL) return -ENOMEM; snd_proc_root = p; @@ -587,12 +590,12 @@ int __exit snd_info_done(void) snd_info_version_done(); if (snd_proc_root) { #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) - snd_info_unregister(snd_seq_root); + snd_info_free_entry(snd_seq_root); #endif #ifdef CONFIG_SND_OSSEMUL - snd_info_unregister(snd_oss_root); + snd_info_free_entry(snd_oss_root); #endif - snd_remove_proc_entry(&proc_root, snd_proc_root); + snd_remove_proc_entry(NULL, snd_proc_root); } return 0; } @@ -649,17 +652,28 @@ int snd_info_card_register(struct snd_card *card) * de-register the card proc file * called from init.c */ -int snd_info_card_free(struct snd_card *card) +void snd_info_card_disconnect(struct snd_card *card) { - snd_assert(card != NULL, return -ENXIO); + snd_assert(card != NULL, return); + mutex_lock(&info_mutex); if (card->proc_root_link) { snd_remove_proc_entry(snd_proc_root, card->proc_root_link); card->proc_root_link = NULL; } - if (card->proc_root) { - snd_info_unregister(card->proc_root); - card->proc_root = NULL; - } + if (card->proc_root) + snd_info_disconnect(card->proc_root); + mutex_unlock(&info_mutex); +} + +/* + * release the card proc file resources + * called from init.c + */ +int snd_info_card_free(struct snd_card *card) +{ + snd_assert(card != NULL, return -ENXIO); + snd_info_free_entry(card->proc_root); + card->proc_root = NULL; return 0; } @@ -768,6 +782,8 @@ static struct snd_info_entry *snd_info_create_entry(const char *name) entry->mode = S_IFREG | S_IRUGO; entry->content = SNDRV_INFO_CONTENT_TEXT; mutex_init(&entry->access); + INIT_LIST_HEAD(&entry->children); + INIT_LIST_HEAD(&entry->list); return entry; } @@ -820,30 +836,35 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, EXPORT_SYMBOL(snd_info_create_card_entry); -static int snd_info_dev_free_entry(struct snd_device *device) +static void snd_info_disconnect(struct snd_info_entry *entry) { - struct snd_info_entry *entry = device->device_data; - snd_info_free_entry(entry); - return 0; -} + struct list_head *p, *n; + struct proc_dir_entry *root; -static int snd_info_dev_register_entry(struct snd_device *device) -{ - struct snd_info_entry *entry = device->device_data; - return snd_info_register(entry); + list_for_each_safe(p, n, &entry->children) { + snd_info_disconnect(list_entry(p, struct snd_info_entry, list)); + } + + if (! entry->p) + return; + list_del_init(&entry->list); + root = entry->parent == NULL ? snd_proc_root : entry->parent->p; + snd_assert(root, return); + snd_remove_proc_entry(root, entry->p); + entry->p = NULL; } -static int snd_info_dev_disconnect_entry(struct snd_device *device) +static int snd_info_dev_free_entry(struct snd_device *device) { struct snd_info_entry *entry = device->device_data; - entry->disconnected = 1; + snd_info_free_entry(entry); return 0; } -static int snd_info_dev_unregister_entry(struct snd_device *device) +static int snd_info_dev_register_entry(struct snd_device *device) { struct snd_info_entry *entry = device->device_data; - return snd_info_unregister(entry); + return snd_info_register(entry); } /** @@ -872,8 +893,7 @@ int snd_card_proc_new(struct snd_card *card, const char *name, static struct snd_device_ops ops = { .dev_free = snd_info_dev_free_entry, .dev_register = snd_info_dev_register_entry, - .dev_disconnect = snd_info_dev_disconnect_entry, - .dev_unregister = snd_info_dev_unregister_entry + /* disconnect is done via snd_info_card_disconnect() */ }; struct snd_info_entry *entry; int err; @@ -902,6 +922,11 @@ void snd_info_free_entry(struct snd_info_entry * entry) { if (entry == NULL) return; + if (entry->p) { + mutex_lock(&info_mutex); + snd_info_disconnect(entry); + mutex_unlock(&info_mutex); + } kfree(entry->name); if (entry->private_free) entry->private_free(entry); @@ -936,38 +961,14 @@ int snd_info_register(struct snd_info_entry * entry) p->size = entry->size; p->data = entry; entry->p = p; + if (entry->parent) + list_add_tail(&entry->list, &entry->parent->children); mutex_unlock(&info_mutex); return 0; } EXPORT_SYMBOL(snd_info_register); -/** - * snd_info_unregister - de-register the info entry - * @entry: the info entry - * - * De-registers the info entry and releases the instance. - * - * Returns zero if successful, or a negative error code on failure. - */ -int snd_info_unregister(struct snd_info_entry * entry) -{ - struct proc_dir_entry *root; - - if (! entry) - return 0; - snd_assert(entry->p != NULL, return -ENXIO); - root = entry->parent == NULL ? snd_proc_root : entry->parent->p; - snd_assert(root, return -ENXIO); - mutex_lock(&info_mutex); - snd_remove_proc_entry(root, entry->p); - mutex_unlock(&info_mutex); - snd_info_free_entry(entry); - return 0; -} - -EXPORT_SYMBOL(snd_info_unregister); - /* */ @@ -1000,8 +1001,7 @@ static int __init snd_info_version_init(void) static int __exit snd_info_version_done(void) { - if (snd_info_version_entry) - snd_info_unregister(snd_info_version_entry); + snd_info_free_entry(snd_info_version_entry); return 0; }