summaryrefslogtreecommitdiff
path: root/zttranscode.c
diff options
context:
space:
mode:
authorkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-02-01 20:17:23 +0000
committerkpfleming <kpfleming@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-02-01 20:17:23 +0000
commitb2af10d896f48ec605ada4af4df70f53bca6badb (patch)
treecb33562d0111d965cee0aae1088ff2be7b794433 /zttranscode.c
parent13179eb2fc4b2384550a1681513986584634bfd6 (diff)
revert some code that appears to be causing crashes
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@2078 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'zttranscode.c')
-rw-r--r--zttranscode.c85
1 files changed, 45 insertions, 40 deletions
diff --git a/zttranscode.c b/zttranscode.c
index aad71cc..39e84ae 100644
--- a/zttranscode.c
+++ b/zttranscode.c
@@ -47,7 +47,7 @@
#endif
static int debug = 0;
-static LIST_HEAD(trans);
+static struct zt_transcoder *trans;
static spinlock_t translock = SPIN_LOCK_UNLOCKED;
EXPORT_SYMBOL(zt_transcoder_register);
@@ -68,12 +68,11 @@ struct zt_transcoder *zt_transcoder_alloc(int numchans)
memset(ztc, 0, size);
strcpy(ztc->name, "<unspecified>");
ztc->numchannels = numchans;
- INIT_LIST_HEAD(&ztc->list);
for (x=0;x<ztc->numchannels;x++) {
init_waitqueue_head(&ztc->channels[x].ready);
ztc->channels[x].parent = ztc;
ztc->channels[x].offset = x;
- ztc->channels[x].chan_built = 0;
+ ztc->channels[x].flags.chan_built = 0;
ztc->channels[x].built_fmts = 0;
}
@@ -104,50 +103,58 @@ void zt_transcoder_free(struct zt_transcoder *ztc)
kfree(ztc);
}
-int zt_transcoder_register(struct zt_transcoder *tc, struct module *owner)
+/* Register a transcoder */
+int zt_transcoder_register(struct zt_transcoder *tc)
{
struct zt_transcoder *cur;
+ int res = -EBUSY;
spin_lock(&translock);
- list_for_each_entry(cur, &trans, list) {
+ for (cur = trans; cur; cur = cur->next) {
if (cur == tc) {
spin_unlock(&translock);
- return -EBUSY;
+ return res;
}
}
- tc->owner = owner;
- list_add(&tc->list, &trans);
+ tc->next = trans;
+ trans = tc;
printk("Registered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n",
tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts);
+ res = 0;
spin_unlock(&translock);
- return 0;
+ return res;
}
/* Unregister a transcoder */
int zt_transcoder_unregister(struct zt_transcoder *tc)
{
- struct zt_transcoder *cur, *next;
+ struct zt_transcoder *cur, *prev;
+ int res = -EINVAL;
spin_lock(&translock);
- list_for_each_entry_safe(cur, next, &trans, list) {
- if (cur == tc) {
- list_del_init(&cur->list);
+ for (cur = trans, prev = NULL; cur; prev = cur, cur = cur->next) {
+ if (cur == tc)
break;
- }
}
if (!cur) {
spin_unlock(&translock);
- return -EINVAL;
+ return res;
}
+ if (prev)
+ prev->next = tc->next;
+ else
+ trans = tc->next;
+ tc->next = NULL;
printk("Unregistered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n",
tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts);
+ res = 0;
spin_unlock(&translock);
- return 0;
+ return res;
}
/* Alert a transcoder */
@@ -178,8 +185,7 @@ static int zt_tc_open(struct inode *inode, struct file *file)
memset(ztc, 0, sizeof(*ztc));
memset(zth, 0, sizeof(*zth));
- ztc->transient = 1;
- ztc->busy = 1;
+ ztc->flags.transient = ztc->flags.busy = 1;
ztc->tch = zth;
if (debug)
printk("Allocated Transcoder Channel, header is at %p!\n", zth);
@@ -201,7 +207,7 @@ static void ztc_release(struct zt_transcoder_channel *ztc)
if (!ztc)
return;
- ztc->busy = 0;
+ ztc->flags.busy = 0;
if (ztc->tch) {
for (page = virt_to_page(zth);
@@ -213,12 +219,12 @@ static void ztc_release(struct zt_transcoder_channel *ztc)
ztc->tch = NULL;
- if (ztc->have_reference) {
+ if (ztc->flags.have_reference) {
module_put(ztc->parent->owner);
- ztc->have_reference = 0;
+ ztc->flags.have_reference = 0;
}
- if (ztc->transient);
+ if (ztc->flags.transient)
kfree(ztc);
if (debug)
@@ -244,7 +250,7 @@ static int do_allocate(struct zt_transcoder_channel **ztc)
((*ztc)->dstfmt != zth->dstfmt)) {
/* Find new transcoder */
spin_lock(&translock);
- list_for_each_entry(tc, &trans, list) {
+ for (tc = trans; tc && !newztc; tc = tc->next) {
if (!(tc->srcfmts & zth->srcfmt))
continue;
@@ -253,10 +259,9 @@ static int do_allocate(struct zt_transcoder_channel **ztc)
match = 1;
for (x = 0; x < tc->numchannels; x++) {
- if (tc->channels[x].busy)
+ if (tc->channels[x].flags.busy)
continue;
-
- if (tc->channels[x].chan_built &&
+ if (tc->channels[x].flags.chan_built &&
((zth->srcfmt | zth->dstfmt) != tc->channels[x].built_fmts))
continue;
@@ -264,8 +269,7 @@ static int do_allocate(struct zt_transcoder_channel **ztc)
continue;
newztc = &tc->channels[x];
- newztc->busy = 1;
- newztc->have_reference = 1;
+ newztc->flags.busy = 1;
break;
}
}
@@ -279,7 +283,14 @@ static int do_allocate(struct zt_transcoder_channel **ztc)
(*ztc) = newztc;
(*ztc)->tch = origztc->tch;
origztc->tch = NULL;
- (*ztc)->transient = 0;
+ /* ensure that the 'busy' flag doesn't get cleared,
+ even for a short time, so no other thread will
+ grab this channel
+ */
+ origztc->flags.busy = 1;
+ (*ztc)->flags = origztc->flags;
+ (*ztc)->flags.transient = 0;
+ (*ztc)->flags.have_reference = 1;
ztc_release(origztc);
}
@@ -295,7 +306,7 @@ static int wait_busy(struct zt_transcoder_channel *ztc)
int ret;
for (;;) {
- if (!(ztc->tch->busy))
+ if (!ztc->tch->busy)
return 0;
if ((ret = schluffen(&ztc->ready)))
return ret;
@@ -312,16 +323,10 @@ static int zt_tc_getinfo(unsigned long data)
return -EFAULT;
spin_lock(&translock);
- x = info.tcnum;
- list_for_each_entry(tc, &trans, list) {
- if (!x)
- break;
- else
- x--;
- }
+ for (tc = trans, x = info.tcnum; tc && x; tc = tc->next, x--);
spin_unlock(&translock);
- if (x || !tc)
+ if (!tc)
return -ENOSYS;
strncpy(info.name, tc->name, sizeof(info.name) - 1);
@@ -357,9 +362,9 @@ static int zt_tc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
break;
case ZT_TCOP_RELEASE:
ret = ztc->parent->operation(ztc, ZT_TCOP_RELEASE);
- if (ztc->have_reference) {
+ if (ztc->flags.have_reference) {
module_put(ztc->parent->owner);
- ztc->have_reference = 0;
+ ztc->flags.have_reference = 0;
}
break;
case ZT_TCOP_TRANSCODE: