aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorPer Forlin <per.forlin@linaro.org>2011-07-01 12:55:22 -0400
committerChris Ball <cjb@laptop.org>2011-07-20 17:21:10 -0400
commitaa8b683a7d392271ed349c6ab9f36b8c313794b7 (patch)
tree82c97c089844a03492be55968c1d3cc993aaafa6 /drivers/mmc
parent0500f10cc2d624034f350edae2529975c0f1c1f8 (diff)
mmc: core: add non-blocking mmc request function
Previously there has only been one function mmc_wait_for_req() to start and wait for a request. This patch adds: * mmc_start_req() - starts a request wihtout waiting If there is on ongoing request wait for completion of that request and start the new one and return. Does not wait for the new command to complete. This patch also adds new function members in struct mmc_host_ops only called from core.c: * pre_req - asks the host driver to prepare for the next job * post_req - asks the host driver to clean up after a completed job The intention is to use pre_req() and post_req() to do cache maintenance while a request is active. pre_req() can be called while a request is active to minimize latency to start next job. post_req() can be used after the next job is started to clean up the request. This will minimize the host driver request end latency. post_req() is typically used before ending the block request and handing over the buffer to the block layer. Add a host-private member in mmc_data to be used by pre_req to mark the data. The host driver will then check this mark to see if the data is prepared or not. Signed-off-by: Per Forlin <per.forlin@linaro.org> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Venkatraman S <svenkatr@ti.com> Tested-by: Sourav Poddar <sourav.poddar@ti.com> Tested-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/core.c113
1 files changed, 103 insertions, 10 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index ac82865b8c2f..ab36c7b491f3 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -198,9 +198,109 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
198 198
199static void mmc_wait_done(struct mmc_request *mrq) 199static void mmc_wait_done(struct mmc_request *mrq)
200{ 200{
201 complete(mrq->done_data); 201 complete(&mrq->completion);
202} 202}
203 203
204static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
205{
206 init_completion(&mrq->completion);
207 mrq->done = mmc_wait_done;
208 mmc_start_request(host, mrq);
209}
210
211static void mmc_wait_for_req_done(struct mmc_host *host,
212 struct mmc_request *mrq)
213{
214 wait_for_completion(&mrq->completion);
215}
216
217/**
218 * mmc_pre_req - Prepare for a new request
219 * @host: MMC host to prepare command
220 * @mrq: MMC request to prepare for
221 * @is_first_req: true if there is no previous started request
222 * that may run in parellel to this call, otherwise false
223 *
224 * mmc_pre_req() is called in prior to mmc_start_req() to let
225 * host prepare for the new request. Preparation of a request may be
226 * performed while another request is running on the host.
227 */
228static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
229 bool is_first_req)
230{
231 if (host->ops->pre_req)
232 host->ops->pre_req(host, mrq, is_first_req);
233}
234
235/**
236 * mmc_post_req - Post process a completed request
237 * @host: MMC host to post process command
238 * @mrq: MMC request to post process for
239 * @err: Error, if non zero, clean up any resources made in pre_req
240 *
241 * Let the host post process a completed request. Post processing of
242 * a request may be performed while another reuqest is running.
243 */
244static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq,
245 int err)
246{
247 if (host->ops->post_req)
248 host->ops->post_req(host, mrq, err);
249}
250
251/**
252 * mmc_start_req - start a non-blocking request
253 * @host: MMC host to start command
254 * @areq: async request to start
255 * @error: out parameter returns 0 for success, otherwise non zero
256 *
257 * Start a new MMC custom command request for a host.
258 * If there is on ongoing async request wait for completion
259 * of that request and start the new one and return.
260 * Does not wait for the new request to complete.
261 *
262 * Returns the completed request, NULL in case of none completed.
263 * Wait for the an ongoing request (previoulsy started) to complete and
264 * return the completed request. If there is no ongoing request, NULL
265 * is returned without waiting. NULL is not an error condition.
266 */
267struct mmc_async_req *mmc_start_req(struct mmc_host *host,
268 struct mmc_async_req *areq, int *error)
269{
270 int err = 0;
271 struct mmc_async_req *data = host->areq;
272
273 /* Prepare a new request */
274 if (areq)
275 mmc_pre_req(host, areq->mrq, !host->areq);
276
277 if (host->areq) {
278 mmc_wait_for_req_done(host, host->areq->mrq);
279 err = host->areq->err_check(host->card, host->areq);
280 if (err) {
281 mmc_post_req(host, host->areq->mrq, 0);
282 if (areq)
283 mmc_post_req(host, areq->mrq, -EINVAL);
284
285 host->areq = NULL;
286 goto out;
287 }
288 }
289
290 if (areq)
291 __mmc_start_req(host, areq->mrq);
292
293 if (host->areq)
294 mmc_post_req(host, host->areq->mrq, 0);
295
296 host->areq = areq;
297 out:
298 if (error)
299 *error = err;
300 return data;
301}
302EXPORT_SYMBOL(mmc_start_req);
303
204/** 304/**
205 * mmc_wait_for_req - start a request and wait for completion 305 * mmc_wait_for_req - start a request and wait for completion
206 * @host: MMC host to start command 306 * @host: MMC host to start command
@@ -212,16 +312,9 @@ static void mmc_wait_done(struct mmc_request *mrq)
212 */ 312 */
213void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) 313void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
214{ 314{
215 DECLARE_COMPLETION_ONSTACK(complete); 315 __mmc_start_req(host, mrq);
216 316 mmc_wait_for_req_done(host, mrq);
217 mrq->done_data = &complete;
218 mrq->done = mmc_wait_done;
219
220 mmc_start_request(host, mrq);
221
222 wait_for_completion(&complete);
223} 317}
224
225EXPORT_SYMBOL(mmc_wait_for_req); 318EXPORT_SYMBOL(mmc_wait_for_req);
226 319
227/** 320/**