Merge "mmc: core: remove the polling for BKOPS completion"
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 7b9e133..8e7e853 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -153,10 +153,18 @@
{
struct mmc_card *card = mmc_dev_to_card(dev);
- if (mmc_use_core_runtime_pm(card->host))
- return 0;
- else
+ if (mmc_use_core_runtime_pm(card->host)) {
+ /*
+ * If idle time bkops is running on the card, let's not get
+ * into suspend.
+ */
+ if (mmc_card_doing_bkops(card) && mmc_card_is_prog_state(card))
+ return -EBUSY;
+ else
+ return 0;
+ } else {
return mmc_power_save_host(card->host);
+ }
}
static int mmc_runtime_resume(struct device *dev)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9fc599b..3d525e1 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -487,11 +487,6 @@
mmc_card_clr_need_bkops(card);
mmc_card_set_doing_bkops(card);
- pr_debug("%s: %s: starting the polling thread\n",
- mmc_hostname(card->host), __func__);
- queue_work(system_nrt_wq,
- &card->bkops_info.poll_for_completion);
-
out:
mmc_release_host(card->host);
mmc_rpm_release(card->host, &card->dev);
@@ -499,81 +494,6 @@
EXPORT_SYMBOL(mmc_start_bkops);
/**
- * mmc_bkops_completion_polling() - Poll on the card status to
- * wait for the non-blocking BKOPS completion
- * @work: The completion polling work
- *
- * The on-going reading of the card status will prevent the card
- * from getting into suspend while it is in the middle of
- * performing BKOPS.
- * Since the non blocking BKOPS can be interrupted by a fetched
- * request we also check IF mmc_card_doing_bkops in each
- * iteration.
- */
-void mmc_bkops_completion_polling(struct work_struct *work)
-{
- struct mmc_card *card = container_of(work, struct mmc_card,
- bkops_info.poll_for_completion);
- unsigned long timeout_jiffies = jiffies +
- msecs_to_jiffies(BKOPS_COMPLETION_POLLING_TIMEOUT_MS);
- u32 status;
- int err;
-
- /*
- * Wait for the BKOPs to complete. Keep reading the status to prevent
- * the host from getting into suspend
- */
- do {
- mmc_rpm_hold(card->host, &card->dev);
- mmc_claim_host(card->host);
-
- if (!mmc_card_doing_bkops(card))
- goto out;
-
- err = mmc_send_status(card, &status);
- if (err) {
- pr_err("%s: error %d requesting status\n",
- mmc_hostname(card->host), err);
- goto out;
- }
-
- /*
- * Some cards mishandle the status bits, so make sure to check
- * both the busy indication and the card state.
- */
- if ((status & R1_READY_FOR_DATA) &&
- (R1_CURRENT_STATE(status) != R1_STATE_PRG)) {
- pr_debug("%s: %s: completed BKOPs, exit polling\n",
- mmc_hostname(card->host), __func__);
- mmc_card_clr_doing_bkops(card);
- card->bkops_info.sectors_changed = 0;
- goto out;
- }
-
- mmc_release_host(card->host);
- mmc_rpm_release(card->host, &card->dev);
-
- /*
- * Sleep before checking the card status again to allow the
- * card to complete the BKOPs operation
- */
- msleep(BKOPS_COMPLETION_POLLING_INTERVAL_MS);
- } while (time_before(jiffies, timeout_jiffies));
-
- pr_err("%s: %s: exit polling due to timeout, stop bkops\n",
- mmc_hostname(card->host), __func__);
- err = mmc_stop_bkops(card);
- if (err)
- pr_err("%s: %s: mmc_stop_bkops failed, err=%d\n",
- mmc_hostname(card->host), __func__, err);
-
- return;
-out:
- mmc_release_host(card->host);
- mmc_rpm_release(card->host, &card->dev);
-}
-
-/**
* mmc_start_idle_time_bkops() - check if a non urgent BKOPS is
* needed
* @work: The idle time BKOPS work
@@ -1066,6 +986,36 @@
}
EXPORT_SYMBOL(mmc_wait_for_req);
+bool mmc_card_is_prog_state(struct mmc_card *card)
+{
+ bool rc;
+ struct mmc_command cmd;
+
+ mmc_claim_host(card->host);
+ memset(&cmd, 0, sizeof(struct mmc_command));
+ cmd.opcode = MMC_SEND_STATUS;
+ if (!mmc_host_is_spi(card->host))
+ cmd.arg = card->rca << 16;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+ rc = mmc_wait_for_cmd(card->host, &cmd, 0);
+ if (rc) {
+ pr_err("%s: Get card status fail. rc=%d\n",
+ mmc_hostname(card->host), rc);
+ rc = false;
+ goto out;
+ }
+
+ if (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG)
+ rc = true;
+ else
+ rc = false;
+out:
+ mmc_release_host(card->host);
+ return rc;
+}
+EXPORT_SYMBOL(mmc_card_is_prog_state);
+
/**
* mmc_interrupt_hpi - Issue for High priority Interrupt
* @card: the MMC card associated with the HPI transfer
@@ -1189,6 +1139,17 @@
if (!mmc_card_doing_bkops(card))
goto out;
+ /*
+ * If idle time bkops is running on the card, let's not get into
+ * suspend.
+ */
+ if (!mmc_use_core_runtime_pm(card->host) && mmc_card_doing_bkops(card)
+ && (card->host->parent->power.runtime_status == RPM_SUSPENDING)
+ && mmc_card_is_prog_state(card)) {
+ err = -EBUSY;
+ goto out;
+ }
+
err = mmc_interrupt_hpi(card);
/*
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 89f8c91..5587492 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1400,8 +1400,6 @@
if (card->ext_csd.bkops_en) {
INIT_DELAYED_WORK(&card->bkops_info.dw,
mmc_start_idle_time_bkops);
- INIT_WORK(&card->bkops_info.poll_for_completion,
- mmc_bkops_completion_polling);
/*
* Calculate the time to start the BKOPs checking.
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 9a4e61d..0d20089 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -276,7 +276,6 @@
* percentage of sectors that should issue check for
* BKOPS need
* @bkops_stats: BKOPS statistics
- * @poll_for_completion: Poll on BKOPS completion
* @cancel_delayed_work: A flag to indicate if the delayed work
* should be cancelled
* @sectors_changed: number of sectors written or
@@ -294,10 +293,6 @@
* is idle.
*/
#define MMC_IDLE_BKOPS_TIME_MS 200
- struct work_struct poll_for_completion;
-/* Polling timeout and interval for waiting on non-blocking BKOPs completion */
-#define BKOPS_COMPLETION_POLLING_TIMEOUT_MS (4 * 60 * 1000) /* in ms */
-#define BKOPS_COMPLETION_POLLING_INTERVAL_MS 1000 /* in ms */
bool cancel_delayed_work;
unsigned int sectors_changed;
/*
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 995f8a2..f548721 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -146,6 +146,7 @@
extern int mmc_stop_bkops(struct mmc_card *);
extern int mmc_read_bkops_status(struct mmc_card *);
+extern bool mmc_card_is_prog_state(struct mmc_card *);
extern struct mmc_async_req *mmc_start_req(struct mmc_host *,
struct mmc_async_req *, int *);
extern int mmc_interrupt_hpi(struct mmc_card *);