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读写分析相关推荐

  1. Linux kernel 3.10内核源码分析--进程上下文切换

    一.疑问 进程调度时,当被选中的next进程不是current进程时,需要进行上下文切换. 进行上下文切换时,有一些问题不太容易理解,比如: 1.进程上下文切换必然发生在内核态吗? 2.上下文切换后原 ...

  2. 一起分析Linux系统设计思想——03内核启动流程分析(六)

    在学习资料满天飞的大环境下,知识变得非常零散,体系化的知识并不多,这就导致很多人每天都努力学习到感动自己,最终却收效甚微,甚至放弃学习.我的使命就是过滤掉大量的垃圾信息,将知识体系化,以短平快的方式直 ...

  3. Linux kernel 3.10内核源码分析--slab原理及相关代码

    1.基本原理 我们知道,Linux保护模式下,采用分页机制,内核中物理内存使用buddy system(伙伴系统)进行管理,管理的内存单元大小为一页,也就是说使用buddy system分配内存最少需 ...

  4. Linux Kernel 3.10内核源码分析--块设备层request plug/unplug机制

    一.基本原理 Linux块设备层使用了plug/unplug(蓄流/泄流)的机制来提升IO吞吐量.基本原理为:当IO请求提交时,不知直接提交给底层驱动,而是先将其放入一个队列中(相当于水池),待一定时 ...

  5. Linux kernel 3.10内核源码分析--TLB相关--TLB概念、flush、TLB lazy模式

    一.概念及基本原理 TLB即Translation Lookaside Buffer,是MMU中的一种硬件cache,用于缓存页表,即缓存线性地址(虚拟地址)到物理地址的映射关系. 如果没有TLB,那 ...

  6. Linux kernel 3.10内核源码分析--进程退出exit_code

    进程退出时,有相应的exit_code,可用于判断进程退出的原因. 比如,waitpid()接口用于等待进程退出,此时被等待退出的进程的返回值比较重要,需要用其来判断进程退出的相应状态,而这就是通过进 ...

  7. Linux mem 2.2 内核地址空间布局详解

    文章目录 1. 简介 2. 内核页表初始化 2.0 decompress阶段 2.1 `head_64.S`和`head64.c` 2.2 start_kernel() 2.2.1 物理内存(e820 ...

  8. Linux驱动——mmc sd card 块设备读写流程(十三)

    Linux驱动--mmc sd card 块设备读写流程(十三) 备注:   1. Kernel版本:5.4   2. 使用工具:Source Insight 4.0   3. 参考博客:   (1) ...

  9. Linux 和uboot下dd命令读写sd,mmc,mm读写内存命令

    Linux 和uboot下dd命令读写sd,mmc名,mm读写内存命令,记录一下,后面写

  10. 嵌入式linux sd卡读写,嵌入式Linux之我行——S3C2440上MMC/SD卡驱动实例开发讲解(二)...

    嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤.一为总结经验,二希望能给想入门嵌入式Linux的朋友提供方便.如有错误之处,谢请指正. 一.开发环境 主  机:VMWa ...

最新文章

  1. Jzzhu and Chocolate
  2. HP DL380 G6安装Windows server 2003(有光驱和无光驱两种方法)
  3. 现半透明的popupwindow
  4. php获取域名与路径
  5. ppt2010基础操作笔记
  6. 简单线性回归(Simple Linear Regression)和多元线性回归(Multiple Regression)学习笔记
  7. (Matlab函数详解)机器学习中的4种分类算法(LDA、QDA、SVM、KNN)
  8. 现代软件工程 第十一章 【软件设计与实现】 练习与讨论
  9. python在线作业_南开大学20春学期《Python编程基础》在线作业参考答案
  10. 看下资深架构师平时需要解决的问题,对比你离资深架构师还有多少距离——再论技术架构的升级之路...
  11. 去除listView和recyclerview滑动到顶部和底部边界的阴影
  12. HDU 5908 Abelian Period 可以直接用multiset
  13. 扑克牌的完美洗牌算法
  14. 万稞pw80线切割编程软件_零基础如何快速学习UG数控编程?
  15. 初识STM32与其选型
  16. m3u8视频下载转为mp4
  17. 行尸走肉第一季/全集The Walking Dead迅雷下载
  18. 阿里云共享型云服务器与独享型云服务器有什么区别?如何选择?
  19. css相对位置之两个同级div下一个div相对上一个div的位置
  20. python框架是什么_python框架是什么?

热门文章

  1. 中国科学院计算机致谢,央视评中科院博士论文致谢走红
  2. 解决Win10锁屏超1分钟,显示器关闭问题
  3. 写脚本的作用是什么?做自媒体,什么样的视频一定要写脚本?
  4. 【Java程序设计】GUI程序设计(设计封装矩形类、利用监听事件对textField进行读取和输入)
  5. linux下同时装ananocda2和anaconda3通过修改.bashrc文件进行切换
  6. Arduino Uno 实验15——MQ-135 气体传感器模块
  7. 数据库系统发展的特点
  8. 核磁谱图分析步骤_核磁一般氢谱和碳谱的解析步骤
  9. 【苹果家庭相册群发】CSR邮箱必须与证书所属的AppID相同
  10. 重新开博,短期目标,工作计划