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 @@ ...@@ -10,6 +10,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/workqueue.h>
#include <linux/fmc.h> #include <linux/fmc.h>
#include <linux/fmc-sdb.h> #include <linux/fmc-sdb.h>
...@@ -35,6 +36,9 @@ static const int zfad_hw_range[] = { ...@@ -35,6 +36,9 @@ static const int zfad_hw_range[] = {
[ZFA_RANGE_OPEN] = 0x00, [ZFA_RANGE_OPEN] = 0x00,
}; };
/* fmc-adc specific workqueue */
struct workqueue_struct *fa_workqueue;
/* /*
* zfad_convert_hw_range * zfad_convert_hw_range
* @usr_val: range value * @usr_val: range value
...@@ -472,6 +476,7 @@ int fa_remove(struct fmc_device *fmc) ...@@ -472,6 +476,7 @@ int fa_remove(struct fmc_device *fmc)
int i = ARRAY_SIZE(mods); int i = ARRAY_SIZE(mods);
fa_free_irqs(fa); fa_free_irqs(fa);
flush_workqueue(fa_workqueue);
while (--i >= 0) { while (--i >= 0) {
m = mods + i; m = mods + i;
...@@ -505,24 +510,35 @@ static int fa_init(void) ...@@ -505,24 +510,35 @@ static int fa_init(void)
{ {
int ret; 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 */ /* First trigger and zio driver */
ret = fa_trig_init(); ret = fa_trig_init();
if (ret) if (ret)
return ret; goto out1;
ret = fa_zio_register(); ret = fa_zio_register();
if (ret) { if (ret)
fa_trig_exit(); goto out2;
return ret;
}
/* Finally the fmc driver, whose probe instantiates zio devices */ /* Finally the fmc driver, whose probe instantiates zio devices */
ret = fmc_driver_register(&fa_dev_drv); ret = fmc_driver_register(&fa_dev_drv);
if (ret) { if (ret)
fa_trig_exit(); goto out3;
fa_zio_unregister();
return ret; return ret;
}
return 0; out3:
fa_zio_unregister();
out2:
fa_trig_exit();
out1:
destroy_workqueue(fa_workqueue);
return ret;
} }
static void fa_exit(void) static void fa_exit(void)
...@@ -530,6 +546,8 @@ static void fa_exit(void) ...@@ -530,6 +546,8 @@ static void fa_exit(void)
fmc_driver_unregister(&fa_dev_drv); fmc_driver_unregister(&fa_dev_drv);
fa_zio_unregister(); fa_zio_unregister();
fa_trig_exit(); fa_trig_exit();
if (fa_workqueue != NULL)
destroy_workqueue(fa_workqueue);
} }
module_init(fa_init); module_init(fa_init);
......
...@@ -356,7 +356,7 @@ irqreturn_t fa_irq_handler(int irq_core_base, void *dev_id) ...@@ -356,7 +356,7 @@ irqreturn_t fa_irq_handler(int irq_core_base, void *dev_id)
if (cset->flags & ZIO_CSET_BUSY) { if (cset->flags & ZIO_CSET_BUSY) {
/* Job deferred to the workqueue: */ /* Job deferred to the workqueue: */
/* Start DMA and ack irq on the carrier */ /* 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 */ /* register the core firing the IRQ in order to */
/* check right IRQ seq.: ACQ_END followed by DMA_END */ /* check right IRQ seq.: ACQ_END followed by DMA_END */
fa->last_irq_core_src = irq_core_base; fa->last_irq_core_src = irq_core_base;
......
...@@ -410,6 +410,9 @@ static inline void fa_writel(struct fa_dev *fa, ...@@ -410,6 +410,9 @@ static inline void fa_writel(struct fa_dev *fa,
fmc_writel(fa->fmc, val, base_off+field->offset); 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 */ /* Global variable exported by fa-spec.c */
extern struct fa_carrier_op fa_spec_op; 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