Skip to content

Commit b1a6659

Browse files
author
Ulf Hansson
committed
mmc: mmci: Add support for SW busy-end timeouts
The ux500 variant doesn't have a HW based timeout to use for busy-end IRQs. To avoid hanging and waiting for the card to stop signaling busy, let's schedule a delayed work, according to the corresponding cmd->busy_timeout for the command. If the work gets to run, let's kick the IRQ handler to complete the currently running request/command. Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Link: https://lore.kernel.org/r/20230620091113.33393-1-ulf.hansson@linaro.org
1 parent c467c8f commit b1a6659

3 files changed

Lines changed: 49 additions & 7 deletions

File tree

drivers/mmc/host/mmci.c

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <linux/pinctrl/consumer.h>
3838
#include <linux/reset.h>
3939
#include <linux/gpio/consumer.h>
40+
#include <linux/workqueue.h>
4041

4142
#include <asm/div64.h>
4243
#include <asm/io.h>
@@ -712,7 +713,8 @@ static void ux500_busy_clear_mask_done(struct mmci_host *host)
712713
* | |
713714
* IRQ1 IRQ2
714715
*/
715-
static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
716+
static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd,
717+
u32 status, u32 err_msk)
716718
{
717719
void __iomem *base = host->base;
718720
int retries = 10;
@@ -756,6 +758,8 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
756758
host->variant->busy_detect_mask,
757759
base + MMCIMASK0);
758760
host->busy_state = MMCI_BUSY_WAITING_FOR_START_IRQ;
761+
schedule_delayed_work(&host->ux500_busy_timeout_work,
762+
msecs_to_jiffies(cmd->busy_timeout));
759763
goto out_ret_state;
760764
}
761765
retries--;
@@ -783,6 +787,7 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
783787
} else {
784788
dev_dbg(mmc_dev(host->mmc),
785789
"lost busy status when waiting for busy start IRQ\n");
790+
cancel_delayed_work(&host->ux500_busy_timeout_work);
786791
ux500_busy_clear_mask_done(host);
787792
}
788793
break;
@@ -791,6 +796,7 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
791796
if (!(status & host->variant->busy_detect_flag)) {
792797
host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND);
793798
writel(host->variant->busy_detect_mask, base + MMCICLEAR);
799+
cancel_delayed_work(&host->ux500_busy_timeout_work);
794800
ux500_busy_clear_mask_done(host);
795801
} else {
796802
dev_dbg(mmc_dev(host->mmc),
@@ -1307,6 +1313,7 @@ static void
13071313
mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
13081314
{
13091315
void __iomem *base = host->base;
1316+
bool busy_resp = cmd->flags & MMC_RSP_BUSY;
13101317
unsigned long long clks;
13111318

13121319
dev_dbg(mmc_dev(host->mmc), "op %02x arg %08x flags %08x\n",
@@ -1334,10 +1341,11 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
13341341
host->busy_status = 0;
13351342
host->busy_state = MMCI_BUSY_DONE;
13361343

1337-
if (host->variant->busy_timeout && cmd->flags & MMC_RSP_BUSY) {
1338-
if (!cmd->busy_timeout)
1339-
cmd->busy_timeout = 10 * MSEC_PER_SEC;
1344+
/* Assign a default timeout if the core does not provide one */
1345+
if (busy_resp && !cmd->busy_timeout)
1346+
cmd->busy_timeout = 10 * MSEC_PER_SEC;
13401347

1348+
if (busy_resp && host->variant->busy_timeout) {
13411349
if (cmd->busy_timeout > host->mmc->max_busy_timeout)
13421350
clks = (unsigned long long)host->mmc->max_busy_timeout * host->cclk;
13431351
else
@@ -1478,7 +1486,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
14781486

14791487
/* Handle busy detection on DAT0 if the variant supports it. */
14801488
if (busy_resp && host->variant->busy_detect)
1481-
if (!host->ops->busy_complete(host, status, err_msk))
1489+
if (!host->ops->busy_complete(host, cmd, status, err_msk))
14821490
return;
14831491

14841492
host->cmd = NULL;
@@ -1525,6 +1533,34 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
15251533
}
15261534
}
15271535

1536+
/*
1537+
* This busy timeout worker is used to "kick" the command IRQ if a
1538+
* busy detect IRQ fails to appear in reasonable time. Only used on
1539+
* variants with busy detection IRQ delivery.
1540+
*/
1541+
static void ux500_busy_timeout_work(struct work_struct *work)
1542+
{
1543+
struct mmci_host *host = container_of(work, struct mmci_host,
1544+
ux500_busy_timeout_work.work);
1545+
unsigned long flags;
1546+
u32 status;
1547+
1548+
spin_lock_irqsave(&host->lock, flags);
1549+
1550+
if (host->cmd) {
1551+
dev_dbg(mmc_dev(host->mmc), "timeout waiting for busy IRQ\n");
1552+
1553+
/* If we are still busy let's tag on a cmd-timeout error. */
1554+
status = readl(host->base + MMCISTATUS);
1555+
if (status & host->variant->busy_detect_flag)
1556+
status |= MCI_CMDTIMEOUT;
1557+
1558+
mmci_cmd_irq(host, host->cmd, status);
1559+
}
1560+
1561+
spin_unlock_irqrestore(&host->lock, flags);
1562+
}
1563+
15281564
static int mmci_get_rx_fifocnt(struct mmci_host *host, u32 status, int remain)
15291565
{
15301566
return remain - (readl(host->base + MMCIFIFOCNT) << 2);
@@ -2339,6 +2375,10 @@ static int mmci_probe(struct amba_device *dev,
23392375
goto clk_disable;
23402376
}
23412377

2378+
if (host->variant->busy_detect)
2379+
INIT_DELAYED_WORK(&host->ux500_busy_timeout_work,
2380+
ux500_busy_timeout_work);
2381+
23422382
writel(MCI_IRQENABLE | variant->start_err, host->base + MMCIMASK0);
23432383

23442384
amba_set_drvdata(dev, mmc);

drivers/mmc/host/mmci.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ struct mmci_host_ops {
397397
void (*dma_error)(struct mmci_host *host);
398398
void (*set_clkreg)(struct mmci_host *host, unsigned int desired);
399399
void (*set_pwrreg)(struct mmci_host *host, unsigned int pwr);
400-
bool (*busy_complete)(struct mmci_host *host, u32 status, u32 err_msk);
400+
bool (*busy_complete)(struct mmci_host *host, struct mmc_command *cmd, u32 status, u32 err_msk);
401401
void (*pre_sig_volt_switch)(struct mmci_host *host);
402402
int (*post_sig_volt_switch)(struct mmci_host *host, struct mmc_ios *ios);
403403
};
@@ -455,6 +455,7 @@ struct mmci_host {
455455
void *dma_priv;
456456

457457
s32 next_cookie;
458+
struct delayed_work ux500_busy_timeout_work;
458459
};
459460

460461
#define dma_inprogress(host) ((host)->dma_in_progress)

drivers/mmc/host/mmci_stm32_sdmmc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,8 @@ static u32 sdmmc_get_dctrl_cfg(struct mmci_host *host)
411411
return datactrl;
412412
}
413413

414-
static bool sdmmc_busy_complete(struct mmci_host *host, u32 status, u32 err_msk)
414+
static bool sdmmc_busy_complete(struct mmci_host *host, struct mmc_command *cmd,
415+
u32 status, u32 err_msk)
415416
{
416417
void __iomem *base = host->base;
417418
u32 busy_d0, busy_d0end, mask, sdmmc_status;

0 commit comments

Comments
 (0)