From 600a595990b4a3ffb5cdfbe98b532ef5f43e7161 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Tue, 3 Apr 2012 19:44:33 +0000 Subject: 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 git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10624 a0bf4364-ded3-4de4-8d8a-66a801d63aff --- drivers/dahdi/dahdi_dynamic.c | 36 +++++++++++++++++++++--------------- 1 file 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); } } -- cgit v1.2.3