linux mmc 读写,linux内核mmc读写分析
MMC 读写分析
EMMC读写操作的调用栈
mmc_queue_thread ->
mmc_blk_issue_rq ->
mmc_blk_issue_rw_rq ->
mmc_start_req ->
__mmc_start_data_req ->
mmc_start_request ->
omap_hsmmc_request
首先mmc_queue_thread获取相应的mmc_request然然后调用mq->issue_fn处理reuqest,issue_fn有可能被阻塞在mmc_wait_for_data_req_done,如果此时有新的请求到达,那么有可能会唤醒阻塞的进程(条件是cur==null, prev!=null)。
然后调用mmc_blk_issue_rq来选择对应的分区,根据req->cmd_flags的命令做不同的事情。REQ_SANITIZE、REQ_DISCARD、REQ_FLUSH分别为
2.1 mmc_blk_issue_secdiscard_rq 和mmc_blk_issue_discard_rq
2.2 mmc_blk_issue_flush
2.3 mmc_blk_issue_rw_rq,这个是我们要分析的读写数据流程
进入mmc_blk_issue_rw_rq函数
如果参数req为空(无新request),或者mmc queue的previous request也为空(无未完成的request),那么mmc_blk_issue_rw_rq直接返回。
mmc_blk_prep_packed_list尝试把当前request和队列中的其他request合并,以增强性能。是否可以合并,要依赖于:
1. 控制器支持packed功能
2. device的MAX_PACKED_WRITES大于0
3. 只对写request进行packed
正常情况下执行mmc_blk_rw_rq_prep函数,从request构造mmc_request,毕竟下发给host请求,是mmc_request,而不是block层通用的request。如果支持packed功能,那么就用pack_list来构造mmc_request
areq表示async req,实际上,只要参数@req存在,就表明这是一个新request,必然是异步传输的。
mmc_start_req 启动一个非阻塞的request,这个函数会等待前一个request完成,然后把启动当前requeset,并立刻返回
如果mmc_start_req返回的areq不为空,说明完成了上一次的request,
如果使用了bounce buffer,那么需要把传输结果从bounce buffer复制会sg buffer。所谓bounce buffer是因为某些DMA控制器只能处理连续物理内存,此时需要通过bounce buffer来达到物理内存连续性。
检查mmc_start_req返回的状态:
1. 如果是MMC_BLK_SUCCESS或者MMC_BLK_PARTIAL,需要调用blk_end_request通知block设备层,完成了本次读写request。
2. 如果是MMC_BLK_CMD_ERR,那么调用mmc_blk_reset复位host。调用mmc_blk_cmd_err尝试blk_end_request,如果发现reuqest未完成,说明本次操作失败,反之成功start_new_req
3. ....
真正的执行读写请求是在执行函数mmc_start_req里:
1、首先它会执行到mmc_wait_for_data_req_done函数,等待上一次的命令的完成,如果上一次未完成就会将当前进程加入等待队列休眠,等待被唤醒。当上一次完成后会立即返回,并将上一次命令执行的状态返回给mmc_blk_issue_rw_rq。
2、if (host->areq) {
err = mmc_wait_for_data_req_done(host, host->areq->mrq, areq);
host->areq不为空,说明有正在处理的reuqest,函数mmc_wait_for_data_req_done用来等待这个host->areq,有两个条件会唤醒该MMC上下文: is_done_rcv和is_new_req
if (!err && areq)
start_err = __mmc_start_data_req(host, areq->mrq);
进入__mmc_start_data_req(host, areq->mrq);
首先会将函数指针mmc_wait_data_done赋给mrq->done
if (host->card && host->card->ext_csd.cmdq_mode_en)
mrq->done = mmc_wait_cmdq_done;
else
mrq->done = mmc_wait_data_done;
mmc_wait_data_done会设置context_info->is_done_rcv=true,这正好是唤醒mmc_wait_for_data_req_done的条件之一,然后调wake_up_interruptible(&context_info->wait);唤醒之。
然后会调用mmc_start_request(host, mrq);
mmc_start_reuqest实际调用host->ops->request方法,进入了平台特定的request函数
进入特定的平台之后,会进入相应的中断对硬件进行读写的命令的执行,当命令执行完毕后,会进行函数回调调到刚才的mmc_wait_data_done唤醒等待的进程进行下一次命令的执行。
linux mmc 读写,linux内核mmc读写分析相关推荐
- Linux kernel 3.10内核源码分析--进程上下文切换
一.疑问 进程调度时,当被选中的next进程不是current进程时,需要进行上下文切换. 进行上下文切换时,有一些问题不太容易理解,比如: 1.进程上下文切换必然发生在内核态吗? 2.上下文切换后原 ...
- 一起分析Linux系统设计思想——03内核启动流程分析(六)
在学习资料满天飞的大环境下,知识变得非常零散,体系化的知识并不多,这就导致很多人每天都努力学习到感动自己,最终却收效甚微,甚至放弃学习.我的使命就是过滤掉大量的垃圾信息,将知识体系化,以短平快的方式直 ...
- Linux kernel 3.10内核源码分析--slab原理及相关代码
1.基本原理 我们知道,Linux保护模式下,采用分页机制,内核中物理内存使用buddy system(伙伴系统)进行管理,管理的内存单元大小为一页,也就是说使用buddy system分配内存最少需 ...
- Linux Kernel 3.10内核源码分析--块设备层request plug/unplug机制
一.基本原理 Linux块设备层使用了plug/unplug(蓄流/泄流)的机制来提升IO吞吐量.基本原理为:当IO请求提交时,不知直接提交给底层驱动,而是先将其放入一个队列中(相当于水池),待一定时 ...
- Linux kernel 3.10内核源码分析--TLB相关--TLB概念、flush、TLB lazy模式
一.概念及基本原理 TLB即Translation Lookaside Buffer,是MMU中的一种硬件cache,用于缓存页表,即缓存线性地址(虚拟地址)到物理地址的映射关系. 如果没有TLB,那 ...
- Linux kernel 3.10内核源码分析--进程退出exit_code
进程退出时,有相应的exit_code,可用于判断进程退出的原因. 比如,waitpid()接口用于等待进程退出,此时被等待退出的进程的返回值比较重要,需要用其来判断进程退出的相应状态,而这就是通过进 ...
- Linux mem 2.2 内核地址空间布局详解
文章目录 1. 简介 2. 内核页表初始化 2.0 decompress阶段 2.1 `head_64.S`和`head64.c` 2.2 start_kernel() 2.2.1 物理内存(e820 ...
- Linux驱动——mmc sd card 块设备读写流程(十三)
Linux驱动--mmc sd card 块设备读写流程(十三) 备注: 1. Kernel版本:5.4 2. 使用工具:Source Insight 4.0 3. 参考博客: (1) ...
- Linux 和uboot下dd命令读写sd,mmc,mm读写内存命令
Linux 和uboot下dd命令读写sd,mmc名,mm读写内存命令,记录一下,后面写
- 嵌入式linux sd卡读写,嵌入式Linux之我行——S3C2440上MMC/SD卡驱动实例开发讲解(二)...
嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤.一为总结经验,二希望能给想入门嵌入式Linux的朋友提供方便.如有错误之处,谢请指正. 一.开发环境 主 机:VMWa ...
最新文章
- Jzzhu and Chocolate
- HP DL380 G6安装Windows server 2003(有光驱和无光驱两种方法)
- 现半透明的popupwindow
- php获取域名与路径
- ppt2010基础操作笔记
- 简单线性回归(Simple Linear Regression)和多元线性回归(Multiple Regression)学习笔记
- (Matlab函数详解)机器学习中的4种分类算法(LDA、QDA、SVM、KNN)
- 现代软件工程 第十一章 【软件设计与实现】 练习与讨论
- python在线作业_南开大学20春学期《Python编程基础》在线作业参考答案
- 看下资深架构师平时需要解决的问题,对比你离资深架构师还有多少距离——再论技术架构的升级之路...
- 去除listView和recyclerview滑动到顶部和底部边界的阴影
- HDU 5908 Abelian Period 可以直接用multiset
- 扑克牌的完美洗牌算法
- 万稞pw80线切割编程软件_零基础如何快速学习UG数控编程?
- 初识STM32与其选型
- m3u8视频下载转为mp4
- 行尸走肉第一季/全集The Walking Dead迅雷下载
- 阿里云共享型云服务器与独享型云服务器有什么区别?如何选择?
- css相对位置之两个同级div下一个div相对上一个div的位置
- python框架是什么_python框架是什么?
热门文章
- 中国科学院计算机致谢,央视评中科院博士论文致谢走红
- 解决Win10锁屏超1分钟,显示器关闭问题
- 写脚本的作用是什么?做自媒体,什么样的视频一定要写脚本?
- 【Java程序设计】GUI程序设计(设计封装矩形类、利用监听事件对textField进行读取和输入)
- linux下同时装ananocda2和anaconda3通过修改.bashrc文件进行切换
- Arduino Uno 实验15——MQ-135 气体传感器模块
- 数据库系统发展的特点
- 核磁谱图分析步骤_核磁一般氢谱和碳谱的解析步骤
- 【苹果家庭相册群发】CSR邮箱必须与证书所属的AppID相同
- 重新开博,短期目标,工作计划