This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Dm3730 GPMC using DMA problem

Other Parts Discussed in Thread: DM3730

Hi everybody.

I want to transfer data between FPGA and DM3730 using GPMC.

My linux platform driver works fine when I read from and write to FPGA using  __reg_read and __reg_write functions.  

However, when I want to use DMA over GPMC, I get  two different problems: 

1-  if I use "omap_set_dma_transfer_params(pdata->dma_ch, OMAP_DMA_DATA_TYPE_S16, 0x10, 1, OMAP_DMA_SYNC_FRAME, 0, OMAP_DMA_SRC_SYNC);"

after starting DMA, I will see that data transfer between FPGA and DM3730 takes place,

but I get this error: info: trying to register non-static key and kernel crashes.

2- if I use "omap_set_dma_transfer_params(pdata->dma_ch, OMAP_DMA_DATA_TYPE_S16, 0x10, 1, OMAP_DMA_SYNC_FRAME, OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);"

after starting DMA, nothing will happen between FPGA and DM3730 and DMA_callback function will not be called.

I appreciate any help or hint.

Here are important parts of my code:

*************************************************************

       if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {                                 
                pr_err("Failed to request GPMC mem region\n");                                         
                return;                                                                                
        }                                                                                              
                                                                                                       
        gpmc_fpga_resources[0].start = cs_mem_base + 0x0;                                              
        gpmc_fpga_resources[0].end = cs_mem_base + 0x10000;   

***************************************************************

static int fpga_probe(struct platform_device *p)

{

struct fpga_device_data *pdata = p->dev.platform_data; res = platform_get_resource_byname(p, IORESOURCE_MEM, "fpga-memory"); request_mem_region(res->start, res_size, FPGA_CHIPNAME); pdata->phys_base = res->start; pdata->ioaddr = ioremap(res->start, res_size); err = omap_request_dma(OMAP24XX_DMA_GPMC, pdata->name, fpga_dma_callback, pdata, &pdata->dma_ch); return err; }

****************************************************

static void fpga_dma_callback(int channel_num, u16 ch_status, void *data)
{

    struct fpga_device_data *pdata;
    pdata = (struct fpga_device_data *)data;
    complete(&pdata->dma_complete);

}

*******************************************************

