Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: Use standard device refcount for card accounting

Drop the own refcount but use the standard device refcounting via
get_device() and put_device(). Introduce a new completion to snd_card
instead of the wait queue for syncing the last release, which is used
in snd_card_free().

Signed-off-by: Takashi Iwai <tiwai@suse.de>

+25 -49
+3 -4
include/sound/core.h
··· 42 42 /* forward declarations */ 43 43 struct pci_dev; 44 44 struct module; 45 + struct completion; 45 46 46 47 /* device allocation stuff */ 47 48 ··· 131 130 state */ 132 131 spinlock_t files_lock; /* lock the files for this card */ 133 132 int shutdown; /* this card is going down */ 134 - int free_on_last_close; /* free in context of file_release */ 135 - wait_queue_head_t shutdown_sleep; 136 - atomic_t refcount; /* refcount for disconnection */ 133 + struct completion *release_completion; 137 134 struct device *dev; /* device assigned to this card */ 138 135 struct device card_dev; /* cardX object for sysfs */ 139 136 bool registered; /* card_dev is registered? */ ··· 305 306 int snd_component_add(struct snd_card *card, const char *component); 306 307 int snd_card_file_add(struct snd_card *card, struct file *file); 307 308 int snd_card_file_remove(struct snd_card *card, struct file *file); 308 - void snd_card_unref(struct snd_card *card); 309 + #define snd_card_unref(card) put_device(&(card)->card_dev) 309 310 310 311 #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) 311 312
+20 -43
sound/core/init.c
··· 28 28 #include <linux/time.h> 29 29 #include <linux/ctype.h> 30 30 #include <linux/pm.h> 31 + #include <linux/completion.h> 31 32 32 33 #include <sound/core.h> 33 34 #include <sound/control.h> ··· 236 235 INIT_LIST_HEAD(&card->ctl_files); 237 236 spin_lock_init(&card->files_lock); 238 237 INIT_LIST_HEAD(&card->files_list); 239 - init_waitqueue_head(&card->shutdown_sleep); 240 - atomic_set(&card->refcount, 0); 241 238 #ifdef CONFIG_PM 242 239 mutex_init(&card->power_lock); 243 240 init_waitqueue_head(&card->power_sleep); ··· 473 474 snd_printk(KERN_WARNING "unable to free card info\n"); 474 475 /* Not fatal error */ 475 476 } 477 + if (card->release_completion) 478 + complete(card->release_completion); 476 479 kfree(card); 477 480 return 0; 478 481 } 479 482 480 - /** 481 - * snd_card_unref - release the reference counter 482 - * @card: the card instance 483 - * 484 - * Decrements the reference counter. When it reaches to zero, wake up 485 - * the sleeper and call the destructor if needed. 486 - */ 487 - void snd_card_unref(struct snd_card *card) 488 - { 489 - if (atomic_dec_and_test(&card->refcount)) { 490 - wake_up(&card->shutdown_sleep); 491 - if (card->free_on_last_close) 492 - put_device(&card->card_dev); 493 - } 494 - } 495 - EXPORT_SYMBOL(snd_card_unref); 496 - 497 483 int snd_card_free_when_closed(struct snd_card *card) 498 - { 499 - int ret; 500 - 501 - atomic_inc(&card->refcount); 502 - ret = snd_card_disconnect(card); 503 - if (ret) { 504 - atomic_dec(&card->refcount); 505 - return ret; 506 - } 507 - 508 - card->free_on_last_close = 1; 509 - if (atomic_dec_and_test(&card->refcount)) 510 - put_device(&card->card_dev); 511 - return 0; 512 - } 513 - 514 - EXPORT_SYMBOL(snd_card_free_when_closed); 515 - 516 - int snd_card_free(struct snd_card *card) 517 484 { 518 485 int ret = snd_card_disconnect(card); 519 486 if (ret) 520 487 return ret; 521 - 522 - /* wait, until all devices are ready for the free operation */ 523 - wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); 524 488 put_device(&card->card_dev); 525 489 return 0; 526 490 } 491 + EXPORT_SYMBOL(snd_card_free_when_closed); 527 492 493 + int snd_card_free(struct snd_card *card) 494 + { 495 + struct completion released; 496 + int ret; 497 + 498 + init_completion(&released); 499 + card->release_completion = &released; 500 + ret = snd_card_free_when_closed(card); 501 + if (ret) 502 + return ret; 503 + /* wait, until all devices are ready for the free operation */ 504 + wait_for_completion(&released); 505 + return 0; 506 + } 528 507 EXPORT_SYMBOL(snd_card_free); 529 508 530 509 /* retrieve the last word of shortname or longname */ ··· 909 932 return -ENODEV; 910 933 } 911 934 list_add(&mfile->list, &card->files_list); 912 - atomic_inc(&card->refcount); 935 + get_device(&card->card_dev); 913 936 spin_unlock(&card->files_lock); 914 937 return 0; 915 938 } ··· 952 975 return -ENOENT; 953 976 } 954 977 kfree(found); 955 - snd_card_unref(card); 978 + put_device(&card->card_dev); 956 979 return 0; 957 980 } 958 981
+1 -1
sound/core/sound.c
··· 118 118 if (mreg && mreg->type == type) { 119 119 private_data = mreg->private_data; 120 120 if (private_data && mreg->card_ptr) 121 - atomic_inc(&mreg->card_ptr->refcount); 121 + get_device(&mreg->card_ptr->card_dev); 122 122 } else 123 123 private_data = NULL; 124 124 mutex_unlock(&sound_mutex);
+1 -1
sound/core/sound_oss.c
··· 55 55 if (mreg && mreg->type == type) { 56 56 private_data = mreg->private_data; 57 57 if (private_data && mreg->card_ptr) 58 - atomic_inc(&mreg->card_ptr->refcount); 58 + get_device(&mreg->card_ptr->card_dev); 59 59 } else 60 60 private_data = NULL; 61 61 mutex_unlock(&sound_oss_mutex);