summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2012-04-03 19:44:33 +0000
committerShaun Ruffell <sruffell@digium.com>2012-04-03 19:44:33 +0000
commit600a595990b4a3ffb5cdfbe98b532ef5f43e7161 (patch)
treeaaf4fdff744737db22ab97f32f7aa0bf88aa9fa4
parent5a9e9d4f8b7c38a9fff9e4c2c4499dcdee82d2e6 (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> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10624 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 602ebe9..4be55ae 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++)
@@ -465,6 +455,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);
@@ -762,19 +770,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);
}
}