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@digium.com> Acked-by: Kinsey Moore <kmoore@digium.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9571 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
parent
7251a7e35a
commit
53fef32a61
@ -97,8 +97,7 @@ struct dahdi_dynamic {
|
|||||||
char addr[40];
|
char addr[40];
|
||||||
char dname[20];
|
char dname[20];
|
||||||
int err;
|
int err;
|
||||||
int usecount;
|
struct kref kref;
|
||||||
int dead;
|
|
||||||
long rxjif;
|
long rxjif;
|
||||||
unsigned short txcnt;
|
unsigned short txcnt;
|
||||||
unsigned short rxcnt;
|
unsigned short rxcnt;
|
||||||
@ -135,7 +134,7 @@ static void checkmaster(void)
|
|||||||
if (d->timing) {
|
if (d->timing) {
|
||||||
d->master = 0;
|
d->master = 0;
|
||||||
if (!(d->span.alarms & DAHDI_ALARM_RED) &&
|
if (!(d->span.alarms & DAHDI_ALARM_RED) &&
|
||||||
(d->timing < best) && !d->dead) {
|
(d->timing < best)) {
|
||||||
/* If not in alarm and they're
|
/* If not in alarm and they're
|
||||||
a better timing source, use them */
|
a better timing source, use them */
|
||||||
master = d;
|
master = d;
|
||||||
@ -226,7 +225,6 @@ static void __dahdi_dynamic_run(void)
|
|||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
list_for_each_entry_rcu(d, &dspan_list, list) {
|
list_for_each_entry_rcu(d, &dspan_list, list) {
|
||||||
if (!d->dead) {
|
|
||||||
for (y = 0; y < d->span.channels; y++) {
|
for (y = 0; y < d->span.channels; y++) {
|
||||||
struct dahdi_chan *const c = d->span.chans[y];
|
struct dahdi_chan *const c = d->span.chans[y];
|
||||||
/* Echo cancel double buffered data */
|
/* Echo cancel double buffered data */
|
||||||
@ -237,7 +235,6 @@ static void __dahdi_dynamic_run(void)
|
|||||||
/* Handle all transmissions now */
|
/* Handle all transmissions now */
|
||||||
dahdi_dynamic_sendmessage(d);
|
dahdi_dynamic_sendmessage(d);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry_rcu(drv, &driver_list, list) {
|
list_for_each_entry_rcu(drv, &driver_list, list) {
|
||||||
/* Flush any traffic still pending in the driver */
|
/* Flush any traffic still pending in the driver */
|
||||||
@ -399,29 +396,47 @@ void dahdi_dynamic_receive(struct dahdi_span *span, unsigned char *msg, int msgl
|
|||||||
dahdi_dynamic_run();
|
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;
|
unsigned int x;
|
||||||
|
|
||||||
/* Unregister span if appropriate */
|
WARN_ON(test_bit(DAHDI_FLAGBIT_REGISTERED, &d->span.flags));
|
||||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &d->span.flags))
|
|
||||||
dahdi_unregister(&d->span);
|
|
||||||
|
|
||||||
/* Destroy the pvt stuff if there */
|
if (d->pvt) {
|
||||||
if (d->pvt)
|
if (d->driver && d->driver->destroy)
|
||||||
d->driver->destroy(d->pvt);
|
d->driver->destroy(d->pvt);
|
||||||
|
else
|
||||||
|
WARN_ON(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Free message buffer if appropriate */
|
|
||||||
kfree(d->msgbuf);
|
kfree(d->msgbuf);
|
||||||
|
|
||||||
/* Free channels */
|
|
||||||
for (x = 0; x < d->span.channels; x++)
|
for (x = 0; x < d->span.channels; x++)
|
||||||
kfree(d->chans[x]);
|
kfree(d->chans[x]);
|
||||||
|
|
||||||
/* Free d */
|
|
||||||
kfree(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)
|
static struct dahdi_dynamic *find_dynamic(struct dahdi_dynamic_span *dds)
|
||||||
@ -432,6 +447,7 @@ static struct dahdi_dynamic *find_dynamic(struct dahdi_dynamic_span *dds)
|
|||||||
list_for_each_entry_rcu(d, &dspan_list, list) {
|
list_for_each_entry_rcu(d, &dspan_list, list) {
|
||||||
if (!strcmp(d->dname, dds->driver) &&
|
if (!strcmp(d->dname, dds->driver) &&
|
||||||
!strcmp(d->addr, dds->addr)) {
|
!strcmp(d->addr, dds->addr)) {
|
||||||
|
dynamic_get(d);
|
||||||
found = d;
|
found = d;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -467,19 +483,20 @@ static int destroy_dynamic(struct dahdi_dynamic_span *dds)
|
|||||||
if (unlikely(!d))
|
if (unlikely(!d))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (d->usecount) {
|
if (atomic_read(&d->kref.refcount) > 1)
|
||||||
printk(KERN_NOTICE "Attempt to destroy dynamic span while it is in use\n");
|
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
|
||||||
|
dahdi_unregister(&d->span);
|
||||||
|
|
||||||
spin_lock_irqsave(&dspan_lock, flags);
|
spin_lock_irqsave(&dspan_lock, flags);
|
||||||
list_del_rcu(&d->list);
|
list_del_rcu(&d->list);
|
||||||
spin_unlock_irqrestore(&dspan_lock, flags);
|
spin_unlock_irqrestore(&dspan_lock, flags);
|
||||||
synchronize_rcu();
|
synchronize_rcu();
|
||||||
|
|
||||||
/* Destroy it */
|
/* One since we've removed the item from the list... */
|
||||||
dynamic_destroy(d);
|
dynamic_put(d);
|
||||||
|
/* ...and one for find_dynamic. */
|
||||||
|
dynamic_put(d);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,11 +509,7 @@ static int dahdi_dynamic_rbsbits(struct dahdi_chan *chan, int bits)
|
|||||||
static int dahdi_dynamic_open(struct dahdi_chan *chan)
|
static int dahdi_dynamic_open(struct dahdi_chan *chan)
|
||||||
{
|
{
|
||||||
struct dahdi_dynamic *d = dynamic_from_span(chan->span);
|
struct dahdi_dynamic *d = dynamic_from_span(chan->span);
|
||||||
if (likely(d)) {
|
dynamic_get(d);
|
||||||
if (unlikely(d->dead))
|
|
||||||
return -ENODEV;
|
|
||||||
d->usecount++;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,11 +521,7 @@ static int dahdi_dynamic_chanconfig(struct dahdi_chan *chan, int sigtype)
|
|||||||
static int dahdi_dynamic_close(struct dahdi_chan *chan)
|
static int dahdi_dynamic_close(struct dahdi_chan *chan)
|
||||||
{
|
{
|
||||||
struct dahdi_dynamic *d = dynamic_from_span(chan->span);
|
struct dahdi_dynamic *d = dynamic_from_span(chan->span);
|
||||||
if (d) {
|
dynamic_put(d);
|
||||||
d->usecount--;
|
|
||||||
if (d->dead && !d->usecount)
|
|
||||||
dynamic_destroy(d);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,20 +554,24 @@ static int create_dynamic(struct dahdi_dynamic_span *dds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
d = find_dynamic(dds);
|
d = find_dynamic(dds);
|
||||||
if (d)
|
if (d) {
|
||||||
|
dynamic_put(d);
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate memory */
|
|
||||||
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
||||||
if (!d)
|
if (!d)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
kref_init(&d->kref);
|
||||||
|
|
||||||
for (x = 0; x < dds->numchans; x++) {
|
for (x = 0; x < dds->numchans; x++) {
|
||||||
d->chans[x] = kzalloc(sizeof(*d->chans[x]), GFP_KERNEL);
|
d->chans[x] = kzalloc(sizeof(*d->chans[x]), GFP_KERNEL);
|
||||||
if (!d->chans[x]) {
|
if (!d->chans[x]) {
|
||||||
dynamic_destroy(d);
|
dynamic_put(d);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
d->span.channels++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate message buffer with sample space and header space */
|
/* Allocate message buffer with sample space and header space */
|
||||||
@ -567,7 +580,7 @@ static int create_dynamic(struct dahdi_dynamic_span *dds)
|
|||||||
d->msgbuf = kzalloc(bufsize, GFP_KERNEL);
|
d->msgbuf = kzalloc(bufsize, GFP_KERNEL);
|
||||||
|
|
||||||
if (!d->msgbuf) {
|
if (!d->msgbuf) {
|
||||||
dynamic_destroy(d);
|
dynamic_put(d);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,7 +591,6 @@ static int create_dynamic(struct dahdi_dynamic_span *dds)
|
|||||||
sprintf(d->span.name, "DYN/%s/%s", dds->driver, dds->addr);
|
sprintf(d->span.name, "DYN/%s/%s", dds->driver, dds->addr);
|
||||||
sprintf(d->span.desc, "Dynamic '%s' span at '%s'",
|
sprintf(d->span.desc, "Dynamic '%s' span at '%s'",
|
||||||
dds->driver, dds->addr);
|
dds->driver, dds->addr);
|
||||||
d->span.channels = dds->numchans;
|
|
||||||
d->span.deflaw = DAHDI_LAW_MULAW;
|
d->span.deflaw = DAHDI_LAW_MULAW;
|
||||||
d->span.flags |= DAHDI_FLAG_RBS;
|
d->span.flags |= DAHDI_FLAG_RBS;
|
||||||
d->span.chans = d->chans;
|
d->span.chans = d->chans;
|
||||||
@ -617,7 +629,7 @@ static int create_dynamic(struct dahdi_dynamic_span *dds)
|
|||||||
if (!dtd) {
|
if (!dtd) {
|
||||||
printk(KERN_NOTICE "No such driver '%s' for dynamic span\n",
|
printk(KERN_NOTICE "No such driver '%s' for dynamic span\n",
|
||||||
dds->driver);
|
dds->driver);
|
||||||
dynamic_destroy(d);
|
dynamic_put(d);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,7 +638,7 @@ static int create_dynamic(struct dahdi_dynamic_span *dds)
|
|||||||
if (!d->pvt) {
|
if (!d->pvt) {
|
||||||
printk(KERN_NOTICE "Driver '%s' (%s) rejected address '%s'\n",
|
printk(KERN_NOTICE "Driver '%s' (%s) rejected address '%s'\n",
|
||||||
dtd->name, dtd->desc, d->addr);
|
dtd->name, dtd->desc, d->addr);
|
||||||
/* Creation failed */
|
dynamic_put(d);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,18 +649,21 @@ static int create_dynamic(struct dahdi_dynamic_span *dds)
|
|||||||
if (dahdi_register(&d->span, 0)) {
|
if (dahdi_register(&d->span, 0)) {
|
||||||
printk(KERN_NOTICE "Unable to register span '%s'\n",
|
printk(KERN_NOTICE "Unable to register span '%s'\n",
|
||||||
d->span.name);
|
d->span.name);
|
||||||
dynamic_destroy(d);
|
dynamic_put(d);
|
||||||
return -EINVAL;
|
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);
|
spin_lock_irqsave(&dspan_lock, flags);
|
||||||
list_add_rcu(&d->list, &dspan_list);
|
list_add_rcu(&d->list, &dspan_list);
|
||||||
spin_unlock_irqrestore(&dspan_lock, flags);
|
spin_unlock_irqrestore(&dspan_lock, flags);
|
||||||
|
|
||||||
checkmaster();
|
checkmaster();
|
||||||
|
|
||||||
/* All done */
|
return x;
|
||||||
return d->span.spanno;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -733,11 +748,7 @@ void dahdi_dynamic_unregister(struct dahdi_dynamic_driver *dri)
|
|||||||
list_del_rcu(&d->list);
|
list_del_rcu(&d->list);
|
||||||
spin_unlock_irqrestore(&dspan_lock, flags);
|
spin_unlock_irqrestore(&dspan_lock, flags);
|
||||||
synchronize_rcu();
|
synchronize_rcu();
|
||||||
|
dynamic_put(d);
|
||||||
if (!d->usecount)
|
|
||||||
dynamic_destroy(d);
|
|
||||||
else
|
|
||||||
d->dead = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user