MMC子系统调用过程浅析(Core层)
来源:互联网 发布:网络在线测速度 编辑:程序博客网 时间:2024/06/07 23:45
Core层关系图:
在Card层中,分析到调用mmc_start_req(card->host, areq, (int *) &status)来处理块设备数据请求。在Caed层实际上完成了一个复杂的封装过程,会把request_queue->reqeust上的信息转到areq(mmc_async_req)->mmc_request上。
下面继续对mmc_start_req分析:
/** * mmc_start_req - start a non-blocking request * @host: MMC host to start command * @areq: async request to start * @error: out parameter returns 0 for success, otherwise non zero * * Start a new MMC custom command request for a host. * If there is on ongoing async request wait for completion * of that request and start the new one and return. * Does not wait for the new request to complete. * * Returns the completed request, NULL in case of none completed. * Wait for the an ongoing request (previoulsy started) to complete and * return the completed request. If there is no ongoing request, NULL * is returned without waiting. NULL is not an error condition. */struct mmc_async_req *mmc_start_req(struct mmc_host *host, struct mmc_async_req *areq, int *error){ int err = 0; int start_err = 0; struct mmc_async_req *data = host->areq; /* Prepare a new request */ if (areq) mmc_pre_req(host, areq->mrq, !host->areq); if (host->areq) { err = mmc_wait_for_data_req_done(host, host->areq->mrq, areq); if (err == MMC_BLK_NEW_REQUEST) { if (error) *error = err; /* * The previous request was not completed, * nothing to return */ return NULL; } /* * Check BKOPS urgency for each R1 response */ if (host->card && mmc_card_mmc(host->card) && ((mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1) || (mmc_resp_type(host->areq->mrq->cmd) == MMC_RSP_R1B)) && (host->areq->mrq->cmd->resp[0] & R1_EXCEPTION_EVENT)) { /* Cancel the prepared request */ if (areq) mmc_post_req(host, areq->mrq, -EINVAL); mmc_start_bkops(host->card, true); /* prepare the request again */ if (areq) mmc_pre_req(host, areq->mrq, !host->areq); } } if (!err && areq) start_err = __mmc_start_data_req(host, areq->mrq); if (host->areq) mmc_post_req(host, host->areq->mrq, 0); /* Cancel a prepared request if it was not started. */ if ((err || start_err) && areq) mmc_post_req(host, areq->mrq, -EINVAL); if (err) host->areq = NULL; else host->areq = areq; if (error) *error = err; return data;}
mmc_wait_for_data_req_done对数据进行处理:
/* * mmc_wait_for_data_req_done() - wait for request completed * @host: MMC host to prepare the command. * @mrq: MMC request to wait for * * Blocks MMC context till host controller will ack end of data request * execution or new request notification arrives from the block layer. * Handles command retries. * * Returns enum mmc_blk_status after checking errors. */static int mmc_wait_for_data_req_done(struct mmc_host *host, struct mmc_request *mrq, struct mmc_async_req *next_req){ struct mmc_command *cmd; struct mmc_context_info *context_info = &host->context_info; int err; unsigned long flags; while (1) { wait_event_interruptible(context_info->wait, (context_info->is_done_rcv || context_info->is_new_req)); spin_lock_irqsave(&context_info->lock, flags); context_info->is_waiting_last_req = false; spin_unlock_irqrestore(&context_info->lock, flags); if (context_info->is_done_rcv) { context_info->is_done_rcv = false; context_info->is_new_req = false; cmd = mrq->cmd; if (!cmd->error || !cmd->retries || mmc_card_removed(host->card)) { err = host->areq->err_check(host->card, host->areq); break; /* return err */ } else { mmc_retune_recheck(host); pr_info("%s: req failed (CMD%u): %d, retrying...\n", mmc_hostname(host), cmd->opcode, cmd->error); cmd->retries--; cmd->error = 0; __mmc_start_request(host, mrq); continue; /* wait for done/new event again */ } } else if (context_info->is_new_req) { context_info->is_new_req = false; if (!next_req) return MMC_BLK_NEW_REQUEST; } } mmc_retune_release(host); return err;}
mmc_wait_for_data_req_done中调用__mmc_start_request(host, mrq)来执行一个请求。
static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq){ int err; /* Assumes host controller has been runtime resumed by mmc_claim_host */ err = mmc_retune(host); if (err) { mrq->cmd->error = err; mmc_request_done(host, mrq); return; } /* * For sdio rw commands we must wait for card busy otherwise some * sdio devices won't work properly. */ if (mmc_is_io_op(mrq->cmd->opcode) && host->ops->card_busy) { int tries = 500; /* Wait aprox 500ms at maximum */ while (host->ops->card_busy(host) && --tries) mmc_delay(1); if (tries == 0) { mrq->cmd->error = -EBUSY; mmc_request_done(host, mrq); return; } } host->ops->request(host, mrq);}
可以看到host->ops->request(host, mrq),来完成request。core层其实最终都是调用mmc_host->mmc_host_ops。mmc_host_ops中放着与硬件相关的操作。内核中封装好了Card和Core两层,厂商只要按照自己的mmc控制器,编写Host层操作方法即可。
阅读全文
0 0
- MMC子系统调用过程浅析(Core层)
- MMC子系统调用过程浅析(Card层)
- Linux MMC子系统(1)-- MMC Host层(2.6.28)
- mmc子系统
- 浅析Linux从API调用到底层驱动的过程
- [mmc subsystem] mmc core(第六章)——mmc core主模块
- [mmc subsystem] mmc core(第一章)——概述
- linux驱动——input输入子系统(1)—输入子系统核心层(Input Core)
- MMC子系统介绍
- mmc子系统学习笔记
- qualcomm MMC子系统
- MMC子系统介绍
- linux mmc驱动子系统
- linux MMC驱动子系统
- mmc子系统总结
- Linux MMC子系统
- [mmc subsystem] mmc core(第五章)——card相关模块(mmc type card)
- linux net子系统-系统调用层
- 记录与分享
- django 微信测试账号 获取 token
- 适合RecyclerView使用的万能侧滑删除控件
- java中RSA加解密的实现
- C#,webservice,http下载word,AsposeWords合并word
- MMC子系统调用过程浅析(Core层)
- JS基于正则实现数字千分位用逗号分割
- C++参数传递方式
- Python中使用ElementTree对XML文件进行解析
- 斐波那契数列
- 敏捷开发与传统开发
- 浅谈MVC架构—你到底有什么本事!!!
- Markdown 基本用法 (2)
- Android面试知识点总结-Android篇