From patchwork Sun Jun 11 19:41:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 13275365 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 2DB64C7EE2F for ; Sun, 11 Jun 2023 19:41:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232058AbjFKTl4 (ORCPT ); Sun, 11 Jun 2023 15:41:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44176 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233772AbjFKTlz (ORCPT ); Sun, 11 Jun 2023 15:41:55 -0400 Received: from mail-lf1-x12d.google.com (mail-lf1-x12d.google.com [IPv6:2a00:1450:4864:20::12d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1554B126 for ; Sun, 11 Jun 2023 12:41:52 -0700 (PDT) Received: by mail-lf1-x12d.google.com with SMTP id 2adb3069b0e04-4f63ab1ac4aso4146758e87.0 for ; Sun, 11 Jun 2023 12:41:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1686512510; x=1689104510; 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=j+1+S9hp0bTxPBqMP9IlZLkTv4wJCYyQn7oPu0mlDDM=; b=wO3ThUt4hp5j3C9HdmnPZMDUtmaKLluhsXOfPKD2WgZtfcDvjFYQLknqeaySvZ2fhq kx5lwGmIZo7AnyHS9n0PuHRGILFVDnTI9UdHMru0nSd34YqrwoueZ/0tkYou6iDqBFgu vgA1Ss7rqkfhnT9u9H4SDzhOn1LR9L9zAVJB8br5/A3RYbWgCsUw/gYP3sPeHVzq9sua vGGDa/GbcL+sBaRDfKIvGS3GZfcaW0NgwpW8EApFZtHc2+G98isB9HVZRb3DhA6TyXAG CZzL6j8HyEaD2E3pMPn96of+sbmdzWEfbg4OYBVgvVG6JZIYLoclZDEyk3FhHMkjWMV5 TdzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1686512510; x=1689104510; 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=j+1+S9hp0bTxPBqMP9IlZLkTv4wJCYyQn7oPu0mlDDM=; b=evVp6LM4vZmEPHA+foy4tHoFZmzeMC+Wb/y9d9QAPrkfbm7yMZzPBiLV83r2+XY+Jl jorYKLd5YgxcQEk4hlfKT0XxcPWh2sSaCWrmRAGoYMDu4FVMFJX2kwT/gnl7297x9FpK wqtqQVhQvf3pc9Oevz3oBnlHqDQqjw+280RRev+rIQuY+QcGu81ZHrmsEKowwCymWtc/ Y1ZvBHQmdhVolLsTfhk3bQfsyLpmQ5YV8Br64yOVd7B3HM9wngRKPmonQsqebDftsDGQ A+TTZ7uQOMYrnSVOWKMSIZYV2mJVL8q5/x23KgOWGSqIxauIcMCwUPNUmG94xkiHo1cu SGjQ== X-Gm-Message-State: AC+VfDwVxyIiPAQVnHi32tLtm5PS6sID4IuQfgmS/tMWVEg8CtnDJsxk tGjM0YopxZWyOhyqxtZnb2PtuQ== X-Google-Smtp-Source: ACHHUZ7gwtSEITF6+GPD71WfSTdThuSmOnOuI2Mb0zrUP0AP15KtxfazuP9qFj/EtAJSsXpvHUUH1Q== X-Received: by 2002:a19:6550:0:b0:4f4:b218:e85f with SMTP id c16-20020a196550000000b004f4b218e85fmr2301600lfj.31.1686512510394; Sun, 11 Jun 2023 12:41:50 -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 u24-20020ac243d8000000b004f14ae5ded8sm1246960lfl.28.2023.06.11.12.41.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 11 Jun 2023 12:41:49 -0700 (PDT) From: Linus Walleij Date: Sun, 11 Jun 2023 21:41:36 +0200 Subject: [PATCH v3 10/10] mmc: mmci: Add busydetect timeout MIME-Version: 1.0 Message-Id: <20230405-pl180-busydetect-fix-v3-10-cd3d5925ae64@linaro.org> References: <20230405-pl180-busydetect-fix-v3-0-cd3d5925ae64@linaro.org> In-Reply-To: <20230405-pl180-busydetect-fix-v3-0-cd3d5925ae64@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.2 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 v2->v3: - Rebased. 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 05b8fad26c10..7e40b8f2dbf3 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -741,6 +742,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_WAITING_FOR_END_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"); @@ -752,6 +755,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), @@ -1487,6 +1491,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); @@ -2300,6 +2320,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 12a7bbd3ce26..95d3d0a6049b 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -451,6 +451,7 @@ struct mmci_host { void *dma_priv; s32 next_cookie; + struct delayed_work busy_timeout_work; }; #define dma_inprogress(host) ((host)->dma_in_progress)