diff options
author | merge <null@invalid> | 2009-01-22 13:55:32 +0000 |
---|---|---|
committer | Andy Green <agreen@octopus.localdomain> | 2009-01-22 13:55:32 +0000 |
commit | aa6f5ffbdba45aa8e19e5048648fc6c7b25376d3 (patch) | |
tree | fbb786d0ac6f8a774fd834e9ce951197e60fbffa /drivers/staging/comedi/rt_pend_tq.c | |
parent | f2d78193eae5dccd3d588d2c8ea0866efc368332 (diff) |
MERGE-via-pending-tracking-hist-MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141
pending-tracking-hist top was MERGE-via-stable-tracking-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040-1232632141 / fdf777a63bcb59e0dfd78bfe2c6242e01f6d4eb9 ... parent commitmessage:
From: merge <null@invalid>
MERGE-via-stable-tracking-hist-MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040
stable-tracking-hist top was MERGE-via-mokopatches-tracking-fix-stray-endmenu-patch-1232632040 / 90463bfd2d5a3c8b52f6e6d71024a00e052b0ced ... parent commitmessage:
From: merge <null@invalid>
MERGE-via-mokopatches-tracking-hist-fix-stray-endmenu-patch
mokopatches-tracking-hist top was fix-stray-endmenu-patch / 3630e0be570de8057e7f8d2fe501ed353cdf34e6 ... parent commitmessage:
From: Andy Green <andy@openmoko.com>
fix-stray-endmenu.patch
Signed-off-by: Andy Green <andy@openmoko.com>
Diffstat (limited to 'drivers/staging/comedi/rt_pend_tq.c')
-rw-r--r-- | drivers/staging/comedi/rt_pend_tq.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/drivers/staging/comedi/rt_pend_tq.c b/drivers/staging/comedi/rt_pend_tq.c new file mode 100644 index 00000000000..995f076e0af --- /dev/null +++ b/drivers/staging/comedi/rt_pend_tq.c @@ -0,0 +1,113 @@ +#define __NO_VERSION__ +/* rt_pend_tq.c */ +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include "comedidev.h" // for rt spinlocks +#include "rt_pend_tq.h" +#ifdef CONFIG_COMEDI_RTAI +#include <rtai.h> +#endif +#ifdef CONFIG_COMEDI_FUSION +#include <nucleus/asm/hal.h> +#endif +#ifdef CONFIG_COMEDI_RTL +#include <rtl_core.h> +#endif + +#ifdef standalone +#include <linux/module.h> +#define rt_pend_tq_init init_module +#define rt_pend_tq_cleanup cleanup_module +#endif + +volatile static struct rt_pend_tq rt_pend_tq[RT_PEND_TQ_SIZE]; +volatile static struct rt_pend_tq *volatile rt_pend_head = rt_pend_tq, + *volatile rt_pend_tail = rt_pend_tq; +int rt_pend_tq_irq = 0; +spinlock_t rt_pend_tq_lock = SPIN_LOCK_UNLOCKED; + +// WARNING: following code not checked against race conditions yet. +#define INC_CIRCULAR_PTR(ptr,begin,size) do {if(++(ptr)>=(begin)+(size)) (ptr)=(begin); } while(0) +#define DEC_CIRCULAR_PTR(ptr,begin,size) do {if(--(ptr)<(begin)) (ptr)=(begin)+(size)-1; } while(0) + +int rt_pend_call(void (*func) (int arg1, void *arg2), int arg1, void *arg2) +{ + unsigned long flags; + + if (func == NULL) + return -EINVAL; + if (rt_pend_tq_irq <= 0) + return -ENODEV; + comedi_spin_lock_irqsave(&rt_pend_tq_lock, flags); + INC_CIRCULAR_PTR(rt_pend_head, rt_pend_tq, RT_PEND_TQ_SIZE); + if (rt_pend_head == rt_pend_tail) { + // overflow, we just refuse to take this request + DEC_CIRCULAR_PTR(rt_pend_head, rt_pend_tq, RT_PEND_TQ_SIZE); + comedi_spin_unlock_irqrestore(&rt_pend_tq_lock, flags); + return -EAGAIN; + } + rt_pend_head->func = func; + rt_pend_head->arg1 = arg1; + rt_pend_head->arg2 = arg2; + comedi_spin_unlock_irqrestore(&rt_pend_tq_lock, flags); +#ifdef CONFIG_COMEDI_RTAI + rt_pend_linux_srq(rt_pend_tq_irq); +#endif +#ifdef CONFIG_COMEDI_FUSION + rthal_apc_schedule(rt_pend_tq_irq); +#endif +#ifdef CONFIG_COMEDI_RTL + rtl_global_pend_irq(rt_pend_tq_irq); + +#endif + return 0; +} + +#ifdef CONFIG_COMEDI_RTAI +void rt_pend_irq_handler(void) +#elif defined(CONFIG_COMEDI_FUSION) +void rt_pend_irq_handler(void *cookie) +#elif defined(CONFIG_COMEDI_RTL) +void rt_pend_irq_handler(int irq, void *dev PT_REGS_ARG) +#endif +{ + while (rt_pend_head != rt_pend_tail) { + INC_CIRCULAR_PTR(rt_pend_tail, rt_pend_tq, RT_PEND_TQ_SIZE); + rt_pend_tail->func(rt_pend_tail->arg1, rt_pend_tail->arg2); + } +} + +int rt_pend_tq_init(void) +{ + rt_pend_head = rt_pend_tail = rt_pend_tq; +#ifdef CONFIG_COMEDI_RTAI + rt_pend_tq_irq = rt_request_srq(0, rt_pend_irq_handler, NULL); +#endif +#ifdef CONFIG_COMEDI_FUSION + rt_pend_tq_irq = + rthal_apc_alloc("comedi APC", rt_pend_irq_handler, NULL); +#endif +#ifdef CONFIG_COMEDI_RTL + rt_pend_tq_irq = rtl_get_soft_irq(rt_pend_irq_handler, "rt_pend_irq"); +#endif + if (rt_pend_tq_irq > 0) + printk("rt_pend_tq: RT bottom half scheduler initialized OK\n"); + else + printk("rt_pend_tq: rtl_get_soft_irq failed\n"); + return 0; +} + +void rt_pend_tq_cleanup(void) +{ + printk("rt_pend_tq: unloading\n"); +#ifdef CONFIG_COMEDI_RTAI + rt_free_srq(rt_pend_tq_irq); +#endif +#ifdef CONFIG_COMEDI_FUSION + rthal_apc_free(rt_pend_tq_irq); +#endif +#ifdef CONFIG_COMEDI_RTL + free_irq(rt_pend_tq_irq, NULL); +#endif +} |