static int fpga_read(struct file *filp, char *buffer, size_t length, loff_t *offset)
{
        struct miscdevice *misc;
        struct fpga_device_data *pdata;
        int size = 2048;
        char *DMA_buf = kmalloc(size, GFP_KERNEL | GFP_DMA);

        misc = filp->private_data;
        pdata = misc->this_device->platform_data;


        pdata->dma_phys_addr = dma_map_single(&pdata->dev, DMA_buf, size, DMA_FROM_DEVICE);
        if (dma_mapping_error(&pdata->dev, pdata->dma_phys_addr)) {
                pr_info("dma_map_single() failed\n");
                kfree(DMA_buf);
                return -1;
        } else {
                pr_info("dma_map_single() succeeded: %d", pdata->dma_phys_addr);
        }

        omap_set_dma_src_params(pdata->dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, pdata->phys_base, 0, 0);
        omap_set_dma_dest_params(pdata->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, pdata->dma_phys_addr, 0, 0);

omap_set_dma_transfer_params(pdata->dma_ch, OMAP_DMA_DATA_TYPE_S16, 0x10, 1, OMAP_DMA_SYNC_FRAME, 0, OMAP_DMA_SRC_SYNC);
//omap_set_dma_transfer_params(pdata->dma_ch, OMAP_DMA_DATA_TYPE_S16, 0x10, 1, OMAP_DMA_SYNC_FRAME, OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);

//wait for interrupt line from FPGA
wait_event_interruptible(fpga_queue, fpga_flag != 0); init_completion(&pdata->dma_complete); omap_start_dma(pdata->dma_ch); wait_for_completion(&pdata->dma_complete); dma_unmap_single(&pdata->dev, pdata->dma_phys_addr, size, DMA_FROM_DEVICE); kfree(DMA_buf); fpga_flag =0; return 0; }


  • Hi Amin,

    The 6th parameter (dma_trigger) of the omap_set_dma_transfer_params function should be 0. I would like to focus on the error message and the conditions which causes the crash. If I understand the data transfer starting and then the crash appears.
    If the system is not stuck could you execute 'dmesg' and post the output. Also the would like to see the crash log.
    I only guess that the reason could be some memory overlapping but it is needed deeper investigation.

    BR
    Tsvetolin Shulev
  • Hi Cvetolin,
    Thanks for your kindly reply.

    Yes, Transfer takes place, but after starting dma, kernel crashes. I can not able to read the buffer which I allocated to DMA data.

    By the way, I use an interrupt line between FPGA and DM3730 to be acknowledged of data in FPGA FIFO. I use wait_event_interruptible(fpga_queue, fpga_flag != 0); in my read function to wait for data interrupt. After receiving interrupt, DMA is initialized and started. the line in read function code is commented by mistake.

    Unfortunately, system is stuck. but here is the crash log:

    [ 1749.738586] dma_map_single() succeeded
    [ 1761.917449] fpga_read: line 137 : interrupt received
    [ 1761.922851] fpga_read: DMA INIT completed!
    [ 1761.927337] fpga_read: line 147 : DMA start
    [ 1761.931762] INFO: trying to register non-static key.
    [ 1761.936981] the code is fine but needs lockdep annotation.
    [ 1761.942749] turning off the locking correctness validator.
    [ 1761.948577] [<c00545b4>] (unwind_backtrace+0x0/0x138) from [<c00b8140>] (__lock_acquire+0x1d 00/0x1d30)
    [ 1761.958374] [<c00b8140>] (__lock_acquire+0x1d00/0x1d30) from [<c00b8778>] (lock_acquire+0xd4 /0xf8)
    [ 1761.967834] [<c00b8778>] (lock_acquire+0xd4/0xf8) from [<c042d5d4>] (_raw_spin_lock_irqsave+ 0x48/0x84)
    [ 1761.977630] [<c042d5d4>] (_raw_spin_lock_irqsave+0x48/0x84) from [<c0077cec>] (complete+0x1c /0x5c)
    [ 1761.987060] [<c0077cec>] (complete+0x1c/0x5c) from [<c006e3d0>] (omap2_dma_irq_handler+0x23c /0x3e0)
    [ 1761.996612] [<c006e3d0>] (omap2_dma_irq_handler+0x23c/0x3e0) from [<c00c9734>] (handle_irq_e vent_percpu+0x78/0x220)
    [ 1762.007598] [<c00c9734>] (handle_irq_event_percpu+0x78/0x220) from [<c00c9918>] (handle_irq_ event+0x3c/0x5c)
    [ 1762.017944] [<c00c9918>] (handle_irq_event+0x3c/0x5c) from [<c00cbb0c>] (handle_level_irq+0x 90/0x100)
    [ 1762.027648] [<c00cbb0c>] (handle_level_irq+0x90/0x100) from [<c00c93a8>] (generic_handle_irq +0x38/0x40)
    [ 1762.037536] [<c00c93a8>] (generic_handle_irq+0x38/0x40) from [<c0042038>] (asm_do_IRQ+0x38/0 x84)
    [ 1762.046813] [<c0042038>] (asm_do_IRQ+0x38/0x84) from [<c042df38>] (__irq_svc+0x38/0xa0)
    [ 1762.055206] Exception stack(0xdf8f7e28 to 0xdf8f7e70)
    [ 1762.060546] 7e20: c008183c dd2d5040 60000013 df8f6000 df8f7ead df8f7ead
    [ 1762.069152] 7e40: 0000000f 000000dc 00000003 c077f7af c077f78c c05daae8 df8f6000 df8f7e70
    [ 1762.077728] 7e60: c0081d44 c0081d4c 60000013 ffffffff
    [ 1762.083068] [<c042df38>] (__irq_svc+0x38/0xa0) from [<c0081d4c>] (vprintk+0x1e4/0x47c)
    [ 1762.091430] [<c0081d4c>] (vprintk+0x1e4/0x47c) from [<c042a24c>] (printk+0x1c/0x2c)
    [ 1762.099487] [<c042a24c>] (printk+0x1c/0x2c) from [<c02eb414>] (fpga_read+0x1f8/0x280)
    [ 1762.107757] [<c02eb414>] (fpga_read+0x1f8/0x280) from [<c0121190>] (vfs_read+0xb4/0x148)
    [ 1762.116271] [<c0121190>] (vfs_read+0xb4/0x148) from [<c01212f4>] (sys_read+0x40/0x70)
    [ 1762.124542] [<c01212f4>] (sys_read+0x40/0x70) from [<c004e120>] (ret_fast_syscall+0x0/0x3c)
    [ 1770.060729] BUG: spinlock lockup on CPU#0, fpga_app_read/540, dece4e40
    [ 1770.067626] [<c00545b4>] (unwind_backtrace+0x0/0x138) from [<c024e940>] (do_raw_spin_lock+0x13c/0x174)
    [ 1770.077423] [<c024e940>] (do_raw_spin_lock+0x13c/0x174) from [<c042d5f8>] (_raw_spin_lock_irqsave+0x6c/0x84)
    [ 1770.087768] [<c042d5f8>] (_raw_spin_lock_irqsave+0x6c/0x84) from [<c0077cec>] (complete+0x1c/0x5c)
    [ 1770.097198] [<c0077cec>] (complete+0x1c/0x5c) from [<c006e3d0>] (omap2_dma_irq_handler+0x23c/0x3e0)
    [ 1770.106719] [<c006e3d0>] (omap2_dma_irq_handler+0x23c/0x3e0) from [<c00c9734>] (handle_irq_event_percpu+0x78/0x220)
    [ 1770.117706] [<c00c9734>] (handle_irq_event_percpu+0x78/0x220) from [<c00c9918>] (handle_irq_event+0x3c/0x5c)
    [ 1770.128051] [<c00c9918>] (handle_irq_event+0x3c/0x5c) from [<c00cbb0c>] (handle_level_irq+0x90/0x100)
    [ 1770.137786] [<c00cbb0c>] (handle_level_irq+0x90/0x100) from [<c00c93a8>] (generic_handle_irq+0x38/0x40)
    [ 1770.147674] [<c00c93a8>] (generic_handle_irq+0x38/0x40) from [<c0042038>] (asm_do_IRQ+0x38/0x84)
    [ 1770.156921] [<c0042038>] (asm_do_IRQ+0x38/0x84) from [<c042df38>] (__irq_svc+0x38/0xa0)
    [ 1770.165313] Exception stack(0xdf8f7e28 to 0xdf8f7e70)
    [ 1770.170654] 7e20: c008183c dd2d5040 60000013 df8f6000 df8f7ead df8f7ead
    [ 1770.179260] 7e40: 0000000f 000000dc 00000003 c077f7af c077f78c c05daae8 df8f6000 df8f7e70
    [ 1770.187835] 7e60: c0081d44 c0081d4c 60000013 ffffffff
    [ 1770.193176] [<c042df38>] (__irq_svc+0x38/0xa0) from [<c0081d4c>] (vprintk+0x1e4/0x47c)
    [ 1770.201507] [<c0081d4c>] (vprintk+0x1e4/0x47c) from [<c042a24c>] (printk+0x1c/0x2c)
    [ 1770.209594] [<c042a24c>] (printk+0x1c/0x2c) from [<c02eb414>] (fpga_read+0x1f8/0x280)
    [ 1770.217834] [<c02eb414>] (fpga_read+0x1f8/0x280) from [<c0121190>] (vfs_read+0xb4/0x148)
    [ 1770.226379] [<c0121190>] (vfs_read+0xb4/0x148) from [<c01212f4>] (sys_read+0x40/0x70)
    [ 1770.234619] [<c01212f4>] (sys_read+0x40/0x70) from [<c004e120>] (ret_fast_syscall+0x0/0x3c)
  • Okay, after doing some kernel hack, I found where kernel does crash.

    at the end of omap_start_dma function, when it tries to dma_write.

    /*********************************************/
    omap_enable_channel_irq(lch);

    l = p->dma_read(CCR, lch);

    if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING))
    l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
    l |= OMAP_DMA_CCR_EN;

    =========> p->dma_write(l, CCR, lch);

    dma_chan[lch].flags |= OMAP_DMA_ACTIVE;

    }
    EXPORT_SYMBOL(omap_start_dma);

    /*********************************************/

    in omap_set_dma_src_params and omap_set_dma_dest_params functions, which are using dma_write function, everything is okay.

    does anybody have any idea about this problem? what is CCR?
  • Amin,

    I only can guess for the reason of the issue but you should check the values of the parameters which corresponds to what values you are writing to the DMA.
    The CCR represents the index (i = 0..31) of the Channel Control Register DMA4_CCRi. You can find more details in the TRM table 11-36.

    BR
    Tsvetolin Shulev