Received: by 2002:ac0:a582:0:0:0:0:0 with SMTP id m2-v6csp3727248imm; Mon, 8 Oct 2018 08:34:58 -0700 (PDT) X-Google-Smtp-Source: ACcGV63ZMfvIxmz8RaIxHBHQ169T5RLG4YVoyBKiPWA4YZB0tv6szkCkySvLsHveCiKbUReG1qdX X-Received: by 2002:a17:902:4403:: with SMTP id k3-v6mr24418710pld.243.1539012897896; Mon, 08 Oct 2018 08:34:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1539012897; cv=none; d=google.com; s=arc-20160816; b=apzMf5UFCkbbffQgD8uH8ih9G5o1WN/V+uUjLVSGt5f5xkn8tf9L3/dGvGFNm0K3wn fkS3HcvXQesBDOJPHf4CaqBr7/GU1b8f6uTKCHATtlVpCdCb08YCEjNfiDQbX96GDs5U 328NLMNsW+DZsCNgW7C4H5Wg0QQE47SvgrnHAo9aTiEi7XK2FI7CdwZIgdf3kpfnh9NC gGbrWW0kDfh9aacVfQp4nUL6AYzhpEIu7Gu+gpOc5BL0radVEkbDvNOWHdqLqGQaN5ii bM85lz17sRh/DcWonzIpsnZqZZy4Pckkmz54n23CxNik0YT9XlaWiMaArofYywwLCD5Q a0qQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=IT6keO98P6iyi10mlZkZuVYwR1VWKwCDBQHqULxQVe8=; b=X187nUWGYhsnNURvdBo4wBnGXE5rfJpViJ8CUL6y1bZbR29QgMsJj3uB/P6pkLLebR /LL2jYGCKJbire0afqSSx2kNBVFnEAdMBKrYSK/ShqXrSLtAIz5SLaP7mSQT1UZnf+oz AjaELDmy0ZD2X9VA6Jr1CeenaENxdgobdYnXHTr1jXKqTvVXbtHzmVqMLNrw7W/gxjqq iklUSiJb0+SvyNAVcuiDZxe7Q4pinP47PFJliFJetLx++xInoOVF4hFaD5opz67OUc7f pJ3+PHzLJ/tXubhhX6mRly6QlY5c4jXC/93YP/kXrNlEzTigrr1O13oO+7++cu48DcX5 nQRw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=M6bDKsE4; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id v32-v6si17944159pgk.16.2018.10.08.08.34.42; Mon, 08 Oct 2018 08:34:57 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=M6bDKsE4; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728107AbeJHWic (ORCPT + 99 others); Mon, 8 Oct 2018 18:38:32 -0400 Received: from mail.kernel.org ([198.145.29.99]:57148 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727563AbeJHWib (ORCPT ); Mon, 8 Oct 2018 18:38:31 -0400 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 17D3D2150F; Mon, 8 Oct 2018 15:26:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1539012376; bh=3MRtnVqi5AAqySeQ2o8Ii8hXF6IhZZHpVsGuNwW6A4A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M6bDKsE4vIi5wOS+7dBdjT1AvAjdGbwbD5mGhYwjOFbSucNZI+gfAyAjHOhHyLLWB gSVPQNDQC/5YsNbsi+zd5ksaKHK8zpTYUCgrctUBp7CPFfswllZKYrrBycnHZpBAC8 McxsyLOlSZio192vAKFIUIIkabO0CnU/CA4myksE= From: Sasha Levin To: stable@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Daniel Kurtz , Linus Walleij , Sasha Levin Subject: [PATCH AUTOSEL 4.18 53/58] pinctrl/amd: poll InterruptEnable bits in amd_gpio_irq_set_type Date: Mon, 8 Oct 2018 11:25:18 -0400 Message-Id: <20181008152523.70705-53-sashal@kernel.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181008152523.70705-1-sashal@kernel.org> References: <20181008152523.70705-1-sashal@kernel.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Daniel Kurtz [ Upstream commit b85bfa246efd24ea3fdb5ee949c28e3110c6d299 ] From the AMD BKDG, if WAKE_INT_MASTER_REG.MaskStsEn is set, a software write to the debounce registers of *any* gpio will block wake/interrupt status generation for *all* gpios for a length of time that depends on WAKE_INT_MASTER_REG.MaskStsLength[11:0]. During this period the Interrupt Delivery bit (INTERRUPT_ENABLE) will read as 0. In commit 4c1de0414a1340 ("pinctrl/amd: poll InterruptEnable bits in enable_irq") we tried to fix this same "gpio Interrupts are blocked immediately after writing debounce registers" problem, but incorrectly assumed it only affected the gpio whose debounce was being configured and not ALL gpios. To solve this for all gpios, we move the polling loop from amd_gpio_irq_enable() to amd_gpio_irq_set_type(), while holding the gpio spinlock. This ensures that another gpio operation (e.g. amd_gpio_irq_unmask()) can read a temporarily disabled IRQ and incorrectly disable it while trying to modify some other register bits. Fixes: 4c1de0414a1340 pinctrl/amd: poll InterruptEnable bits in enable_irq Signed-off-by: Daniel Kurtz Signed-off-by: Linus Walleij Signed-off-by: Sasha Levin --- drivers/pinctrl/pinctrl-amd.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index b91db89eb924..d3ba867d01f0 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -348,21 +348,12 @@ static void amd_gpio_irq_enable(struct irq_data *d) unsigned long flags; struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct amd_gpio *gpio_dev = gpiochip_get_data(gc); - u32 mask = BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF); raw_spin_lock_irqsave(&gpio_dev->lock, flags); pin_reg = readl(gpio_dev->base + (d->hwirq)*4); pin_reg |= BIT(INTERRUPT_ENABLE_OFF); pin_reg |= BIT(INTERRUPT_MASK_OFF); writel(pin_reg, gpio_dev->base + (d->hwirq)*4); - /* - * When debounce logic is enabled it takes ~900 us before interrupts - * can be enabled. During this "debounce warm up" period the - * "INTERRUPT_ENABLE" bit will read as 0. Poll the bit here until it - * reads back as 1, signaling that interrupts are now enabled. - */ - while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask) - continue; raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); } @@ -426,7 +417,7 @@ static void amd_gpio_irq_eoi(struct irq_data *d) static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type) { int ret = 0; - u32 pin_reg; + u32 pin_reg, pin_reg_irq_en, mask; unsigned long flags, irq_flags; struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct amd_gpio *gpio_dev = gpiochip_get_data(gc); @@ -495,6 +486,28 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type) } pin_reg |= CLR_INTR_STAT << INTERRUPT_STS_OFF; + /* + * If WAKE_INT_MASTER_REG.MaskStsEn is set, a software write to the + * debounce registers of any GPIO will block wake/interrupt status + * generation for *all* GPIOs for a lenght of time that depends on + * WAKE_INT_MASTER_REG.MaskStsLength[11:0]. During this period the + * INTERRUPT_ENABLE bit will read as 0. + * + * We temporarily enable irq for the GPIO whose configuration is + * changing, and then wait for it to read back as 1 to know when + * debounce has settled and then disable the irq again. + * We do this polling with the spinlock held to ensure other GPIO + * access routines do not read an incorrect value for the irq enable + * bit of other GPIOs. We keep the GPIO masked while polling to avoid + * spurious irqs, and disable the irq again after polling. + */ + mask = BIT(INTERRUPT_ENABLE_OFF); + pin_reg_irq_en = pin_reg; + pin_reg_irq_en |= mask; + pin_reg_irq_en &= ~BIT(INTERRUPT_MASK_OFF); + writel(pin_reg_irq_en, gpio_dev->base + (d->hwirq)*4); + while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask) + continue; writel(pin_reg, gpio_dev->base + (d->hwirq)*4); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); -- 2.17.1