From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2A489C47257 for ; Mon, 4 May 2020 18:12:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0BBD420663 for ; Mon, 4 May 2020 18:12:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1588615977; bh=sKd4IOOd+1Slt8yImQ9WOxQZC4UE/kImsmCfjq/0hBQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=tHUfXGgUAA/IuyQbsRnKbUfxtgFlpFuMaUnE/h+ikW2xBsX2iARZk1FGq+LYtvNgi ao6E9rT7dPuTKqgABWSxJcemxRQMB0pJBqBqyMwnVY69tUF02b30UIrsWdKKdsFQfv cfRvjBgeLOHJzXy0qqug/HOj2J7ZOxNCfrgmZOcw= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732303AbgEDSM4 (ORCPT ); Mon, 4 May 2020 14:12:56 -0400 Received: from mail.kernel.org ([198.145.29.99]:58274 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731284AbgEDSCJ (ORCPT ); Mon, 4 May 2020 14:02:09 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id EF61F20721; Mon, 4 May 2020 18:02:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1588615328; bh=sKd4IOOd+1Slt8yImQ9WOxQZC4UE/kImsmCfjq/0hBQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RUlNZuPdXQQdTDr5sWeDdhS9wdSACuCEuMMecZ4efz6NjrB5QOq3E3IeVOEJLTwyd kBHtPByFTQpBoH+LEg0Gu+FF9oiBC5SRgd9SC0E7ZhLBioVK7GXs6QtUYoSz2kgpUO k/dorYnfnYPQOP3mxl5BZDIdVL0zLEVU4vQRnfVM= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Douglas Anderson , Adrian Hunter , Ulf Hansson Subject: [PATCH 4.19 32/37] mmc: cqhci: Avoid false "cqhci: CQE stuck on" by not open-coding timeout loop Date: Mon, 4 May 2020 19:57:45 +0200 Message-Id: <20200504165451.529374240@linuxfoundation.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200504165448.264746645@linuxfoundation.org> References: <20200504165448.264746645@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Douglas Anderson commit b1ac62a7ac386d76968af5f374a4a7a82a35fe31 upstream. Open-coding a timeout loop invariably leads to errors with handling the timeout properly in one corner case or another. In the case of cqhci we might report "CQE stuck on" even if it wasn't stuck on. You'd just need this sequence of events to happen in cqhci_off(): 1. Call ktime_get(). 2. Something happens to interrupt the CPU for > 100 us (context switch or interrupt). 3. Check time and; set "timed_out" to true since > 100 us. 4. Read CQHCI_CTL. 5. Both "reg & CQHCI_HALT" and "timed_out" are true, so break. 6. Since "timed_out" is true, falsely print the error message. Rather than fixing the polling loop, use readx_poll_timeout() like many people do. This has been time tested to handle the corner cases. Fixes: a4080225f51d ("mmc: cqhci: support for command queue enabled host") Signed-off-by: Douglas Anderson Acked-by: Adrian Hunter Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200413162717.1.Idece266f5c8793193b57a1ddb1066d030c6af8e0@changeid Signed-off-by: Ulf Hansson Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/host/cqhci.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) --- a/drivers/mmc/host/cqhci.c +++ b/drivers/mmc/host/cqhci.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -351,12 +352,16 @@ static int cqhci_enable(struct mmc_host /* CQHCI is idle and should halt immediately, so set a small timeout */ #define CQHCI_OFF_TIMEOUT 100 +static u32 cqhci_read_ctl(struct cqhci_host *cq_host) +{ + return cqhci_readl(cq_host, CQHCI_CTL); +} + static void cqhci_off(struct mmc_host *mmc) { struct cqhci_host *cq_host = mmc->cqe_private; - ktime_t timeout; - bool timed_out; u32 reg; + int err; if (!cq_host->enabled || !mmc->cqe_on || cq_host->recovery_halt) return; @@ -366,15 +371,9 @@ static void cqhci_off(struct mmc_host *m cqhci_writel(cq_host, CQHCI_HALT, CQHCI_CTL); - timeout = ktime_add_us(ktime_get(), CQHCI_OFF_TIMEOUT); - while (1) { - timed_out = ktime_compare(ktime_get(), timeout) > 0; - reg = cqhci_readl(cq_host, CQHCI_CTL); - if ((reg & CQHCI_HALT) || timed_out) - break; - } - - if (timed_out) + err = readx_poll_timeout(cqhci_read_ctl, cq_host, reg, + reg & CQHCI_HALT, 0, CQHCI_OFF_TIMEOUT); + if (err < 0) pr_err("%s: cqhci: CQE stuck on\n", mmc_hostname(mmc)); else pr_debug("%s: cqhci: CQE off\n", mmc_hostname(mmc));