From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qt1-f169.google.com (mail-qt1-f169.google.com [209.85.160.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6AC953655D5 for ; Fri, 19 Jun 2026 16:56:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.169 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781888219; cv=none; b=bo+T6hikQuuWqHQEU2577hWaRMPEGdDKUg8Dn+rXUzoYuYk/wvuhGLMbYqU2aFLnwog79ci1MPiBJ2jFjN+6Awv4c5Io2zorHp+668eBbj6o1T3l9R6r5dj3mZx8ZQsCgZlpQN5+GU882yfHii+/32tvlrfCG4+7AuRFQaEBJkM= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781888219; c=relaxed/simple; bh=44g7GlTtj+bBdMyx/myuw9dDJZjZSJ7y3x1TfMkW7p4=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=QxUs4+V6C+6nls7is7GyrJpXqCV8cAzBGCksW+kGZl58gnf0D/wLIdAyPjr/h7W04ZFY7PKhOLwnbVu5J2/hQxbuSGLNcYvLddmY7C/UsGNcJiGe1kfdl1WViJfMYWH0EO5vvXZlwhHa/T2SYcsoYsGy9luGbsM7ueGAzx3rbeY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ejVVLYsp; arc=none smtp.client-ip=209.85.160.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ejVVLYsp" Received: by mail-qt1-f169.google.com with SMTP id d75a77b69052e-517907feed0so33732141cf.1 for ; Fri, 19 Jun 2026 09:56:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781888217; x=1782493017; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=RhDxX4cHuT4tfnpR0AipKseIEfBclnv+hzggOQhE2+U=; b=ejVVLYspc2c1hX/T3wlBzuFd88m1t4GWPj7K67AHDKDR6+aP06hJMfGC6sozES+XoV Qj3bA8Iuq5wg9TuEBYkjMWV7Qk5w3LUT7TG+VOATr9Qp+QNX1i5hknsf3vQU1J1VduS1 U9Yu5F9PdTBBwraINdy4aaIyqZ+cP12Q1TSInXLrauJBCy8WOOVhFhK1yO3CRmoIrq72 jQVjKxcKZCJRjLMDkG9xZSs4qr2C0/QkYrbfYM2YAkUQFXI5YcNpPmbuZT1XvleyyOlz P7LfgtFLeuwpSZk7yvS4qP5Mq3Is7E4dsC7jaw9BdG5ICFXpCU2Ojv3EPNkj9aair/9V 0omg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781888217; x=1782493017; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=RhDxX4cHuT4tfnpR0AipKseIEfBclnv+hzggOQhE2+U=; b=MSV2zU+KsdIMrOkZO0LVJCtMZsGd6OT9Gd48AyuE4QAhGc/ei5FFPrqN5Siwd+JMEO iJOlr9Vmcl5YkOG2jctfvojXzZTSTU3Vp6ppNuaDbp0onbUNfwWzOH2cmI0cDhMwVZxq A8YC95Fhr4wvVrdEXJyjGr3qEUD8S5kgO3DSDAckSHQpFuUpssludx96zwfbV+wiWO6+ X9B3bUaWkHw4TBi8wO5zU2x+VykdfzAjXyNsYdoGWALd0sX6QxqRpzCBNxyFA1fctrL9 nzyudkyiqozN0pFMXmXU1WrPM+LE/kOVpG8rcEQjrrxxzWyZ6mZW3R31aEDk/sbDEdkb B3lw== X-Gm-Message-State: AOJu0Yxqki5/G7RHwEwTtaIdI3CAsVpqlqIxgjtyX6W5yEN1OYSAIVJi /3O2/0AJjfoPo473sfss6wBZiI2Re6jWJOUedFgsJitUY2BHkJVQAAnR X-Gm-Gg: AfdE7clucLLS2kr9SlbzhmorOxW4TLW+3suXaW+Vws4FZa51D9D3k1MtCb8O5RpgQoi EYKN+ffNZjdRBln8lIZ/h1uDQmdZsi1t13yfyOWDdAkMf60HFdLfP5JpGAsVg0bQa4bGdK5itU7 hPx4tenj5U286pSCBxdBnjgnzXoiSxAKBwKQiAojgec+7Xf+uoTXdVPp1HuJdm8oGMjPx62Mm9x Ok5BT8WI+cukNWpxGIMp/a2CpmxH0si8aoBVrhRdFgzHxpVFZ7Q/dlZxajTnuCd71Q7D1st4zWB yPYayLq1koYi6Mn3Esw4QpbCEJbjbPIx/NpuWyO9Y1NK6X5Cpo15+j6D4o/gFCUcaOtFqBOVZLc JFZvUae2jeq3pFUZvYGs3lXhO94rrFiZYwrB5zSM3FxutDh+YxXlNZfADAqAviEpCDzJ0/a/JPf q7iJnq2ldXv70sm364sXH+Wk/U7k4eRg== X-Received: by 2002:ac8:7fd5:0:b0:50f:b61c:ec4c with SMTP id d75a77b69052e-519e6618f84mr51242181cf.7.1781888217426; Fri, 19 Jun 2026 09:56:57 -0700 (PDT) Received: from i4-gl-tmk5904.ad.psu.edu ([130.203.156.186]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-519e6127858sm24687081cf.27.2026.06.19.09.56.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 19 Jun 2026 09:56:56 -0700 (PDT) From: Yuho Choi To: Lee Jones , Matthias Brugger , AngeloGioacchino Del Regno Cc: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, Yuho Choi Subject: [PATCH v2] mfd: mt6397-irq: Fix PM notifier and IRQ domain teardown Date: Fri, 19 Jun 2026 12:56:49 -0400 Message-ID: <20260619165649.1067266-1-dbgh9129@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit mt6397_irq_init() registers a PM notifier and creates an irq_domain. Both objects point back to the devm-managed mt6397_chip. The notifier was not unregistered on probe failure or unbind, so a later PM transition could dereference freed chip state. The irq_domain had the opposite lifetime problem: it could be removed while the devm-managed parent IRQ was still active, but it was leaked on successful unbind. Manage both lifetimes with devm actions. Register the domain cleanup before requesting the parent IRQ, so devres frees the parent IRQ before removing child mappings and the irq_domain. This keeps the domain alive while the parent IRQ handler can still run. Also serialize PM notifier mask writes with irqlock. While suspend is in progress, keep wake_mask programmed in hardware even if a concurrent IRQ sync updates irq_masks_cur in software. Fixes: a4872e80ce7d ("mfd: mt6397: Extract IRQ related code from core driver") Fixes: 4e2e7cfec13a ("mfd: mt6397: Modify suspend/resume behavior") Signed-off-by: Yuho Choi --- Changes in v2: - Use devm actions for PM notifier and irq_domain cleanup. - Remove direct irq_domain_remove() calls from failure paths. - Serialize PM notifier mask writes with irqlock. --- drivers/mfd/mt6397-core.c | 4 +- drivers/mfd/mt6397-irq.c | 85 +++++++++++++++++++++++---------- include/linux/mfd/mt6397/core.h | 1 + 3 files changed, 63 insertions(+), 27 deletions(-) diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c index 1bdacda9a933..ff1e393202ee 100644 --- a/drivers/mfd/mt6397-core.c +++ b/drivers/mfd/mt6397-core.c @@ -389,10 +389,8 @@ static int mt6397_probe(struct platform_device *pdev) ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, pmic_core->cells, pmic_core->cell_size, NULL, 0, pmic->irq_domain); - if (ret) { - irq_domain_remove(pmic->irq_domain); + if (ret) dev_err(&pdev->dev, "failed to add child devices: %d\n", ret); - } return ret; } diff --git a/drivers/mfd/mt6397-irq.c b/drivers/mfd/mt6397-irq.c index 5d2e5459f744..4be74d8325cd 100644 --- a/drivers/mfd/mt6397-irq.c +++ b/drivers/mfd/mt6397-irq.c @@ -25,17 +25,23 @@ static void mt6397_irq_lock(struct irq_data *data) mutex_lock(&mt6397->irqlock); } +static void mt6397_irq_write_masks(struct mt6397_chip *mt6397, + const u16 *masks) +{ + regmap_write(mt6397->regmap, mt6397->int_con[0], masks[0]); + regmap_write(mt6397->regmap, mt6397->int_con[1], masks[1]); + if (mt6397->int_con[2]) + regmap_write(mt6397->regmap, mt6397->int_con[2], masks[2]); +} + static void mt6397_irq_sync_unlock(struct irq_data *data) { struct mt6397_chip *mt6397 = irq_data_get_irq_chip_data(data); + const u16 *masks; - regmap_write(mt6397->regmap, mt6397->int_con[0], - mt6397->irq_masks_cur[0]); - regmap_write(mt6397->regmap, mt6397->int_con[1], - mt6397->irq_masks_cur[1]); - if (mt6397->int_con[2]) - regmap_write(mt6397->regmap, mt6397->int_con[2], - mt6397->irq_masks_cur[2]); + masks = mt6397->irq_suspended ? mt6397->wake_mask : + mt6397->irq_masks_cur; + mt6397_irq_write_masks(mt6397, masks); mutex_unlock(&mt6397->irqlock); } @@ -141,24 +147,20 @@ static int mt6397_irq_pm_notifier(struct notifier_block *notifier, switch (pm_event) { case PM_SUSPEND_PREPARE: - regmap_write(chip->regmap, - chip->int_con[0], chip->wake_mask[0]); - regmap_write(chip->regmap, - chip->int_con[1], chip->wake_mask[1]); - if (chip->int_con[2]) - regmap_write(chip->regmap, - chip->int_con[2], chip->wake_mask[2]); + mutex_lock(&chip->irqlock); + chip->irq_suspended = true; + mt6397_irq_write_masks(chip, chip->wake_mask); + mutex_unlock(&chip->irqlock); + enable_irq_wake(chip->irq); break; case PM_POST_SUSPEND: - regmap_write(chip->regmap, - chip->int_con[0], chip->irq_masks_cur[0]); - regmap_write(chip->regmap, - chip->int_con[1], chip->irq_masks_cur[1]); - if (chip->int_con[2]) - regmap_write(chip->regmap, - chip->int_con[2], chip->irq_masks_cur[2]); + mutex_lock(&chip->irqlock); + chip->irq_suspended = false; + mt6397_irq_write_masks(chip, chip->irq_masks_cur); + mutex_unlock(&chip->irqlock); + disable_irq_wake(chip->irq); break; @@ -169,6 +171,29 @@ static int mt6397_irq_pm_notifier(struct notifier_block *notifier, return NOTIFY_DONE; } +static void mt6397_irq_pm_notifier_unregister(void *data) +{ + struct mt6397_chip *chip = data; + + unregister_pm_notifier(&chip->pm_nb); +} + +static void mt6397_irq_domain_remove(void *data) +{ + struct mt6397_chip *chip = data; + unsigned int hwirq; + unsigned int virq; + + for (hwirq = 0; hwirq < MT6397_IRQ_NR; hwirq++) { + virq = irq_find_mapping(chip->irq_domain, hwirq); + if (virq) + irq_dispose_mapping(virq); + } + + irq_domain_remove(chip->irq_domain); + chip->irq_domain = NULL; +} + int mt6397_irq_init(struct mt6397_chip *chip) { int ret; @@ -223,16 +248,28 @@ int mt6397_irq_init(struct mt6397_chip *chip) return -ENOMEM; } + ret = devm_add_action_or_reset(chip->dev, mt6397_irq_domain_remove, + chip); + if (ret) + return ret; + ret = devm_request_threaded_irq(chip->dev, chip->irq, NULL, mt6397_irq_thread, IRQF_ONESHOT, "mt6397-pmic", chip); if (ret) { dev_err(chip->dev, "failed to register irq=%d; err: %d\n", chip->irq, ret); - irq_domain_remove(chip->irq_domain); return ret; } - register_pm_notifier(&chip->pm_nb); - return 0; + ret = register_pm_notifier(&chip->pm_nb); + if (ret) { + dev_err(chip->dev, "failed to register PM notifier: %d\n", ret); + return ret; + } + + ret = devm_add_action_or_reset(chip->dev, + mt6397_irq_pm_notifier_unregister, chip); + + return ret; } diff --git a/include/linux/mfd/mt6397/core.h b/include/linux/mfd/mt6397/core.h index 340fc72e22aa..f9c2cbd17c5c 100644 --- a/include/linux/mfd/mt6397/core.h +++ b/include/linux/mfd/mt6397/core.h @@ -66,6 +66,7 @@ struct mt6397_chip { int irq; struct irq_domain *irq_domain; struct mutex irqlock; + bool irq_suspended; u16 wake_mask[3]; u16 irq_masks_cur[3]; u16 irq_masks_cache[3]; -- 2.43.0