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): ...@@ -43,3 +43,22 @@ class TestDma(object):
data = spec.dma_read(dma_size) data = spec.dma_read(dma_size)
assert len(data) == dma_size assert len(data) == dma_size
spec.dma_stop() 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: ...@@ -20,7 +20,7 @@ class PySPEC:
self.dma_stop() self.dma_stop()
def dma_start(self): 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): def dma_stop(self):
if hasattr(self, "dma_file"): if hasattr(self, "dma_file"):
...@@ -35,3 +35,11 @@ class PySPEC: ...@@ -35,3 +35,11 @@ class PySPEC:
while size - len(data) > 0: while size - len(data) > 0:
data += self.dma_file.read(size - len(data)) data += self.dma_file.read(size - len(data))
return 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) ...@@ -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); struct gn412x_dma_chan *chan = to_gn412x_dma_chan(dchan);
memset(&chan->sconfig, 0, sizeof(struct dma_slave_config)); memset(&chan->sconfig, 0, sizeof(struct dma_slave_config));
chan->sconfig.direction = DMA_DEV_TO_MEM;
return 0; return 0;
} }
...@@ -389,8 +388,8 @@ static void gn412x_dma_prep_fixup(struct gn412x_dma_tx_hw *tx_hw, ...@@ -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, static void gn412x_dma_prep(struct gn412x_dma_tx_hw *tx_hw,
struct scatterlist *sg, struct scatterlist *sg, dma_addr_t start_addr,
dma_addr_t start_addr) enum dma_transfer_direction direction)
{ {
tx_hw->start_addr = start_addr & 0xFFFFFFFF; tx_hw->start_addr = start_addr & 0xFFFFFFFF;
tx_hw->dma_addr_l = sg_dma_address(sg); 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, ...@@ -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_l = 0x00000000;
tx_hw->next_addr_h = 0x00000000; tx_hw->next_addr_h = 0x00000000;
tx_hw->attribute = 0x0; 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)) 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( 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( ...@@ -417,12 +418,6 @@ static struct dma_async_tx_descriptor *gn412x_dma_prep_slave_sg(
dma_addr_t src_addr; dma_addr_t src_addr;
int i; 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)) { if (unlikely(sconfig->direction != direction)) {
dev_err(&chan->dev->device, dev_err(&chan->dev->device,
"Transfer and slave configuration disagree on DMA direction\n"); "Transfer and slave configuration disagree on DMA direction\n");
...@@ -479,7 +474,8 @@ static struct dma_async_tx_descriptor *gn412x_dma_prep_slave_sg( ...@@ -479,7 +474,8 @@ static struct dma_async_tx_descriptor *gn412x_dma_prep_slave_sg(
} else { } else {
gn412x_dma_tx->tx.phys = phys; 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); 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