--- Quote Start ---
I am trying to use the functions to sync the memory buffer so the FPGA can handle the data, but I am getting a segmentation fault when calling the dma_sync_single_for_device function, so I wonder if I am using the wrong parameters,
what is the dma_addr_t dma_handle parameter? is it the physical address? or the virtual address after the mem allocation? I read that the dma_addr_t is not the same as the physical address, or am I missing something before calling the functions, something like doing a dma map before?
--- Quote End ---
Here's how my driver gets buf_phys_addr for dma_handle parameter:
typedef struct _yx_buffer {
struct page *buf;
unsigned long buf_phys_addr;
size_t buf_len;
} Buffer;
static int
_allocBuffer(struct platform_device *pdev, Buffer *b, int page){
dma_addr_t dma;
b->buf = alloc_pages(GFP_ATOMIC, page);
if (!b->buf) {
dev_err(&pdev->dev, "Error allocating buffer 2^%d pages of %lu\n",
page, PAGE_SIZE);
return -ENOMEM;
}
dma = dma_map_page(&pdev->dev, b->buf, 0, page, DMA_BIDIRECTIONAL);
if(dma != page_to_phys(b->buf)){
dev_err(&pdev->dev, "BAD DMA ASSUMPTION: page address is %u, and dma is %u\n",
page_to_phys(b->buf), dma);
return -ENOMEM;
}
b->buf_phys_addr = page_to_phys(b->buf);
b->buf_len = (1 << page) * PAGE_SIZE;
dev_info(&pdev->dev, "allocBuffer, %lx at size %u bytes\n",
b->buf_phys_addr, b->buf_len);
return 0;
}
Also, if you're using ioctl control between app and driver, make sure you define it with the _IOR macro. I first made the mistake of using a simple number which collides with existing ioctl.
# define SYNC_DEVICE _IOR(0xAF, 1, unsigned long)# define SYNC_CPU _IOR(0xAF, 2, unsigned long)
On the memory mapping, I guess that should work but I don't have working experience with that arrangement.
--- Quote Start ---
If I would like to use the ACP port, I need to send to the FPGA module the physical address | 0x80000000, right? so how did you get the buffer's physical address you allocated? Using the same function page_to_phys?
--- Quote End ---
Yes, page_to_phys in the driver is where it is first assigned. The GnuRadio FPGA module approach I linked to earlier takes that address and creates a device attribute out of it which is then read by the user-space application using the udev library given the device tree node of the accelerator (which looks something like "ff203000.accel" on my system).
Yes, definitely test using the ACP because that's simpler than the DMA scheme.