DMA usage at linux kernel - B4860 (fsl BSP)

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

DMA usage at linux kernel - B4860 (fsl BSP)

1,288 Views
ihaymov
Contributor II

Hello.

I am trying to write a kernel driver which copies a large buffer (say 25KB in length) from user space into kernel space with a final destination to the PCIe EP (endpoint) device which is an FPGA device having a memory FIFO to be written into.

I am using an old kernel linux: 3.8.13 

The DMA allocation should be consistent/coherent DMA mapping.

Already written in driver:

//check if core device has properly DMA access:

if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))

{ ... }

else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))

{ ... }

else

{  ... //no suitable DMA avilable... }

dma_buffer = pci_alloc_consistent(pdevice, BUFFER_SIZE, &dma_bus);

... 

// at the ioctl function:

copy_from_user(...);

memcpy(dma_buffer, &WriteBuffer.Buffer[0], BUFFER_SIZE);

Please your advice - why the memcpy() function does not copy the content of the buffer into the DMA allocated buffer?

Labels (1)
Tags (4)
0 Kudos
3 Replies

1,023 Views
yipingwang
NXP TechSupport
NXP TechSupport

To allocate and map large (PAGE_SIZE or so) consistent DMA regions, you should do:

dma_addr_t dma_handle;

cpu_addr = pci_alloc_consistent(dev, size, &dma_handle);

This routine will allocate RAM for that region, so it acts similarly to __get_free_pages (but takes size instead of a page order).  If your

driver needs regions sized smaller than a page, you may prefer using the pci_pool interface, described below.

 

It returns two values: the virtual address which you can use to access it from the CPU and dma_handle which you pass to the card.

The cpu return address and the DMA bus master address are both guaranteed to be aligned to the smallest PAGE_SIZE order which

is greater than or equal to the requested size.  This invariant exists (for example) to guarantee that if you allocate a chunk which is smaller than or equal to 64 kilobytes, the extent of the buffer you receive will not cross a 64K boundary.

Please refer to drivers/net/ethernet/intel/e100.c.
static int e100_alloc(struct nic *nic)
{
        nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem),
                &nic->dma_addr);
        return nic->mem ? 0 : -ENOMEM;
}

 if ((err = e100_alloc(nic))) {
         netif_err(nic, probe, nic->netdev, "Cannot alloc driver memory, aborting\n");
         goto err_out_iounmap
 }

... ...

memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);

Thanks,

Yiping





0 Kudos

1,023 Views
ihaymov
Contributor II

Hello Yiping.

I am not able to use memcpy to copy the source buffer content into that DMA-allocated buffer.

Is there an example (a kernel driver and a userspace application) to test the DMA?

Also: what is it :uio-dma? - how it can be used?

Thanks,

I.H.

0 Kudos

1,023 Views
yipingwang
NXP TechSupport
NXP TechSupport
0 Kudos