|
@@ -198,9 +198,109 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
|
|
|
|
|
|
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
|
|
@@ -212,16 +312,9 @@ static void mmc_wait_done(struct mmc_request *mrq)
|
|
|
*/
|
|
|
void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
|
|
|
{
|
|
|
- DECLARE_COMPLETION_ONSTACK(complete);
|
|
|
-
|
|
|
- mrq->done_data = &complete;
|
|
|
- mrq->done = mmc_wait_done;
|
|
|
-
|
|
|
- mmc_start_request(host, mrq);
|
|
|
-
|
|
|
- wait_for_completion(&complete);
|
|
|
+ __mmc_start_req(host, mrq);
|
|
|
+ mmc_wait_for_req_done(host, mrq);
|
|
|
}
|
|
|
-
|
|
|
EXPORT_SYMBOL(mmc_wait_for_req);
|
|
|
|
|
|
/**
|