summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/dahdi/dahdi-base.c47
-rw-r--r--drivers/dahdi/dahdi_dynamic.c12
-rw-r--r--include/dahdi/kernel.h7
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(&registration_mutex);
+ dahdi_dynamic_ops = ops;
+ mutex_unlock(&registration_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(&registration_mutex);
+ if (!dahdi_dynamic_ops) {
+ mutex_unlock(&registration_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(&registration_mutex);
+ return -ENOSYS;
+ }
+ mutex_unlock(&registration_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));