I am trying to allocate some memory on CycloneV ARM9 in the Linux kernel.
This is the code in the driver
typedef struct tx_dma_buf {
volatile phys_addr_t phys_addr;
volatile unsigned int *virt_addr;
volatile unsigned int *dma_regs;
dma_addr_t *dma_handle;
struct device *dev;
} buf_t;
typedef struct bufs
{
buf_t *tx_buf;
buf_t *rx_buf;
struct cdev cdev;
struct class *class;
dev_t dev_node;
} buffers_t;
buf_t *tx_buf;
buf_t *rx_buf;
buffers_t *buf;
static int __init my_init(void)
{
int err;
printk(KERN_INFO, "my_init\n");
buf = (buffers_t*)kmalloc(sizeof(buffers_t*), GFP_KERNEL);
tx_buf = (buf_t *) kmalloc(sizeof(buf_t), GFP_KERNEL);
tx_buf->dev = (struct device*)kmalloc(sizeof(struct device), GFP_KERNEL);
tx_buf->virt_addr = dma_alloc_coherent(tx_buf->dev, BUFFER_SIZE, tx_buf->dma_handle, GFP_KERNEL);
rx_buf = (buf_t *) kmalloc(sizeof(buf_t), GFP_KERNEL);
rx_buf->dev = (struct device*)kmalloc(sizeof(struct device), GFP_KERNEL);
rx_buf->phys_addr = dma_alloc_coherent(rx_buf->dev, BUFFER_SIZE, rx_buf->dma_handle, GFP_KERNEL);
buf->tx_buf = tx_buf;
buf->rx_buf = rx_buf;
Then in the dmesg upon loading the module
[ 138.309547] buff_alloc: loading out-of-tree module taints kernel.
[ 138.316499] ------------[ cut here ]------------
[ 138.321165] WARNING: CPU: 0 PID: 344 at kernel/dma/mapping.c:303 dma_alloc_attrs+0x114/0x124
[ 138.329624] Modules linked in: buff_alloc(O+)
[ 138.333979] CPU: 0 PID: 344 Comm: insmod Tainted: G O 5.4.44-05622-gcda983e75c17 #3
[ 138.342896] Hardware name: Altera SOCFPGA
[ 138.346889] Backtrace:
[ 138.349340] [<c010d5a0>] (dump_backtrace) from [<c010d8b8>] (show_stack+0x20/0x24)
...
[ 138.539173] 8<--- cut here ---
[ 138.542223] Unable to handle kernel paging request at virtual address 6e69622f
[ 138.549442] pgd = 954810e3
[ 138.552142] [6e69622f] *pgd=00000000
[ 138.555731] Internal error: Oops: 5 [#1] SMP ARM
[ 138.560335] Modules linked in: buff_alloc(O+)
[ 138.564683] CPU: 0 PID: 344 Comm: insmod Tainted: G W O 5.4.44-05622-gcda983e75c17 #3
[ 138.573598] Hardware name: Altera SOCFPGA
[ 138.577598] PC is at string_nocheck+0x28/0x90
[ 138.581938] LR is at 0xffffffff
[ 138.585065] pc : [<c08ad3d4>] lr : [<ffffffff>] psr: a00f0013
...
I think everything in the driver is allocated such that dma_alloc_coherent isn't receiving NULLs that it should not be. I was able to get kmalloc to work, but when using kmalloc, I think I am having cache consistency issues between the OS and firmware that is interacting with the SDRAM. If there is an obvious problem with the code, I don't see it, but if it is a deeper issue with the call to the OS (something in the kernel), I will need help diagnosing the problem.
UPDATE
I tried putting the same call in a probe function and using the platform_device dev. I looked at a Xilinx driver example, and it seemed that was how it was done. https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842418/Linux+DMA+From+User+Space?preview=/18842418/18848721/dma-proxy.zip
It seems to fail the same way. Here is my new snippet
static int dmabuffer_probe(struct platform_device *pdev)
{
printk(KERN_INFO "dmabuffer module initialized\n");
buf = (buf_t*)kmalloc(sizeof(buf_t*), GFP_KERNEL);
buf->dev = &pdev->dev;
buf->virt_addr = dma_alloc_coherent(buf->dev, BUFFER_SIZE, buf->dma_handle, GFP_KERNEL);
return 0;
}
User contributions licensed under CC BY-SA 3.0