Hello,
I am using a scatter gather DMA operation provided on the
PPC44EPx to handle a large data move of 2MB from sixteen 128k kmalloc buffers.
I have sixteen scatter / gather descriptors pointing to the allocated memory
which will be transferred to a peripheral on the EBC. This all appears to
be setup and working correctly. Now I want to provide these 16 kmalloc
buffers to a user space process and make them all appear as a contiguous 2MB buffer.
When the handler is called pageptr appears to be a valid
page but the kernel traps with “Bad page state” “Trying to
fix it up, but a reboot is needed” when returned from the handler.
Am I missing something required to modify the page state for the requested
page? Am I even handling the nopage request correctly? I notice the
nopage handler gets called for every 4096 byte page it is trying to map.
How do I map my 128k memory area into the 4k page requests? Is there example
code somewhere that demonstrates using a contiguous memory buffer in user space
when it is comprised of multiple buffers in the kernel space?
First I am allocating 16 buffers using kmalloc:
#define DMABLOCKSIZE 1024
* 128
for (I = 0; I < 16; i++)
{
device->dma_buf[i]
= kmalloc(DMABLOCKSIZE, GFP_DMA | GFP_KERNEL);
sgl->phyaddress
= virt_to_phys(device->dma_buf[i]);
}
Then I am doing the following in the nopage handler:
page* nopage_handler(struct vma, ul address, int* type)
{
unsigned
long physaddr = address – vma->start;
int
index = physaddr / DMABLOCKSIZE;
int
off = physaddr % DMABLOCKSIZE;
struct
page* pageptr = virt_to_page(device->dma_buf[index] + off);
get_page(pageptr);
if
(type)
*type
= VM_FAULT_MINOR;
return
pageptr;
}
Dave Cogley
Software Engineer
Ultra Stereo Labs, Inc.
(805) 549-0161