hisi mmz模块驱动讲解
一、概述如图所示,在海思平台上将内存分为两个部分:os内存和mmz内存。os内存指:由linux操作系统管理的内存;mmz内存:由mmz驱动模块进行管理供媒体业务单独使用的内存,在驱动加载时可以指定该模块管理内存的大小: insmod hi_osal.ko mmz=anonymous,0x4fa00000,6Manony=1 || report_error 二、数据结构1、mmz区域描述符struct hil_media_memory_zone { ???char name[HIL_MMZ_NAME_LEN+1]; //mmz区域名字:anonymous ??????? ???unsigned long gfp;?? //区域标识:0 ? ???unsigned long phys_start; //mmz区域起始物理地址:0x4fa00000 ???unsigned long nbytes; //mmz区域大小:6M ??????? ???struct list_head list; //mmz链表 ? ???unsigned char *bitmap; //位图 ???struct list_head mmb_list; //mmz区域的mmb链表,存放所有申请到的物理内存 ??? ???unsigned int alloc_type; ???unsigned long block_align; ??? ???void (*destructor)(const void *); }; 2、mmb内存描述符hil_media_memory_block描述了从mmz区域申请一块内存,同一个mmz区域内的所有mmb通过链表连接。 struct hil_media_memory_block { ???#ifndef MMZ_V2_SUPPORT ???unsigned int id; ???#endif ???char name[HIL_MMB_NAME_LEN+1]; //该mmb模块使用者名字 ???struct hil_media_memory_zone *zone; //指向mmb所属的mmz区域 ???struct list_head list; //mmb链表 ??? ???? ???unsigned long phys_addr; //申请到的mmb起始物理地址 ???void *kvirt;? //对应内核虚拟地址,从代码看未用 ???unsigned long length; //申请的mmb大小 ??? ???unsigned long flags; //标识 ??? ???unsigned int order; ? ???int phy_ref; //引用计数 ???int map_ref; //引用计数 }; 3、mmz_userdev_info该结构体保存打开该设备文件的进程信息,存放在file结构体的private_data成员里。 struct mmz_userdev_info { ???pid_t pid; ??????? //打开设备文件的进程pid ???pid_t mmap_pid; ???struct semaphore sem; //信号量 ???struct list_head list; //指向mmb_info链表 }; 4、mmb_info该结构体描述应用申请到mmb后的相关信息,同进程的mmb_info通过链表形式管理。 struct mmb_info { ???unsigned long phys_addr;??? //申请到的物理内存,同mmb.phys.addr ???unsigned long align;??????? /* ifyou need your phys-memory have special align size */ ???unsigned long size;???? //申请的物理内存大小 ???unsigned int order; ??? ??? void *mapped;?????? //指向mmap后的虚拟地址空间 ??????? ???union { ???????struct { ???????????unsigned long prot? :8; /*PROT_READ or PROT_WRITE */ ???????????unsigned long flags :12;/* MAP_SHARED or MAP_PRIVATE */ ??? #ifdef __KERNEL__ ???????????unsigned long reserved :8; /* reserved,do not use */ ???????????unsigned long delayed_free :1; ???????????unsigned long map_cached :1; #endif ???????}; ???????unsigned long w32_stuf; ???}; ??? ???char mmb_name[HIL_MMB_NAME_LEN+1]; ???char mmz_name[HIL_MMZ_NAME_LEN+1]; ???unsigned long gfp;????? /*reserved,do set to 0 */ ??? #ifdef __KERNEL__ ???int map_ref; ???int mmb_ref; ??????? ???struct list_head list;??? //mmb_info链表 ???hil_mmb_t *mmb;???? //指向申请到的mmb #endif }; 三、关系图1、mmz和mmb关系下图展示了mmz驱动管理mmz和mmb的关系。mmz驱动模块支持多个mmz区域,只要在加载mmz.ko时通过参数传递即可,一般情况下只有一个mmz区域。多个mmz区域之间通过链表的形式组织在一起,链表头为mmz_list;而每个mmz区域通过mmb_list维护mmb链表,管理该区域内所有已经申请了的物理内存区域;每个mmb通过zone成员知道自己属于哪个mmz区域。 通过/proc/media-mem可以查看mmz和mmb使用情况: +---ZONE: PHYS(0x4FA00000,0x4FFFFFFF),GFP=0,nBYTES=6144KB,??NAME="anonymous" ??|-MMB: phys(0x4FA00000,0x4FA81FFF),kvirt=0x? (null),flags=0x00000000,length=520KB,?????? name="DCCM_MSG_BUF" ??|-MMB: phys(0x4FA82000,0x4FA84FFF),length=12KB,??????? name="SYS_scale_coef" ??|-MMB: phys(0x4FA85000,0x4FA87FFF),??????? name="SYS_scale_coef" ??|-MMB: phys(0x4FA88000,0x4FB07FFF),length=512KB,?????? name="TDE_MemPool" ?? |-MMB: phys(0x4FB08000,0x4FB3CFFF),length=212KB,??????name="IVE_QUEUE" ??|-MMB: phys(0x4FB3D000,0x4FB3DFFF),length=4KB,name="IVE_TEMP_NODE" ?? ??--MMZ_USE_INFO: total size=6144KB(6MB),used=1272KB(1MB +248KB),remain=4872KB(4MB + 776KB),zone_number=1,block_number=6 2、mmb、mmb_info和mmb_userdev_info关系下图展示了mmz驱动和应用申请数据结构之间的关系: 当应用打开设备文件/dev/mmz_userdev时会申请一个属于该进程的mmb_userdev_info结构体,mmb_userdev_info成员list指向属于该进程的所有mmb_info,mmb_info的mmb成员指向为其分配的mmb,而*mmaped存放mmb物理内存(phy_addr)进行映射后的虚拟地址供用户空间使用。 由于mmz大部分为媒体业务独立使用,内存在媒体硬件模块流转,应用无需访问,这时不用映射,只有当应用需要访问时才需要进行映射。可以把mmz管理的整个内存看做存储盘上的一个大文件,应用层要访问mmz的物理内存通过mmap方式进行映射(类似文件),映射的文件偏移就是mmb.phy_addr,映射大小就是申请的mmb.length,通过mmap方式映射到内核后根据返回的虚拟地址就可以访问该mmb内存。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |