Linux - KernelThis forum is for all discussion relating to the Linux kernel.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I have written a PCI driver for my device. The device is an FPGA which is configured with a design that allows it to have direct access to memory of a host computer to which the fpga board is connected. My device driver is responsible for translating virtual addresses to physical addresses and sending these to the FPGA so the DMA unit in the FPGA can directly access pages in memory using the physical address.
I want to send about 1 MB of data to the FPGA. I currently 1st mmap the required data file in my c program as follows :
//Open the bitstream file
int fd = open(filename, O_RDWR);
if (fd < 0){
perror("molen_set : Filename Open");
return;
}
//Map bitstream file to memory to read it in via page faults(faster than explicit file I/O)
bs_map = mmap(NULL, length, PROT_WRITE | PROT_READ, MAP_PRIVATE, fd, 0);
This allows the file to be read in via page faults.
Then I get a suitable area from the kernel using another mmap which is called on the PCI device :
//Get user space address of empty kernel memory of length bytes
arg = mmap(NULL, length, PROT_WRITE | PROT_READ, MAP_PRIVATE, htex_handle, 0);
Then I copy the data using memcpy and signal the PCI device to start reading the data using a IOCTL
The problem I have is in the mmap implementation in the PCI driver :
if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
vma->vm_ops = &htex_vm_ops;
htex_vma_open(vma);
return 0;
}
When the driver gets the above call then I assume the kernel has already allocated the required space and its details are in the vma parameter. When I try to view the physical address of the virtual address in the vma i use :
virt_to_phys(vma->vm_start)
But this gives me back the original address. A call like :
DEBUG_MSG("htex_mmap called start:%lx, end:%lx, size:%lx, pfn:%lx, pa:%lx\n",
vma->vm_start, vma->vm_end, vma->vm_end - vma->vm_start,
vma->vm_pgoff, virt_to_phys(vma->vm_start));
Hmm.... Kind of sounds like a pointer issue. Have you double checked your code for inconsistent pointers for specific addresses? I say it like that because if the physical address is not really the address you are hoping for, it may be looking else where instead of the location that you need, hence maybe you missed a pointer? I am just giving my two cents on your issue, that is all.
Well yes, the pointers i have used in my code are correct. It seems that perhaps I am not looking up the physical address in the right way.
virt_to_phys(vma->vm_start) seem to only work for kernel logical addresses and not virtual addresses.
struct page *pg = pfn_to_page(vma->vm_pgoff); may be returniing 0 because vma->vm_pgoff represents the offset of the area in the file, in pages. When a file or device is mapped, this is apparently the file position of the first page mapped in this area. So it should be 0
Which leaves the question, how would I translate a virtual address to physical address inside the driver's mmap() implementation ?
-----------
Well it seems that I need to use the DMA API as virt_to_phys() does not work on all platforms.
One thing I am not sure of though is , when my driver gets the mmap() call then has the
kernel already allocated memory and put its details in the vma
parameter or do I need to allocate memory myself (using dma API or whatever else)
I am already using the driver read and write functions to read/write
some other parameters to the FPGA, so I will setup the DMA in mmap()
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.