Commit 9afa3d2e authored by Federico Vaga's avatar Federico Vaga

drv: request DMA channel at probe

On SPEC each ADC has its own DMA channel which can be requested at
probe time. For SVEC, we need to request/release for every
acquisition.

In principle it is also possible for SVEC as well, but this will need
some work on the VME bridge driver to support virtual DMA
channels. And even in that case it could be tricky. Alternativelly we
could implement a share DMA channel, but it is not possible to
implement it in a clean way using the DMA engine framework.

So, this code put down the foundations for the ideal world where we
request the DMA channel once at probe time. But to support the SVEC
case there are *_svec variants in the code.
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 60f175cb
......@@ -700,6 +700,10 @@ int fa_probe(struct platform_device *pdev)
if(!fa_fmc_slot_is_valid(fa))
goto out_fmc_err;
err = fa_dma_request_channel(fa);
if (err)
goto out_dma;
/* init all subsystems */
for (i = 0, m = mods; i < ARRAY_SIZE(mods); i++, m++) {
dev_dbg(fa->msgdev, "Calling init for \"%s\"\n", m->name);
......@@ -727,6 +731,8 @@ out:
if (m->exit)
m->exit(fa);
iounmap(fa->fa_top_level);
fa_dma_release_channel(fa);
out_dma:
out_fmc_err:
out_fmc_eeprom:
out_fmc_pre:
......@@ -754,6 +760,8 @@ int fa_remove(struct platform_device *pdev)
if (m->exit)
m->exit(fa);
}
fa_dma_release_channel(fa);
iounmap(fa->fa_top_level);
fmc_slot_put(fa->slot);
......
......@@ -73,7 +73,7 @@ static bool fa_dmaengine_filter(struct dma_chan *dchan, void *arg)
return ddev->dev_id == dev_id && dchan->chan_id == chan_id;
}
static int fa_dma_request_channel(struct fa_dev *fa)
static int __fa_dma_request_channel(struct fa_dev *fa)
{
dma_cap_mask_t dma_mask;
struct resource *r;
......@@ -96,11 +96,49 @@ static int fa_dma_request_channel(struct fa_dev *fa)
return 0;
}
static void fa_dma_release_channel(struct fa_dev *fa)
int fa_dma_request_channel(struct fa_dev *fa)
{
if (fa_is_flag_set(fa, FMC_ADC_SVEC))
return 0;
return __fa_dma_request_channel(fa);
}
/**
* Remove this function and its use when VME Bridge will support virtual
* DMA channels. Then we will request a channel only once at probe like
* on SPEC
*/
static int fa_dma_request_channel_svec(struct fa_dev *fa)
{
if (fa_is_flag_set(fa, FMC_ADC_SVEC))
return fa_dma_request_channel(fa);
return 0;
}
static void __fa_dma_release_channel(struct fa_dev *fa)
{
dma_release_channel(fa->dchan);
}
void fa_dma_release_channel(struct fa_dev *fa)
{
if (fa_is_flag_set(fa, FMC_ADC_SVEC))
return;
__fa_dma_release_channel(fa);
}
/**
* Remove this function and its use when VME Bridge will support virtual
* DMA channels. Then we will request a channel only once at probe like
* on SPEC
*/
static void fa_dma_release_channel_svec(struct fa_dev *fa)
{
if (fa_is_flag_set(fa, FMC_ADC_SVEC))
__fa_dma_release_channel(fa);
}
static uint32_t zfad_dev_mem_offset(struct zio_cset *cset)
{
struct fa_dev *fa = cset->zdev->priv_d;
......@@ -301,7 +339,7 @@ static void fa_dma_complete(void *arg,
/* Complete the full acquisition when the last transfer is over */
--fa->transfers_left;
if (!fa->transfers_left) {
fa_dma_release_channel(fa);
fa_dma_release_channel_svec(fa);
zfad_dma_done(cset);
}
}
......@@ -422,7 +460,7 @@ static int zfad_dma_start(struct zio_cset *cset)
}
dev_dbg(fa->msgdev, "Start DMA transfer\n");
err = fa_dma_request_channel(fa);
err = fa_dma_request_channel_svec(fa);
if (err)
return err;
......@@ -468,7 +506,7 @@ static int zfad_dma_start(struct zio_cset *cset)
err_prep:
err_config:
dmaengine_terminate_all(fa->dchan);
fa_dma_release_channel(fa);
fa_dma_release_channel_svec(fa);
while (--i >= 0) {
dma_unmap_sg(&fa->pdev->dev,
zfad_block[i].sgt.sgl,
......
......@@ -630,6 +630,8 @@ extern int zfad_get_chx_index(unsigned long addr, unsigned int chan);
/* Function exported by fa-dma.c */
extern void fa_irq_work(struct work_struct *work);
extern int fa_dma_request_channel(struct fa_dev *fa);
extern void fa_dma_release_channel(struct fa_dev *fa);
/* Functions exported by fa-zio-drv.c */
extern int fa_zio_register(void);
......
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