Merge tag 'mmc-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
[linux-2.6-microblaze.git] / drivers / mmc / core / block.c
index 6a15fdf..431af5e 100644 (file)
@@ -98,6 +98,11 @@ static int max_devices;
 static DEFINE_IDA(mmc_blk_ida);
 static DEFINE_IDA(mmc_rpmb_ida);
 
+struct mmc_blk_busy_data {
+       struct mmc_card *card;
+       u32 status;
+};
+
 /*
  * There is one mmc_blk_data per slot.
  */
@@ -456,42 +461,6 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
        return 0;
 }
 
-static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
-                           u32 *resp_errs)
-{
-       unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
-       int err = 0;
-       u32 status;
-
-       do {
-               bool done = time_after(jiffies, timeout);
-
-               err = __mmc_send_status(card, &status, 5);
-               if (err) {
-                       dev_err(mmc_dev(card->host),
-                               "error %d requesting status\n", err);
-                       return err;
-               }
-
-               /* Accumulate any response error bits seen */
-               if (resp_errs)
-                       *resp_errs |= status;
-
-               /*
-                * Timeout if the device never becomes ready for data and never
-                * leaves the program state.
-                */
-               if (done) {
-                       dev_err(mmc_dev(card->host),
-                               "Card stuck in wrong state! %s status: %#x\n",
-                                __func__, status);
-                       return -ETIMEDOUT;
-               }
-       } while (!mmc_ready_for_data(status));
-
-       return err;
-}
-
 static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
                               struct mmc_blk_ioc_data *idata)
 {
@@ -588,6 +557,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
                return mmc_sanitize(card, idata->ic.cmd_timeout_ms);
 
        mmc_wait_for_req(card->host, &mrq);
+       memcpy(&idata->ic.response, cmd.resp, sizeof(cmd.resp));
 
        if (cmd.error) {
                dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
@@ -637,14 +607,13 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
        if (idata->ic.postsleep_min_us)
                usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us);
 
-       memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
-
        if (idata->rpmb || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
                /*
                 * Ensure RPMB/R1B command has completed by polling CMD13
                 * "Send Status".
                 */
-               err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL);
+               err = mmc_poll_for_busy(card, MMC_BLK_TIMEOUT_MS, false,
+                                       MMC_BUSY_IO);
        }
 
        return err;
@@ -1696,7 +1665,7 @@ static int mmc_blk_fix_state(struct mmc_card *card, struct request *req)
 
        mmc_blk_send_stop(card, timeout);
 
-       err = card_busy_detect(card, timeout, NULL);
+       err = mmc_poll_for_busy(card, timeout, false, MMC_BUSY_IO);
 
        mmc_retune_release(card->host);
 
@@ -1911,28 +1880,48 @@ static inline bool mmc_blk_rq_error(struct mmc_blk_request *brq)
               brq->data.error || brq->cmd.resp[0] & CMD_ERRORS;
 }
 
+static int mmc_blk_busy_cb(void *cb_data, bool *busy)
+{
+       struct mmc_blk_busy_data *data = cb_data;
+       u32 status = 0;
+       int err;
+
+       err = mmc_send_status(data->card, &status);
+       if (err)
+               return err;
+
+       /* Accumulate response error bits. */
+       data->status |= status;
+
+       *busy = !mmc_ready_for_data(status);
+       return 0;
+}
+
 static int mmc_blk_card_busy(struct mmc_card *card, struct request *req)
 {
        struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
-       u32 status = 0;
+       struct mmc_blk_busy_data cb_data;
        int err;
 
        if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ)
                return 0;
 
-       err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, &status);
+       cb_data.card = card;
+       cb_data.status = 0;
+       err = __mmc_poll_for_busy(card, MMC_BLK_TIMEOUT_MS, &mmc_blk_busy_cb,
+                                 &cb_data);
 
        /*
         * Do not assume data transferred correctly if there are any error bits
         * set.
         */
-       if (status & mmc_blk_stop_err_bits(&mqrq->brq)) {
+       if (cb_data.status & mmc_blk_stop_err_bits(&mqrq->brq)) {
                mqrq->brq.data.bytes_xfered = 0;
                err = err ? err : -EIO;
        }
 
        /* Copy the exception bit so it will be seen later on */
-       if (mmc_card_mmc(card) && status & R1_EXCEPTION_EVENT)
+       if (mmc_card_mmc(card) && cb_data.status & R1_EXCEPTION_EVENT)
                mqrq->brq.cmd.resp[0] |= R1_EXCEPTION_EVENT;
 
        return err;