Commit 389ee876 authored by Federico Vaga's avatar Federico Vaga

sw:drv: add DMA write support

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 00a51e44
......@@ -43,3 +43,22 @@ class TestDma(object):
data = spec.dma_read(dma_size)
assert len(data) == dma_size
spec.dma_stop()
@pytest.mark.parametrize("dma_size",
[0, 1, 2, 3] + \
[5, 7, 9] + \
[2**i for i in range(24)])
def test_dma_write(self, spec, dma_size):
"""
We just want to see if the DMA engine reports errors. Test the
engine with different sizes, but same offset (default:
0x0). On the engine side we will get several transfers
(scatterlist) depending on the size.
Regressions:
- 0: the driver returns immediatly without starting any DMA transfer
- 1, 2, 3, 4: performing transfers of these sizes led to a failure
"""
spec.dma_start()
spec.dma_write(b"\x00" * dma_size)
spec.dma_stop()
......@@ -20,7 +20,7 @@ class PySPEC:
self.dma_stop()
def dma_start(self):
self.dma_file = open(self.dma, "rb", buffering=0)
self.dma_file = open(self.dma, "rb+", buffering=0)
def dma_stop(self):
if hasattr(self, "dma_file"):
......@@ -35,3 +35,11 @@ class PySPEC:
while size - len(data) > 0:
data += self.dma_file.read(size - len(data))
return data
def dma_write(self, data):
"""
Trigger a *device to memory* DMA transfer
"""
start = 0
while len(data) - start > 0:
start += self.dma_file.write(data[start:])
......@@ -349,7 +349,6 @@ static int gn412x_dma_alloc_chan_resources(struct dma_chan *dchan)
struct gn412x_dma_chan *chan = to_gn412x_dma_chan(dchan);
memset(&chan->sconfig, 0, sizeof(struct dma_slave_config));
chan->sconfig.direction = DMA_DEV_TO_MEM;
return 0;
}
......@@ -389,8 +388,8 @@ static void gn412x_dma_prep_fixup(struct gn412x_dma_tx_hw *tx_hw,
}
static void gn412x_dma_prep(struct gn412x_dma_tx_hw *tx_hw,
struct scatterlist *sg,
dma_addr_t start_addr)
struct scatterlist *sg, dma_addr_t start_addr,
enum dma_transfer_direction direction)
{
tx_hw->start_addr = start_addr & 0xFFFFFFFF;
tx_hw->dma_addr_l = sg_dma_address(sg);
......@@ -401,8 +400,10 @@ static void gn412x_dma_prep(struct gn412x_dma_tx_hw *tx_hw,
tx_hw->next_addr_l = 0x00000000;
tx_hw->next_addr_h = 0x00000000;
tx_hw->attribute = 0x0;
if (direction == DMA_MEM_TO_DEV)
tx_hw->attribute |= GN412X_DMA_ATTR_DIR_MEM_TO_DEV;
if (!sg_is_last(sg))
tx_hw->attribute = GN412X_DMA_ATTR_CHAIN;
tx_hw->attribute |= GN412X_DMA_ATTR_CHAIN;
}
static struct dma_async_tx_descriptor *gn412x_dma_prep_slave_sg(
......@@ -417,12 +418,6 @@ static struct dma_async_tx_descriptor *gn412x_dma_prep_slave_sg(
dma_addr_t src_addr;
int i;
if (unlikely(direction != DMA_DEV_TO_MEM)) {
dev_err(&chan->dev->device,
"Support only DEV -> MEM transfers\n");
goto err;
}
if (unlikely(sconfig->direction != direction)) {
dev_err(&chan->dev->device,
"Transfer and slave configuration disagree on DMA direction\n");
......@@ -479,7 +474,8 @@ static struct dma_async_tx_descriptor *gn412x_dma_prep_slave_sg(
} else {
gn412x_dma_tx->tx.phys = phys;
}
gn412x_dma_prep(gn412x_dma_tx->sgl_hw[i], sg, src_addr);
gn412x_dma_prep(gn412x_dma_tx->sgl_hw[i], sg, src_addr,
direction);
src_addr += sg_dma_len(sg);
}
......
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