简体   繁体   English

MMAP失败超过4k

[英]MMAP fails above 4k size

This is my first post so please let me know if there is any mistake from . 这是我的第一篇文章,如果有任何错误,请告诉我。

My aim is to get approx 150MBytes of data transfer from KERNEL to user space. 我的目标是从KERNEL到用户空间获得大约150MB的数据传输。 [This is because i am building an driver for DMA device on OMAP l138 to transfer and receive data between DMA DEVICE and FPGA] [这是因为我在OMAP l138上为DMA设备构建驱动程序,以便在DMA DEVICE和FPGA之间传输和接收数据]

  1. Now in LINUX KERNEL i am allocating BUFFER of VARIABLE size using dma_alloc_coherent 现在在LINUX KERNEL中,我使用dma_alloc_coherent分配VARIABLE大小的BUFFER
  2. Then the PHYSICAL address of this buffer i am passing to user space to be user as OFFSET parameter to be used for mmap call from user space . 然后我将这个缓冲区的PHYSICAL地址传递给用户空间作为OFFSET参数,用于从用户空间进行mmap调用。
  3. Then from data is copied and read back to and from from user space to kernel 然后从数据中复制并读回用户空间到内核

This logic work fine till size of buffer is 4096. Above 4k the mmap fails and return "MAP_FAILED" 这个逻辑工作正常,直到缓冲区大小为4096.高于4k mmap失败并返回“MAP_FAILED”

static int driver_mmap(struct file *f, struct vm_area_struct *vma)
{

    u32bit ret;
    u32bit size = (vma->vm_end)-(vma->vm_start);

    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);

    if (size > (NUM_PAGE*PAGE_SIZE)){
        return(-1);  
    }

    if ((ret = remap_pfn_range(vma,vma->vm_start,
                    (virt_to_phys((void *)krnl_area) >> PAGE_SHIFT),
                    size,vma->vm_page_prot)) < 0)
    {
        return ret;  
    }
    printk("\nDVR:The MMAP returned %x to USER SAPCE \n",ret);
    return 0;  

}


//MMAP STEP 1
dmasrc_ptr = dma_alloc_coherent( NULL ,GLOBAL_BUFFER_SIZE , &dmasrc ,0);
if( !dmasrc_ptr ) {
    printk(KERN_INFO "DMA_ALLOC_FAILED for the source buffer ...\n");
    return -ENOMEM;
}else{
    printk( "\n--->The address of SRC is %x..\n",dmasrc_ptr);       
}

temp_source=dmasrc_ptr;



//MMAP STEP 2
// Round the allocated KERNEL MEMORY to the page bondary   
krnl_area=(int *)((((unsigned long)dmasrc_ptr) + PAGE_SIZE - 1)&PAGE_MASK); 
printk(KERN_CRIT "DVR:The KERNEL VIRTUAL ADDRS is %x..\n",krnl_area);

//MMAP STEP 3
// Marking the PAGES as RESERVED 
for (i = 0; i < (NUM_PAGE * PAGE_SIZE); i+= PAGE_SIZE) {  
    SetPageReserved(virt_to_page(((unsigned long)krnl_area) + i)); 


//Application code part

while(1){

    fflush(stdin);
    fflush(stdout);

    printf("\n\n\n----------------------------------------------------\n");
    printf("USR:Please enter your requirement ");
    printf("\n----------------------------------------------------\n");
    printf("\t1----->GET_UPP_OFFSET\n");
    printf("\t2----->UPP_MMAP_CALL\n");
    printf("\t3----->IOCTL_UPP_WRITE\n");
    printf("\t4----->IOCTL_UPP_READ\n");

    printf("\n");
    scanf("%d",&option);
    printf("\nThe OPTION is %d..\n",option);
    printf("\n");

    switch(option){

    case 1 :
    {
        offset=0;
        ret = ioctl(dev_FD ,IOCTL_UPP_START, &info);
        if (ret < 0) {
            printf("dma buffer info ioctl failed\n");
        }       
        offset = info.var;      
        printf("THE ADDRESS WE GOT IS %X..\n",offset);

    }
    break;

    case 2 :
    {
        printf("THE OFFSET is %X..\n",offset);
        mmap_Ptr= mmap(0,BUFFER_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, dev_FD, 0);     
        if (mmap_Ptr == MAP_FAILED){
            printf("USR[UPP] :MMAP FAiled \n\n");
            close(dev_FD);
            exit(-1);   
        }
        printf("THE MMAP address is %X..\n",mmap_Ptr);

    }
    break;

    case 3:
    {
        struct upp_struct user_local_struct;

        printf("\n***************************************************\n");
        for (i = 0; i <(1024);i++) {  
            *(mmap_Ptr+i)=test_var;
            printf("WR:%X ",*(mmap_Ptr+i));
            //test_var++; 
        } 
        ioctl(dev_FD , IOCTL_UPP_WRITE ,&user_local_struct);    

        printf("\n***************************************************\n\n\n");
        for(i=0;i<20402;i++){
            //NOP
        }

        //test_var=0x00;
    }
    break;

    case 4:
    {
        struct upp_struct user_local_struct;
        ioctl(dev_FD , IOCTL_UPP_READ,&user_local_struct);

        for(i=0;i<20402;i++){
            //NOP
        }
        printf("\n***************************************************\n");
        for (i = 0; i <(1024);i++) {  
            printf("RD:%X",*(mmap_Ptr+i));  
        }
        printf("\n***************************************************\n\n\n");  
    }
    break;

    default:
    { 
        printf("USR:You have entered an wrong option \n");
        printf("\nUSR:CLosing the FILE ENTERIES ...\n");
        munmap(mmap_Ptr,BUFFER_SIZE);
        free(source_ptr);
        free(dest_ptr);
        close(dev_FD);
        exit(0);
    }
    break;

} //END OF SWITCH LOOP  

} //END OF WHILE LOOP

使用get_free_pages分配多个页面,或者使用vmalloc但是你需要在每个页面都调用remap_pfn_range,因为vmalloc-ed物理内存可能不是物理上连续的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM