Physical to virtual address mapping failed

Hi,

For DMA operation i have created a buffer of 300KB,

virtaddr = mmap(NULL, (300*1024), PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_PHYS|MAP_ANON,NOFD, 0);

and then converting this virtaddr to phyaddr by

mem_offset(virtAddr, NOFD, 1, phyAddr, 0);

after that to make use of that buffer for application I am converting physical to virtual addr by

virtaddr = mmap(NULL, 1, PROT_READ|PROT_WRITE, MAP_PHYS,NOFD, phyAddr);

Once the buffer allocated the buffer will be keep on filled and used in for DMA as well as application so the conversion operation also happen in loop which will continuously run. This physical to virtual conversion get fail after some 100 MB transfer of data using that buffer.

with perror() , it is showing “no enough memory” and memory fault is happening.
In linux to convert virt to phy addr or phy to virt no need to free the buffer. Is any similar kind of api available in QNX ??
Since the actual buffer will be in use continuously i don’t want to free the buffer. If I free the virt addr after application uses it, then it free the actual buffer memory too?
How to solve this problem??

Any help would be highly appreciated!!

Thanks, Jagan

You are probably consuming virtual addresses. mmap is NOT a fonction to convert physical address to virtual. It maps it, if you remap the same physical area, this will use up more virtual adresses.

The memory fault is fixed by unmapping the virtual address after using the buffer in the application on the loop-which i have metioned in the last post.

But i don’t want to do unmap the virtual addr (after remapping) in the application.
So is there any API to convert physical addr to virtual? so no unmap is required.

whether the physical to virtual really mapping needed here, we are not able to use the phy addr of mem|_offset() in the application? then is there any other way?

Thanks
Jagan

This was discuss before, it does not make any sense to convert a physical address to virtual. A virtual address only come to existance when mmap occurs. mmap is NOT a fonction that convert physical adresses to virtual addresses, it CREATES virtual addresses out of a pool of available virtual addresses. However strongly you might disagree with this concept you have to accept and live with it.

In your OP what you need to do is keep the orignal virtaddr return by mmap.

Exactly! Getting phys. address of virtual makes sense to program DMA buffer, but why trying to get virt. address of physical? You already have the virtual address!

I agree that I am having the virtual address returned from mmap() and I can use that.
But I am splitting the 300KB into 200 buffers of each 1536 bytes, getting the physical address of 200 buffers using mem_offset() and give each to a descriptor.
I am not maintaining the references of virtual address here. (I am writing some of the code to be generic for linux as well as QNX).

So after the DMA transaction I need virtual address to handle the buffer so I am doing physical to virtual conversion and use the virtual address. That’s why I am using mmap() to do the mapping of the physical address to virtual address. I thought it will return already mapped virtual address but here it is mapping to some other location of process address location and I am getting another virtual address which maps the same physical address. So will you please clarify the following things.

How this works in QNX?
With this I am allocating 1MB of physically contiguous memory.
Virt_addr_1 = mmap(NULL, 1024*1024, PROT_READ|PROT_WRITE|PROT_NOCACHE, MAP_PHYS|MAP_ANON,NOFD, 0);
With this I have got the physical address of the Virt_addr_1
mem_offset(Virt_addr_1, NOFD, 1, phyAddr, 0);

  1. Here I have given the length as 1 (not as 1MB)and I am accessing up to 1MB (ie from phyAddr to phyAddr + 1MB). Here I gave length 1 then how I am able to access phyaddr + 1MB which I am using with DMA and getting proper Data?

After DMA operation I am mapping the phyAddr to another process address space “Virt_addr_2â€

You’ve made assumptions that are wrong. For example, if you mmap a memory area of 1 bytes, you should only access it as if it was a 1 byte memory block, not more. It works only because everything is rounded to 4K which is the smallest page size. You program doesn’t work by design, it work by luck ;-)

Here is what you could do:

Server program mmap 1Meg from which you obtain the physical address to deal with hardware.

Client also mmap the same 1Meg, they don’t need to know about the physical address. If you want to access byte 10000 of the 1Meg block, you simply take the virtual address mmap returned and add 10000. mmap is an expensive operation, you don’t want to do it all the time. If possible only once in the life of the program (both server and client).

As a matter of fact I wouldn’t let the client have direct access to the mmap area of the server. The server would do the job and use messaging to send/receive data. That is how most of QNX subsystem works (network, disk, usb)

Hi Mario,

You’re right, In the allocated 1MB for every mmap of Virt_addr_2 i am accessing only up to 1536 bytes which is less than 4K so it is working some how.

But in qnx there is no equivalent virt_to_phy() & phy_to_virt() calls?? as in linux, which will return the mapped physical and virtual address of a memory block.

please clarify the 3) on my last post (how munmap knows, it should free mapping or to free the allocated contiguous physical memory. in case of contiguous physical memory it also needs to take care of unmapping the virtual address return by it during the allocation.how it will do?).

Thanks
Jagan

No there isn’t, at least that I know of. I had some doubt so I check what the man page about phy_to_virt on Linux says “This function does not handle bus mappings for DMA transfers. In almost all conceivable cases a device driver should not be using this function”. I think that says it all :wink:

If mmap is used to allocated memory (DMAable or not) it’s the corresponding unmap that will return that memory to the system. If mmap is used to map memory into virtual addressing (which is also perfom when allocating memory) , the corresponding unmap will release the virtual address. How it’s done, I do not know the detail, but since the kernel handles virtual adresses it’s not hard to imagine that it keeps track of all this stuff, much like it keeps track of file descriptor. With mmap the pointer returned is like a file descriptor.

Hope this helps.