@@ -676,6 +676,12 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
goto out_ret_state;
}
+ /*
+ * 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
@@ -686,7 +692,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_IDLE) {
+ case MMCI_BUSY_IDLE:
host->busy_status = status & (MCI_CMDSENT | MCI_CMDRESPEND);
while (retries) {
status = readl(base + MMCISTATUS);
@@ -706,8 +712,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
@@ -720,12 +725,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_IRQS) {
+ case MMCI_BUSY_WAITING_FOR_IRQS:
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_START_IRQ;
- goto out_ret_state;
} else {
dev_dbg(mmc_dev(host->mmc),
"lost busy status when waiting for busy start IRQ\n");
@@ -734,16 +738,14 @@ 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_START_IRQ) {
+ case MMCI_BUSY_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_END_IRQ;
- goto out_ret_state;
} else {
dev_dbg(mmc_dev(host->mmc),
"lost busy status when waiting for busy end IRQ\n");
@@ -752,9 +754,8 @@ 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 there is a command in-progress that has been successfully
@@ -762,11 +763,10 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
* the busy end IRQ. Clear and mask the IRQ, then continue to
* process the command.
*/
- if (host->busy_state == MMCI_BUSY_END_IRQ) {
+ case MMCI_BUSY_END_IRQ:
if (status & host->variant->busy_detect_flag) {
/* We should just get two IRQs for busy detect */
dev_err(mmc_dev(host->mmc), "spurious busy detect IRQ\n");
- goto out_ret_state;
}
writel(host->variant->busy_detect_mask, base + MMCICLEAR);
@@ -775,9 +775,15 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
host->busy_state = MMCI_BUSY_DONE;
host->busy_status = 0;
- } else {
+ break;
+
+ case MMCI_BUSY_DONE:
+ break;
+
+ default:
dev_dbg(mmc_dev(host->mmc), "fell through on state %d\n",
host->busy_state);
+ break;
}
out_ret_state:
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> --- drivers/mmc/host/mmci.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-)