From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794061086; b=5MLY3J2vM1XowmFQHC7w156n7IX88CxoK1gvYHXyovM0h3O3zP/ZuJfShuP+koAoeFhN zjyyCFpNFJ4Gnsfc03kCxoFJYtwfyaxb+zeaWeqMLxMqB5FGLeeYdIqyvMTUWbisSekZG tZeE1bvYZuMYjuGgRnnVA2oqqvAyRg0ixF+yHs+fRaE/h0Xmz2/xi1ifU05bSpoAxGEU7 5VekE+DRjeqXJUjKB9J01c9d0ucB6r5m/CUqQaO3AFhPVNLHdfTb2eKMuYqJggiDyh737 WucsOpEiP4k0prg4acnx0Ka25WRcItZhPMEoMw8zLzZ9wcbE/xNI7RLtdnNFgDI0FuA== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794061086; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Transfer-Encoding; bh=rps7OSWjdXIzK3U4UQrdXmrS6lifzz/SjMJBuuebD9s=; b=nt6AdBuLOap0ZVMfHdDzT8krghhjhvuGhIDq6nW0vgCMX/5yKM5Nuxa6WGeNLvLFlD3d 58BgrmRGGtXvVEhw3vR2iNxGXb44LgOJGjwyeFqsps9D49tGt0K4TZusNUcUvWkklW5dn ibvRjiPhfCxBVmJN9wyiOFF6ZQJFuW+MsSulQmiNlKEU0GloKfQ1bVppCipGhcnsr4UmQ OjrBMYhmWg84d1VUGj+PQMi4hhBf/RARlM3St3cgsui98JZp+JSYVt5LYTRm7IV0acjBC 5k9QsDe10KiuPlVpSfFS574lrs8oYhPeItIVcbDykx37tE2l6r+LJUH+iX0nvmCSGjQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=0A0tOBRr; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 09AA0608363B; Sat, 7 Nov 2026 14:18:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=0A0tOBRr Received: by smtp.kernel.org (Postfix) with ESMTPSA id AD1521F008A2; Sat, 7 Nov 2026 14:18:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1794061085; bh=rps7OSWjdXIzK3U4UQrdXmrS6lifzz/SjMJBuuebD9s=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=0A0tOBRrfZ0DfnbPHwTjUl+ZcAhkEqHgGzz5nFlNHm7GTaoM4FA4ic5hvVLORVFsT WdTeEOMxadNviyMsVevGYUsrLdwkICZlyxHaAebg2yvmfvaeO/1OXUxwnt+nqME+5f 4qmtDXKifV1YrxdGd7FBTr+7PzooJ6waT0EnLU7Q= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Rosen Penev , Bartosz Golaszewski , Sasha Levin Subject: [PATCH 6.12 0408/1536] gpio: mvebu: keep resume masks within the irqchip cache Date: Sat, 7 Nov 2026 08:40:24 -0500 Message-ID: <20261107135009.038063656@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261107134957.653319350@linuxfoundation.org> References: <20261107134957.653319350@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: stable@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Rosen Penev [ Upstream commit 02af7eac17bc62a72335c1fc8c4af4471654f6cc ] mvebu_gpio_resume() writes the edge/level mask registers saved at suspend time straight back to hardware, bypassing the irqchip's mask_cache_priv. genirq skips mask_irq() for a line it already considers masked, so restoring a bit in hardware that genirq thinks is still masked leaves that line unmasked behind genirq's back. An asserted level line then has nobody to ack it, and the moment interrupts are re-enabled the chained handler storms, hanging resume. AND the restored mask values with the matching irqchip mask cache so only lines genirq currently considers unmasked are unmasked again. Read the caches under gc->lock to keep them consistent with the mask/unmask handlers. Tested on Helios4 (armhf): 5 suspend cycles woken by magic packet, no hang; mvebu_gpio_resume() returns in 6 usecs. Assisted-by: LLM Signed-off-by: Rosen Penev Link: https://patch.msgid.link/20260915004406.115230-1-rosenp@gmail.com Signed-off-by: Bartosz Golaszewski Signed-off-by: Sasha Levin --- drivers/gpio/gpio-mvebu.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index e554bd0fb1a8f..933a335af8c5b 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -1011,6 +1011,8 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state) static int mvebu_gpio_resume(struct platform_device *pdev) { struct mvebu_gpio_chip *mvchip = platform_get_drvdata(pdev); + u32 edge_cache = ~0U, level_cache = ~0U; + unsigned long flags; int i; regmap_write(mvchip->regs, GPIO_OUT_OFF + mvchip->offset, @@ -1022,32 +1024,51 @@ static int mvebu_gpio_resume(struct platform_device *pdev) regmap_write(mvchip->regs, GPIO_IN_POL_OFF + mvchip->offset, mvchip->in_pol_reg); + /* + * genirq skips mask_irq() for a line it already considers masked, so + * unmasking one behind its back leaves an asserted level line that + * nobody masks. Restore only bits the irqchip cache still has set. + * + * Snapshot the caches under the raw spinlock, but release it before + * the regmap writes below: regmap_write() takes a sleepable lock on + * PREEMPT_RT. + */ + if (mvchip->domain) { + struct irq_chip_generic *gc; + + gc = irq_get_domain_generic_chip(mvchip->domain, 0); + raw_spin_lock_irqsave(&gc->lock, flags); + level_cache = gc->chip_types[0].mask_cache_priv; + edge_cache = gc->chip_types[1].mask_cache_priv; + raw_spin_unlock_irqrestore(&gc->lock, flags); + } + switch (mvchip->soc_variant) { case MVEBU_GPIO_SOC_VARIANT_ORION: case MVEBU_GPIO_SOC_VARIANT_A8K: regmap_write(mvchip->regs, GPIO_EDGE_MASK_OFF + mvchip->offset, - mvchip->edge_mask_regs[0]); + mvchip->edge_mask_regs[0] & edge_cache); regmap_write(mvchip->regs, GPIO_LEVEL_MASK_OFF + mvchip->offset, - mvchip->level_mask_regs[0]); + mvchip->level_mask_regs[0] & level_cache); break; case MVEBU_GPIO_SOC_VARIANT_MV78200: for (i = 0; i < 2; i++) { regmap_write(mvchip->regs, GPIO_EDGE_MASK_MV78200_OFF(i), - mvchip->edge_mask_regs[i]); + mvchip->edge_mask_regs[i] & edge_cache); regmap_write(mvchip->regs, GPIO_LEVEL_MASK_MV78200_OFF(i), - mvchip->level_mask_regs[i]); + mvchip->level_mask_regs[i] & level_cache); } break; case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: for (i = 0; i < 4; i++) { regmap_write(mvchip->regs, GPIO_EDGE_MASK_ARMADAXP_OFF(i), - mvchip->edge_mask_regs[i]); + mvchip->edge_mask_regs[i] & edge_cache); regmap_write(mvchip->regs, GPIO_LEVEL_MASK_ARMADAXP_OFF(i), - mvchip->level_mask_regs[i]); + mvchip->level_mask_regs[i] & level_cache); } break; default: -- 2.53.0