Skip to content

Commit 73115d8

Browse files
committed
Merge tag 'dmaengine_topic_dma_vec' into next
Dmaengine topic - New device_prep_peripheral_dma_vec, documentation and user
2 parents f8f530b + 380afcc commit 73115d8

File tree

4 files changed

+92
-0
lines changed

4 files changed

+92
-0
lines changed

Documentation/driver-api/dmaengine/client.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ The details of these operations are:
8080

8181
- slave_sg: DMA a list of scatter gather buffers from/to a peripheral
8282

83+
- peripheral_dma_vec: DMA an array of scatter gather buffers from/to a
84+
peripheral. Similar to slave_sg, but uses an array of dma_vec
85+
structures instead of a scatterlist.
86+
8387
- dma_cyclic: Perform a cyclic DMA operation from/to a peripheral till the
8488
operation is explicitly stopped.
8589

@@ -102,6 +106,11 @@ The details of these operations are:
102106
unsigned int sg_len, enum dma_data_direction direction,
103107
unsigned long flags);
104108
109+
struct dma_async_tx_descriptor *dmaengine_prep_peripheral_dma_vec(
110+
struct dma_chan *chan, const struct dma_vec *vecs,
111+
size_t nents, enum dma_data_direction direction,
112+
unsigned long flags);
113+
105114
struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic(
106115
struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
107116
size_t period_len, enum dma_data_direction direction);

Documentation/driver-api/dmaengine/provider.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,12 @@ supported.
433433
- residue: Provides the residue bytes of the transfer for those that
434434
support residue.
435435

436+
- ``device_prep_peripheral_dma_vec``
437+
438+
- Similar to ``device_prep_slave_sg``, but it takes a pointer to a
439+
array of ``dma_vec`` structures, which (in the long run) will replace
440+
scatterlists.
441+
436442
- ``device_issue_pending``
437443

438444
- Takes the first transaction descriptor in the pending queue,
@@ -544,6 +550,10 @@ dma_cookie_t
544550
- Not really relevant any more since the introduction of ``virt-dma``
545551
that abstracts it away.
546552

553+
dma_vec
554+
555+
- A small structure that contains a DMA address and length.
556+
547557
DMA_CTRL_ACK
548558

549559
- If clear, the descriptor cannot be reused by provider until the

drivers/dma/dma-axi-dmac.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,45 @@ static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *chan,
620620
return sg;
621621
}
622622

623+
static struct dma_async_tx_descriptor *
624+
axi_dmac_prep_peripheral_dma_vec(struct dma_chan *c, const struct dma_vec *vecs,
625+
size_t nb, enum dma_transfer_direction direction,
626+
unsigned long flags)
627+
{
628+
struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
629+
struct axi_dmac_desc *desc;
630+
unsigned int num_sgs = 0;
631+
struct axi_dmac_sg *dsg;
632+
size_t i;
633+
634+
if (direction != chan->direction)
635+
return NULL;
636+
637+
for (i = 0; i < nb; i++)
638+
num_sgs += DIV_ROUND_UP(vecs[i].len, chan->max_length);
639+
640+
desc = axi_dmac_alloc_desc(chan, num_sgs);
641+
if (!desc)
642+
return NULL;
643+
644+
dsg = desc->sg;
645+
646+
for (i = 0; i < nb; i++) {
647+
if (!axi_dmac_check_addr(chan, vecs[i].addr) ||
648+
!axi_dmac_check_len(chan, vecs[i].len)) {
649+
kfree(desc);
650+
return NULL;
651+
}
652+
653+
dsg = axi_dmac_fill_linear_sg(chan, direction, vecs[i].addr, 1,
654+
vecs[i].len, dsg);
655+
}
656+
657+
desc->cyclic = false;
658+
659+
return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
660+
}
661+
623662
static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg(
624663
struct dma_chan *c, struct scatterlist *sgl,
625664
unsigned int sg_len, enum dma_transfer_direction direction,
@@ -1061,6 +1100,7 @@ static int axi_dmac_probe(struct platform_device *pdev)
10611100
dma_dev->device_tx_status = dma_cookie_status;
10621101
dma_dev->device_issue_pending = axi_dmac_issue_pending;
10631102
dma_dev->device_prep_slave_sg = axi_dmac_prep_slave_sg;
1103+
dma_dev->device_prep_peripheral_dma_vec = axi_dmac_prep_peripheral_dma_vec;
10641104
dma_dev->device_prep_dma_cyclic = axi_dmac_prep_dma_cyclic;
10651105
dma_dev->device_prep_interleaved_dma = axi_dmac_prep_interleaved;
10661106
dma_dev->device_terminate_all = axi_dmac_terminate_all;

include/linux/dmaengine.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,16 @@ struct dma_interleaved_template {
160160
struct data_chunk sgl[];
161161
};
162162

163+
/**
164+
* struct dma_vec - DMA vector
165+
* @addr: Bus address of the start of the vector
166+
* @len: Length in bytes of the DMA vector
167+
*/
168+
struct dma_vec {
169+
dma_addr_t addr;
170+
size_t len;
171+
};
172+
163173
/**
164174
* enum dma_ctrl_flags - DMA flags to augment operation preparation,
165175
* control completion, and communicate status.
@@ -910,6 +920,10 @@ struct dma_device {
910920
struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
911921
struct dma_chan *chan, unsigned long flags);
912922

923+
struct dma_async_tx_descriptor *(*device_prep_peripheral_dma_vec)(
924+
struct dma_chan *chan, const struct dma_vec *vecs,
925+
size_t nents, enum dma_transfer_direction direction,
926+
unsigned long flags);
913927
struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
914928
struct dma_chan *chan, struct scatterlist *sgl,
915929
unsigned int sg_len, enum dma_transfer_direction direction,
@@ -973,6 +987,25 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
973987
dir, flags, NULL);
974988
}
975989

990+
/**
991+
* dmaengine_prep_peripheral_dma_vec() - Prepare a DMA scatter-gather descriptor
992+
* @chan: The channel to be used for this descriptor
993+
* @vecs: The array of DMA vectors that should be transferred
994+
* @nents: The number of DMA vectors in the array
995+
* @dir: Specifies the direction of the data transfer
996+
* @flags: DMA engine flags
997+
*/
998+
static inline struct dma_async_tx_descriptor *dmaengine_prep_peripheral_dma_vec(
999+
struct dma_chan *chan, const struct dma_vec *vecs, size_t nents,
1000+
enum dma_transfer_direction dir, unsigned long flags)
1001+
{
1002+
if (!chan || !chan->device || !chan->device->device_prep_peripheral_dma_vec)
1003+
return NULL;
1004+
1005+
return chan->device->device_prep_peripheral_dma_vec(chan, vecs, nents,
1006+
dir, flags);
1007+
}
1008+
9761009
static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg(
9771010
struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
9781011
enum dma_transfer_direction dir, unsigned long flags)

0 commit comments

Comments
 (0)