summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2012-04-03 20:10:08 +0000
committerShaun Ruffell <sruffell@digium.com>2012-04-03 20:10:08 +0000
commite82b302fcd78f7265a086220d017042806cf2869 (patch)
treed1855dd67a3384a9524736d4ff6cdc5bd55d7de1
parent3625c5dc5d694ffc3795b5f46c3b0e97686374e9 (diff)
dahdi_dynamic: Remove calls to __module_get().
The board drivers are the ones calling the unregister function, and therefore we do not need to worry about them unloading while calling the destroy callback. When destroying spans with the ioctl, replace __module_get() with try_module_get. This avoids hitting a BUG in module_get on kernel versions < 2.6.29. ALSO move the call to try_module_get out of the dahdi_dynamic_release function and into destroy. This way if the destroy callback isn't called because the dynamic driver is unloading the dynamic device can be left on the list to be cleaned up by the dahdi_dynamic_unregister_driver function(). Signed-off-by: Shaun Ruffell <sruffell@digium.com> Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10624 git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.6@10629 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/dahdi_dynamic.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/drivers/dahdi/dahdi_dynamic.c b/drivers/dahdi/dahdi_dynamic.c
index 832e283..ba6b68e 100644
--- a/drivers/dahdi/dahdi_dynamic.c
+++ b/drivers/dahdi/dahdi_dynamic.c
@@ -385,16 +385,6 @@ static void dahdi_dynamic_release(struct kref *kref)
WARN_ON(test_bit(DAHDI_FLAGBIT_REGISTERED, &d->span.flags));
- if (d->pvt) {
- if (d->driver && d->driver->destroy) {
- __module_get(d->driver->owner);
- d->driver->destroy(d);
- module_put(d->driver->owner);
- } else {
- WARN_ON(1);
- }
- }
-
kfree(d->msgbuf);
for (x = 0; x < d->span.channels; x++)
@@ -470,6 +460,24 @@ static int _destroy_dynamic(struct dahdi_dynamic_span *dds)
return -EBUSY;
}
+ if (d->pvt) {
+ if (d->driver && d->driver->destroy) {
+ if (!try_module_get(d->driver->owner)) {
+ /* The driver for this device is in the
+ * process of unloading. Leave this dynamic on
+ * the list so it's cleaned up when the driver
+ * unregisters. */
+ dynamic_put(d);
+ return -ENXIO;
+ }
+ d->driver->destroy(d);
+ module_put(d->driver->owner);
+ } else {
+ WARN_ON(1);
+ }
+ d->pvt = NULL;
+ }
+
dahdi_unregister_device(d->ddev);
spin_lock_irqsave(&dspan_lock, flags);
@@ -767,19 +775,17 @@ void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *dri)
list_for_each_entry_safe(d, n, &dspan_list, list) {
if (d->driver == dri) {
if (d->pvt) {
- if (d->driver && d->driver->destroy) {
- __module_get(d->driver->owner);
+ if (d->driver && d->driver->destroy)
d->driver->destroy(d);
- module_put(d->driver->owner);
- } else {
+ else
WARN_ON(1);
- }
}
dahdi_unregister_device(d->ddev);
spin_lock_irqsave(&dspan_lock, flags);
list_del_rcu(&d->list);
spin_unlock_irqrestore(&dspan_lock, flags);
synchronize_rcu();
+ d->driver = NULL;
dynamic_put(d);
}
}