Skip to content

Commit bd96f1b

Browse files
alanmikhak-at-sifivevinodkoul
authored andcommitted
dmaengine: dw-edma: support local dma device transfer semantics
Modify dw_edma_device_transfer() to also support the semantics of dma device transfer for additional use cases involving pcitest utility as a local initiator. For its original use case, dw-edma supported the semantics of dma device transfer from the perspective of a remote initiator who is located across the PCIe bus from dma channel hardware. To a remote initiator, DMA_DEV_TO_MEM means using a remote dma WRITE channel to transfer from remote memory to local memory. A WRITE channel would be employed on the remote device in order to move the contents of remote memory to the bus destined for local memory. To a remote initiator, DMA_MEM_TO_DEV means using a remote dma READ channel to transfer from local memory to remote memory. A READ channel would be employed on the remote device in order to move the contents of local memory to the bus destined for remote memory. >From the perspective of a local dma initiator who is co-located on the same side of the PCIe bus as the dma channel hardware, the semantics of dma device transfer are flipped. To a local initiator, DMA_DEV_TO_MEM means using a local dma READ channel to transfer from remote memory to local memory. A READ channel would be employed on the local device in order to move the contents of remote memory to the bus destined for local memory. To a local initiator, DMA_MEM_TO_DEV means using a local dma WRITE channel to transfer from local memory to remote memory. A WRITE channel would be employed on the local device in order to move the contents of local memory to the bus destined for remote memory. To support local dma initiators, dw_edma_device_transfer() is modified to now examine the direction field of struct dma_slave_config for the channel which initiators can configure by calling dmaengine_slave_config(). If direction is configured as either DMA_DEV_TO_MEM or DMA_MEM_TO_DEV, local initiator semantics are used. If direction is a value other than DMA_DEV_TO_MEM nor DMA_MEM_TO_DEV, then remote initiator semantics are used. This should maintain backward compatibility with the original use case of dw-edma. The dw-edma-test utility is an example of a remote initiator. From reading its patch, dw-edma-test does not specifically set the direction field of struct dma_slave_config. Since dw_edma_device_transfer() also does not check the direction field of struct dma_slave_config, it seems safe to use this convention in dw-edma to support both local and remote initiator semantics. Signed-off-by: Alan Mikhak <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent 9872e23 commit bd96f1b

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

drivers/dma/dw-edma/dw-edma-core.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ static struct dma_async_tx_descriptor *
323323
dw_edma_device_transfer(struct dw_edma_transfer *xfer)
324324
{
325325
struct dw_edma_chan *chan = dchan2dw_edma_chan(xfer->dchan);
326-
enum dma_transfer_direction direction = xfer->direction;
326+
enum dma_transfer_direction dir = xfer->direction;
327327
phys_addr_t src_addr, dst_addr;
328328
struct scatterlist *sg = NULL;
329329
struct dw_edma_chunk *chunk;
@@ -332,10 +332,26 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
332332
u32 cnt;
333333
int i;
334334

335-
if ((direction == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_WRITE) ||
336-
(direction == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_READ))
335+
if (!chan->configured)
337336
return NULL;
338337

338+
switch (chan->config.direction) {
339+
case DMA_DEV_TO_MEM: /* local dma */
340+
if (dir == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_READ)
341+
break;
342+
return NULL;
343+
case DMA_MEM_TO_DEV: /* local dma */
344+
if (dir == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_WRITE)
345+
break;
346+
return NULL;
347+
default: /* remote dma */
348+
if (dir == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_READ)
349+
break;
350+
if (dir == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_WRITE)
351+
break;
352+
return NULL;
353+
}
354+
339355
if (xfer->cyclic) {
340356
if (!xfer->xfer.cyclic.len || !xfer->xfer.cyclic.cnt)
341357
return NULL;
@@ -344,9 +360,6 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
344360
return NULL;
345361
}
346362

347-
if (!chan->configured)
348-
return NULL;
349-
350363
desc = dw_edma_alloc_desc(chan);
351364
if (unlikely(!desc))
352365
goto err_alloc;
@@ -387,7 +400,7 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
387400
chunk->ll_region.sz += burst->sz;
388401
desc->alloc_sz += burst->sz;
389402

390-
if (direction == DMA_DEV_TO_MEM) {
403+
if (chan->dir == EDMA_DIR_WRITE) {
391404
burst->sar = src_addr;
392405
if (xfer->cyclic) {
393406
burst->dar = xfer->xfer.cyclic.paddr;

0 commit comments

Comments
 (0)