Commit 95fb2544 authored by Federico Vaga's avatar Federico Vaga Committed by Federico Vaga

kernel: add SGT allocation operation

The SVEC version allows DMA within a PAGE_SIZE (4KiB) window. This means
that we cannot perform DMA transfers bigger than PAGE_SIZE (4K).
The sg_alloc_table_from_pages automatically squash continguos transfers
to improve performances, but we cannot use it.

In order to avoid to avoid one `if`, I defined this new operation that is
configured at probe time so that we can use a no_squash version when
necessary.
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@vaga.pv.it>
parent 467c3470
......@@ -36,6 +36,39 @@ static const int zfad_hw_range[] = {
/* fmc-adc specific workqueue */
struct workqueue_struct *fa_workqueue;
/**
* Description:
* The version from the Linux kernel automatically squash contiguous pages.
* Sometimes we do not want to squash (e.g. SVEC)
*/
static int sg_alloc_table_from_pages_no_squash(struct sg_table *sgt,
struct page **pages,
unsigned int n_pages,
unsigned long offset,
unsigned long size,
gfp_t gfp_mask)
{
struct scatterlist *sg;
int err, i;
err = sg_alloc_table(sgt, n_pages, GFP_KERNEL);
if (unlikely(err))
return err;
for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) {
unsigned long chunk_size;
chunk_size = PAGE_SIZE - offset;
sg_set_page(sg, pages[i], min(size, chunk_size), offset);
offset = 0;
size -= chunk_size;
}
return 0;
}
/*
* zfad_convert_hw_range
* @usr_val: range value
......@@ -507,12 +540,14 @@ int fa_probe(struct platform_device *pdev)
memops.read = ioread32;
memops.write = iowrite32;
fa->carrier_op = &fa_spec_op;
fa->sg_alloc_table_from_pages = sg_alloc_table_from_pages;
break;
#ifdef CONFIG_FMC_ADC_SVEC
case ADC_VER_SVEC:
memops.read = ioread32be;
memops.write = iowrite32be;
fa->carrier_op = &fa_svec_op;
fa->sg_alloc_table_from_pages = sg_alloc_table_from_pages_no_squash;
break;
#endif
default:
......
......@@ -462,6 +462,12 @@ struct fa_dev {
int enable_auto_start;
struct dentry *reg_dump;
/* Operations */
int (*sg_alloc_table_from_pages)(struct sg_table *sgt,
struct page **pages, unsigned int n_pages,
unsigned long offset, unsigned long size,
gfp_t gfp_mask);
};
/*
......
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