Loading include/sound/seq_kernel.h +4 −0 Original line number Diff line number Diff line Loading @@ -108,9 +108,13 @@ int snd_seq_event_port_detach(int client, int port); #ifdef CONFIG_MODULES void snd_seq_autoload_lock(void); void snd_seq_autoload_unlock(void); void snd_seq_autoload_init(void); #define snd_seq_autoload_exit() snd_seq_autoload_lock() #else #define snd_seq_autoload_lock() #define snd_seq_autoload_unlock() #define snd_seq_autoload_init() #define snd_seq_autoload_exit() #endif #endif /* __SOUND_SEQ_KERNEL_H */ sound/core/seq/seq.c +3 −2 Original line number Diff line number Diff line Loading @@ -86,7 +86,6 @@ static int __init alsa_seq_init(void) { int err; snd_seq_autoload_lock(); if ((err = client_init_data()) < 0) goto error; Loading @@ -110,8 +109,8 @@ static int __init alsa_seq_init(void) if ((err = snd_seq_system_client_init()) < 0) goto error; snd_seq_autoload_init(); error: snd_seq_autoload_unlock(); return err; } Loading @@ -131,6 +130,8 @@ static void __exit alsa_seq_exit(void) /* release event memory */ snd_sequencer_memory_done(); snd_seq_autoload_exit(); } module_init(alsa_seq_init) Loading sound/core/seq/seq_device.c +72 −31 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ MODULE_LICENSE("GPL"); #define DRIVER_LOADED (1<<0) #define DRIVER_REQUESTED (1<<1) #define DRIVER_LOCKED (1<<2) #define DRIVER_REQUESTING (1<<3) struct ops_list { char id[ID_LEN]; /* driver id */ Loading Loading @@ -127,32 +128,26 @@ static void snd_seq_device_info(struct snd_info_entry *entry, #ifdef CONFIG_MODULES /* avoid auto-loading during module_init() */ static int snd_seq_in_init; static atomic_t snd_seq_in_init = ATOMIC_INIT(1); /* blocked as default */ void snd_seq_autoload_lock(void) { snd_seq_in_init++; atomic_inc(&snd_seq_in_init); } void snd_seq_autoload_unlock(void) { snd_seq_in_init--; atomic_dec(&snd_seq_in_init); } #endif void snd_seq_device_load_drivers(void) static void autoload_drivers(void) { #ifdef CONFIG_MODULES /* avoid reentrance */ if (atomic_inc_return(&snd_seq_in_init) == 1) { struct ops_list *ops; /* Calling request_module during module_init() * may cause blocking. */ if (snd_seq_in_init) return; mutex_lock(&ops_mutex); list_for_each_entry(ops, &opslist, list) { if (! (ops->driver & DRIVER_LOADED) && if ((ops->driver & DRIVER_REQUESTING) && !(ops->driver & DRIVER_REQUESTED)) { ops->used++; mutex_unlock(&ops_mutex); Loading @@ -163,6 +158,52 @@ void snd_seq_device_load_drivers(void) } } mutex_unlock(&ops_mutex); } atomic_dec(&snd_seq_in_init); } static void call_autoload(struct work_struct *work) { autoload_drivers(); } static DECLARE_WORK(autoload_work, call_autoload); static void try_autoload(struct ops_list *ops) { if (!ops->driver) { ops->driver |= DRIVER_REQUESTING; schedule_work(&autoload_work); } } static void queue_autoload_drivers(void) { struct ops_list *ops; mutex_lock(&ops_mutex); list_for_each_entry(ops, &opslist, list) try_autoload(ops); mutex_unlock(&ops_mutex); } void snd_seq_autoload_init(void) { atomic_dec(&snd_seq_in_init); #ifdef CONFIG_SND_SEQUENCER_MODULE /* initial autoload only when snd-seq is a module */ queue_autoload_drivers(); #endif } #else #define try_autoload(ops) /* NOP */ #endif void snd_seq_device_load_drivers(void) { #ifdef CONFIG_MODULES queue_autoload_drivers(); flush_work(&autoload_work); #endif } Loading Loading @@ -214,13 +255,14 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, ops->num_devices++; mutex_unlock(&ops->reg_mutex); unlock_driver(ops); if ((err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops)) < 0) { snd_seq_device_free(dev); return err; } try_autoload(ops); unlock_driver(ops); if (result) *result = dev; Loading Loading @@ -318,16 +360,12 @@ int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, entry->init_device == NULL || entry->free_device == NULL) return -EINVAL; snd_seq_autoload_lock(); ops = find_driver(id, 1); if (ops == NULL) { snd_seq_autoload_unlock(); if (ops == NULL) return -ENOMEM; } if (ops->driver & DRIVER_LOADED) { pr_warn("ALSA: seq: driver_register: driver '%s' already exists\n", id); unlock_driver(ops); snd_seq_autoload_unlock(); return -EBUSY; } Loading @@ -344,7 +382,6 @@ int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, mutex_unlock(&ops->reg_mutex); unlock_driver(ops); snd_seq_autoload_unlock(); return 0; } Loading Loading @@ -554,6 +591,9 @@ static int __init alsa_seq_device_init(void) static void __exit alsa_seq_device_exit(void) { #ifdef CONFIG_MODULES cancel_work_sync(&autoload_work); #endif remove_drivers(); #ifdef CONFIG_PROC_FS snd_info_free_entry(info_entry); Loading @@ -570,6 +610,7 @@ EXPORT_SYMBOL(snd_seq_device_new); EXPORT_SYMBOL(snd_seq_device_register_driver); EXPORT_SYMBOL(snd_seq_device_unregister_driver); #ifdef CONFIG_MODULES EXPORT_SYMBOL(snd_seq_autoload_init); EXPORT_SYMBOL(snd_seq_autoload_lock); EXPORT_SYMBOL(snd_seq_autoload_unlock); #endif Loading
include/sound/seq_kernel.h +4 −0 Original line number Diff line number Diff line Loading @@ -108,9 +108,13 @@ int snd_seq_event_port_detach(int client, int port); #ifdef CONFIG_MODULES void snd_seq_autoload_lock(void); void snd_seq_autoload_unlock(void); void snd_seq_autoload_init(void); #define snd_seq_autoload_exit() snd_seq_autoload_lock() #else #define snd_seq_autoload_lock() #define snd_seq_autoload_unlock() #define snd_seq_autoload_init() #define snd_seq_autoload_exit() #endif #endif /* __SOUND_SEQ_KERNEL_H */
sound/core/seq/seq.c +3 −2 Original line number Diff line number Diff line Loading @@ -86,7 +86,6 @@ static int __init alsa_seq_init(void) { int err; snd_seq_autoload_lock(); if ((err = client_init_data()) < 0) goto error; Loading @@ -110,8 +109,8 @@ static int __init alsa_seq_init(void) if ((err = snd_seq_system_client_init()) < 0) goto error; snd_seq_autoload_init(); error: snd_seq_autoload_unlock(); return err; } Loading @@ -131,6 +130,8 @@ static void __exit alsa_seq_exit(void) /* release event memory */ snd_sequencer_memory_done(); snd_seq_autoload_exit(); } module_init(alsa_seq_init) Loading
sound/core/seq/seq_device.c +72 −31 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ MODULE_LICENSE("GPL"); #define DRIVER_LOADED (1<<0) #define DRIVER_REQUESTED (1<<1) #define DRIVER_LOCKED (1<<2) #define DRIVER_REQUESTING (1<<3) struct ops_list { char id[ID_LEN]; /* driver id */ Loading Loading @@ -127,32 +128,26 @@ static void snd_seq_device_info(struct snd_info_entry *entry, #ifdef CONFIG_MODULES /* avoid auto-loading during module_init() */ static int snd_seq_in_init; static atomic_t snd_seq_in_init = ATOMIC_INIT(1); /* blocked as default */ void snd_seq_autoload_lock(void) { snd_seq_in_init++; atomic_inc(&snd_seq_in_init); } void snd_seq_autoload_unlock(void) { snd_seq_in_init--; atomic_dec(&snd_seq_in_init); } #endif void snd_seq_device_load_drivers(void) static void autoload_drivers(void) { #ifdef CONFIG_MODULES /* avoid reentrance */ if (atomic_inc_return(&snd_seq_in_init) == 1) { struct ops_list *ops; /* Calling request_module during module_init() * may cause blocking. */ if (snd_seq_in_init) return; mutex_lock(&ops_mutex); list_for_each_entry(ops, &opslist, list) { if (! (ops->driver & DRIVER_LOADED) && if ((ops->driver & DRIVER_REQUESTING) && !(ops->driver & DRIVER_REQUESTED)) { ops->used++; mutex_unlock(&ops_mutex); Loading @@ -163,6 +158,52 @@ void snd_seq_device_load_drivers(void) } } mutex_unlock(&ops_mutex); } atomic_dec(&snd_seq_in_init); } static void call_autoload(struct work_struct *work) { autoload_drivers(); } static DECLARE_WORK(autoload_work, call_autoload); static void try_autoload(struct ops_list *ops) { if (!ops->driver) { ops->driver |= DRIVER_REQUESTING; schedule_work(&autoload_work); } } static void queue_autoload_drivers(void) { struct ops_list *ops; mutex_lock(&ops_mutex); list_for_each_entry(ops, &opslist, list) try_autoload(ops); mutex_unlock(&ops_mutex); } void snd_seq_autoload_init(void) { atomic_dec(&snd_seq_in_init); #ifdef CONFIG_SND_SEQUENCER_MODULE /* initial autoload only when snd-seq is a module */ queue_autoload_drivers(); #endif } #else #define try_autoload(ops) /* NOP */ #endif void snd_seq_device_load_drivers(void) { #ifdef CONFIG_MODULES queue_autoload_drivers(); flush_work(&autoload_work); #endif } Loading Loading @@ -214,13 +255,14 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, ops->num_devices++; mutex_unlock(&ops->reg_mutex); unlock_driver(ops); if ((err = snd_device_new(card, SNDRV_DEV_SEQUENCER, dev, &dops)) < 0) { snd_seq_device_free(dev); return err; } try_autoload(ops); unlock_driver(ops); if (result) *result = dev; Loading Loading @@ -318,16 +360,12 @@ int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, entry->init_device == NULL || entry->free_device == NULL) return -EINVAL; snd_seq_autoload_lock(); ops = find_driver(id, 1); if (ops == NULL) { snd_seq_autoload_unlock(); if (ops == NULL) return -ENOMEM; } if (ops->driver & DRIVER_LOADED) { pr_warn("ALSA: seq: driver_register: driver '%s' already exists\n", id); unlock_driver(ops); snd_seq_autoload_unlock(); return -EBUSY; } Loading @@ -344,7 +382,6 @@ int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, mutex_unlock(&ops->reg_mutex); unlock_driver(ops); snd_seq_autoload_unlock(); return 0; } Loading Loading @@ -554,6 +591,9 @@ static int __init alsa_seq_device_init(void) static void __exit alsa_seq_device_exit(void) { #ifdef CONFIG_MODULES cancel_work_sync(&autoload_work); #endif remove_drivers(); #ifdef CONFIG_PROC_FS snd_info_free_entry(info_entry); Loading @@ -570,6 +610,7 @@ EXPORT_SYMBOL(snd_seq_device_new); EXPORT_SYMBOL(snd_seq_device_register_driver); EXPORT_SYMBOL(snd_seq_device_unregister_driver); #ifdef CONFIG_MODULES EXPORT_SYMBOL(snd_seq_autoload_init); EXPORT_SYMBOL(snd_seq_autoload_lock); EXPORT_SYMBOL(snd_seq_autoload_unlock); #endif