summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2023-06-16 22:42:26 +0200
committerUlf Hansson <ulf.hansson@linaro.org>2023-06-19 13:14:26 +0200
commitddb5a92da5f32779958303716429d50a46c3177d (patch)
treeda2cb6f9a0103a48dd44ff64d729a3f7e1a9f955
parente85fecc386b98db890b869780573b33af49a7a7c (diff)
mmc: mmci: Use a switch statement machine
As is custom, use a big switch statement to transition between the edges of the state machine inside the ux500 ->busy_complete callback. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://lore.kernel.org/r/20230405-pl180-busydetect-fix-v7-8-69a7164f2a61@linaro.org Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/mmci.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index f59c6eb5258b..6bd8b367bb8f 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -687,6 +687,12 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
}
/*
+ * The state transitions are encoded in a state machine crossing
+ * the edges in this switch statement.
+ */
+ switch (host->busy_state) {
+
+ /*
* Before unmasking for the busy end IRQ, confirm that the
* command was sent successfully. To keep track of having a
* command in-progress, waiting for busy signaling to end,
@@ -696,7 +702,7 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
* it starts signaling busy on DAT0, hence re-read the
* MMCISTATUS register here, to allow the busy bit to be set.
*/
- if (host->busy_state == MMCI_BUSY_DONE) {
+ case MMCI_BUSY_DONE:
/*
* Save the first status register read to be sure to catch
* all bits that may be lost will retrying. If the command
@@ -722,8 +728,7 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
writel(readl(base + MMCIMASK0) &
~host->variant->busy_detect_mask, base + MMCIMASK0);
host->busy_state = MMCI_BUSY_DONE;
- goto out_ret_state;
- }
+ break;
/*
* If there is a command in-progress that has been successfully
@@ -736,12 +741,11 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
* both the start and the end interrupts needs to be cleared,
* one after the other. So, clear the busy start IRQ here.
*/
- if (host->busy_state == MMCI_BUSY_WAITING_FOR_START_IRQ) {
+ case MMCI_BUSY_WAITING_FOR_START_IRQ:
if (status & host->variant->busy_detect_flag) {
host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND);
writel(host->variant->busy_detect_mask, base + MMCICLEAR);
host->busy_state = MMCI_BUSY_WAITING_FOR_END_IRQ;
- goto out_ret_state;
} else {
dev_dbg(mmc_dev(host->mmc),
"lost busy status when waiting for busy start IRQ\n");
@@ -750,23 +754,24 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
~host->variant->busy_detect_mask, base + MMCIMASK0);
host->busy_state = MMCI_BUSY_DONE;
host->busy_status = 0;
- goto out_ret_state;
}
- }
+ break;
- if (host->busy_state == MMCI_BUSY_WAITING_FOR_END_IRQ) {
+ case MMCI_BUSY_WAITING_FOR_END_IRQ:
if (!(status & host->variant->busy_detect_flag)) {
host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND);
host->busy_state = MMCI_BUSY_DONE;
- goto out_ret_state;
} else {
dev_dbg(mmc_dev(host->mmc),
"busy status still asserted when handling busy end IRQ - will keep waiting\n");
- goto out_ret_state;
}
- }
+ break;
- return true;
+ default:
+ dev_dbg(mmc_dev(host->mmc), "fell through on state %d\n",
+ host->busy_state);
+ break;
+ }
out_ret_state:
return (host->busy_state == MMCI_BUSY_DONE);