diff options
-rw-r--r-- | drivers/dahdi/dahdi-base.c | 47 | ||||
-rw-r--r-- | drivers/dahdi/dahdi_dynamic.c | 12 | ||||
-rw-r--r-- | include/dahdi/kernel.h | 7 |
3 files changed, 49 insertions, 17 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index e829e6c..d006799 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -121,7 +121,6 @@ EXPORT_SYMBOL(dahdi_qevent_nolock); EXPORT_SYMBOL(dahdi_qevent_lock); EXPORT_SYMBOL(dahdi_hooksig); EXPORT_SYMBOL(dahdi_alarm_notify); -EXPORT_SYMBOL(dahdi_set_dynamic_ioctl); EXPORT_SYMBOL(dahdi_hdlc_abort); EXPORT_SYMBOL(dahdi_hdlc_finish); EXPORT_SYMBOL(dahdi_hdlc_getbuf); @@ -4405,12 +4404,14 @@ static int dahdi_common_ioctl(struct file *file, unsigned int cmd, return 0; } -static int (*dahdi_dynamic_ioctl)(unsigned int cmd, unsigned long data); - -void dahdi_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)) +static const struct dahdi_dynamic_ops *dahdi_dynamic_ops; +void dahdi_set_dynamic_ops(const struct dahdi_dynamic_ops *ops) { - dahdi_dynamic_ioctl = func; + mutex_lock(®istration_mutex); + dahdi_dynamic_ops = ops; + mutex_unlock(®istration_mutex); } +EXPORT_SYMBOL(dahdi_set_dynamic_ops); static int (*dahdi_hpec_ioctl)(unsigned int cmd, unsigned long data); @@ -5129,6 +5130,33 @@ static int dahdi_ioctl_maint(unsigned long data) return 0; } +static int dahdi_ioctl_dynamic(unsigned int cmd, unsigned long data) +{ + bool tried_load = false; + int res; + +retry_check: + mutex_lock(®istration_mutex); + if (!dahdi_dynamic_ops) { + mutex_unlock(®istration_mutex); + if (tried_load) + return -ENOSYS; + + request_module("dahdi_dynamic"); + tried_load = true; + goto retry_check; + } + if (!try_module_get(dahdi_dynamic_ops->owner)) { + mutex_unlock(®istration_mutex); + return -ENOSYS; + } + mutex_unlock(®istration_mutex); + + res = dahdi_dynamic_ops->ioctl(cmd, data); + module_put(dahdi_dynamic_ops->owner); + return res; +} + static int dahdi_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long data) { @@ -5163,14 +5191,7 @@ dahdi_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long data) return dahdi_ioctl_maint(data); case DAHDI_DYNAMIC_CREATE: case DAHDI_DYNAMIC_DESTROY: - if (dahdi_dynamic_ioctl) { - return dahdi_dynamic_ioctl(cmd, data); - } else { - request_module("dahdi_dynamic"); - if (dahdi_dynamic_ioctl) - return dahdi_dynamic_ioctl(cmd, data); - } - return -ENOSYS; + return dahdi_ioctl_dynamic(cmd, data); case DAHDI_EC_LICENSE_CHALLENGE: case DAHDI_EC_LICENSE_RESPONSE: if (dahdi_hpec_ioctl) { diff --git a/drivers/dahdi/dahdi_dynamic.c b/drivers/dahdi/dahdi_dynamic.c index 79c8bba..602ebe9 100644 --- a/drivers/dahdi/dahdi_dynamic.c +++ b/drivers/dahdi/dahdi_dynamic.c @@ -818,10 +818,13 @@ static void check_for_red_alarm(unsigned long ignored) mod_timer(&alarmcheck, jiffies + 1 * HZ); } +static const struct dahdi_dynamic_ops dahdi_dynamic_ops = { + .owner = THIS_MODULE, + .ioctl = dahdi_dynamic_ioctl, +}; + static int dahdi_dynamic_init(void) { - dahdi_set_dynamic_ioctl(dahdi_dynamic_ioctl); - /* Start process to check for RED ALARM */ init_timer(&alarmcheck); alarmcheck.expires = 0; @@ -832,19 +835,22 @@ static int dahdi_dynamic_init(void) #ifdef ENABLE_TASKLETS tasklet_init(&dahdi_dynamic_tlet, dahdi_dynamic_tasklet, 0); #endif + dahdi_set_dynamic_ops(&dahdi_dynamic_ops); + printk(KERN_INFO "DAHDI Dynamic Span support LOADED\n"); return 0; } static void dahdi_dynamic_cleanup(void) { + dahdi_set_dynamic_ops(NULL); + #ifdef ENABLE_TASKLETS if (taskletpending) { tasklet_disable(&dahdi_dynamic_tlet); tasklet_kill(&dahdi_dynamic_tlet); } #endif - dahdi_set_dynamic_ioctl(NULL); del_timer(&alarmcheck); printk(KERN_INFO "DAHDI Dynamic Span support unloaded\n"); } diff --git a/include/dahdi/kernel.h b/include/dahdi/kernel.h index 8097cb3..9922f11 100644 --- a/include/dahdi/kernel.h +++ b/include/dahdi/kernel.h @@ -1260,8 +1260,13 @@ extern u_char __dahdi_lin2mu[16384]; extern u_char __dahdi_lin2a[16384]; #endif +struct dahdi_dynamic_ops { + struct module *owner; + int (*ioctl)(unsigned int cmd, unsigned long data); +}; + /*! \brief Used by dynamic DAHDI -- don't use directly */ -void dahdi_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)); +void dahdi_set_dynamic_ops(const struct dahdi_dynamic_ops *ops); /*! \brief Used by DAHDI HPEC module -- don't use directly */ void dahdi_set_hpec_ioctl(int (*func)(unsigned int cmd, unsigned long data)); |