From nobody Mon Jun 8 04:26:16 2026 Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6867E403EA0; Wed, 3 Jun 2026 08:09:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.210.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780474200; cv=none; b=t40eRMO58GrGV4y7zIAExj4wf6p2kUpPhAKixD6UNI1/ErkB6xLeq0RnACYKekO8ACtAosPxQWPL6+XuaQ5EMnwfjk6Ey3UZVLWHxouCuTdYwLuHZPnlI9dlEVLnqBy/XunH/KtGMg4UXkmSJsa3sTT9pq11U6aHJAO4yOgr2ik= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780474200; c=relaxed/simple; bh=trhe3JQRuZD6Z2eqR2dt5x0aSlZ4iceV6hLNqZtc3MA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=VikB5+JtpfaIXj27HDPj+JteJq3QBVhbFljVUXt7hTgvAp6GGRpGeqxxo+0N4FJmMpsXBmR4kZJBhW4ErlQ9ti1bU58x0niIlb5yM5HHnMSaH/AJdwuLupAMXl7YkeOZTdrDP7T5R6VS7ejUAJFOhsXonBzMCPwtn7PJc45HnQQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=OzPeuMXl; arc=none smtp.client-ip=117.135.210.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="OzPeuMXl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=Cp 9RRL9kcLgzNgDIMzSk2IWxzcSq68texAEeDTI94JI=; b=OzPeuMXlE+fbxjOXcC i8EQtfvAb33WiPleJOaerKFhnM4n9245Vp9kFzG1md/d+PTgJ3Wok0CO0Hz6DcaK gvhSaa8qF4zpd99yEGym/8z+C+EHdrN4T/6yOf5PuZqfplNSBEKoK4ISV5W/+Od9 0z0ZpLc6gZd2bNwqMa+zjfa0k= Received: from pek-lpg-core5.wrs.com (unknown []) by gzga-smtp-mtada-g1-4 (Coremail) with SMTP id _____wDXPyQp4R9qrA3TBA--.7184S2; Wed, 03 Jun 2026 16:09:13 +0800 (CST) From: Robert Garcia To: stable@vger.kernel.org, Prathamesh Shete Cc: Thierry Reding , Petlozu Pravareshwar , Jon Hunter , Greg Kroah-Hartman , Meng Li , Ulf Hansson , Robert Garcia , linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 6.6.y] soc/tegra: pmc: Fix unsafe generic_handle_irq() call Date: Wed, 3 Jun 2026 16:09:12 +0800 Message-ID: <20260603080912.2022575-1-rob_garcia@163.com> X-Mailer: git-send-email 2.44.3 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wDXPyQp4R9qrA3TBA--.7184S2 X-Coremail-Antispam: 1Uf129KBjvJXoW3Wry5KFyruF1fAFWkWr13XFb_yoWxGFWUpa y5KF4F9w4UJFWfua15ua10vF13CF18X3yxGrW3Aas3G3yUKrn09FnxXFyYqF48ArZakF45 A3yvyryUKw4UXFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x0pRT89AUUUUU= X-CM-SenderInfo: 5uresw5dufxti6rwjhhfrp/xtbC5grkUGof4Sr8aAAA3y Content-Type: text/plain; charset="utf-8" From: Prathamesh Shete [ Upstream commit e6d96073af681780820c94079b978474a8a44413 ] Currently, when resuming from system suspend on Tegra platforms, the following warning is observed: WARNING: CPU: 0 PID: 14459 at kernel/irq/irqdesc.c:666 Call trace: handle_irq_desc+0x20/0x58 (P) tegra186_pmc_wake_syscore_resume+0xe4/0x15c syscore_resume+0x3c/0xb8 suspend_devices_and_enter+0x510/0x540 pm_suspend+0x16c/0x1d8 The warning occurs because generic_handle_irq() is being called from a non-interrupt context which is considered as unsafe. Fix this warning by deferring generic_handle_irq() call to an IRQ work which gets executed in hard IRQ context where generic_handle_irq() can be called safely. When PREEMPT_RT kernels are used, regular IRQ work (initialized with init_irq_work) is deferred to run in per-CPU kthreads in preemptible context rather than hard IRQ context. Hence, use the IRQ_WORK_INIT_HARD variant so that with PREEMPT_RT kernels, the IRQ work is processed in hardirq context instead of being deferred to a thread which is required for calling generic_handle_irq(). On non-PREEMPT_RT kernels, both init_irq_work() and IRQ_WORK_INIT_HARD() execute in IRQ context, so this change has no functional impact for standard kernel configurations. Signed-off-by: Petlozu Pravareshwar Signed-off-by: Prathamesh Shete Reviewed-by: Jon Hunter Tested-by: Jon Hunter [treding@nvidia.com: miscellaneous cleanups] Signed-off-by: Thierry Reding Signed-off-by: Robert Garcia --- drivers/soc/tegra/pmc.c | 104 ++++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 30 deletions(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 1306e3b8b5c0..4cb47c29dc6b 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -467,6 +468,10 @@ struct tegra_pmc { unsigned long *wake_sw_status_map; unsigned long *wake_cntrl_level_map; struct syscore_ops syscore; + + /* Pending wake IRQ processing */ + struct irq_work wake_work; + u32 *wake_status; }; =20 static struct tegra_pmc *pmc =3D &(struct tegra_pmc) { @@ -1940,6 +1945,50 @@ static int tegra_pmc_parse_dt(struct tegra_pmc *pmc,= struct device_node *np) return 0; } =20 +/* translate sc7 wake sources back into IRQs to catch edge triggered wakeu= ps */ +static void tegra186_pmc_wake_handler(struct irq_work *work) +{ + struct tegra_pmc *pmc =3D container_of(work, struct tegra_pmc, wake_work); + unsigned int i, wake; + + for (i =3D 0; i < pmc->soc->max_wake_vectors; i++) { + unsigned long status =3D pmc->wake_status[i]; + + for_each_set_bit(wake, &status, 32) { + irq_hw_number_t hwirq =3D wake + (i * 32); + struct irq_desc *desc; + unsigned int irq; + + irq =3D irq_find_mapping(pmc->domain, hwirq); + if (!irq) { + dev_warn(pmc->dev, + "No IRQ found for WAKE#%lu!\n", + hwirq); + continue; + } + + dev_dbg(pmc->dev, + "Resume caused by WAKE#%lu mapped to IRQ#%u\n", + hwirq, irq); + + desc =3D irq_to_desc(irq); + if (!desc) { + dev_warn(pmc->dev, + "No descriptor found for IRQ#%u\n", + irq); + continue; + } + + if (!desc->action || !desc->action->name) + continue; + + generic_handle_irq(irq); + } + + pmc->wake_status[i] =3D 0; + } +} + static int tegra_pmc_init(struct tegra_pmc *pmc) { if (pmc->soc->max_wake_events > 0) { @@ -1958,6 +2007,18 @@ static int tegra_pmc_init(struct tegra_pmc *pmc) pmc->wake_cntrl_level_map =3D bitmap_zalloc(pmc->soc->max_wake_events, G= FP_KERNEL); if (!pmc->wake_cntrl_level_map) return -ENOMEM; + + pmc->wake_status =3D kcalloc(pmc->soc->max_wake_vectors, sizeof(u32), GF= P_KERNEL); + if (!pmc->wake_status) + return -ENOMEM; + + /* + * Initialize IRQ work for processing wake IRQs. Must use + * HARD_IRQ variant to run in hard IRQ context on PREEMPT_RT + * because we call generic_handle_irq() which requires hard + * IRQ context. + */ + pmc->wake_work =3D IRQ_WORK_INIT_HARD(tegra186_pmc_wake_handler); } =20 if (pmc->soc->init) @@ -3156,47 +3217,30 @@ static void wke_clear_wake_status(struct tegra_pmc = *pmc) } } =20 -/* translate sc7 wake sources back into IRQs to catch edge triggered wakeu= ps */ -static void tegra186_pmc_process_wake_events(struct tegra_pmc *pmc, unsign= ed int index, - unsigned long status) -{ - unsigned int wake; - - dev_dbg(pmc->dev, "Wake[%d:%d] status=3D%#lx\n", (index * 32) + 31, inde= x * 32, status); - - for_each_set_bit(wake, &status, 32) { - irq_hw_number_t hwirq =3D wake + 32 * index; - struct irq_desc *desc; - unsigned int irq; - - irq =3D irq_find_mapping(pmc->domain, hwirq); - - desc =3D irq_to_desc(irq); - if (!desc || !desc->action || !desc->action->name) { - dev_dbg(pmc->dev, "Resume caused by WAKE%ld, IRQ %d\n", hwirq, irq); - continue; - } - - dev_dbg(pmc->dev, "Resume caused by WAKE%ld, %s\n", hwirq, desc->action-= >name); - generic_handle_irq(irq); - } -} - static void tegra186_pmc_wake_syscore_resume(void) { - u32 status, mask; unsigned int i; + u32 mask; =20 for (i =3D 0; i < pmc->soc->max_wake_vectors; i++) { mask =3D readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(i)); - status =3D readl(pmc->wake + WAKE_AOWAKE_STATUS_R(i)) & mask; - - tegra186_pmc_process_wake_events(pmc, i, status); + pmc->wake_status[i] =3D readl(pmc->wake + WAKE_AOWAKE_STATUS_R(i)) & mas= k; } + + /* Schedule IRQ work to process wake IRQs (if any) */ + irq_work_queue(&pmc->wake_work); } =20 static int tegra186_pmc_wake_syscore_suspend(void) { + unsigned int i; + + /* Check if there are unhandled wake IRQs */ + for (i =3D 0; i < pmc->soc->max_wake_vectors; i++) + if (pmc->wake_status[i]) + dev_warn(pmc->dev, + "Unhandled wake IRQs pending vector[%u]: 0x%x\n", + i, pmc->wake_status[i]); wke_read_sw_wake_status(pmc); =20 /* flip the wakeup trigger for dual-edge triggered pads --=20 2.44.3