[10/12] mmc: core: Convert to mmc_poll_for_busy() for HPI commands

Message ID 20200204085449.32585-11-ulf.hansson@linaro.org
State New
Headers show
Series
  • mmc: core: Improve code for polling and HW busy detect
Related show

Commit Message

Ulf Hansson Feb. 4, 2020, 8:54 a.m.
Rather than open coding the polling loop in mmc_interrupt_hpi(), let's
convert to use mmc_poll_for_busy().

Note that, moving to mmc_poll_for_busy() for HPI also improves the
behaviour according to below.

- Adds support for polling via the optional ->card_busy() host ops.
- Require R1_READY_FOR_DATA to be set in the CMD13 response before exiting
  the polling loop.
- Adds a throttling mechanism to avoid CPU hogging when polling.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

---
 drivers/mmc/core/mmc_ops.c | 20 +++++---------------
 drivers/mmc/core/mmc_ops.h |  1 +
 2 files changed, 6 insertions(+), 15 deletions(-)

-- 
2.17.1

Patch

diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 4d8f90d01740..87d54a559b31 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -471,6 +471,8 @@  static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err,
 	case MMC_BUSY_ERASE:
 		err = R1_STATUS(status) ? -EIO : 0;
 		break;
+	case MMC_BUSY_HPI:
+		break;
 	default:
 		err = -EINVAL;
 	}
@@ -829,6 +831,7 @@  int mmc_bus_test(struct mmc_card *card, u8 bus_width)
 
 static int mmc_send_hpi_cmd(struct mmc_card *card)
 {
+	unsigned int busy_timeout_ms = card->ext_csd.out_of_int_time;
 	struct mmc_command cmd = {};
 	unsigned int opcode;
 	int err;
@@ -850,7 +853,8 @@  static int mmc_send_hpi_cmd(struct mmc_card *card)
 		return err;
 	}
 
-	return 0;
+	/* Let's poll to find out when the HPI request completes. */
+	return mmc_poll_for_busy(card, busy_timeout_ms, MMC_BUSY_HPI);
 }
 
 /**
@@ -864,7 +868,6 @@  int mmc_interrupt_hpi(struct mmc_card *card)
 {
 	int err;
 	u32 status;
-	unsigned long prg_wait;
 
 	if (!card->ext_csd.hpi_en) {
 		pr_info("%s: HPI enable bit unset\n", mmc_hostname(card->host));
@@ -898,19 +901,6 @@  int mmc_interrupt_hpi(struct mmc_card *card)
 	}
 
 	err = mmc_send_hpi_cmd(card);
-	if (err)
-		goto out;
-
-	prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time);
-	do {
-		err = mmc_send_status(card, &status);
-
-		if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN)
-			break;
-		if (time_after(jiffies, prg_wait))
-			err = -ETIMEDOUT;
-	} while (!err);
-
 out:
 	return err;
 }
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h
index 8cd05fb583da..38dcfeeaf6d5 100644
--- a/drivers/mmc/core/mmc_ops.h
+++ b/drivers/mmc/core/mmc_ops.h
@@ -13,6 +13,7 @@ 
 enum mmc_busy_cmd {
 	MMC_BUSY_CMD6,
 	MMC_BUSY_ERASE,
+	MMC_BUSY_HPI,
 };
 
 struct mmc_host;