Commit d313407c authored by Michel Arruat's avatar Michel Arruat Committed by Federico Vaga

adc driver: create specific workqueue to execute DMA.

Application using the ADC driver may run with real-time scheduling and
high priority.
The default shared queue is running with non real-time scheduling
policy.
ADC crates its own workqueue, that one can adjust in terms
of scheduling policy to fulfill application's real-time constraints.
parent 6970670a
......@@ -10,6 +10,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/workqueue.h>
#include <linux/fmc.h>
#include <linux/fmc-sdb.h>
......@@ -35,6 +36,9 @@ static const int zfad_hw_range[] = {
[ZFA_RANGE_OPEN] = 0x00,
};
/* fmc-adc specific workqueue */
struct workqueue_struct *fa_workqueue;
/*
* zfad_convert_hw_range
* @usr_val: range value
......@@ -472,6 +476,7 @@ int fa_remove(struct fmc_device *fmc)
int i = ARRAY_SIZE(mods);
fa_free_irqs(fa);
flush_workqueue(fa_workqueue);
while (--i >= 0) {
m = mods + i;
......@@ -505,24 +510,35 @@ static int fa_init(void)
{
int ret;
fa_workqueue = alloc_workqueue(fa_dev_drv.driver.name,
WQ_NON_REENTRANT | WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
if (fa_workqueue == NULL)
return -ENOMEM;
/* First trigger and zio driver */
ret = fa_trig_init();
if (ret)
return ret;
goto out1;
ret = fa_zio_register();
if (ret) {
fa_trig_exit();
return ret;
}
if (ret)
goto out2;
/* Finally the fmc driver, whose probe instantiates zio devices */
ret = fmc_driver_register(&fa_dev_drv);
if (ret) {
fa_trig_exit();
fa_zio_unregister();
return ret;
}
return 0;
if (ret)
goto out3;
return ret;
out3:
fa_zio_unregister();
out2:
fa_trig_exit();
out1:
destroy_workqueue(fa_workqueue);
return ret;
}
static void fa_exit(void)
......@@ -530,6 +546,8 @@ static void fa_exit(void)
fmc_driver_unregister(&fa_dev_drv);
fa_zio_unregister();
fa_trig_exit();
if (fa_workqueue != NULL)
destroy_workqueue(fa_workqueue);
}
module_init(fa_init);
......
......@@ -356,7 +356,7 @@ irqreturn_t fa_irq_handler(int irq_core_base, void *dev_id)
if (cset->flags & ZIO_CSET_BUSY) {
/* Job deferred to the workqueue: */
/* Start DMA and ack irq on the carrier */
schedule_work(&fa->irq_work);
queue_work(fa_workqueue, &fa->irq_work);
/* register the core firing the IRQ in order to */
/* check right IRQ seq.: ACQ_END followed by DMA_END */
fa->last_irq_core_src = irq_core_base;
......
......@@ -410,6 +410,9 @@ static inline void fa_writel(struct fa_dev *fa,
fmc_writel(fa->fmc, val, base_off+field->offset);
}
/* Global variable exported by fa-core.c */
extern struct workqueue_struct *fa_workqueue;
/* Global variable exported by fa-spec.c */
extern struct fa_carrier_op fa_spec_op;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment