From patchwork Sat Apr 8 22:00:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 13205851 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0C78FC77B71 for ; Sat, 8 Apr 2023 22:00:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229503AbjDHWAt (ORCPT ); Sat, 8 Apr 2023 18:00:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48840 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229531AbjDHWAs (ORCPT ); Sat, 8 Apr 2023 18:00:48 -0400 Received: from mail-lf1-x132.google.com (mail-lf1-x132.google.com [IPv6:2a00:1450:4864:20::132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0ACEE7D8C for ; Sat, 8 Apr 2023 15:00:47 -0700 (PDT) Received: by mail-lf1-x132.google.com with SMTP id t14so2156970lft.7 for ; Sat, 08 Apr 2023 15:00:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1680991245; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=NK/Fry9T9gbXULkf+X1lnmSQBtAcyXPtx15VS/8mjZQ=; b=uVqJUmRLIEBX067m4GrdxYkkBbmoL93WK/V0QPpzSlQlHjdHL+TM+3p45evtn9jw7z dKkfjIznLuceUL2QMGjpI0QBWpodTQV0SSe9n9Ii8QV1ohGQ0UPAWYrTIDIBDZFTIMRK 4KK3PN+iwo3zQQNIgECnTlcCznJ6uY7XhYcepsHb7fcwBRNyBgfG8/Jxk9qdO21+Ykf2 nybbBMbd+2kIfXQjlmO9crx0B8br2DkWemP4X+BcoJkw+g3dRh5RiuHNsPoAS5oxOWIe 5kHRjjNa4zUMJFE8fYl/Jg2DDaunp6jph7EdJxxTNuLyYs8PnPTvZP+VdVFu1uRt2/nF Z5RQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680991245; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NK/Fry9T9gbXULkf+X1lnmSQBtAcyXPtx15VS/8mjZQ=; b=HAhpflQXZwlW+aNHbybYEtgJ2onBrrc1FmJD0hCZ3oMSf72Z9y779crjRFpcXVLmEY cwAdnLBOQcy9++REXQgt29OoXOAQqKrxuggKmlgmonPt00V4yKYmvhOamGADZsX3lxBa OswAF0jmRBsKoBehcXD6bOFuUzloy9PPW3nx0rBd5EodawyyV42YnVZkQ/ETHkQZu+3k XtT+88e1gc6hFP6Wr6UfNlyDZMLIu4ZeDRK3U1KIsPmMAkGKSrSY6oEP0+dCoZRs8vE2 ftr7takv/bId4LwH+Lym8VbtmPT6BW1ZhdT1cnSzJxyc/t3ZO6ZAcvw7SrLdAA31kIJc sfzA== X-Gm-Message-State: AAQBX9ecYCa7nMsnGJkaKYN4lL+K6gR8vHryMBC1kxh41vXohUGgX96D hj5j55aG9slKl80OF8Q0tvLUJg== X-Google-Smtp-Source: AKy350an2GH9i7wmQ/+Ebm1829Zb1RXtBYT4meUnPlrJWgb7glP+JurXh9Xwhe9//nJscwBjStDNtg== X-Received: by 2002:ac2:4477:0:b0:4eb:2ac1:52a6 with SMTP id y23-20020ac24477000000b004eb2ac152a6mr1839681lfl.36.1680991245335; Sat, 08 Apr 2023 15:00:45 -0700 (PDT) Received: from [192.168.1.2] (c-05d8225c.014-348-6c756e10.bbcust.telenor.se. [92.34.216.5]) by smtp.gmail.com with ESMTPSA id v9-20020a056512048900b004e9cad1cd7csm1328904lfq.229.2023.04.08.15.00.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Apr 2023 15:00:44 -0700 (PDT) From: Linus Walleij Date: Sun, 09 Apr 2023 00:00:33 +0200 Subject: [PATCH v2 12/12] mmc: mmci: Add busydetect timeout MIME-Version: 1.0 Message-Id: <20230405-pl180-busydetect-fix-v2-12-eeb10323b546@linaro.org> References: <20230405-pl180-busydetect-fix-v2-0-eeb10323b546@linaro.org> In-Reply-To: <20230405-pl180-busydetect-fix-v2-0-eeb10323b546@linaro.org> To: Yann Gautier , Stefan Hansson , Ulf Hansson , Maxime Coquelin , Alexandre Torgue Cc: linux-mmc@vger.kernel.org, linux-stm32@st-md-mailman.stormreply.com, Linus Walleij X-Mailer: b4 0.12.0 Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org Add a timeout for busydetect IRQs using a delayed work. It might happen (and does happen) on Ux500 that the first busy detect IRQ appears and not the second one. This will make the host hang indefinitely waiting for the second IRQ to appear. Fire a delayed work after 10ms and re-engage the command IRQ so the transaction finishes: we are certainly done at this point, or we will catch an error in the status register. This makes the eMMC work again on Skomer. Signed-off-by: Linus Walleij --- ChangeLog v1->v2: - No changes --- drivers/mmc/host/mmci.c | 23 +++++++++++++++++++++++ drivers/mmc/host/mmci.h | 1 + 2 files changed, 24 insertions(+) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 17233702e7fb..1af129fba0ed 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -747,6 +748,8 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk) host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND); writel(host->variant->busy_detect_mask, base + MMCICLEAR); host->busy_state = MMCI_BUSY_START_IRQ; + schedule_delayed_work(&host->busy_timeout_work, + msecs_to_jiffies(10)); } else { dev_dbg(mmc_dev(host->mmc), "lost busy status when waiting for busy start IRQ\n"); @@ -758,6 +761,7 @@ static bool ux500_busy_complete(struct mmci_host *host, u32 status, u32 err_msk) if (status & host->variant->busy_detect_flag) { host->busy_status |= status & (MCI_CMDSENT | MCI_CMDRESPEND); writel(host->variant->busy_detect_mask, base + MMCICLEAR); + cancel_delayed_work_sync(&host->busy_timeout_work); ux500_busy_clear_mask_done(host); } else { dev_dbg(mmc_dev(host->mmc), @@ -1498,6 +1502,22 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, } } +/* + * This busy timeout worker is used to "kick" the command IRQ if a + * busy detect IRQ fails to appear in reasonable time. Only used on + * variants with busy detection IRQ delivery. + */ +static void busy_timeout_work(struct work_struct *work) +{ + struct mmci_host *host = + container_of(work, struct mmci_host, busy_timeout_work.work); + u32 status; + + dev_dbg(mmc_dev(host->mmc), "timeout waiting for busy IRQ\n"); + status = readl(host->base + MMCISTATUS); + mmci_cmd_irq(host, host->cmd, status); +} + static int mmci_get_rx_fifocnt(struct mmci_host *host, u32 status, int remain) { return remain - (readl(host->base + MMCIFIFOCNT) << 2); @@ -2311,6 +2331,9 @@ static int mmci_probe(struct amba_device *dev, goto clk_disable; } + if (host->variant->busy_detect && host->ops->busy_complete) + INIT_DELAYED_WORK(&host->busy_timeout_work, busy_timeout_work); + writel(MCI_IRQENABLE | variant->start_err, host->base + MMCIMASK0); amba_set_drvdata(dev, mmc); diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 82f3850325c8..68ce7ea4d3b2 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -453,6 +453,7 @@ struct mmci_host { void *dma_priv; s32 next_cookie; + struct delayed_work busy_timeout_work; }; #define dma_inprogress(host) ((host)->dma_in_progress)