[svn-commits] sruffell: linux/trunk r9571 - /linux/trunk/drivers/dahdi/dahdi_dynamic.c
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Mon Jan 3 18:25:27 UTC 2011
Author: sruffell
Date: Mon Jan 3 12:25:23 2011
New Revision: 9571
URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=9571
Log:
dahdi_dynamic: Replace usecount and dead members with 'struct kref'
dahdi_dynamic can be converted to use kernel idiomatic reference
counting since DAHDI only supports 2.6.9+ kernels now.
Signed-off-by: Shaun Ruffell <sruffell at digium.com>
Acked-by: Kinsey Moore <kmoore at digium.com>
Modified:
linux/trunk/drivers/dahdi/dahdi_dynamic.c
Modified: linux/trunk/drivers/dahdi/dahdi_dynamic.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/dahdi_dynamic.c?view=diff&rev=9571&r1=9570&r2=9571
==============================================================================
--- linux/trunk/drivers/dahdi/dahdi_dynamic.c (original)
+++ linux/trunk/drivers/dahdi/dahdi_dynamic.c Mon Jan 3 12:25:23 2011
@@ -97,8 +97,7 @@
char addr[40];
char dname[20];
int err;
- int usecount;
- int dead;
+ struct kref kref;
long rxjif;
unsigned short txcnt;
unsigned short rxcnt;
@@ -135,7 +134,7 @@
if (d->timing) {
d->master = 0;
if (!(d->span.alarms & DAHDI_ALARM_RED) &&
- (d->timing < best) && !d->dead) {
+ (d->timing < best)) {
/* If not in alarm and they're
a better timing source, use them */
master = d;
@@ -226,17 +225,15 @@
rcu_read_lock();
list_for_each_entry_rcu(d, &dspan_list, list) {
- if (!d->dead) {
- for (y = 0; y < d->span.channels; y++) {
- struct dahdi_chan *const c = d->span.chans[y];
- /* Echo cancel double buffered data */
- dahdi_ec_chunk(c, c->readchunk, c->writechunk);
- }
- dahdi_receive(&d->span);
- dahdi_transmit(&d->span);
- /* Handle all transmissions now */
- dahdi_dynamic_sendmessage(d);
- }
+ for (y = 0; y < d->span.channels; y++) {
+ struct dahdi_chan *const c = d->span.chans[y];
+ /* Echo cancel double buffered data */
+ dahdi_ec_chunk(c, c->readchunk, c->writechunk);
+ }
+ dahdi_receive(&d->span);
+ dahdi_transmit(&d->span);
+ /* Handle all transmissions now */
+ dahdi_dynamic_sendmessage(d);
}
list_for_each_entry_rcu(drv, &driver_list, list) {
@@ -399,29 +396,47 @@
dahdi_dynamic_run();
}
-static void dynamic_destroy(struct dahdi_dynamic *d)
-{
+/**
+ * dahdi_dynamic_release() - Free the memory associated with the dahdi_dynamic.
+ * @kref: Pointer to kref embedded in dahdi_dynamic structure.
+ *
+ */
+static void dahdi_dynamic_release(struct kref *kref)
+{
+ struct dahdi_dynamic *d = container_of(kref, struct dahdi_dynamic,
+ kref);
unsigned int x;
- /* Unregister span if appropriate */
- if (test_bit(DAHDI_FLAGBIT_REGISTERED, &d->span.flags))
- dahdi_unregister(&d->span);
-
- /* Destroy the pvt stuff if there */
- if (d->pvt)
- d->driver->destroy(d->pvt);
-
- /* Free message buffer if appropriate */
+ WARN_ON(test_bit(DAHDI_FLAGBIT_REGISTERED, &d->span.flags));
+
+ if (d->pvt) {
+ if (d->driver && d->driver->destroy)
+ d->driver->destroy(d->pvt);
+ else
+ WARN_ON(1);
+ }
+
kfree(d->msgbuf);
- /* Free channels */
for (x = 0; x < d->span.channels; x++)
kfree(d->chans[x]);
- /* Free d */
kfree(d);
-
- checkmaster();
+}
+
+static inline int dynamic_put(struct dahdi_dynamic *d)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
+ kref_put(&d->kref, dahdi_dynamic_release);
+ return 1;
+#else
+ return kref_put(&d->kref, dahdi_dynamic_release);
+#endif
+}
+
+static inline void dynamic_get(struct dahdi_dynamic *d)
+{
+ kref_get(&d->kref);
}
static struct dahdi_dynamic *find_dynamic(struct dahdi_dynamic_span *dds)
@@ -432,6 +447,7 @@
list_for_each_entry_rcu(d, &dspan_list, list) {
if (!strcmp(d->dname, dds->driver) &&
!strcmp(d->addr, dds->addr)) {
+ dynamic_get(d);
found = d;
break;
}
@@ -467,19 +483,20 @@
if (unlikely(!d))
return -EINVAL;
- if (d->usecount) {
- printk(KERN_NOTICE "Attempt to destroy dynamic span while it is in use\n");
+ if (atomic_read(&d->kref.refcount) > 1)
return -EBUSY;
- }
+
+ dahdi_unregister(&d->span);
spin_lock_irqsave(&dspan_lock, flags);
list_del_rcu(&d->list);
spin_unlock_irqrestore(&dspan_lock, flags);
synchronize_rcu();
- /* Destroy it */
- dynamic_destroy(d);
-
+ /* One since we've removed the item from the list... */
+ dynamic_put(d);
+ /* ...and one for find_dynamic. */
+ dynamic_put(d);
return 0;
}
@@ -492,11 +509,7 @@
static int dahdi_dynamic_open(struct dahdi_chan *chan)
{
struct dahdi_dynamic *d = dynamic_from_span(chan->span);
- if (likely(d)) {
- if (unlikely(d->dead))
- return -ENODEV;
- d->usecount++;
- }
+ dynamic_get(d);
return 0;
}
@@ -508,11 +521,7 @@
static int dahdi_dynamic_close(struct dahdi_chan *chan)
{
struct dahdi_dynamic *d = dynamic_from_span(chan->span);
- if (d) {
- d->usecount--;
- if (d->dead && !d->usecount)
- dynamic_destroy(d);
- }
+ dynamic_put(d);
return 0;
}
@@ -545,20 +554,24 @@
}
d = find_dynamic(dds);
- if (d)
+ if (d) {
+ dynamic_put(d);
return -EEXIST;
-
- /* Allocate memory */
+ }
+
d = kzalloc(sizeof(*d), GFP_KERNEL);
if (!d)
return -ENOMEM;
+ kref_init(&d->kref);
+
for (x = 0; x < dds->numchans; x++) {
d->chans[x] = kzalloc(sizeof(*d->chans[x]), GFP_KERNEL);
if (!d->chans[x]) {
- dynamic_destroy(d);
+ dynamic_put(d);
return -ENOMEM;
}
+ d->span.channels++;
}
/* Allocate message buffer with sample space and header space */
@@ -567,7 +580,7 @@
d->msgbuf = kzalloc(bufsize, GFP_KERNEL);
if (!d->msgbuf) {
- dynamic_destroy(d);
+ dynamic_put(d);
return -ENOMEM;
}
@@ -578,7 +591,6 @@
sprintf(d->span.name, "DYN/%s/%s", dds->driver, dds->addr);
sprintf(d->span.desc, "Dynamic '%s' span at '%s'",
dds->driver, dds->addr);
- d->span.channels = dds->numchans;
d->span.deflaw = DAHDI_LAW_MULAW;
d->span.flags |= DAHDI_FLAG_RBS;
d->span.chans = d->chans;
@@ -617,7 +629,7 @@
if (!dtd) {
printk(KERN_NOTICE "No such driver '%s' for dynamic span\n",
dds->driver);
- dynamic_destroy(d);
+ dynamic_put(d);
return -EINVAL;
}
@@ -626,7 +638,7 @@
if (!d->pvt) {
printk(KERN_NOTICE "Driver '%s' (%s) rejected address '%s'\n",
dtd->name, dtd->desc, d->addr);
- /* Creation failed */
+ dynamic_put(d);
return -EINVAL;
}
@@ -637,18 +649,21 @@
if (dahdi_register(&d->span, 0)) {
printk(KERN_NOTICE "Unable to register span '%s'\n",
d->span.name);
- dynamic_destroy(d);
+ dynamic_put(d);
return -EINVAL;
}
+ x = d->span.spanno;
+
+ /* Transfer our reference to the dspan_list. Do not touch d after
+ * this point. It also must remain on the list while registered. */
spin_lock_irqsave(&dspan_lock, flags);
list_add_rcu(&d->list, &dspan_list);
spin_unlock_irqrestore(&dspan_lock, flags);
checkmaster();
- /* All done */
- return d->span.spanno;
+ return x;
}
@@ -733,11 +748,7 @@
list_del_rcu(&d->list);
spin_unlock_irqrestore(&dspan_lock, flags);
synchronize_rcu();
-
- if (!d->usecount)
- dynamic_destroy(d);
- else
- d->dead = 1;
+ dynamic_put(d);
}
}
}
More information about the svn-commits
mailing list