diff options
Diffstat (limited to 'kernel/zttranscode.c')
-rw-r--r-- | kernel/zttranscode.c | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/kernel/zttranscode.c b/kernel/zttranscode.c index 58d098c..5f1b3c0 100644 --- a/kernel/zttranscode.c +++ b/kernel/zttranscode.c @@ -3,7 +3,7 @@ * * Written by Mark Spencer <markster@digium.com> * - * Copyright (C) 2006-2008, Digium, Inc. + * Copyright (C) 2006-2009, Digium, Inc. * * All rights reserved. * @@ -39,7 +39,13 @@ #include <zaptel.h> static int debug; -LIST_HEAD(trans); +/* The registration list contains transcoders in the order in which they were + * registered. */ +static LIST_HEAD(registration_list); +/* The active list is sorted by the most recently used transcoder is last. This + * is used as a simplistic way to spread the load amongst the different hardware + * transcoders in the system. */ +static LIST_HEAD(active_list); static spinlock_t translock = SPIN_LOCK_UNLOCKED; EXPORT_SYMBOL(zt_transcoder_register); @@ -60,7 +66,9 @@ struct zt_transcoder *zt_transcoder_alloc(int numchans) memset(tc, 0, size); strcpy(tc->name, "<unspecified>"); tc->numchannels = numchans; - INIT_LIST_HEAD(&tc->node); + INIT_LIST_HEAD(&tc->registration_list_node); + INIT_LIST_HEAD(&tc->active_list_node); + for (x=0;x<tc->numchannels;x++) { init_waitqueue_head(&tc->channels[x].ready); tc->channels[x].parent = tc; @@ -93,11 +101,10 @@ static int is_on_list(struct list_head *entry, struct list_head *head) /* Register a transcoder */ int zt_transcoder_register(struct zt_transcoder *tc) { - static int count = 0; - tc->pos = count++; spin_lock(&translock); - BUG_ON(is_on_list(&tc->node, &trans)); - list_add_tail(&tc->node, &trans); + BUG_ON(is_on_list(&tc->registration_list_node, ®istration_list)); + list_add_tail(&tc->registration_list_node, ®istration_list); + list_add_tail(&tc->active_list_node, &active_list); spin_unlock(&translock); printk(KERN_INFO "%s: Registered codec translator '%s' " \ @@ -117,13 +124,14 @@ int zt_transcoder_unregister(struct zt_transcoder *tc) * that is still in use? */ spin_lock(&translock); - if (!is_on_list(&tc->node, &trans)) { + if (!is_on_list(&tc->registration_list_node, ®istration_list)) { spin_unlock(&translock); printk(KERN_WARNING "%s: Failed to unregister %s, which is " \ "not currently registerd.\n", THIS_MODULE->name, tc->name); return -EINVAL; } - list_del_init(&tc->node); + list_del_init(&tc->registration_list_node); + list_del_init(&tc->active_list_node); spin_unlock(&translock); printk(KERN_INFO "Unregistered codec translator '%s' with %d " \ @@ -223,7 +231,7 @@ __find_free_channel(struct list_head *list, const struct zt_transcoder_formats * struct zt_transcoder_channel *chan = NULL; unsigned int match = 0; - list_for_each_entry(tc, list, node) { + list_for_each_entry(tc, list, active_list_node) { if ((tc->dstfmts & fmts->dstfmt) && (tc->srcfmts & fmts->srcfmt)) { /* We found a transcoder that can handle our formats. * Now look for an available channel. */ @@ -234,7 +242,7 @@ __find_free_channel(struct list_head *list, const struct zt_transcoder_formats * * transcoders (when there are more than one * transcoder in the system) we'll move tc * to the end of the list. */ - list_move_tail(&tc->node, list); + list_move_tail(&tc->active_list_node, list); return chan; } } @@ -253,7 +261,7 @@ static long zt_tc_allocate(struct file *file, unsigned long data) } spin_lock(&translock); - chan = __find_free_channel(&trans, &fmts); + chan = __find_free_channel(&active_list, &fmts); spin_unlock(&translock); if (IS_ERR(chan)) { @@ -303,14 +311,15 @@ static long zt_tc_getinfo(unsigned long data) struct zt_transcoder_info info; struct zt_transcoder *cur; struct zt_transcoder *tc = NULL; + unsigned int count = 0; if (copy_from_user(&info, (const void *) data, sizeof(info))) { return -EFAULT; } spin_lock(&translock); - list_for_each_entry(cur, &trans, node) { - if (cur->pos == info.tcnum) { + list_for_each_entry(cur, ®istration_list, registration_list_node) { + if (info.tcnum == count++) { tc = cur; break; } |