static void mmc_wait_done(struct mmc_request *mrq)
{
- complete(mrq->done_data);
+ complete(&mrq->completion);
}
+static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+ init_completion(&mrq->completion);
+ mrq->done = mmc_wait_done;
+ mmc_start_request(host, mrq);
+}
+
+static void mmc_wait_for_req_done(struct mmc_host *host,
+ struct mmc_request *mrq)
+{
+ wait_for_completion(&mrq->completion);
+}
+
+/**
+ * mmc_pre_req - Prepare for a new request
+ * @host: MMC host to prepare command
+ * @mrq: MMC request to prepare for
+ * @is_first_req: true if there is no previous started request
+ * that may run in parellel to this call, otherwise false
+ *
+ * mmc_pre_req() is called in prior to mmc_start_req() to let
+ * host prepare for the new request. Preparation of a request may be
+ * performed while another request is running on the host.
+ */
+static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
+ bool is_first_req)
+{
+ if (host->ops->pre_req)
+ host->ops->pre_req(host, mrq, is_first_req);
+}
+
+/**
+ * mmc_post_req - Post process a completed request
+ * @host: MMC host to post process command
+ * @mrq: MMC request to post process for
+ * @err: Error, if non zero, clean up any resources made in pre_req
+ *
+ * Let the host post process a completed request. Post processing of
+ * a request may be performed while another reuqest is running.
+ */
+static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq,
+ int err)
+{
+ if (host->ops->post_req)
+ host->ops->post_req(host, mrq, err);
+}
+
+/**
+ * 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;
+ struct mmc_async_req *data = host->areq;
+
+ /* Prepare a new request */
+ if (areq)
+ mmc_pre_req(host, areq->mrq, !host->areq);
+
+ if (host->areq) {
+ mmc_wait_for_req_done(host, host->areq->mrq);
+ err = host->areq->err_check(host->card, host->areq);
+ if (err) {
+ mmc_post_req(host, host->areq->mrq, 0);
+ if (areq)
+ mmc_post_req(host, areq->mrq, -EINVAL);
+
+ host->areq = NULL;
+ goto out;
+ }
+ }
+
+ if (areq)
+ __mmc_start_req(host, areq->mrq);
+
+ if (host->areq)
+ mmc_post_req(host, host->areq->mrq, 0);
+
+ host->areq = areq;
+ out:
+ if (error)
+ *error = err;
+ return data;
+}
+EXPORT_SYMBOL(mmc_start_req);
+
/**
* mmc_wait_for_req - start a request and wait for completion
* @host: MMC host to start command
* for the command to complete. Does not attempt to parse the
* response.
*/
-void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
+static void sdmmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
{
#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
unsigned long datasize, waittime = 0xFFFF;
u32 multi, unit;
#endif
- DECLARE_COMPLETION_ONSTACK(complete);
- mrq->done_data = &complete;
+ init_completion(&mrq->completion);
mrq->done = mmc_wait_done;
mmc_start_request(host, mrq);
if( strncmp( mmc_hostname(host) ,"mmc0" , strlen("mmc0")) )
{
multi = (mrq->cmd->retries>0)?mrq->cmd->retries:1;
- waittime = wait_for_completion_timeout(&complete,HZ*7*multi); //sdio; for cmd dead. Modifyed by xbw at 2011-06-02
+ waittime = wait_for_completion_timeout(&mrq->completion ,HZ*7*multi); //sdio; for cmd dead. Modifyed by xbw at 2011-06-02
}
else
{
multi += (datasize%unit)?1:0;
multi = (multi>0) ? multi : 1;
multi += (mrq->cmd->retries>0)?1:0;
- waittime = wait_for_completion_timeout(&complete,HZ*7*multi); //It should be longer than bottom driver's time,due to the sum of two cmd time.
+ waittime = wait_for_completion_timeout(&mrq->completion,HZ*7*multi); //It should be longer than bottom driver's time,due to the sum of two cmd time.
//modifyed by xbw at 2011-10-08
//
//example:
else
{
multi = (mrq->cmd->retries>0)?mrq->cmd->retries:1;
- waittime = wait_for_completion_timeout(&complete,HZ*7*multi);
+ waittime = wait_for_completion_timeout(&mrq->completion,HZ*7*multi);
}
}
}
}
#else
- wait_for_completion(&complete);
+ wait_for_completion(&mrq->completion);
#endif
}
+static void emmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+ __mmc_start_req(host, mrq);
+ mmc_wait_for_req_done(host, mrq);
+}
+
+void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+ if(HOST_IS_EMMC(host))
+ emmc_wait_for_req(host, mrq);
+ else
+ sdmmc_wait_for_req(host, mrq);
+}
EXPORT_SYMBOL(mmc_wait_for_req);
/**