Kirkwood DMA engine transfer to PCI memory space?

Wolfgang Wegner ww-ml at gmx.de
Wed Oct 6 05:31:34 EDT 2010


Hi all,

I once more started an attempt to implement DMA transfer to the
PCI memory using the Kirkwood XOR (DMA) engine. The device is
an FPGA connected to PCIe via a 88SB2211 PCIe->PCI bridge.

That's my PCI device:
01:08.0 Class ff00: Device 1731:0101 (rev 10)
        Control: I/O- Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx-
        Status: Cap- 66MHz- UDF- FastB2B- ParErr+ DEVSEL=slow >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
        Region 0: Memory at e0000000 (32-bit, non-prefetchable) [size=64M]
        Region 1: Memory at e4000000 (32-bit, non-prefetchable) [size=256]

I can write to the 64M buffer space via writel() or map the
buffer to userspace and then write to it, both successfully.

And this is my DMA transfer function, I guess its source should
be obvious (dma_async_memcpy_buf_to_buf() slightly castrated):

dma_cookie_t
dma_async_memcpy_buf_to_dev(struct dma_chan *chan, void *dest,
                        void *src, size_t len)
{
        struct dma_device *dev = chan->device;
        struct dma_async_tx_descriptor *tx;
        dma_addr_t dma_dest, dma_src;
        dma_cookie_t cookie;
        int cpu;
        unsigned long flags;

        dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
#if 0
        dma_dest = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
#else
        dma_dest = dest;
#endif
        flags = DMA_CTRL_ACK |
                DMA_COMPL_SRC_UNMAP_SINGLE |
                DMA_COMPL_DEST_UNMAP_SINGLE;
        tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags);

        if (!tx) {
                dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
//                dma_unmap_single(dev->dev, dma_dest, len, DMA_FROM_DEVICE);
                return -ENOMEM;
        }

        tx->callback = NULL;
        cookie = tx->tx_submit(tx);

        cpu = get_cpu();
        per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
        per_cpu_ptr(chan->local, cpu)->memcpy_count++;
        put_cpu();

        return cookie;
}

When using a buffer obtained with dma_alloc_coherent() as the destination
the transfer works fine. When using the PCI memory address as the
destination, the transfer silently fails - the buffer simply does not
change contents, but I did not see any error condition either (cookie
is always non-negative).

Is there something obvious I am doing wrong? From Kirkwood documentation
I can not see a limitation of the XOR engine like being able to do
mem-mem transfers only, neither in the kernel code (which, however, I
did not yet completely understand).

Any hints would be appreciated!

Best regards,
Wolfgang




More information about the linux-arm-kernel mailing list