Message ID | 20221122132304.1482508-1-peter.suti@streamunlimited.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2198997wrr; Tue, 22 Nov 2022 05:29:11 -0800 (PST) X-Google-Smtp-Source: AA0mqf5bZc6zauh49F1jjZlk/JUATZKYCJuqRzZnwExAFdP37xwWEolnWT3ALd3lB+mWJdAuROwh X-Received: by 2002:a63:d556:0:b0:46b:158f:6265 with SMTP id v22-20020a63d556000000b0046b158f6265mr3299040pgi.193.1669123751367; Tue, 22 Nov 2022 05:29:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669123751; cv=none; d=google.com; s=arc-20160816; b=PxF6kgjrwSXTi2PPDDNJo3obmFkHJXv+Trd1lwwJsbY4gr5c6YHaHYg4Vg2Mxsm0IA sOLprrjUJAryLNFfw2KA95Vpudf0hkAj9WXWUR6uEU2o0XzhKtYVjrOFyPafNViYIdkJ 4sO/dKcPIcuS4TrlpZCFAJURuuOJOfiW13vXR5098vLZLX4jlMntRZSRaolc8aCiGvEO SR9g1n8dn1CDJOR0M6RU7VJDKkPRB6IXGdoDEsMqCjVpwf0ry2mh0/ctSAGPHRNMkNVz Wnw3zrIaRhpXKCqr8VewPYmXHB8e/0z0QyGmxmMhI8NNPh3tHHPQNLwNCUnPeanZh4tE hU9w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=issWTojkRWwRHPZ2j+gQ8ojVqtNRu9IZkFS8IgCllcQ=; b=uLmScg4AqkFTnIAB3hCX17Sb5Y2cG/Zlra4Ey1qO51QXFDVTdDLDU2V6/EEm1U37p6 8ssk6EjG2L1seABnDTyVMLCdGq1WJJIHXbaeCUkLrUi2hw0F/hiculFCv1KE5KTBDRQ9 g7rgKcTU2VbCHkFVFE20JBlJmDWv0+H7F3UZ3GS+MSvzW00RxjbuUnITsqmRIlJ78qeD lFrmCSdSLd1iR8JB++GYpwioO3PotCF+rytjFNBUC+y2K5ibFMF/va6lbYMOS5l6ThOT U/GTI38qT0TvEeSzaM+j3x8DdczTY93tYmZFb1YtvUT4wt3oUMhM3zGsQsciZ8lTOuL2 HsUA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@streamunlimited.com header.s=google header.b="Q6aoLE/g"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=streamunlimited.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bj9-20020a170902850900b00186a8bd137fsi12582914plb.453.2022.11.22.05.28.57; Tue, 22 Nov 2022 05:29:11 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@streamunlimited.com header.s=google header.b="Q6aoLE/g"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=streamunlimited.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232853AbiKVNXs (ORCPT <rfc822;cjcooper78@gmail.com> + 99 others); Tue, 22 Nov 2022 08:23:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52958 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232802AbiKVNXp (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Tue, 22 Nov 2022 08:23:45 -0500 Received: from mail-qt1-x82b.google.com (mail-qt1-x82b.google.com [IPv6:2607:f8b0:4864:20::82b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4FA4F1F62A for <linux-kernel@vger.kernel.org>; Tue, 22 Nov 2022 05:23:41 -0800 (PST) Received: by mail-qt1-x82b.google.com with SMTP id l2so9186407qtq.11 for <linux-kernel@vger.kernel.org>; Tue, 22 Nov 2022 05:23:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=streamunlimited.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=issWTojkRWwRHPZ2j+gQ8ojVqtNRu9IZkFS8IgCllcQ=; b=Q6aoLE/g+fzPHn+PnCKdrn/BrRxrGWD0/CX5ONbAQckV97NqTO8xj2TigP9aYVdRUX AoIAvco6DhsUru77+CJBvtWPK+uovNdFeERay1OWYOEI2r0CQdtwQaIjQQcsWTmcXyti FJXYD8hXeWr76NwVyFXjygZkUQcFwyQGyjaXM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=issWTojkRWwRHPZ2j+gQ8ojVqtNRu9IZkFS8IgCllcQ=; b=USdA4nKZfS7ttEqZxkmPVTiFpG2LrjxHO2lp+shi2HJZ/VEG7NQUJglWHaH5X2pOQ8 JS+na84KsHjPn7Y7Z/klFQWMDmXBTOsXULESGPh7YIKaqj9CbXw/JROnmTsu1Idq7qGB mZaMOsbaUDVQqf+jZXH2sqZwxPGrXuzoybISmyRQm2yRhWWcijhnqmbIfS7SiXRZcDiS JdlF2KfBdlQKBtqo2RCuSGZQCx2KE210vJ1HGohiqmbcEuxb7LP1sx4ABORJu4YKWmJg g0s/EtdkaqBJ/zkkx+pluPOioxvQH6YdA3PE4slVFnCNkKqRTB5PIssDxoWZGHUGAalH jkzA== X-Gm-Message-State: ANoB5pnMSMlvQHp0hlmPz0fWC6rK5dIjRNXUk6zK3cGcpRFL3ZGbPXIO 994uZuPHQF/H+gcRhNgS0joQJw== X-Received: by 2002:a05:622a:4c18:b0:3a6:275a:8538 with SMTP id ey24-20020a05622a4c1800b003a6275a8538mr17685007qtb.109.1669123420436; Tue, 22 Nov 2022 05:23:40 -0800 (PST) Received: from localhost.localdomain (vpn.streamunlimited.com. [91.114.0.140]) by smtp.gmail.com with ESMTPSA id w11-20020a05620a444b00b006fb72dbbaa4sm10084441qkp.27.2022.11.22.05.23.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 22 Nov 2022 05:23:39 -0800 (PST) From: Peter Suti <peter.suti@streamunlimited.com> To: Ulf Hansson <ulf.hansson@linaro.org>, Neil Armstrong <neil.armstrong@linaro.org>, Kevin Hilman <khilman@baylibre.com>, Jerome Brunet <jbrunet@baylibre.com>, Martin Blumenstingl <martin.blumenstingl@googlemail.com>, Heiner Kallweit <hkallweit1@gmail.com> Cc: Peter Suti <peter.suti@streamunlimited.com>, linux-mmc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-amlogic@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] mmc: meson-gx: fix SDIO interrupt handling Date: Tue, 22 Nov 2022 14:23:03 +0100 Message-Id: <20221122132304.1482508-1-peter.suti@streamunlimited.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <CAPDyKFqrCCtY_A072WswEFa3Bnz7EfMp40MRYtr3G7Jbq_hbTw@mail.gmail.com> References: <CAPDyKFqrCCtY_A072WswEFa3Bnz7EfMp40MRYtr3G7Jbq_hbTw@mail.gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749464611573751529?= X-GMAIL-MSGID: =?utf-8?q?1750203106271372657?= |
Series |
[v2] mmc: meson-gx: fix SDIO interrupt handling
|
|
Commit Message
Peter Suti
Nov. 22, 2022, 1:23 p.m. UTC
With the interrupt support introduced in commit 066ecde sometimes the
Marvell-8987 wifi chip entered a deadlock using the marvell-sd-uapsta-8987
vendor driver. The cause seems to be that sometimes the interrupt handler
handles 2 IRQs and one of them disables the interrupts which are not reenabled
when all interrupts are finished. To work around this, disable all interrupts
when we are in the IRQ context and reenable them when the current IRQ is handled.
Fixes: 066ecde ("mmc: meson-gx: add SDIO interrupt support")
Signed-off-by: Peter Suti <peter.suti@streamunlimited.com>
---
Changes in v2:
- use spin_lock instead of spin_lock_irqsave
- only reenable interrupts if they were enabled already
drivers/mmc/host/meson-gx-mmc.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)
Comments
On Tue, 22 Nov 2022 at 14:23, Peter Suti <peter.suti@streamunlimited.com> wrote: > > With the interrupt support introduced in commit 066ecde sometimes the > Marvell-8987 wifi chip entered a deadlock using the marvell-sd-uapsta-8987 > vendor driver. The cause seems to be that sometimes the interrupt handler > handles 2 IRQs and one of them disables the interrupts which are not reenabled > when all interrupts are finished. To work around this, disable all interrupts > when we are in the IRQ context and reenable them when the current IRQ is handled. > > Fixes: 066ecde ("mmc: meson-gx: add SDIO interrupt support") > > Signed-off-by: Peter Suti <peter.suti@streamunlimited.com> > --- > Changes in v2: > - use spin_lock instead of spin_lock_irqsave > - only reenable interrupts if they were enabled already > > drivers/mmc/host/meson-gx-mmc.c | 30 +++++++++++++++++++++++------- > 1 file changed, 23 insertions(+), 7 deletions(-) > > diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c > index 6e5ea0213b47..0c95f8640b34 100644 > --- a/drivers/mmc/host/meson-gx-mmc.c > +++ b/drivers/mmc/host/meson-gx-mmc.c > @@ -934,6 +934,13 @@ static void meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd) > } > } > > +static bool __meson_mmc_sdio_irq_is_enabled(struct mmc_host *mmc) Looks like it's better to pass a struct meson_host *host, rather than a struct mmc_host *mmc. > +{ > + struct meson_host *host = mmc_priv(mmc); > + > + return readl(host->regs + SD_EMMC_IRQ_EN) & IRQ_SDIO; > +} > + > static void __meson_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) > { > struct meson_host *host = mmc_priv(mmc); > @@ -950,6 +957,11 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) > struct mmc_command *cmd; > u32 status, raw_status; > irqreturn_t ret = IRQ_NONE; > + bool irq_enabled; Nitpick: (since I have a few comments anyway). May I suggest rename this to sdio_irq_enabled instead? > + > + spin_lock(&host->lock); > + irq_enabled = __meson_mmc_sdio_irq_is_enabled(host->mmc); > + __meson_mmc_enable_sdio_irq(host->mmc, 0); > > raw_status = readl(host->regs + SD_EMMC_STATUS); > status = raw_status & (IRQ_EN_MASK | IRQ_SDIO); > @@ -958,11 +970,11 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) > dev_dbg(host->dev, > "Unexpected IRQ! irq_en 0x%08lx - status 0x%08x\n", > IRQ_EN_MASK | IRQ_SDIO, raw_status); > - return IRQ_NONE; > + goto out_unlock; > } > > if (WARN_ON(!host)) > - return IRQ_NONE; > + goto out_unlock; This part looks like it now becomes incorrectly redundant, since we are now using "host->mmc" a few lines above while calling __meson_mmc_sdio_irq_is_enabled(). Maybe move the new code below this part instead? > > /* ack all raised interrupts */ > writel(status, host->regs + SD_EMMC_STATUS); > @@ -970,17 +982,16 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) > cmd = host->cmd; > > if (status & IRQ_SDIO) { > - spin_lock(&host->lock); > - __meson_mmc_enable_sdio_irq(host->mmc, 0); > sdio_signal_irq(host->mmc); > - spin_unlock(&host->lock); > status &= ~IRQ_SDIO; > - if (!status) > + if (!status) { > + spin_unlock(&host->lock); > return IRQ_HANDLED; > + } > } > > if (WARN_ON(!cmd)) > - return IRQ_NONE; > + goto out_unlock; > > cmd->error = 0; > if (status & IRQ_CRC_ERR) { > @@ -1023,6 +1034,11 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) > if (ret == IRQ_HANDLED) > meson_mmc_request_done(host->mmc, cmd->mrq); > > +out_unlock: > + if (irq_enabled) > + __meson_mmc_enable_sdio_irq(host->mmc, 1); > + spin_unlock(&host->lock); > + > return ret; > } > Kind regards Uffe
On 22.11.2022 14:23, Peter Suti wrote: > With the interrupt support introduced in commit 066ecde sometimes the > Marvell-8987 wifi chip entered a deadlock using the marvell-sd-uapsta-8987 > vendor driver. The cause seems to be that sometimes the interrupt handler > handles 2 IRQs and one of them disables the interrupts which are not reenabled > when all interrupts are finished. To work around this, disable all interrupts > when we are in the IRQ context and reenable them when the current IRQ is handled. > To me it's still not clear what you mean with "handles 2 IRQs". Hard irq handlers aren't re-entrant. Can you provide the exact call sequence for the issue you're facing? Are SDIO interrupts handled on more than one CPU in your case? Are you concerned about the hard irq handler running in parallel on more than one CPU? The proposed patch looks hacky and somewhat bypasses the SDIO core logic by partially re-enabling SDIO interrupts in the hard irq handler. In the first review round I wrote the following but didn't see a feedback yet. Did you check the linked discussion whether it may be related to your issue? -> IIRC I had a similar/same problem in mind when discussing the following: -> https://lore.kernel.org/linux-arm-kernel/CAPDyKFoameOb7d3cn8_ki1O6DbMEAFvkQh1uUsYp4S-Lkq41oQ@mail.gmail.com/ -> Not sure though whether it's related to the issue you're facing. > Fixes: 066ecde ("mmc: meson-gx: add SDIO interrupt support") > > Signed-off-by: Peter Suti <peter.suti@streamunlimited.com> > --- > Changes in v2: > - use spin_lock instead of spin_lock_irqsave > - only reenable interrupts if they were enabled already > > drivers/mmc/host/meson-gx-mmc.c | 30 +++++++++++++++++++++++------- > 1 file changed, 23 insertions(+), 7 deletions(-) > > diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c > index 6e5ea0213b47..0c95f8640b34 100644 > --- a/drivers/mmc/host/meson-gx-mmc.c > +++ b/drivers/mmc/host/meson-gx-mmc.c > @@ -934,6 +934,13 @@ static void meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd) > } > } > > +static bool __meson_mmc_sdio_irq_is_enabled(struct mmc_host *mmc) > +{ > + struct meson_host *host = mmc_priv(mmc); > + > + return readl(host->regs + SD_EMMC_IRQ_EN) & IRQ_SDIO; > +} > + > static void __meson_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) > { > struct meson_host *host = mmc_priv(mmc); > @@ -950,6 +957,11 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) > struct mmc_command *cmd; > u32 status, raw_status; > irqreturn_t ret = IRQ_NONE; > + bool irq_enabled; > + > + spin_lock(&host->lock); > + irq_enabled = __meson_mmc_sdio_irq_is_enabled(host->mmc); > + __meson_mmc_enable_sdio_irq(host->mmc, 0); > > raw_status = readl(host->regs + SD_EMMC_STATUS); > status = raw_status & (IRQ_EN_MASK | IRQ_SDIO); > @@ -958,11 +970,11 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) > dev_dbg(host->dev, > "Unexpected IRQ! irq_en 0x%08lx - status 0x%08x\n", > IRQ_EN_MASK | IRQ_SDIO, raw_status); > - return IRQ_NONE; > + goto out_unlock; > } > > if (WARN_ON(!host)) > - return IRQ_NONE; > + goto out_unlock; > > /* ack all raised interrupts */ > writel(status, host->regs + SD_EMMC_STATUS); > @@ -970,17 +982,16 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) > cmd = host->cmd; > > if (status & IRQ_SDIO) { > - spin_lock(&host->lock); > - __meson_mmc_enable_sdio_irq(host->mmc, 0); > sdio_signal_irq(host->mmc); > - spin_unlock(&host->lock); > status &= ~IRQ_SDIO; > - if (!status) > + if (!status) { > + spin_unlock(&host->lock); > return IRQ_HANDLED; > + } > } > > if (WARN_ON(!cmd)) > - return IRQ_NONE; > + goto out_unlock; > > cmd->error = 0; > if (status & IRQ_CRC_ERR) { > @@ -1023,6 +1034,11 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) > if (ret == IRQ_HANDLED) > meson_mmc_request_done(host->mmc, cmd->mrq); > > +out_unlock: > + if (irq_enabled) > + __meson_mmc_enable_sdio_irq(host->mmc, 1); > + spin_unlock(&host->lock); > + > return ret; > } >
diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 6e5ea0213b47..0c95f8640b34 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -934,6 +934,13 @@ static void meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd) } } +static bool __meson_mmc_sdio_irq_is_enabled(struct mmc_host *mmc) +{ + struct meson_host *host = mmc_priv(mmc); + + return readl(host->regs + SD_EMMC_IRQ_EN) & IRQ_SDIO; +} + static void __meson_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) { struct meson_host *host = mmc_priv(mmc); @@ -950,6 +957,11 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) struct mmc_command *cmd; u32 status, raw_status; irqreturn_t ret = IRQ_NONE; + bool irq_enabled; + + spin_lock(&host->lock); + irq_enabled = __meson_mmc_sdio_irq_is_enabled(host->mmc); + __meson_mmc_enable_sdio_irq(host->mmc, 0); raw_status = readl(host->regs + SD_EMMC_STATUS); status = raw_status & (IRQ_EN_MASK | IRQ_SDIO); @@ -958,11 +970,11 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) dev_dbg(host->dev, "Unexpected IRQ! irq_en 0x%08lx - status 0x%08x\n", IRQ_EN_MASK | IRQ_SDIO, raw_status); - return IRQ_NONE; + goto out_unlock; } if (WARN_ON(!host)) - return IRQ_NONE; + goto out_unlock; /* ack all raised interrupts */ writel(status, host->regs + SD_EMMC_STATUS); @@ -970,17 +982,16 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) cmd = host->cmd; if (status & IRQ_SDIO) { - spin_lock(&host->lock); - __meson_mmc_enable_sdio_irq(host->mmc, 0); sdio_signal_irq(host->mmc); - spin_unlock(&host->lock); status &= ~IRQ_SDIO; - if (!status) + if (!status) { + spin_unlock(&host->lock); return IRQ_HANDLED; + } } if (WARN_ON(!cmd)) - return IRQ_NONE; + goto out_unlock; cmd->error = 0; if (status & IRQ_CRC_ERR) { @@ -1023,6 +1034,11 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) if (ret == IRQ_HANDLED) meson_mmc_request_done(host->mmc, cmd->mrq); +out_unlock: + if (irq_enabled) + __meson_mmc_enable_sdio_irq(host->mmc, 1); + spin_unlock(&host->lock); + return ret; }