linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 00/10] RISC-V IMSIC driver improvements
@ 2025-02-17  8:56 Anup Patel
  2025-02-17  8:56 ` [PATCH v6 01/10] irqchip/riscv-imsic: Set irq_set_affinity for IMSIC base Anup Patel
                   ` (9 more replies)
  0 siblings, 10 replies; 18+ messages in thread
From: Anup Patel @ 2025-02-17  8:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86
  Cc: hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx, Anup Patel

This series is based on recent discussion on LKML:
https://lore.kernel.org/lkml/20241114161845.502027-18-ajones@ventanamicro.com/

It primarily focuses on moving to RISC-V IMSIC driver use common MSI
lib and GENERIC_PENDING_IRQ.

PATCH1 & PATCH2: Preparatory patches
PATCH3: Updates IMSIC driver to use MSI lib
PATCH4 to PATCH5: Preparatory patches for moving to GENERIC_PENDING_IRQ
PATCH6 to PATCH10: Patches to use GENERIC_PENDING_IRQ in IMSIC driver

These patches can also be found in the riscv_imsic_imp_v6 branch at:
https://github.com/avpatel/linux.git

Changes since v5:
 - Rebased upon Linux-6.14-rc1
 - Drop PATCH6 since it is already merged
 - Update commit description of PATCH1

Changes since v4:
 - Updated PATCH4 with better irq_force_complete_move() implementation
   provided by Thomas.

Changes since v3:
 - Dropped PATCH1 of v3 series and updated last patch of this series
   to handle the intermediate state for non-atomic MSI update.
 - Added new PATCH6 in this series to remove stale kconfig option
   GENERIC_PENDING_IRQ_CHIPFLAGS.

Changes since v2:
 - Rebased upon Linux-6.14-rc1
 - Dropped PATCH5 of v2 series since that patch is already merged

Changes since v1:
 - Changed series subject
 - Expand this series to use GENERIC_PENDING_IRQ in IMSIC driver

Andrew Jones (1):
  irqchip/riscv-imsic: Set irq_set_affinity for IMSIC base

Anup Patel (6):
  genirq: Introduce irq_can_move_in_process_context()
  RISC-V: Select GENERIC_PENDING_IRQ
  irqchip/riscv-imsic: Separate next and previous pointers in IMSIC
    vector
  irqchip/riscv-imsic: Implement irq_force_complete_move() for IMSIC
  irqchip/riscv-imsic: Replace hwirq with irq in the IMSIC vector
  irqchip/riscv-imsic: Special handling for non-atomic device MSI update

Thomas Gleixner (3):
  irqchip/irq-msi-lib: Optionally set default irq_eoi/irq_ack
  irqchip/riscv-imsic: Move to common MSI lib
  genirq: Introduce common irq_force_complete_move() implementation

 arch/riscv/Kconfig                         |   1 +
 arch/x86/kernel/apic/vector.c              | 231 ++++++++++-----------
 drivers/irqchip/Kconfig                    |   8 +-
 drivers/irqchip/irq-gic-v2m.c              |   1 +
 drivers/irqchip/irq-imx-mu-msi.c           |   1 +
 drivers/irqchip/irq-msi-lib.c              |  11 +-
 drivers/irqchip/irq-mvebu-gicp.c           |   1 +
 drivers/irqchip/irq-mvebu-odmi.c           |   1 +
 drivers/irqchip/irq-mvebu-sei.c            |   1 +
 drivers/irqchip/irq-riscv-imsic-early.c    |  14 +-
 drivers/irqchip/irq-riscv-imsic-platform.c | 197 +++++++++---------
 drivers/irqchip/irq-riscv-imsic-state.c    | 152 ++++++++++----
 drivers/irqchip/irq-riscv-imsic-state.h    |  12 +-
 include/linux/irq.h                        |   7 +-
 include/linux/msi.h                        |  11 +
 kernel/irq/internals.h                     |   2 +
 kernel/irq/migration.c                     |  21 ++
 17 files changed, 389 insertions(+), 283 deletions(-)

-- 
2.43.0



^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v6 01/10] irqchip/riscv-imsic: Set irq_set_affinity for IMSIC base
  2025-02-17  8:56 [PATCH v6 00/10] RISC-V IMSIC driver improvements Anup Patel
@ 2025-02-17  8:56 ` Anup Patel
  2025-02-17  8:56 ` [PATCH v6 02/10] irqchip/irq-msi-lib: Optionally set default irq_eoi/irq_ack Anup Patel
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2025-02-17  8:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86
  Cc: hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx, Anup Patel

From: Andrew Jones <ajones@ventanamicro.com>

Instead of using imsic_irq_set_affinity() for leaf MSI domains, use
imsic_irq_set_affinity() for the non-leaf IMSIC base domain and use
irq_chip_set_affinity_parent() for leaf MSI domains. This is required
for moving the IMSIC driver to the common MSI lib which uses a generic
msi_domain_set_affinity() for device MSI domains.

Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 drivers/irqchip/irq-riscv-imsic-platform.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c
index c708780e8760..5d7c30ad8855 100644
--- a/drivers/irqchip/irq-riscv-imsic-platform.c
+++ b/drivers/irqchip/irq-riscv-imsic-platform.c
@@ -96,9 +96,8 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask
 				  bool force)
 {
 	struct imsic_vector *old_vec, *new_vec;
-	struct irq_data *pd = d->parent_data;
 
-	old_vec = irq_data_get_irq_chip_data(pd);
+	old_vec = irq_data_get_irq_chip_data(d);
 	if (WARN_ON(!old_vec))
 		return -ENOENT;
 
@@ -116,13 +115,13 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask
 		return -ENOSPC;
 
 	/* Point device to the new vector */
-	imsic_msi_update_msg(d, new_vec);
+	imsic_msi_update_msg(irq_get_irq_data(d->irq), new_vec);
 
 	/* Update irq descriptors with the new vector */
-	pd->chip_data = new_vec;
+	d->chip_data = new_vec;
 
-	/* Update effective affinity of parent irq data */
-	irq_data_update_effective_affinity(pd, cpumask_of(new_vec->cpu));
+	/* Update effective affinity */
+	irq_data_update_effective_affinity(d, cpumask_of(new_vec->cpu));
 
 	/* Move state of the old vector to the new vector */
 	imsic_vector_move(old_vec, new_vec);
@@ -135,6 +134,9 @@ static struct irq_chip imsic_irq_base_chip = {
 	.name			= "IMSIC",
 	.irq_mask		= imsic_irq_mask,
 	.irq_unmask		= imsic_irq_unmask,
+#ifdef CONFIG_SMP
+	.irq_set_affinity	= imsic_irq_set_affinity,
+#endif
 	.irq_retrigger		= imsic_irq_retrigger,
 	.irq_compose_msi_msg	= imsic_irq_compose_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE |
@@ -245,7 +247,7 @@ static bool imsic_init_dev_msi_info(struct device *dev,
 		if (WARN_ON_ONCE(domain != real_parent))
 			return false;
 #ifdef CONFIG_SMP
-		info->chip->irq_set_affinity = imsic_irq_set_affinity;
+		info->chip->irq_set_affinity = irq_chip_set_affinity_parent;
 #endif
 		break;
 	default:
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v6 02/10] irqchip/irq-msi-lib: Optionally set default irq_eoi/irq_ack
  2025-02-17  8:56 [PATCH v6 00/10] RISC-V IMSIC driver improvements Anup Patel
  2025-02-17  8:56 ` [PATCH v6 01/10] irqchip/riscv-imsic: Set irq_set_affinity for IMSIC base Anup Patel
@ 2025-02-17  8:56 ` Anup Patel
  2025-02-19 14:41   ` Mark Brown
  2025-02-17  8:56 ` [PATCH v6 03/10] irqchip/riscv-imsic: Move to common MSI lib Anup Patel
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Anup Patel @ 2025-02-17  8:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86
  Cc: hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx, Anup Patel

From: Thomas Gleixner <tglx@linutronix.de>

Introduce chip_flags in struct msi_parent_ops. This allows
msi_lib_init_dev_msi_info() set default irq_eoi/irq_ack
callbacks only when the corresponding flags are set in
the chip_flags.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 drivers/irqchip/irq-gic-v2m.c    |  1 +
 drivers/irqchip/irq-imx-mu-msi.c |  1 +
 drivers/irqchip/irq-msi-lib.c    | 11 ++++++-----
 drivers/irqchip/irq-mvebu-gicp.c |  1 +
 drivers/irqchip/irq-mvebu-odmi.c |  1 +
 drivers/irqchip/irq-mvebu-sei.c  |  1 +
 include/linux/msi.h              | 11 +++++++++++
 7 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index be35c5349986..1e3476c335ca 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -255,6 +255,7 @@ static void __init gicv2m_teardown(void)
 static struct msi_parent_ops gicv2m_msi_parent_ops = {
 	.supported_flags	= GICV2M_MSI_FLAGS_SUPPORTED,
 	.required_flags		= GICV2M_MSI_FLAGS_REQUIRED,
+	.chip_flags		= MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK,
 	.bus_select_token	= DOMAIN_BUS_NEXUS,
 	.bus_select_mask	= MATCH_PCI_MSI | MATCH_PLATFORM_MSI,
 	.prefix			= "GICv2m-",
diff --git a/drivers/irqchip/irq-imx-mu-msi.c b/drivers/irqchip/irq-imx-mu-msi.c
index 4342a21de1eb..69aacdfc8bef 100644
--- a/drivers/irqchip/irq-imx-mu-msi.c
+++ b/drivers/irqchip/irq-imx-mu-msi.c
@@ -214,6 +214,7 @@ static void imx_mu_msi_irq_handler(struct irq_desc *desc)
 static const struct msi_parent_ops imx_mu_msi_parent_ops = {
 	.supported_flags	= IMX_MU_MSI_FLAGS_SUPPORTED,
 	.required_flags		= IMX_MU_MSI_FLAGS_REQUIRED,
+	.chip_flags		= MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK,
 	.bus_select_token       = DOMAIN_BUS_NEXUS,
 	.bus_select_mask	= MATCH_PLATFORM_MSI,
 	.prefix			= "MU-MSI-",
diff --git a/drivers/irqchip/irq-msi-lib.c b/drivers/irqchip/irq-msi-lib.c
index d8e29fc0d406..51464c6257f3 100644
--- a/drivers/irqchip/irq-msi-lib.c
+++ b/drivers/irqchip/irq-msi-lib.c
@@ -28,6 +28,7 @@ bool msi_lib_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
 			       struct msi_domain_info *info)
 {
 	const struct msi_parent_ops *pops = real_parent->msi_parent_ops;
+	struct irq_chip *chip = info->chip;
 	u32 required_flags;
 
 	/* Parent ops available? */
@@ -92,10 +93,10 @@ bool msi_lib_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
 	info->flags			|= required_flags;
 
 	/* Chip updates for all child bus types */
-	if (!info->chip->irq_eoi)
-		info->chip->irq_eoi	= irq_chip_eoi_parent;
-	if (!info->chip->irq_ack)
-		info->chip->irq_ack	= irq_chip_ack_parent;
+	if (!chip->irq_eoi && (pops->chip_flags & MSI_CHIP_FLAG_SET_EOI))
+		chip->irq_eoi = irq_chip_eoi_parent;
+	if (!chip->irq_ack && (pops->chip_flags & MSI_CHIP_FLAG_SET_ACK))
+		chip->irq_ack = irq_chip_ack_parent;
 
 	/*
 	 * The device MSI domain can never have a set affinity callback. It
@@ -105,7 +106,7 @@ bool msi_lib_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
 	 * device MSI domain aside of mask/unmask which is provided e.g. by
 	 * PCI/MSI device domains.
 	 */
-	info->chip->irq_set_affinity	= msi_domain_set_affinity;
+	chip->irq_set_affinity = msi_domain_set_affinity;
 	return true;
 }
 EXPORT_SYMBOL_GPL(msi_lib_init_dev_msi_info);
diff --git a/drivers/irqchip/irq-mvebu-gicp.c b/drivers/irqchip/irq-mvebu-gicp.c
index 2b6183919ea4..d67f93f6d750 100644
--- a/drivers/irqchip/irq-mvebu-gicp.c
+++ b/drivers/irqchip/irq-mvebu-gicp.c
@@ -161,6 +161,7 @@ static const struct irq_domain_ops gicp_domain_ops = {
 static const struct msi_parent_ops gicp_msi_parent_ops = {
 	.supported_flags	= GICP_MSI_FLAGS_SUPPORTED,
 	.required_flags		= GICP_MSI_FLAGS_REQUIRED,
+	.chip_flags		= MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK,
 	.bus_select_token       = DOMAIN_BUS_GENERIC_MSI,
 	.bus_select_mask	= MATCH_PLATFORM_MSI,
 	.prefix			= "GICP-",
diff --git a/drivers/irqchip/irq-mvebu-odmi.c b/drivers/irqchip/irq-mvebu-odmi.c
index ff19bfd258dc..28f7e81df94f 100644
--- a/drivers/irqchip/irq-mvebu-odmi.c
+++ b/drivers/irqchip/irq-mvebu-odmi.c
@@ -157,6 +157,7 @@ static const struct irq_domain_ops odmi_domain_ops = {
 static const struct msi_parent_ops odmi_msi_parent_ops = {
 	.supported_flags	= ODMI_MSI_FLAGS_SUPPORTED,
 	.required_flags		= ODMI_MSI_FLAGS_REQUIRED,
+	.chip_flags		= MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK,
 	.bus_select_token	= DOMAIN_BUS_GENERIC_MSI,
 	.bus_select_mask	= MATCH_PLATFORM_MSI,
 	.prefix			= "ODMI-",
diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c
index 065166ab5dbc..ebd4a9014e8d 100644
--- a/drivers/irqchip/irq-mvebu-sei.c
+++ b/drivers/irqchip/irq-mvebu-sei.c
@@ -356,6 +356,7 @@ static void mvebu_sei_reset(struct mvebu_sei *sei)
 static const struct msi_parent_ops sei_msi_parent_ops = {
 	.supported_flags	= SEI_MSI_FLAGS_SUPPORTED,
 	.required_flags		= SEI_MSI_FLAGS_REQUIRED,
+	.chip_flags		= MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK,
 	.bus_select_mask	= MATCH_PLATFORM_MSI,
 	.bus_select_token	= DOMAIN_BUS_GENERIC_MSI,
 	.prefix			= "SEI-",
diff --git a/include/linux/msi.h b/include/linux/msi.h
index b10093c4d00e..9abef442c146 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -558,11 +558,21 @@ enum {
 	MSI_FLAG_NO_AFFINITY		= (1 << 21),
 };
 
+/*
+ * Flags for msi_parent_ops::chip_flags
+ */
+enum {
+	MSI_CHIP_FLAG_SET_EOI		= (1 << 0),
+	MSI_CHIP_FLAG_SET_ACK		= (1 << 1),
+};
+
 /**
  * struct msi_parent_ops - MSI parent domain callbacks and configuration info
  *
  * @supported_flags:	Required: The supported MSI flags of the parent domain
  * @required_flags:	Optional: The required MSI flags of the parent MSI domain
+ * @chip_flags:		Optional: Select MSI chip callbacks to update with defaults
+ *			in msi_lib_init_dev_msi_info().
  * @bus_select_token:	Optional: The bus token of the real parent domain for
  *			irq_domain::select()
  * @bus_select_mask:	Optional: A mask of supported BUS_DOMAINs for
@@ -575,6 +585,7 @@ enum {
 struct msi_parent_ops {
 	u32		supported_flags;
 	u32		required_flags;
+	u32		chip_flags;
 	u32		bus_select_token;
 	u32		bus_select_mask;
 	const char	*prefix;
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v6 03/10] irqchip/riscv-imsic: Move to common MSI lib
  2025-02-17  8:56 [PATCH v6 00/10] RISC-V IMSIC driver improvements Anup Patel
  2025-02-17  8:56 ` [PATCH v6 01/10] irqchip/riscv-imsic: Set irq_set_affinity for IMSIC base Anup Patel
  2025-02-17  8:56 ` [PATCH v6 02/10] irqchip/irq-msi-lib: Optionally set default irq_eoi/irq_ack Anup Patel
@ 2025-02-17  8:56 ` Anup Patel
  2025-02-17  8:56 ` [PATCH v6 04/10] genirq: Introduce common irq_force_complete_move() implementation Anup Patel
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2025-02-17  8:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86
  Cc: hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx, Anup Patel

From: Thomas Gleixner <tglx@linutronix.de>

Simplify the leaf MSI domain handling in the RISC-V IMSIC driver by
using msi_lib_init_dev_msi_info() and msi_lib_irq_domain_select()
provided by common MSI lib.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 drivers/irqchip/Kconfig                    |   8 +-
 drivers/irqchip/irq-riscv-imsic-platform.c | 114 +--------------------
 2 files changed, 6 insertions(+), 116 deletions(-)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index c11b9965c4ad..fe95ef723bb3 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -590,13 +590,7 @@ config RISCV_IMSIC
 	select IRQ_DOMAIN_HIERARCHY
 	select GENERIC_IRQ_MATRIX_ALLOCATOR
 	select GENERIC_MSI_IRQ
-
-config RISCV_IMSIC_PCI
-	bool
-	depends on RISCV_IMSIC
-	depends on PCI
-	depends on PCI_MSI
-	default RISCV_IMSIC
+	select IRQ_MSI_LIB
 
 config SIFIVE_PLIC
 	bool
diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c
index 5d7c30ad8855..9a5e7b4541f6 100644
--- a/drivers/irqchip/irq-riscv-imsic-platform.c
+++ b/drivers/irqchip/irq-riscv-imsic-platform.c
@@ -20,6 +20,7 @@
 #include <linux/spinlock.h>
 #include <linux/smp.h>
 
+#include "irq-msi-lib.h"
 #include "irq-riscv-imsic-state.h"
 
 static bool imsic_cpu_page_phys(unsigned int cpu, unsigned int guest_index,
@@ -174,22 +175,6 @@ static void imsic_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 	irq_domain_free_irqs_parent(domain, virq, nr_irqs);
 }
 
-static int imsic_irq_domain_select(struct irq_domain *domain, struct irq_fwspec *fwspec,
-				   enum irq_domain_bus_token bus_token)
-{
-	const struct msi_parent_ops *ops = domain->msi_parent_ops;
-	u32 busmask = BIT(bus_token);
-
-	if (fwspec->fwnode != domain->fwnode || fwspec->param_count != 0)
-		return 0;
-
-	/* Handle pure domain searches */
-	if (bus_token == ops->bus_select_token)
-		return 1;
-
-	return !!(ops->bus_select_mask & busmask);
-}
-
 #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
 static void imsic_irq_debug_show(struct seq_file *m, struct irq_domain *d,
 				 struct irq_data *irqd, int ind)
@@ -206,110 +191,21 @@ static void imsic_irq_debug_show(struct seq_file *m, struct irq_domain *d,
 static const struct irq_domain_ops imsic_base_domain_ops = {
 	.alloc		= imsic_irq_domain_alloc,
 	.free		= imsic_irq_domain_free,
-	.select		= imsic_irq_domain_select,
+	.select		= msi_lib_irq_domain_select,
 #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
 	.debug_show	= imsic_irq_debug_show,
 #endif
 };
 
-#ifdef CONFIG_RISCV_IMSIC_PCI
-
-static void imsic_pci_mask_irq(struct irq_data *d)
-{
-	pci_msi_mask_irq(d);
-	irq_chip_mask_parent(d);
-}
-
-static void imsic_pci_unmask_irq(struct irq_data *d)
-{
-	irq_chip_unmask_parent(d);
-	pci_msi_unmask_irq(d);
-}
-
-#define MATCH_PCI_MSI		BIT(DOMAIN_BUS_PCI_MSI)
-
-#else
-
-#define MATCH_PCI_MSI		0
-
-#endif
-
-static bool imsic_init_dev_msi_info(struct device *dev,
-				    struct irq_domain *domain,
-				    struct irq_domain *real_parent,
-				    struct msi_domain_info *info)
-{
-	const struct msi_parent_ops *pops = real_parent->msi_parent_ops;
-
-	/* MSI parent domain specific settings */
-	switch (real_parent->bus_token) {
-	case DOMAIN_BUS_NEXUS:
-		if (WARN_ON_ONCE(domain != real_parent))
-			return false;
-#ifdef CONFIG_SMP
-		info->chip->irq_set_affinity = irq_chip_set_affinity_parent;
-#endif
-		break;
-	default:
-		WARN_ON_ONCE(1);
-		return false;
-	}
-
-	/* Is the target supported? */
-	switch (info->bus_token) {
-#ifdef CONFIG_RISCV_IMSIC_PCI
-	case DOMAIN_BUS_PCI_DEVICE_MSI:
-	case DOMAIN_BUS_PCI_DEVICE_MSIX:
-		info->chip->irq_mask = imsic_pci_mask_irq;
-		info->chip->irq_unmask = imsic_pci_unmask_irq;
-		break;
-#endif
-	case DOMAIN_BUS_DEVICE_MSI:
-		/*
-		 * Per-device MSI should never have any MSI feature bits
-		 * set. It's sole purpose is to create a dumb interrupt
-		 * chip which has a device specific irq_write_msi_msg()
-		 * callback.
-		 */
-		if (WARN_ON_ONCE(info->flags))
-			return false;
-
-		/* Core managed MSI descriptors */
-		info->flags |= MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS |
-			       MSI_FLAG_FREE_MSI_DESCS;
-		break;
-	case DOMAIN_BUS_WIRED_TO_MSI:
-		break;
-	default:
-		WARN_ON_ONCE(1);
-		return false;
-	}
-
-	/* Use hierarchial chip operations re-trigger */
-	info->chip->irq_retrigger = irq_chip_retrigger_hierarchy;
-
-	/*
-	 * Mask out the domain specific MSI feature flags which are not
-	 * supported by the real parent.
-	 */
-	info->flags &= pops->supported_flags;
-
-	/* Enforce the required flags */
-	info->flags |= pops->required_flags;
-
-	return true;
-}
-
-#define MATCH_PLATFORM_MSI		BIT(DOMAIN_BUS_PLATFORM_MSI)
-
 static const struct msi_parent_ops imsic_msi_parent_ops = {
 	.supported_flags	= MSI_GENERIC_FLAGS_MASK |
 				  MSI_FLAG_PCI_MSIX,
 	.required_flags		= MSI_FLAG_USE_DEF_DOM_OPS |
-				  MSI_FLAG_USE_DEF_CHIP_OPS,
+				  MSI_FLAG_USE_DEF_CHIP_OPS |
+				  MSI_FLAG_PCI_MSI_MASK_PARENT,
 	.bus_select_token	= DOMAIN_BUS_NEXUS,
 	.bus_select_mask	= MATCH_PCI_MSI | MATCH_PLATFORM_MSI,
-	.init_dev_msi_info	= imsic_init_dev_msi_info,
+	.init_dev_msi_info	= msi_lib_init_dev_msi_info,
 };
 
 int imsic_irqdomain_init(void)
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v6 04/10] genirq: Introduce common irq_force_complete_move() implementation
  2025-02-17  8:56 [PATCH v6 00/10] RISC-V IMSIC driver improvements Anup Patel
                   ` (2 preceding siblings ...)
  2025-02-17  8:56 ` [PATCH v6 03/10] irqchip/riscv-imsic: Move to common MSI lib Anup Patel
@ 2025-02-17  8:56 ` Anup Patel
  2025-04-03 13:13   ` Frank Scheiner
  2025-02-17  8:56 ` [PATCH v6 05/10] genirq: Introduce irq_can_move_in_process_context() Anup Patel
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 18+ messages in thread
From: Anup Patel @ 2025-02-17  8:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86
  Cc: hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx, Anup Patel

From: Thomas Gleixner <tglx@linutronix.de>

The GENERIC_PENDING_IRQ requires an arch specific implementation of
irq_force_complete_move(). At the moment, only x86 implements this
but for RISC-V the irq_force_complete_move() is only needed when
RISC-V IMSIC driver is in use and not needed otherwise.

To address the above, introduce a common irq_force_complete_move()
implementation in kernel irq migration which lets irqchip do the
actual irq_force_complete_move() and also update x86 APIC to use
this common implementation.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 arch/x86/kernel/apic/vector.c | 231 ++++++++++++++++------------------
 include/linux/irq.h           |   5 +-
 kernel/irq/internals.h        |   2 +
 kernel/irq/migration.c        |  10 ++
 4 files changed, 123 insertions(+), 125 deletions(-)

diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index 736f62812f5c..72fa4bb78f0a 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -888,8 +888,109 @@ static int apic_set_affinity(struct irq_data *irqd,
 	return err ? err : IRQ_SET_MASK_OK;
 }
 
+static void free_moved_vector(struct apic_chip_data *apicd)
+{
+	unsigned int vector = apicd->prev_vector;
+	unsigned int cpu = apicd->prev_cpu;
+	bool managed = apicd->is_managed;
+
+	/*
+	 * Managed interrupts are usually not migrated away
+	 * from an online CPU, but CPU isolation 'managed_irq'
+	 * can make that happen.
+	 * 1) Activation does not take the isolation into account
+	 *    to keep the code simple
+	 * 2) Migration away from an isolated CPU can happen when
+	 *    a non-isolated CPU which is in the calculated
+	 *    affinity mask comes online.
+	 */
+	trace_vector_free_moved(apicd->irq, cpu, vector, managed);
+	irq_matrix_free(vector_matrix, cpu, vector, managed);
+	per_cpu(vector_irq, cpu)[vector] = VECTOR_UNUSED;
+	hlist_del_init(&apicd->clist);
+	apicd->prev_vector = 0;
+	apicd->move_in_progress = 0;
+}
+
+/*
+ * Called from fixup_irqs() with @desc->lock held and interrupts disabled.
+ */
+static void apic_force_complete_move(struct irq_data *irqd)
+{
+	unsigned int cpu = smp_processor_id();
+	struct apic_chip_data *apicd;
+	unsigned int vector;
+
+	guard(raw_spinlock)(&vector_lock);
+	apicd = apic_chip_data(irqd);
+	if (!apicd)
+		return;
+
+	/*
+	 * If prev_vector is empty or the descriptor is neither currently
+	 * nor previously on the outgoing CPU no action required.
+	 */
+	vector = apicd->prev_vector;
+	if (!vector || (apicd->cpu != cpu && apicd->prev_cpu != cpu))
+		return;
+
+	/*
+	 * This is tricky. If the cleanup of the old vector has not been
+	 * done yet, then the following setaffinity call will fail with
+	 * -EBUSY. This can leave the interrupt in a stale state.
+	 *
+	 * All CPUs are stuck in stop machine with interrupts disabled so
+	 * calling __irq_complete_move() would be completely pointless.
+	 *
+	 * 1) The interrupt is in move_in_progress state. That means that we
+	 *    have not seen an interrupt since the io_apic was reprogrammed to
+	 *    the new vector.
+	 *
+	 * 2) The interrupt has fired on the new vector, but the cleanup IPIs
+	 *    have not been processed yet.
+	 */
+	if (apicd->move_in_progress) {
+		/*
+		 * In theory there is a race:
+		 *
+		 * set_ioapic(new_vector) <-- Interrupt is raised before update
+		 *			      is effective, i.e. it's raised on
+		 *			      the old vector.
+		 *
+		 * So if the target cpu cannot handle that interrupt before
+		 * the old vector is cleaned up, we get a spurious interrupt
+		 * and in the worst case the ioapic irq line becomes stale.
+		 *
+		 * But in case of cpu hotplug this should be a non issue
+		 * because if the affinity update happens right before all
+		 * cpus rendezvous in stop machine, there is no way that the
+		 * interrupt can be blocked on the target cpu because all cpus
+		 * loops first with interrupts enabled in stop machine, so the
+		 * old vector is not yet cleaned up when the interrupt fires.
+		 *
+		 * So the only way to run into this issue is if the delivery
+		 * of the interrupt on the apic/system bus would be delayed
+		 * beyond the point where the target cpu disables interrupts
+		 * in stop machine. I doubt that it can happen, but at least
+		 * there is a theoretical chance. Virtualization might be
+		 * able to expose this, but AFAICT the IOAPIC emulation is not
+		 * as stupid as the real hardware.
+		 *
+		 * Anyway, there is nothing we can do about that at this point
+		 * w/o refactoring the whole fixup_irq() business completely.
+		 * We print at least the irq number and the old vector number,
+		 * so we have the necessary information when a problem in that
+		 * area arises.
+		 */
+		pr_warn("IRQ fixup: irq %d move in progress, old vector %d\n",
+			irqd->irq, vector);
+	}
+	free_moved_vector(apicd);
+}
+
 #else
-# define apic_set_affinity	NULL
+# define apic_set_affinity		NULL
+# define apic_force_complete_move	NULL
 #endif
 
 static int apic_retrigger_irq(struct irq_data *irqd)
@@ -923,39 +1024,16 @@ static void x86_vector_msi_compose_msg(struct irq_data *data,
 }
 
 static struct irq_chip lapic_controller = {
-	.name			= "APIC",
-	.irq_ack		= apic_ack_edge,
-	.irq_set_affinity	= apic_set_affinity,
-	.irq_compose_msi_msg	= x86_vector_msi_compose_msg,
-	.irq_retrigger		= apic_retrigger_irq,
+	.name				= "APIC",
+	.irq_ack			= apic_ack_edge,
+	.irq_set_affinity		= apic_set_affinity,
+	.irq_compose_msi_msg		= x86_vector_msi_compose_msg,
+	.irq_force_complete_move	= apic_force_complete_move,
+	.irq_retrigger			= apic_retrigger_irq,
 };
 
 #ifdef CONFIG_SMP
 
-static void free_moved_vector(struct apic_chip_data *apicd)
-{
-	unsigned int vector = apicd->prev_vector;
-	unsigned int cpu = apicd->prev_cpu;
-	bool managed = apicd->is_managed;
-
-	/*
-	 * Managed interrupts are usually not migrated away
-	 * from an online CPU, but CPU isolation 'managed_irq'
-	 * can make that happen.
-	 * 1) Activation does not take the isolation into account
-	 *    to keep the code simple
-	 * 2) Migration away from an isolated CPU can happen when
-	 *    a non-isolated CPU which is in the calculated
-	 *    affinity mask comes online.
-	 */
-	trace_vector_free_moved(apicd->irq, cpu, vector, managed);
-	irq_matrix_free(vector_matrix, cpu, vector, managed);
-	per_cpu(vector_irq, cpu)[vector] = VECTOR_UNUSED;
-	hlist_del_init(&apicd->clist);
-	apicd->prev_vector = 0;
-	apicd->move_in_progress = 0;
-}
-
 static void __vector_cleanup(struct vector_cleanup *cl, bool check_irr)
 {
 	struct apic_chip_data *apicd;
@@ -1068,99 +1146,6 @@ void irq_complete_move(struct irq_cfg *cfg)
 		__vector_schedule_cleanup(apicd);
 }
 
-/*
- * Called from fixup_irqs() with @desc->lock held and interrupts disabled.
- */
-void irq_force_complete_move(struct irq_desc *desc)
-{
-	unsigned int cpu = smp_processor_id();
-	struct apic_chip_data *apicd;
-	struct irq_data *irqd;
-	unsigned int vector;
-
-	/*
-	 * The function is called for all descriptors regardless of which
-	 * irqdomain they belong to. For example if an IRQ is provided by
-	 * an irq_chip as part of a GPIO driver, the chip data for that
-	 * descriptor is specific to the irq_chip in question.
-	 *
-	 * Check first that the chip_data is what we expect
-	 * (apic_chip_data) before touching it any further.
-	 */
-	irqd = irq_domain_get_irq_data(x86_vector_domain,
-				       irq_desc_get_irq(desc));
-	if (!irqd)
-		return;
-
-	raw_spin_lock(&vector_lock);
-	apicd = apic_chip_data(irqd);
-	if (!apicd)
-		goto unlock;
-
-	/*
-	 * If prev_vector is empty or the descriptor is neither currently
-	 * nor previously on the outgoing CPU no action required.
-	 */
-	vector = apicd->prev_vector;
-	if (!vector || (apicd->cpu != cpu && apicd->prev_cpu != cpu))
-		goto unlock;
-
-	/*
-	 * This is tricky. If the cleanup of the old vector has not been
-	 * done yet, then the following setaffinity call will fail with
-	 * -EBUSY. This can leave the interrupt in a stale state.
-	 *
-	 * All CPUs are stuck in stop machine with interrupts disabled so
-	 * calling __irq_complete_move() would be completely pointless.
-	 *
-	 * 1) The interrupt is in move_in_progress state. That means that we
-	 *    have not seen an interrupt since the io_apic was reprogrammed to
-	 *    the new vector.
-	 *
-	 * 2) The interrupt has fired on the new vector, but the cleanup IPIs
-	 *    have not been processed yet.
-	 */
-	if (apicd->move_in_progress) {
-		/*
-		 * In theory there is a race:
-		 *
-		 * set_ioapic(new_vector) <-- Interrupt is raised before update
-		 *			      is effective, i.e. it's raised on
-		 *			      the old vector.
-		 *
-		 * So if the target cpu cannot handle that interrupt before
-		 * the old vector is cleaned up, we get a spurious interrupt
-		 * and in the worst case the ioapic irq line becomes stale.
-		 *
-		 * But in case of cpu hotplug this should be a non issue
-		 * because if the affinity update happens right before all
-		 * cpus rendezvous in stop machine, there is no way that the
-		 * interrupt can be blocked on the target cpu because all cpus
-		 * loops first with interrupts enabled in stop machine, so the
-		 * old vector is not yet cleaned up when the interrupt fires.
-		 *
-		 * So the only way to run into this issue is if the delivery
-		 * of the interrupt on the apic/system bus would be delayed
-		 * beyond the point where the target cpu disables interrupts
-		 * in stop machine. I doubt that it can happen, but at least
-		 * there is a theoretical chance. Virtualization might be
-		 * able to expose this, but AFAICT the IOAPIC emulation is not
-		 * as stupid as the real hardware.
-		 *
-		 * Anyway, there is nothing we can do about that at this point
-		 * w/o refactoring the whole fixup_irq() business completely.
-		 * We print at least the irq number and the old vector number,
-		 * so we have the necessary information when a problem in that
-		 * area arises.
-		 */
-		pr_warn("IRQ fixup: irq %d move in progress, old vector %d\n",
-			irqd->irq, vector);
-	}
-	free_moved_vector(apicd);
-unlock:
-	raw_spin_unlock(&vector_lock);
-}
-
 #ifdef CONFIG_HOTPLUG_CPU
 /*
  * Note, this is not accurate accounting, but at least good enough to
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 8daa17f0107a..56f6583093d2 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -486,6 +486,7 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
  * @ipi_send_mask:	send an IPI to destination cpus in cpumask
  * @irq_nmi_setup:	function called from core code before enabling an NMI
  * @irq_nmi_teardown:	function called from core code after disabling an NMI
+ * @irq_force_complete_move:	optional function to force complete pending irq move
  * @flags:		chip specific flags
  */
 struct irq_chip {
@@ -537,6 +538,8 @@ struct irq_chip {
 	int		(*irq_nmi_setup)(struct irq_data *data);
 	void		(*irq_nmi_teardown)(struct irq_data *data);
 
+	void		(*irq_force_complete_move)(struct irq_data *data);
+
 	unsigned long	flags;
 };
 
@@ -619,11 +622,9 @@ static inline void irq_move_irq(struct irq_data *data)
 		__irq_move_irq(data);
 }
 void irq_move_masked_irq(struct irq_data *data);
-void irq_force_complete_move(struct irq_desc *desc);
 #else
 static inline void irq_move_irq(struct irq_data *data) { }
 static inline void irq_move_masked_irq(struct irq_data *data) { }
-static inline void irq_force_complete_move(struct irq_desc *desc) { }
 #endif
 
 extern int no_irq_affinity;
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index a979523640d0..d4e190e690bd 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -442,6 +442,7 @@ static inline struct cpumask *irq_desc_get_pending_mask(struct irq_desc *desc)
 	return desc->pending_mask;
 }
 bool irq_fixup_move_pending(struct irq_desc *desc, bool force_clear);
+void irq_force_complete_move(struct irq_desc *desc);
 #else /* CONFIG_GENERIC_PENDING_IRQ */
 static inline bool irq_can_move_pcntxt(struct irq_data *data)
 {
@@ -467,6 +468,7 @@ static inline bool irq_fixup_move_pending(struct irq_desc *desc, bool fclear)
 {
 	return false;
 }
+static inline void irq_force_complete_move(struct irq_desc *desc) { }
 #endif /* !CONFIG_GENERIC_PENDING_IRQ */
 
 #if !defined(CONFIG_IRQ_DOMAIN) || !defined(CONFIG_IRQ_DOMAIN_HIERARCHY)
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index eb150afd671f..e110300ad650 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -35,6 +35,16 @@ bool irq_fixup_move_pending(struct irq_desc *desc, bool force_clear)
 	return true;
 }
 
+void irq_force_complete_move(struct irq_desc *desc)
+{
+	for (struct irq_data *d = irq_desc_get_irq_data(desc); d; d = d->parent_data) {
+		if (d->chip && d->chip->irq_force_complete_move) {
+			d->chip->irq_force_complete_move(d);
+			return;
+		}
+	}
+}
+
 void irq_move_masked_irq(struct irq_data *idata)
 {
 	struct irq_desc *desc = irq_data_to_desc(idata);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v6 05/10] genirq: Introduce irq_can_move_in_process_context()
  2025-02-17  8:56 [PATCH v6 00/10] RISC-V IMSIC driver improvements Anup Patel
                   ` (3 preceding siblings ...)
  2025-02-17  8:56 ` [PATCH v6 04/10] genirq: Introduce common irq_force_complete_move() implementation Anup Patel
@ 2025-02-17  8:56 ` Anup Patel
  2025-02-17  8:56 ` [PATCH v6 06/10] RISC-V: Select GENERIC_PENDING_IRQ Anup Patel
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2025-02-17  8:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86
  Cc: hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx, Anup Patel

The interrupt controller drivers which use GENERIC_PENDING_IRQ
can move interrupts in process context for downstrean devices
which support atomic MSI configuration.

Introduce irq_can_move_in_process_context() which allows interrupt
controller drivers to test whether a particular interrupt can be
moved process context.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 include/linux/irq.h    |  2 ++
 kernel/irq/migration.c | 11 +++++++++++
 2 files changed, 13 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 56f6583093d2..dd5df1e2d032 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -615,6 +615,7 @@ extern int irq_affinity_online_cpu(unsigned int cpu);
 #endif
 
 #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ)
+bool irq_can_move_in_process_context(struct irq_data *data);
 void __irq_move_irq(struct irq_data *data);
 static inline void irq_move_irq(struct irq_data *data)
 {
@@ -623,6 +624,7 @@ static inline void irq_move_irq(struct irq_data *data)
 }
 void irq_move_masked_irq(struct irq_data *data);
 #else
+static inline bool irq_can_move_in_process_context(struct irq_data *data) { return true; }
 static inline void irq_move_irq(struct irq_data *data) { }
 static inline void irq_move_masked_irq(struct irq_data *data) { }
 #endif
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index e110300ad650..5acea2ac57be 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -127,3 +127,14 @@ void __irq_move_irq(struct irq_data *idata)
 	if (!masked)
 		idata->chip->irq_unmask(idata);
 }
+
+bool irq_can_move_in_process_context(struct irq_data *data)
+{
+	/*
+	 * Get top level irq_data when CONFIG_IRQ_DOMAIN_HIERARCHY is enabled,
+	 * and it should be optimized away when CONFIG_IRQ_DOMAIN_HIERARCHY is
+	 * disabled. So we avoid an "#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY" here.
+	 */
+	data = irq_desc_get_irq_data(irq_data_to_desc(data));
+	return irq_can_move_pcntxt(data);
+}
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v6 06/10] RISC-V: Select GENERIC_PENDING_IRQ
  2025-02-17  8:56 [PATCH v6 00/10] RISC-V IMSIC driver improvements Anup Patel
                   ` (4 preceding siblings ...)
  2025-02-17  8:56 ` [PATCH v6 05/10] genirq: Introduce irq_can_move_in_process_context() Anup Patel
@ 2025-02-17  8:56 ` Anup Patel
  2025-02-17  8:56 ` [PATCH v6 07/10] irqchip/riscv-imsic: Separate next and previous pointers in IMSIC vector Anup Patel
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2025-02-17  8:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86
  Cc: hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx, Anup Patel

Enable GENERIC_PENDING_IRQ for RISC-V so that RISC-V irqchips can
support delayed irq mirgration in the interrupt context.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 arch/riscv/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 7612c52e9b1e..a32f39748775 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -111,6 +111,7 @@ config RISCV
 	select GENERIC_IRQ_SHOW
 	select GENERIC_IRQ_SHOW_LEVEL
 	select GENERIC_LIB_DEVMEM_IS_ALLOWED
+	select GENERIC_PENDING_IRQ if SMP
 	select GENERIC_PCI_IOMAP
 	select GENERIC_PTDUMP if MMU
 	select GENERIC_SCHED_CLOCK
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v6 07/10] irqchip/riscv-imsic: Separate next and previous pointers in IMSIC vector
  2025-02-17  8:56 [PATCH v6 00/10] RISC-V IMSIC driver improvements Anup Patel
                   ` (5 preceding siblings ...)
  2025-02-17  8:56 ` [PATCH v6 06/10] RISC-V: Select GENERIC_PENDING_IRQ Anup Patel
@ 2025-02-17  8:56 ` Anup Patel
  2025-02-17  8:56 ` [PATCH v6 08/10] irqchip/riscv-imsic: Implement irq_force_complete_move() for IMSIC Anup Patel
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2025-02-17  8:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86
  Cc: hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx, Anup Patel

Currently, there is only one "move" pointer in the struct imsic_vector
so during vector movement the old vector points to the new vector and
new vector points to itself.

To support force cleanup of old vector, add separate "move_next" and
"move_prev" pointers in the struct imsic_vector where during vector
movement the "move_next" pointer of the old vector points to the new
vector and the "move_prev" pointer of the new vector points to the
old vector.

Both "move_next" and "move_prev" pointers are cleared separately by
__imsic_local_sync() with a restriction that "move_prev" on the new
CPU is cleared only after old CPU has cleared "move_next".

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 drivers/irqchip/irq-riscv-imsic-early.c |  8 ++-
 drivers/irqchip/irq-riscv-imsic-state.c | 96 +++++++++++++++++--------
 drivers/irqchip/irq-riscv-imsic-state.h |  7 +-
 3 files changed, 78 insertions(+), 33 deletions(-)

diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
index 275df5005705..553650932c75 100644
--- a/drivers/irqchip/irq-riscv-imsic-early.c
+++ b/drivers/irqchip/irq-riscv-imsic-early.c
@@ -77,6 +77,12 @@ static void imsic_handle_irq(struct irq_desc *desc)
 	struct imsic_vector *vec;
 	unsigned long local_id;
 
+	/*
+	 * Process pending local synchronization instead of waiting
+	 * for per-CPU local timer to expire.
+	 */
+	imsic_local_sync_all(false);
+
 	chained_irq_enter(chip, desc);
 
 	while ((local_id = csr_swap(CSR_TOPEI, 0))) {
@@ -120,7 +126,7 @@ static int imsic_starting_cpu(unsigned int cpu)
 	 * Interrupts identities might have been enabled/disabled while
 	 * this CPU was not running so sync-up local enable/disable state.
 	 */
-	imsic_local_sync_all();
+	imsic_local_sync_all(true);
 
 	/* Enable local interrupt delivery */
 	imsic_local_delivery(true);
diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index b97e6cd89ed7..96e994443fc7 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -124,10 +124,11 @@ void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend,
 	}
 }
 
-static void __imsic_local_sync(struct imsic_local_priv *lpriv)
+static bool __imsic_local_sync(struct imsic_local_priv *lpriv)
 {
 	struct imsic_local_config *mlocal;
 	struct imsic_vector *vec, *mvec;
+	bool ret = true;
 	int i;
 
 	lockdep_assert_held(&lpriv->lock);
@@ -143,35 +144,75 @@ static void __imsic_local_sync(struct imsic_local_priv *lpriv)
 			__imsic_id_clear_enable(i);
 
 		/*
-		 * If the ID was being moved to a new ID on some other CPU
-		 * then we can get a MSI during the movement so check the
-		 * ID pending bit and re-trigger the new ID on other CPU
-		 * using MMIO write.
+		 * Clear the pervious vector pointer of the new vector only
+		 * after the movement is complete on the old CPU.
 		 */
-		mvec = READ_ONCE(vec->move);
-		WRITE_ONCE(vec->move, NULL);
-		if (mvec && mvec != vec) {
+		mvec = READ_ONCE(vec->move_prev);
+		if (mvec) {
+			/*
+			 * If the old vector has not been updated then
+			 * try again in the next sync-up call.
+			 */
+			if (READ_ONCE(mvec->move_next)) {
+				ret = false;
+				continue;
+			}
+
+			WRITE_ONCE(vec->move_prev, NULL);
+		}
+
+		/*
+		 * If a vector was being moved to a new vector on some other
+		 * CPU then we can get a MSI during the movement so check the
+		 * ID pending bit and re-trigger the new ID on other CPU using
+		 * MMIO write.
+		 */
+		mvec = READ_ONCE(vec->move_next);
+		if (mvec) {
 			if (__imsic_id_read_clear_pending(i)) {
 				mlocal = per_cpu_ptr(imsic->global.local, mvec->cpu);
 				writel_relaxed(mvec->local_id, mlocal->msi_va);
 			}
 
+			WRITE_ONCE(vec->move_next, NULL);
 			imsic_vector_free(&lpriv->vectors[i]);
 		}
 
 skip:
 		bitmap_clear(lpriv->dirty_bitmap, i, 1);
 	}
+
+	return ret;
 }
 
-void imsic_local_sync_all(void)
+#ifdef CONFIG_SMP
+static void __imsic_local_timer_start(struct imsic_local_priv *lpriv)
+{
+	lockdep_assert_held(&lpriv->lock);
+
+	if (!timer_pending(&lpriv->timer)) {
+		lpriv->timer.expires = jiffies + 1;
+		add_timer_on(&lpriv->timer, smp_processor_id());
+	}
+}
+#else
+static inline void __imsic_local_timer_start(struct imsic_local_priv *lpriv)
+{
+}
+#endif
+
+void imsic_local_sync_all(bool force_all)
 {
 	struct imsic_local_priv *lpriv = this_cpu_ptr(imsic->lpriv);
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&lpriv->lock, flags);
-	bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1);
-	__imsic_local_sync(lpriv);
+
+	if (force_all)
+		bitmap_fill(lpriv->dirty_bitmap, imsic->global.nr_ids + 1);
+	if (!__imsic_local_sync(lpriv))
+		__imsic_local_timer_start(lpriv);
+
 	raw_spin_unlock_irqrestore(&lpriv->lock, flags);
 }
 
@@ -190,12 +231,7 @@ void imsic_local_delivery(bool enable)
 #ifdef CONFIG_SMP
 static void imsic_local_timer_callback(struct timer_list *timer)
 {
-	struct imsic_local_priv *lpriv = this_cpu_ptr(imsic->lpriv);
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&lpriv->lock, flags);
-	__imsic_local_sync(lpriv);
-	raw_spin_unlock_irqrestore(&lpriv->lock, flags);
+	imsic_local_sync_all(false);
 }
 
 static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu)
@@ -216,14 +252,11 @@ static void __imsic_remote_sync(struct imsic_local_priv *lpriv, unsigned int cpu
 	 */
 	if (cpu_online(cpu)) {
 		if (cpu == smp_processor_id()) {
-			__imsic_local_sync(lpriv);
-			return;
+			if (__imsic_local_sync(lpriv))
+				return;
 		}
 
-		if (!timer_pending(&lpriv->timer)) {
-			lpriv->timer.expires = jiffies + 1;
-			add_timer_on(&lpriv->timer, cpu);
-		}
+		__imsic_local_timer_start(lpriv);
 	}
 }
 #else
@@ -278,8 +311,9 @@ void imsic_vector_unmask(struct imsic_vector *vec)
 	raw_spin_unlock(&lpriv->lock);
 }
 
-static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, struct imsic_vector *vec,
-				     bool new_enable, struct imsic_vector *new_move)
+static bool imsic_vector_move_update(struct imsic_local_priv *lpriv,
+				     struct imsic_vector *vec, bool is_old_vec,
+				     bool new_enable, struct imsic_vector *move_vec)
 {
 	unsigned long flags;
 	bool enabled;
@@ -289,7 +323,10 @@ static bool imsic_vector_move_update(struct imsic_local_priv *lpriv, struct imsi
 	/* Update enable and move details */
 	enabled = READ_ONCE(vec->enable);
 	WRITE_ONCE(vec->enable, new_enable);
-	WRITE_ONCE(vec->move, new_move);
+	if (is_old_vec)
+		WRITE_ONCE(vec->move_next, move_vec);
+	else
+		WRITE_ONCE(vec->move_prev, move_vec);
 
 	/* Mark the vector as dirty and synchronize */
 	bitmap_set(lpriv->dirty_bitmap, vec->local_id, 1);
@@ -322,8 +359,8 @@ void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_ve
 	 * interrupt on the old vector while device was being moved
 	 * to the new vector.
 	 */
-	enabled = imsic_vector_move_update(old_lpriv, old_vec, false, new_vec);
-	imsic_vector_move_update(new_lpriv, new_vec, enabled, new_vec);
+	enabled = imsic_vector_move_update(old_lpriv, old_vec, true, false, new_vec);
+	imsic_vector_move_update(new_lpriv, new_vec, false, enabled, old_vec);
 }
 
 #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
@@ -386,7 +423,8 @@ struct imsic_vector *imsic_vector_alloc(unsigned int hwirq, const struct cpumask
 	vec = &lpriv->vectors[local_id];
 	vec->hwirq = hwirq;
 	vec->enable = false;
-	vec->move = NULL;
+	vec->move_next = NULL;
+	vec->move_prev = NULL;
 
 	return vec;
 }
diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h
index 391e44280827..f02842b84ed5 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.h
+++ b/drivers/irqchip/irq-riscv-imsic-state.h
@@ -23,7 +23,8 @@ struct imsic_vector {
 	unsigned int				hwirq;
 	/* Details accessed using local lock held */
 	bool					enable;
-	struct imsic_vector			*move;
+	struct imsic_vector			*move_next;
+	struct imsic_vector			*move_prev;
 };
 
 struct imsic_local_priv {
@@ -74,7 +75,7 @@ static inline void __imsic_id_clear_enable(unsigned long id)
 	__imsic_eix_update(id, 1, false, false);
 }
 
-void imsic_local_sync_all(void);
+void imsic_local_sync_all(bool force_all);
 void imsic_local_delivery(bool enable);
 
 void imsic_vector_mask(struct imsic_vector *vec);
@@ -87,7 +88,7 @@ static inline bool imsic_vector_isenabled(struct imsic_vector *vec)
 
 static inline struct imsic_vector *imsic_vector_get_move(struct imsic_vector *vec)
 {
-	return READ_ONCE(vec->move);
+	return READ_ONCE(vec->move_prev);
 }
 
 void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_vec);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v6 08/10] irqchip/riscv-imsic: Implement irq_force_complete_move() for IMSIC
  2025-02-17  8:56 [PATCH v6 00/10] RISC-V IMSIC driver improvements Anup Patel
                   ` (6 preceding siblings ...)
  2025-02-17  8:56 ` [PATCH v6 07/10] irqchip/riscv-imsic: Separate next and previous pointers in IMSIC vector Anup Patel
@ 2025-02-17  8:56 ` Anup Patel
  2025-02-17  8:56 ` [PATCH v6 09/10] irqchip/riscv-imsic: Replace hwirq with irq in the IMSIC vector Anup Patel
  2025-02-17  8:56 ` [PATCH v6 10/10] irqchip/riscv-imsic: Special handling for non-atomic device MSI update Anup Patel
  9 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2025-02-17  8:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86
  Cc: hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx, Anup Patel

Implement irq_force_complete_move() for IMSIC driver so that in-flight
vector movements on a CPU can be cleaned-up when the CPU goes down.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 drivers/irqchip/irq-riscv-imsic-platform.c | 32 ++++++++++++++++++++++
 drivers/irqchip/irq-riscv-imsic-state.c    | 17 ++++++++++++
 drivers/irqchip/irq-riscv-imsic-state.h    |  1 +
 3 files changed, 50 insertions(+)

diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c
index 9a5e7b4541f6..b9e3f9030bdf 100644
--- a/drivers/irqchip/irq-riscv-imsic-platform.c
+++ b/drivers/irqchip/irq-riscv-imsic-platform.c
@@ -129,6 +129,37 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask
 
 	return IRQ_SET_MASK_OK_DONE;
 }
+
+static void imsic_irq_force_complete_move(struct irq_data *d)
+{
+	struct imsic_vector *mvec, *vec = irq_data_get_irq_chip_data(d);
+	unsigned int cpu = smp_processor_id();
+
+	if (WARN_ON(!vec))
+		return;
+
+	/* Do nothing if there is no in-flight move */
+	mvec = imsic_vector_get_move(vec);
+	if (!mvec)
+		return;
+
+	/* Do nothing if the old IMSIC vector does not belong to current CPU */
+	if (mvec->cpu != cpu)
+		return;
+
+	/*
+	 * The best we can do is force cleanup the old IMSIC vector.
+	 *
+	 * The challenges over here are same as x86 vector domain so
+	 * refer to the comments in irq_force_complete_move() function
+	 * implemented at arch/x86/kernel/apic/vector.c.
+	 */
+
+	/* Force cleanup in-flight move */
+	pr_info("IRQ fixup: irq %d move in progress, old vector cpu %d local_id %d\n",
+		d->irq, mvec->cpu, mvec->local_id);
+	imsic_vector_force_move_cleanup(vec);
+}
 #endif
 
 static struct irq_chip imsic_irq_base_chip = {
@@ -137,6 +168,7 @@ static struct irq_chip imsic_irq_base_chip = {
 	.irq_unmask		= imsic_irq_unmask,
 #ifdef CONFIG_SMP
 	.irq_set_affinity	= imsic_irq_set_affinity,
+	.irq_force_complete_move = imsic_irq_force_complete_move,
 #endif
 	.irq_retrigger		= imsic_irq_retrigger,
 	.irq_compose_msi_msg	= imsic_irq_compose_msg,
diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index 96e994443fc7..5ec2b6bdffb2 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -311,6 +311,23 @@ void imsic_vector_unmask(struct imsic_vector *vec)
 	raw_spin_unlock(&lpriv->lock);
 }
 
+void imsic_vector_force_move_cleanup(struct imsic_vector *vec)
+{
+	struct imsic_local_priv *lpriv;
+	struct imsic_vector *mvec;
+	unsigned long flags;
+
+	lpriv = per_cpu_ptr(imsic->lpriv, vec->cpu);
+	raw_spin_lock_irqsave(&lpriv->lock, flags);
+
+	mvec = READ_ONCE(vec->move_prev);
+	WRITE_ONCE(vec->move_prev, NULL);
+	if (mvec)
+		imsic_vector_free(mvec);
+
+	raw_spin_unlock_irqrestore(&lpriv->lock, flags);
+}
+
 static bool imsic_vector_move_update(struct imsic_local_priv *lpriv,
 				     struct imsic_vector *vec, bool is_old_vec,
 				     bool new_enable, struct imsic_vector *move_vec)
diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h
index f02842b84ed5..19dea0c77738 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.h
+++ b/drivers/irqchip/irq-riscv-imsic-state.h
@@ -91,6 +91,7 @@ static inline struct imsic_vector *imsic_vector_get_move(struct imsic_vector *ve
 	return READ_ONCE(vec->move_prev);
 }
 
+void imsic_vector_force_move_cleanup(struct imsic_vector *vec);
 void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_vec);
 
 struct imsic_vector *imsic_vector_from_local_id(unsigned int cpu, unsigned int local_id);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v6 09/10] irqchip/riscv-imsic: Replace hwirq with irq in the IMSIC vector
  2025-02-17  8:56 [PATCH v6 00/10] RISC-V IMSIC driver improvements Anup Patel
                   ` (7 preceding siblings ...)
  2025-02-17  8:56 ` [PATCH v6 08/10] irqchip/riscv-imsic: Implement irq_force_complete_move() for IMSIC Anup Patel
@ 2025-02-17  8:56 ` Anup Patel
  2025-02-17  8:56 ` [PATCH v6 10/10] irqchip/riscv-imsic: Special handling for non-atomic device MSI update Anup Patel
  9 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2025-02-17  8:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86
  Cc: hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx, Anup Patel

Currently, the imsic_handle_irq() uses generic_handle_domain_irq() to
handle the irq which internally has an extra step of resolving hwirq
using domain. This extra step can be avoided by replacing hwirq with
irq in the IMSIC vector and directly calling generic_handle_irq().

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 drivers/irqchip/irq-riscv-imsic-early.c    | 6 ++----
 drivers/irqchip/irq-riscv-imsic-platform.c | 2 +-
 drivers/irqchip/irq-riscv-imsic-state.c    | 8 ++++----
 drivers/irqchip/irq-riscv-imsic-state.h    | 4 ++--
 4 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
index 553650932c75..d9ae87808651 100644
--- a/drivers/irqchip/irq-riscv-imsic-early.c
+++ b/drivers/irqchip/irq-riscv-imsic-early.c
@@ -73,7 +73,7 @@ static int __init imsic_ipi_domain_init(void) { return 0; }
 static void imsic_handle_irq(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
-	int err, cpu = smp_processor_id();
+	int cpu = smp_processor_id();
 	struct imsic_vector *vec;
 	unsigned long local_id;
 
@@ -103,9 +103,7 @@ static void imsic_handle_irq(struct irq_desc *desc)
 			continue;
 		}
 
-		err = generic_handle_domain_irq(imsic->base_domain, vec->hwirq);
-		if (unlikely(err))
-			pr_warn_ratelimited("hwirq 0x%x mapping not found\n", vec->hwirq);
+		generic_handle_irq(vec->irq);
 	}
 
 	chained_irq_exit(chip, desc);
diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c
index b9e3f9030bdf..6bf5d63f614e 100644
--- a/drivers/irqchip/irq-riscv-imsic-platform.c
+++ b/drivers/irqchip/irq-riscv-imsic-platform.c
@@ -111,7 +111,7 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask
 		return -EBUSY;
 
 	/* Get a new vector on the desired set of CPUs */
-	new_vec = imsic_vector_alloc(old_vec->hwirq, mask_val);
+	new_vec = imsic_vector_alloc(old_vec->irq, mask_val);
 	if (!new_vec)
 		return -ENOSPC;
 
diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index 5ec2b6bdffb2..d0148e48ab05 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -422,7 +422,7 @@ struct imsic_vector *imsic_vector_from_local_id(unsigned int cpu, unsigned int l
 	return &lpriv->vectors[local_id];
 }
 
-struct imsic_vector *imsic_vector_alloc(unsigned int hwirq, const struct cpumask *mask)
+struct imsic_vector *imsic_vector_alloc(unsigned int irq, const struct cpumask *mask)
 {
 	struct imsic_vector *vec = NULL;
 	struct imsic_local_priv *lpriv;
@@ -438,7 +438,7 @@ struct imsic_vector *imsic_vector_alloc(unsigned int hwirq, const struct cpumask
 
 	lpriv = per_cpu_ptr(imsic->lpriv, cpu);
 	vec = &lpriv->vectors[local_id];
-	vec->hwirq = hwirq;
+	vec->irq = irq;
 	vec->enable = false;
 	vec->move_next = NULL;
 	vec->move_prev = NULL;
@@ -451,7 +451,7 @@ void imsic_vector_free(struct imsic_vector *vec)
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&imsic->matrix_lock, flags);
-	vec->hwirq = UINT_MAX;
+	vec->irq = 0;
 	irq_matrix_free(imsic->matrix, vec->cpu, vec->local_id, false);
 	raw_spin_unlock_irqrestore(&imsic->matrix_lock, flags);
 }
@@ -510,7 +510,7 @@ static int __init imsic_local_init(void)
 			vec = &lpriv->vectors[i];
 			vec->cpu = cpu;
 			vec->local_id = i;
-			vec->hwirq = UINT_MAX;
+			vec->irq = 0;
 		}
 	}
 
diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h
index 19dea0c77738..3202ffa4e849 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.h
+++ b/drivers/irqchip/irq-riscv-imsic-state.h
@@ -20,7 +20,7 @@ struct imsic_vector {
 	unsigned int				cpu;
 	unsigned int				local_id;
 	/* Details saved by driver in the vector */
-	unsigned int				hwirq;
+	unsigned int				irq;
 	/* Details accessed using local lock held */
 	bool					enable;
 	struct imsic_vector			*move_next;
@@ -96,7 +96,7 @@ void imsic_vector_move(struct imsic_vector *old_vec, struct imsic_vector *new_ve
 
 struct imsic_vector *imsic_vector_from_local_id(unsigned int cpu, unsigned int local_id);
 
-struct imsic_vector *imsic_vector_alloc(unsigned int hwirq, const struct cpumask *mask);
+struct imsic_vector *imsic_vector_alloc(unsigned int irq, const struct cpumask *mask);
 void imsic_vector_free(struct imsic_vector *vector);
 
 void imsic_vector_debug_show(struct seq_file *m, struct imsic_vector *vec, int ind);
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v6 10/10] irqchip/riscv-imsic: Special handling for non-atomic device MSI update
  2025-02-17  8:56 [PATCH v6 00/10] RISC-V IMSIC driver improvements Anup Patel
                   ` (8 preceding siblings ...)
  2025-02-17  8:56 ` [PATCH v6 09/10] irqchip/riscv-imsic: Replace hwirq with irq in the IMSIC vector Anup Patel
@ 2025-02-17  8:56 ` Anup Patel
  9 siblings, 0 replies; 18+ messages in thread
From: Anup Patel @ 2025-02-17  8:56 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86
  Cc: hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx, Anup Patel

Device having non-atomic MSI update might see an intermediate
state when changing target IMSIC vector from one CPU to another.

To avoid losing interrupt to such intermediate state, do the
following (just like x86 APIC):
 1) First write a temporary IMSIC vector to the device which
    has MSI address same as the old IMSIC vector but with MSI
    data matches the new IMSIC vector.
 2) Next write the new IMSIC vector to the device.

Based on the above, the __imsic_local_sync() must check pending
status of both old MSI data and new MSI data on the old CPU. In
addition, the movement of IMSIC vector for non-atomic device MSI
update must be done in interrupt context using IRQCHIP_MOVE_DEFERRED.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
 drivers/irqchip/irq-riscv-imsic-platform.c | 73 +++++++++++++++++++++-
 drivers/irqchip/irq-riscv-imsic-state.c    | 31 +++++++--
 2 files changed, 98 insertions(+), 6 deletions(-)

diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c
index 6bf5d63f614e..828102c46f51 100644
--- a/drivers/irqchip/irq-riscv-imsic-platform.c
+++ b/drivers/irqchip/irq-riscv-imsic-platform.c
@@ -64,6 +64,11 @@ static int imsic_irq_retrigger(struct irq_data *d)
 	return 0;
 }
 
+static void imsic_irq_ack(struct irq_data *d)
+{
+	irq_move_irq(d);
+}
+
 static void imsic_irq_compose_vector_msg(struct imsic_vector *vec, struct msi_msg *msg)
 {
 	phys_addr_t msi_addr;
@@ -97,6 +102,21 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask
 				  bool force)
 {
 	struct imsic_vector *old_vec, *new_vec;
+	struct imsic_vector tmp_vec;
+
+	/*
+	 * Requirements for the downstream irqdomains (or devices):
+	 *
+	 * 1) Downstream irqdomains (or devices) with atomic MSI update can
+	 *    happily do imsic_irq_set_affinity() in the process-context on
+	 *    any CPU so the irqchip of such irqdomains must not set the
+	 *    IRQCHIP_MOVE_DEFERRED flag.
+	 *
+	 * 2) Downstream irqdomains (or devices) with non-atomic MSI update
+	 *    must do imsic_irq_set_affinity() in the interrupt-context upon
+	 *    next interrupt so the irqchip of such irqdomains must set the
+	 *    IRQCHIP_MOVE_DEFERRED flag.
+	 */
 
 	old_vec = irq_data_get_irq_chip_data(d);
 	if (WARN_ON(!old_vec))
@@ -115,6 +135,33 @@ static int imsic_irq_set_affinity(struct irq_data *d, const struct cpumask *mask
 	if (!new_vec)
 		return -ENOSPC;
 
+	/*
+	 * Device having non-atomic MSI update might see an intermediate
+	 * state when changing target IMSIC vector from one CPU to another.
+	 *
+	 * To avoid losing interrupt to such intermediate state, do the
+	 * following (just like x86 APIC):
+	 *
+	 * 1) First write a temporary IMSIC vector to the device which
+	 * has MSI address same as the old IMSIC vector but MSI data
+	 * matches the new IMSIC vector.
+	 *
+	 * 2) Next write the new IMSIC vector to the device.
+	 *
+	 * Based on the above, the __imsic_local_sync() must check pending
+	 * status of both old MSI data and new MSI data on the old CPU.
+	 */
+
+	if (!irq_can_move_in_process_context(d) &&
+	    new_vec->local_id != old_vec->local_id) {
+		/* Setup temporary vector */
+		tmp_vec.cpu = old_vec->cpu;
+		tmp_vec.local_id = new_vec->local_id;
+
+		/* Point device to the temporary vector */
+		imsic_msi_update_msg(irq_get_irq_data(d->irq), &tmp_vec);
+	}
+
 	/* Point device to the new vector */
 	imsic_msi_update_msg(irq_get_irq_data(d->irq), new_vec);
 
@@ -171,6 +218,7 @@ static struct irq_chip imsic_irq_base_chip = {
 	.irq_force_complete_move = imsic_irq_force_complete_move,
 #endif
 	.irq_retrigger		= imsic_irq_retrigger,
+	.irq_ack		= imsic_irq_ack,
 	.irq_compose_msi_msg	= imsic_irq_compose_msg,
 	.flags			= IRQCHIP_SKIP_SET_WAKE |
 				  IRQCHIP_MASK_ON_SUSPEND,
@@ -190,7 +238,7 @@ static int imsic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 		return -ENOSPC;
 
 	irq_domain_set_info(domain, virq, virq, &imsic_irq_base_chip, vec,
-			    handle_simple_irq, NULL, NULL);
+			    handle_edge_irq, NULL, NULL);
 	irq_set_noprobe(virq);
 	irq_set_affinity(virq, cpu_online_mask);
 	irq_data_update_effective_affinity(irq_get_irq_data(virq), cpumask_of(vec->cpu));
@@ -229,15 +277,36 @@ static const struct irq_domain_ops imsic_base_domain_ops = {
 #endif
 };
 
+static bool imsic_init_dev_msi_info(struct device *dev,
+				    struct irq_domain *domain,
+				    struct irq_domain *real_parent,
+				    struct msi_domain_info *info)
+{
+	if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info))
+		return false;
+
+	switch (info->bus_token) {
+	case DOMAIN_BUS_PCI_DEVICE_MSI:
+	case DOMAIN_BUS_PCI_DEVICE_MSIX:
+		info->chip->flags |= IRQCHIP_MOVE_DEFERRED;
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
 static const struct msi_parent_ops imsic_msi_parent_ops = {
 	.supported_flags	= MSI_GENERIC_FLAGS_MASK |
 				  MSI_FLAG_PCI_MSIX,
 	.required_flags		= MSI_FLAG_USE_DEF_DOM_OPS |
 				  MSI_FLAG_USE_DEF_CHIP_OPS |
 				  MSI_FLAG_PCI_MSI_MASK_PARENT,
+	.chip_flags		= MSI_CHIP_FLAG_SET_ACK,
 	.bus_select_token	= DOMAIN_BUS_NEXUS,
 	.bus_select_mask	= MATCH_PCI_MSI | MATCH_PLATFORM_MSI,
-	.init_dev_msi_info	= msi_lib_init_dev_msi_info,
+	.init_dev_msi_info	= imsic_init_dev_msi_info,
 };
 
 int imsic_irqdomain_init(void)
diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index d0148e48ab05..3a2a381e4fa1 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -126,8 +126,8 @@ void __imsic_eix_update(unsigned long base_id, unsigned long num_id, bool pend,
 
 static bool __imsic_local_sync(struct imsic_local_priv *lpriv)
 {
-	struct imsic_local_config *mlocal;
-	struct imsic_vector *vec, *mvec;
+	struct imsic_local_config *tlocal, *mlocal;
+	struct imsic_vector *vec, *tvec, *mvec;
 	bool ret = true;
 	int i;
 
@@ -169,13 +169,36 @@ static bool __imsic_local_sync(struct imsic_local_priv *lpriv)
 		 */
 		mvec = READ_ONCE(vec->move_next);
 		if (mvec) {
-			if (__imsic_id_read_clear_pending(i)) {
+			/*
+			 * Device having non-atomic MSI update might see an
+			 * intermediate state so check both old ID and new ID
+			 * for pending interrupts.
+			 *
+			 * For details, refer imsic_irq_set_affinity().
+			 */
+
+			tvec = vec->local_id == mvec->local_id ?
+			       NULL : &lpriv->vectors[mvec->local_id];
+			if (tvec &&
+			    !irq_can_move_in_process_context(irq_get_irq_data(vec->irq)) &&
+			    __imsic_id_read_clear_pending(tvec->local_id)) {
+				/* Retrigger temporary vector if it was already in-use */
+				if (READ_ONCE(tvec->enable)) {
+					tlocal = per_cpu_ptr(imsic->global.local, tvec->cpu);
+					writel_relaxed(tvec->local_id, tlocal->msi_va);
+				}
+
+				mlocal = per_cpu_ptr(imsic->global.local, mvec->cpu);
+				writel_relaxed(mvec->local_id, mlocal->msi_va);
+			}
+
+			if (__imsic_id_read_clear_pending(vec->local_id)) {
 				mlocal = per_cpu_ptr(imsic->global.local, mvec->cpu);
 				writel_relaxed(mvec->local_id, mlocal->msi_va);
 			}
 
 			WRITE_ONCE(vec->move_next, NULL);
-			imsic_vector_free(&lpriv->vectors[i]);
+			imsic_vector_free(vec);
 		}
 
 skip:
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v6 02/10] irqchip/irq-msi-lib: Optionally set default irq_eoi/irq_ack
  2025-02-17  8:56 ` [PATCH v6 02/10] irqchip/irq-msi-lib: Optionally set default irq_eoi/irq_ack Anup Patel
@ 2025-02-19 14:41   ` Mark Brown
  2025-02-20 13:54     ` Thomas Gleixner
  0 siblings, 1 reply; 18+ messages in thread
From: Mark Brown @ 2025-02-19 14:41 UTC (permalink / raw)
  To: Anup Patel
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	hpa, Marc Zyngier, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Andrew Lunn, Gregory Clement,
	Sebastian Hesselbarth, Palmer Dabbelt, Paul Walmsley, Atish Patra,
	Andrew Jones, Sunil V L, Anup Patel, linux-riscv,
	linux-arm-kernel, linux-kernel, imx

[-- Attachment #1: Type: text/plain, Size: 33967 bytes --]

On Mon, Feb 17, 2025 at 02:26:48PM +0530, Anup Patel wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> Introduce chip_flags in struct msi_parent_ops. This allows
> msi_lib_init_dev_msi_info() set default irq_eoi/irq_ack
> callbacks only when the corresponding flags are set in
> the chip_flags.

I'm seeing boot regressions with qemu on arm64 in -next which bisect
down to this patch.  We hit a NULL pointer dereference:

<6>[    0.898900] virtio_blk virtio1: 1/0/0 default/read/poll queues
<5>[    0.910197] virtio_blk virtio1: [vda] 3906250 512-byte logical blocks (2.00 GB/1.86 GiB)
<1>[    0.924459] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
<1>[    0.924508] Mem abort info:
<1>[    0.924521]   ESR = 0x000000008600002b
<1>[    0.924559]   EC = 0x21: IABT (current EL), IL = 32 bits
<1>[    0.924580]   SET = 0, FnV = 0
<1>[    0.924597]   EA = 0, S1PTW = 0
<1>[    0.924616]   FSC = 0x2b: level -1 translation fault
<1>[    0.924667] [0000000000000000] user address but active_mm is swapper
<0>[    0.924833] Internal error: Oops: 000000008600002b [#1] PREEMPT SMP

...

<4>[    0.933487] Call trace:
<4>[    0.933767]  0x0 (P)
<4>[    0.934028]  handle_fasteoi_irq+0xb0/0x1cc
<4>[    0.934296]  handle_irq_desc+0x40/0x58
<4>[    0.934502]  generic_handle_domain_irq+0x1c/0x28
<4>[    0.934686]  gic_handle_irq+0x4c/0x120
<4>[    0.934866]  call_on_irq_stack+0x24/0x4c
<4>[    0.935034]  do_interrupt_handler+0x80/0x84
<4>[    0.935233]  el1_interrupt+0x34/0x68
<4>[    0.935417]  el1h_64_irq_handler+0x18/0x24
<4>[    0.935573]  el1h_64_irq+0x6c/0x70
<4>[    0.935775]  blk_mq_dispatch_rq_list+0x29c/0x6f0 (P)
<4>[    0.935964]  __blk_mq_sched_dispatch_requests+0x460/0x57c

Full log:

   https://lava.sirena.org.uk/scheduler/job/1126644

bisect log (there's a bunch of good commits added at the start since my
automation harvests results it already knows about to feed bisects):

# bad: [8936cec5cb6e27649b86fabf383d7ce4113bba49] Add linux-next specific files for 20250219
# good: [67961d4f4e34f5ed1aeebab08f42c2e706837ec5] Merge branch 'for-linux-next-fixes' of https://gitlab.freedesktop.org/drm/misc/kernel.git
# good: [d1a09c610027e446ed30c21f61c2f2443bf92a3f] MAINTAINERS: adjust the file entry in SPI OFFLOAD
# good: [a78f244a9150da0878a37a1b59fb0608b1ccfb9d] ASoC: SOF: imx: Fix error code in probe()
# good: [b20be2c77ce5341ded1a2d8aec119f6dca8ef1ad] ASoC: SOF: imx: Fix an IS_ERR() vs NULL bug in imx_parse_ioremap_memory()
# good: [5d9fca12f54d3e25e02521aa8f3ec5d53759b334] ASoC: amd: ps: fix inconsistent indenting warning in check_and_handle_sdw_dma_irq()
# good: [3f02dedf1566858736f351a8d4a3ce91375e48f1] ASoC: random cleanup
# good: [0770b7cc095e015af302f0758d3d85c7f17c719a] ASoC: tas2764: Random patches from the Asahi Linux
# good: [e0f421d73053eaeb441aa77054b75992705656c7] ASoC: SOF: ipc3: Use str_enabled_disabled() helper function
# good: [5c7e4c4da8586d2ef55a11a9f4df626b8ea9a146] ASoC: dt-bindings: wlf,wm8960: add 'port' property
# good: [783db6851c1821d8b983ffb12b99c279ff64f2ee] ASoC: ops: Enforce platform maximum on initial value
# good: [9f25b6f2568d50c247a8e3b031a0a5caee8c17d2] ASoC: wm_hubs: Use str_enable_disable() in wm_hubs_update_class_w()
# good: [9dc016eaba3a70febcd1db5f1a0beeb7430166aa] ASoC: SOF: Intel: Don't import non-existing module namespace
# good: [e08fe24c34d37d00e84009f2fb4c35f5978041e6] ASoC: SOF: Intel: Use str_enable_disable() helper
# good: [1c3b5f37409682184669457a5bdf761268eafbe5] ASoC: tas2764: Power up/down amp on mute ops
# good: [f37f1748564ac51d32f7588bd7bfc99913ccab8e] ASoC: tas2764: Mark SW_RESET as volatile
# good: [7e1caa679686dde5c24d60b139f234568045758f] ASoC: soc-pcm: makes dpcm_dapm_stream_event() void
# good: [d64c4c3d1c578f98d70db1c5e2535b47adce9d07] ASoC: tas2764: Add reg defaults for TAS2764_INT_CLK_CFG
# good: [40b1f89a1691c4b7740bec2c868f1e4c60346353] ASoC: remove dpcm_process_paths()
# good: [42da18e62652b58ba5ecd1524c146b202cda9bb7] ASoC: soc-pcm: cleanup dpcm_fe_dai_do_trigger()
# good: [3aebbcba4baaa81bc8c83f2229ed8e774cf40618] ASoC: soc-pcm: cleanup dpcm_dai_trigger_fe_be()
# good: [1248d29464cc682c2a1793cfc5d4ebeb374c6738] ASoC: soc-ops: makes snd_soc_read_signed() void
# good: [7f1186a8d738661b941b298fd6d1d5725ed71428] ASoC: soc-dai: check return value at snd_soc_dai_set_tdm_slot()
# good: [238c863eb3d3c6ed58493bacfd1f4b36bdcfa92f] ASoC: soc-core: makes snd_soc_set_dmi_name() local
# good: [0c4a06395156d16ea33e959fccea84e4cfec04c4] ASoC: soc-pcm: remove duplicate param from __soc_pcm_hw_params()
# good: [08a66f55f7246d477b19620a953476dfc02beefc] ASoC: tas2764: Wait for ramp-down after shutdown
# good: [257a060fe219bb0dcb98f12ce34f04eca6d08352] ASoC: remove update from snd_soc_card
# good: [11c1967f1a796bf2ff56a7118147f1d39d9f5ee0] ASoC: soc-pcm: no need to check dpcm->fe on dpcm_be_connect()
# good: [994719ed6d81a6f4677875ab6730254c0bc484ea] ASoC: Intel: avs: Use str_on_off() in avs_dsp_core_power()
# good: [ae575d2145d1a2c8bb5d2835d7d54751f3b0bace] ASoC: tegra: Remove the isomgr_bw APIs export
# good: [828c0aa63706410503526d0ee522b9ac3232c86b] ASoC: amd: ps: use switch statements for acp pci revision id check
# good: [74e0fcbd705d4277267311f8f26a00bb8ce93820] gpiolib: add gpiod_multi_set_value_cansleep
# good: [f22ba3561daa792dd138ed543e0bf48efe0b999c] ASoC: SOF: imx-common: set sdev->pdata->hw_pdata after common is alloc'd
# good: [ad0fbcebb5f6e093d433a0873758a2778d747eb8] ASoC: adau1701: use gpiod_multi_set_value_cansleep
# good: [c6bb909b8f11b9403715a325b51c2bcf01e2bbc0] Merge branch 'slab/for-6.15/kfree_rcu_tiny' into slab/for-next
# good: [e957c96455e8f4c630d5e374312cad0633ca7e17] spi: offload: fix use after free
# good: [d795a052b0ddad3da83dda6ff522c1b1aaa4a525] spi: fix missing offload_flags doc
# good: [91931af18bd22437e08e2471f5484d6fbdd8ab93] gpiolib: add gpiod_multi_set_value_cansleep()
# good: [ff4d4158ef9143327a42f7be4298751cb0d1be69] spi: spi-offload-trigger-pwm: add extra headers
# good: [fcd7ace9a725ae034ff9f24cb94c9fe12a1f02da] spi: offload: types: include linux/bits.h
# good: [21aa330fec31bb530a4ef6c9555fb157d0711112] ASoC: fsl_micfil: Add decimation filter bypass mode support
# good: [e97d06cb4386af4e069a2dc713de70500538d0bd] ASoC: tscs454: Use str_enable_disable() in pll_power_event()
# good: [ad1212a9cc24b740b2711014933fac6ace32aa2d] arm64: dts: rockchip: Add SPDIF on RK3588
# good: [d1541caab053cf94b114582a23b51a8cb90f4a46] Add SDCA DisCo parsing support
# good: [f46eb2bfb878ce3345725252f77fa3ba36a0f087] spi: axi-spi-engine: add offload support
# good: [c5528214c7c0a753c908a7b353309ba665985fb4] ASoC: codecs: wcd93xx-sdw: fix of_property_read_bool() warnings
# good: [2c17e9ea0caa5555e31e154fa1b06260b816f5cc] dmaengine: idxd: Delete unnecessary NULL check
# good: [3c331bdeececb629669961a80c0f929301c088d2] Refactor imx drivers and introduce support for
# good: [93354d866ac44d0f9d65b2e4adb5cc9a1c1912c9] prandom: remove next_pseudo_random32
# good: [330cbb40bb3664a18a19760bd6dc6003d6624041] dt-bindings: ASoC: rockchip: Add compatible for RK3588 SPDIF
# good: [2f9523091a97abf8584a79ed406fd8ffe9063ec0] Merge branch 'misc' into for-next
# good: [651e0ed391b148f83afba0bfbd8a56e38e58c34d] ASoC: SOF: imx: introduce more common structures and functions
# good: [005859a2cf7aa349fbbfe433ab1769b15c535b72] ASoC: amd: Add support for ACP7.0 & ACP7.1
# good: [563e40153a56cbfae8721f9591022df5d930f939] ASoC: SOF: imx8: use IMX_SOF_* macros
# good: [700a281905f2a4ccf6f3b2d3cd6985e034b4b021] spi: add offload TX/RX streaming APIs
# good: [629dd55cf77bd3a8f80049150d3c05fef6d3b468] ASoC: SDCA: Minor formatting and naming tweaks
# good: [d7231be4b4657e5f922a4c6dc11e8dffc71fee87] spi: offload: add support for hardware triggers
# good: [d920908fe36c2b3a1c6fe444831e0c8c2a995fd1] Merge branch 'for-6.14-fixes' into for-next
# good: [07e3e514dd385300bd08da4a8df09240d272821e] ASoC: SOF: imx: merge imx8 and imx8ulp drivers
# good: [645753d01356ff1a756812f1c69c53eb5c9081cd] ASoC: SOF: imx8: use common imx chip interface
# good: [f98d42000216677d177384f202ff1cc896a7395f] ASoC: Intel: soc-acpi-intel-ptl-match typo fixups
# good: [5a19e1985d014fab9892348f6175a19143cec810] spi: axi-spi-engine: implement offload support
# good: [896530b7b0c08ee8b3296d5f012bfe1b0a979b86] ASoC: SOF: imx: merge imx8 and imx8m drivers
# good: [19f6748abbab8523a7b32a5e371e39d4d8d4aba5] ASoC: SDCA: Parse initialization write table
# good: [9ee6d50ae4b0fe14ed70a5265a05874d41e10848] ASoC: SDCA: Add support for Entity 0
# good: [f87c2a275033120e15213f3d65234d98e726c4b7] ASoC: SDCA: Add Channel Cluster parsing
# good: [ebb398ae1e052c4245b7bcea679fe073111db2ce] spi: offload-trigger: add PWM trigger driver
# good: [8e02d188698851436f76038ea998b726193d1b10] spi: add basic support for SPI offloading
# good: [5c93b20f6de4478e1fbcfb38eb46738bca74180e] ASoC: SDCA: Add support for IT/OT Entity properties
# good: [42b144cb6a2d87385fa0b124c975d6cf1e3ec630] ASoC: SDCA: Add SDCA Control parsing
# good: [e1101373df5cd7672d988bb4e9cdd5eb97003165] spi: dt-bindings: axi-spi-engine: add SPI offload properties
# good: [e80b8e5c53c30df1cba45258d10b04872b7eea67] ASoC: SDCA: Add support for clock Entity properties
# good: [9da195880f167ab7c2d595388decf783c9920121] ASoC: SDCA: Add support for PDE Entity properties
# good: [83f37ba7b76ab17e029ab4127ec64ccccce64c00] dt-bindings: trigger-source: add generic PWM trigger source
# good: [45e02edd8422b6c4a511f38403dbd805cd139733] ASoC: SOF: imx8: drop unneeded/unused macros/header includes
# good: [6cf5df1040ba0694aea6a5edc6f31811a442ea36] ASoC: SOF: imx: add driver for the imx95 chip
# good: [64fb5af1d1bbcf1b808e9bb092b22fa1b691ae63] ASoC: SDCA: Add parsing for Control range structures
# good: [996bf834d0b61cb5a1389356c1ed7db1230139d7] ASoC: SDCA: Add code to parse Function information
# good: [d0252b0b945ec67fd09fc764dcadf445fb7757ee] ASoC: amd: acp: amd-acp70-acpi-match: Add rt722 support
# good: [187150671d83324f1ca56f7ab5e00f16a3b9f2a9] ASoC: amd: acp: add RT711, RT714 & RT1316 support for ACP7.0 platform
# good: [fcb754602724fa2a1d0db72f13ddc3ef0306f911] ASoC: amd: ps: store acp revision id in SoundWire dma driver private data
# good: [43d6140cedad9f031b47dfde6f85856e007b3f04] ASoC: amd: ps: refactor soundwire dma interrupts enable/disable sequence
# good: [31e3100d5e1fe69f944f84867be0cbfa5fd380c8] ASoC: amd: acp: amd-acp70-acpi-match: Add RT1320 & RT722 combination soundwire machine
# good: [491628388005a26c02d6827e649284357daec213] ASoC: amd: ps: add callback functions for acp pci driver pm ops
# good: [1c35755f46423150e19ff57448786b4bb48fdb46] ASoC: amd: ps: implement function to restore dma config for ACP7.0 platform
# good: [0b6914a0121b4c9fc8f575b60a5dd43b74612908] ASoC: amd: ps: add soundwire dma interrupts handling for ACP7.0 platform
# good: [0eb8f83c055cb3461734710d1b1ce2dd4f01806e] ASoC: amd: ps: update module description
# good: [852c0b7204ded184924c41ab99b2ac7a70ad4dab] ASoC: Intel: soc-acpi-intel-ptl-match: add rt713_vb_l2_rt1320_l13
# good: [3898b189079c85735f57759b0d407518c01c745e] ASoC: amd: ps: add soundwire wake interrupt handling
# good: [c878d5c1a525b88807d9d79888fe8340bcbf1aa3] ASoC: amd: ps: add ACP7.0 & ACP7.1 specific soundwire dma driver changes
# good: [4b36a47e2d989b98953dbfb1e97da0f0169f5086] ASoC: amd: ps: use macro for ACP6.3 pci revision id
# good: [fde277dbcf53be685d0b9976d636366c80a74da8] ASoC: amd: ps: add pm ops related hw_ops for ACP7.0 & ACP7.1 platforms
# good: [91f505dc3a94c04421a2a51e8c40acf7ea67ecbc] ASoC: Intel: soc-acpi-intel-ptl-match: add rt712_vb + rt1320 support
# good: [552f66c40134542f15d4302837e7d581a0b8e217] ASoC: amd: update Pink Sardine platform Kconfig description
# good: [638ad2bdb2f994c8bd99cc40e0c4796a8617ccf3] ASoC: amd: acp: add machine driver changes for ACP7.0 and ACP7.1 platforms
# good: [4bb5b6f13fd83b32c8a93fbd399e7558415d1ce0] ASoC: amd: amd_sdw: Add quirks for Dell SKU's
# good: [e2ceac2f323625632f12dd5333092976298a0cde] ASoC: amd: ps: rename structure names, variable and other macros
# good: [0fa0843db17ccd427fc7a23d313aafa88fc89e04] ASoC: amd: ps: refactor soundwire dma driver code
# good: [7c0ea26c57b0bb72d503fe27d6533f5addc5e3a3] ASoC: amd: ps: add pci driver hw_ops for ACP7.0 & ACP7.1 variants
# good: [f1e91acacf86fb2cd7478af490326cb9aa63e8ae] ASoC: amd: ps: update file description and copyright year
# good: [0a27b2d7a224326fab543ca586d501fe1857b655] ASoC: amd: ps: add soundwire dma irq thread callback
# good: [6547577e94ae3d9f8ff30d3267fe7ec394e3b20d] ASoC: amd: ps: add callback to read acp pin configuration
# good: [605aab3b3ca83f58681841b2dd16d4a7baefde6c] ASoC: amd: ps: rename acp_restore_sdw_dma_config() function
# good: [4516be370ced14c4fb454fd6cc016e47bffe109e] ASoC: amd: ps: refactor soundwire dma interrupt handling
# good: [db746fff89a14419379226ce0df8b94f472cf38c] ASoC: amd: ps: add acp pci driver hw_ops for acp6.3 platform
# good: [a23ff143804d3b8c27157ffa19e48b4e22939115] ASoC: Intel: avs: Add support for MalibouLake
# good: [f0703ce627a25b4a1307d8a92cfd6d6bf7e27e7a] ASoC: cpcap: Implement jack headset detection
# good: [5585e342e8d38cc598279bdb87f235f8b954dd5a] cxl/memdev: Remove unused partition values
# good: [f2d161e5804d8da070988624b9edd179ef31b478] ASoC: and adn use snd_soc_ret()
# good: [6b8f162bd3fa82c3c1b3653100d04172c1dbd8a5] ASoC: SOF: Improve the spcm and ipc4 copier prints
# good: [46ab7d80ed4f378e02cb249bd49a76026a2d683f] Add static channel mapping between soundwire master
# good: [cb161c333927142818d6bf22a4da2b023fb2b8c9] ASoC: tas2781: Switch to use %ptTsr
# good: [96dd187c93afe0ae0535276a92ed488759ace5a2] This is continued work on Samsung S9(SM-9600)
# good: [153dbf4adad0082d030c30d20541df2b1af52db6] regmap: irq: Use one way of setting all bits in the register
# good: [861e232e15c278d6cfc5a675efe393b4838b1773] Merge branch 'for-6.15/fw-first-error-logging' into cxl-for-next
# good: [5ea46b4360791345bd0bf4c7bf8fff5151374ea1] ASoC: SOF: ipc4-pcm: Move out be_rate initialization from for loop in fixup
# good: [0e9a970d7b2cb98d741bc0e32ad8c8f30c009c63] ASoC: qcom: sdw: Add get and set channel maps support from codec to cpu dais
# good: [0a7c85b516830c0bb088b0bdb2f2c50c76fc531a] regulator: ad5398: Fix incorrect power down bit mask
# good: [315c2f0b53ba2645062627443a12cea73f3dad9c] acpi/ghes, cper: Recognize and cache CXL Protocol errors
# good: [2466b62268c020606d20b45e007c166399e639ee] ASoC: dapm: unexport dapm_mark_endpoints_dirty()
# good: [583348bd65ceaf4a5067a6267dd236929e1b4b37] ASoC: SOF: ipc4-topology: Improve the information in prepare_copier prints
# good: [ecfcee245cc99def0f6bf84ac75ac372f8ab65eb] ASoC: dapm: unexport snd_soc_dapm_init()
# good: [a0ef5b4b101424b8a666ed56bf1717dafe2d37f5] ASoC: simple-card: use snd_soc_ret()
# good: [4c7518062d638837cea915e0ffe30f846780639a] ASoC: SOF: ipc4: Add support for split firmware releases
# good: [3f78762d17701f0435ad958b2821dc3243ff34b3] ASoC: dapm: unexport snd_soc_dapm_update_dai()
# good: [9bbbf33a5ab84c0f3643f43350b0f473b60af5b8] spi: gpio: Enable a single always-selected device
# good: [062b7ef6b103dcbcb3c084e8ace8e74e260b2346] ASoC: soc-utils: care -EOPNOTSUPP on snd_soc_ret()
# good: [c06c4f7cbea1d8dc71485bfddef2849a1b721e67] ASoC: codecs: wcd937x: Add static channel mapping support in wcd937x-sdw
# good: [943116ba2a6ab472e8ad2d1e57a3f10f13485cc2] ASoC: add common snd_soc_ret() and use it
# good: [7796c97df6b1b2206681a07f3c80f6023a6593d5] soundwire: qcom: Add set_channel_map api support
# good: [78e66dd5f32a1a8e5ee6decadd4e4dffa7d2c40d] ASoC: mediatek: mt8186: Remove unused mt8186_afe_(suspend|resume)_clock
# good: [61eac5f7f6439e8fe99b5fb29406acb0fd7b83c6] efi/cper, cxl: Remove cper_cxl.h
# good: [860693187c597645b28a421d8acb26428b8afd3f] ASoC: SOF: pcm: Add snd_sof_pcm specific wrappers for dev_dbg() and dev_err()
# good: [2d7395b23dbf4c2d60be49b73e4c4705fc446662] ASoC: simple-card-utils: use snd_soc_ret()
# good: [be61cd4242e4a53f5cf989ee7573121d041444bc] ASoC: soc-pcm: use snd_soc_ret()
# good: [72826381215e2f9d2bd2f32f63f76a80942b7fdf] ASoC: dt-bindings: wcd937x-sdw: Add static channel mapping support
# good: [4d2ea16576c8aa1437048cf436bff85653f139fe] ASoC: SOF: pcm: Move period/buffer configuration print after platform open
# good: [169ec0a541aac8afb215ab591b0fd53276686014] ASoC: SOF: Relocate and rework functionality for PCM stream freeing
# good: [74a0ca4c7f19f1b273d665b3b53f7ae8af879658] ASoC: audio-graph-card: use snd_soc_ret()
# good: [8d83282e53185ec257a4ce08812e8fabee2c7212] ASoC: audio-graph-card2: use snd_soc_ret()
# good: [43ca2463df9de2c192b03a0f4dc964e6ba7d7993] cxl: Refactor user ioctl command path from mds to mailbox
# good: [b3d993c7566fed1c027c5c18f3ef482ba8e6307a] ASoC: amd: acp: Use str_low_high() helper function
# good: [215705db51eb23052c73126d2efb6acbc2db0424] spi: Replace custom fsleep() implementation
# good: [c108905a7423d44237d17374f845fc5bb9cb9728] spi: gpio: Remove stale documentation part
# good: [185ac20a7b055e025027d303b63dab456b4f5d5e] ASoC: rt722: get lane mapping property
# good: [3f75771987f32a9f512c8944e70e343f8c6d71c1] ASoC: SOF: mediatek: Use str_on_off() helper function
# good: [6603c5133daadbb3277fbd93be0d0d5b8ec928e8] ASoC: dt-bindings: atmel,at91-ssc: Convert to YAML format
# good: [678681828bf4abfd3c31f36390d2097682141d11] ASoC: dmic: Add DSD big endian format support
# good: [25fac20edd09b60651eabcc57c187b1277f43d08] spi: gpio: Support a single always-selected device
# good: [991d98f17d31644826977e49477544987000a08a] cxl: Make cxl_dpa_alloc() DPA partition number agnostic
# good: [78d9ee370ed33cd8b662981fe1f47cff7b4f0e43] dt-bindings: eeprom: at24: Add compatible for Puya P24C64F
# good: [e27c125040b1e1f26d910b46daabbe55e67fdf3b] ASoC: codecs: wcd934x: use wcd934x binding header
# good: [c2a756660324fceca26780a50950e6d91dfdc210] counter: ti-eqep: add direction support
# good: [8478dadc8148af311c3d43d4867cfb6632686ede] ASoC: dt-bindings: Add bindings for WCD934x DAIs
# good: [e3cd85963a20d2b92e77046a8d9f0777815f1f71] x86/mtrr: Use str_enabled_disabled() helper in print_mtrr_state()
# good: [652ffad172d089acb1a20e5fde1b66e687832b06] spi: fsi: Batch TX operations
# good: [b2f10aa2eb18d289e48097e0ed973e714322175b] x86/entry: Add __init to ia32_emulation_override_cmdline()
# good: [fb6ec1d27608c008bfe1ab0dfec3720990eb2451] ASoC: mediatek: mt6358: Remove unused functions
# good: [1a4a5a752fcd60797ed2cb7c06253c6433d13f63] ASoC: soc-ops: remove soc-dpcm.h
# good: [e92f042642aed6f6206caace892d9df2d0166841] ASoC: codecs: pcm3168a: Relax probing conditions
# good: [4a91fe4c0d683c56044579fb263c660f5d18efac] ASoC: tegra: Add interconnect support
# good: [79ebb596201c86712fe38b0ef73d25d07b932664] ASoC: Intel: avs: Add pcm3168a machine board
# good: [f0173cbe7fa79eafbdf32eed32337209f84ddacd] ASoC: Intel: avs: New gateway configuration mechanism
# good: [cbe37a4d2b3c25d2e2a94097e09b6d87461b8833] ASoC: Intel: avs: Configure basefw on TGL-based platforms
# good: [320155a61f7fc810a915644e9e2a451bdcea90b1] ASoC: Intel: avs: Remove unused gateway configuration code
# good: [e995c51903384be1c7aead246dc30cb5244179ac] ASoC: Intel: avs: Move DSP-boot steps into individual functions
# good: [7d92a38d67e5d937b64b20aa4fd14451ee1772f3] ASoC: codecs: pcm3168a: Allow for 24-bit in provider mode
# good: [6eab7034579917f207ca6d8e3f4e11e85e0ab7d5] ASoC: soc-core: Stop using of_property_read_bool() for non-boolean properties
# good: [856366dc924a9561dae39f252b45dfd6cc6895ce] ALSA: hda: Select avs-driver by default on MBL
# good: [3c32a4386909e8023b3c49253fec33d267be16bb] regulator: Add device tree support to AD5398
# good: [299ce4beaf714abe76e3ad106f2e745748f693e9] ASoC: rt722-sdca: Make use of new expanded MBQ regmap
# good: [a05143a8f713d9ae6abc41141dac52c66fca8b06] ASoC: SOF: topology: Use krealloc_array() to replace krealloc()
# good: [26a756fc10fac6f133ef47f12362a39769dfe24d] spi: zynqmp-gqspi: Clean up the driver a bit
# good: [dc561ab16d8be9cbe8f07a49a7b2f5428fbcfeea] ASoC: codecs: pcm3168a: Add ACPI match table
# good: [c9e9aa80022c6db71bc097a621a6145f39aa0ade] ASoC: mediatek: Remove unused mtk_memif_set_rate
# good: [b9fb91692af881736f8fa1741fa0dbadf07d99ee] ASoC: Intel: avs: pcm3168a board selection
# good: [4343af66b8e1df1d3a2e6f1f8612506cb45b2afd] ASoC: Intel: avs: Add WHM module support
# good: [f9a5c4b6afc79073491acdab7f1e943ee3a19fbb] ASoC: rt722-sdca: Add some missing readable registers
# good: [b5ec74c2aec76fbdff9bc16951455602e11902bf] arm64: dts: imx8mp-skov-reva: Use hardware signal for SD card VSELECT
# good: [c73be62caabbec6629689c705aea65e5ce364d5d] Revert "regulator: pca9450: Add SD_VSEL GPIO for LDO5"
# good: [9b32c86e40da792544c53076f5ec43f115e56687] spi: zynqmp-gqspi: Clean up fillgenfifo
# good: [d61009bd578ee7381a3cce5c506190ecb8f9d6e8] spi: zynqmp-gqspi: Reformat long line
# good: [7ed1b265021dd13ce5619501b388e489ddc8e204] ASoC: cpcap: Implement jack detection
# good: [c1ac98492d1584d31f335d233a5cd7a4d4116e5a] spi: realtek-rtl-snand: Drop unneeded assignment for cache_type
# good: [5a6a461079decea452fdcae955bccecf92e07e97] regulator: ad5398: Add device tree support
# good: [d2ead60d853189f8e5ec6b301fac1e60e0b4b47d] spi: zynqmp-gqspi: Add helpers for enabling/disabling DMA
# good: [f5aab0438ef17f01c5ecd25e61ae6a03f82a4586] regulator: pca9450: Fix enable register for LDO5
# good: [19d022d67d7353f0e6e9ba255435d3de93862ac4] regulator: ad5398: change enable bit name to improve readibility
# good: [02d4a97ce30c0494ce6a614cd54d583caa0f8016] dt-bindings: mfd: motorola-cpcap: Document audio-codec interrupts
# good: [3ce6f4f943ddd9edc03e450a2a0d89cb025b165b] regulator: pca9450: Fix control register for LDO5
# good: [89785306453ce6d949e783f6936821a0b7649ee2] spi: zynqmp-gqspi: Always acknowledge interrupts
# good: [f9cbf56b0a1966d977df87d15a5bdbff2c342062] dt-bindings: regulator: pca9450: Add properties for handling LDO5
# good: [5b4288792ff246cf2bda0c81cebcc02d1f631ca3] ASoC: cpcap: Implement .set_bias_level
# good: [995cf0e014b0144edf1125668a97c252c5ab775e] regmap: Reorder 'struct regmap'
# good: [ba54629287f58b22c1d37f80f1875373e4b51ea6] spi: zynqmp-gqspi: Add some more debug prints
# good: [aefadf03b3e319fe5c406a6e41a9eecd90ac423c] ipe: policy_fs: fix kernel-doc warnings
# good: [3566784817aeb1a733c95953998a29adc386d2ff] drm/i915/display: Update DBUF_TRACKER_STATE_SERVICE only on appropriate platforms
# good: [589c30de062eb4029f84ba4064209b4db153ac95] Merge branch 'for-6.14/intel-thc' into for-next
# good: [9fbf78b6d6cecc2e9833c2f74eb2edc027c9b4cb] Merge branch 'for-6.12/trivial' into for-next
# good: [5dcf8655cc80a48065ba0a224e794106c147c14b] Merge branch 'for-6.11/trivial' into for-next
# good: [7e17e80c3a7eb2734795f66ba946f933412d597f] Merge branch 'for-6.14/stack-order' into for-next
# good: [9871e6af43db3892811f5a4ed0ed2e2d7cf6cf3c] Merge branch 'for-6.11/sysfs-patch-replace' into for-next
git bisect start '8936cec5cb6e27649b86fabf383d7ce4113bba49' '67961d4f4e34f5ed1aeebab08f42c2e706837ec5' 'd1a09c610027e446ed30c21f61c2f2443bf92a3f' 'a78f244a9150da0878a37a1b59fb0608b1ccfb9d' 'b20be2c77ce5341ded1a2d8aec119f6dca8ef1ad' '5d9fca12f54d3e25e02521aa8f3ec5d53759b334' '3f02dedf1566858736f351a8d4a3ce91375e48f1' '0770b7cc095e015af302f0758d3d85c7f17c719a' 'e0f421d73053eaeb441aa77054b75992705656c7' '5c7e4c4da8586d2ef55a11a9f4df626b8ea9a146' '783db6851c1821d8b983ffb12b99c279ff64f2ee' '9f25b6f2568d50c247a8e3b031a0a5caee8c17d2' '9dc016eaba3a70febcd1db5f1a0beeb7430166aa' 'e08fe24c34d37d00e84009f2fb4c35f5978041e6' '1c3b5f37409682184669457a5bdf761268eafbe5' 'f37f1748564ac51d32f7588bd7bfc99913ccab8e' '7e1caa679686dde5c24d60b139f234568045758f' 'd64c4c3d1c578f98d70db1c5e2535b47adce9d07' '40b1f89a1691c4b7740bec2c868f1e4c60346353' '42da18e62652b58ba5ecd1524c146b202cda9bb7' '3aebbcba4baaa81bc8c83f2229ed8e774cf40618' '1248d29464cc682c2a1793cfc5d4ebeb374c6738' '7f1186a8d738661b941b298fd6d1d5725ed71428' '238c863eb3d3c6ed58493bacfd1f4b36bdcfa92f' '0c4a06395156d16ea33e959fccea84e4cfec04c4' '08a66f55f7246d477b19620a953476dfc02beefc' '257a060fe219bb0dcb98f12ce34f04eca6d08352' '11c1967f1a796bf2ff56a7118147f1d39d9f5ee0' '994719ed6d81a6f4677875ab6730254c0bc484ea' 'ae575d2145d1a2c8bb5d2835d7d54751f3b0bace' '828c0aa63706410503526d0ee522b9ac3232c86b' '74e0fcbd705d4277267311f8f26a00bb8ce93820' 'f22ba3561daa792dd138ed543e0bf48efe0b999c' 'ad0fbcebb5f6e093d433a0873758a2778d747eb8' 'c6bb909b8f11b9403715a325b51c2bcf01e2bbc0' 'e957c96455e8f4c630d5e374312cad0633ca7e17' 'd795a052b0ddad3da83dda6ff522c1b1aaa4a525' '91931af18bd22437e08e2471f5484d6fbdd8ab93' 'ff4d4158ef9143327a42f7be4298751cb0d1be69' 'fcd7ace9a725ae034ff9f24cb94c9fe12a1f02da' '21aa330fec31bb530a4ef6c9555fb157d0711112' 'e97d06cb4386af4e069a2dc713de70500538d0bd' 'ad1212a9cc24b740b2711014933fac6ace32aa2d' 'd1541caab053cf94b114582a23b51a8cb90f4a46' 'f46eb2bfb878ce3345725252f77fa3ba36a0f087' 'c5528214c7c0a753c908a7b353309ba665985fb4' '2c17e9ea0caa5555e31e154fa1b06260b816f5cc' '3c331bdeececb629669961a80c0f929301c088d2' '93354d866ac44d0f9d65b2e4adb5cc9a1c1912c9' '330cbb40bb3664a18a19760bd6dc6003d6624041' '2f9523091a97abf8584a79ed406fd8ffe9063ec0' '651e0ed391b148f83afba0bfbd8a56e38e58c34d' '005859a2cf7aa349fbbfe433ab1769b15c535b72' '563e40153a56cbfae8721f9591022df5d930f939' '700a281905f2a4ccf6f3b2d3cd6985e034b4b021' '629dd55cf77bd3a8f80049150d3c05fef6d3b468' 'd7231be4b4657e5f922a4c6dc11e8dffc71fee87' 'd920908fe36c2b3a1c6fe444831e0c8c2a995fd1' '07e3e514dd385300bd08da4a8df09240d272821e' '645753d01356ff1a756812f1c69c53eb5c9081cd' 'f98d42000216677d177384f202ff1cc896a7395f' '5a19e1985d014fab9892348f6175a19143cec810' '896530b7b0c08ee8b3296d5f012bfe1b0a979b86' '19f6748abbab8523a7b32a5e371e39d4d8d4aba5' '9ee6d50ae4b0fe14ed70a5265a05874d41e10848' 'f87c2a275033120e15213f3d65234d98e726c4b7' 'ebb398ae1e052c4245b7bcea679fe073111db2ce' '8e02d188698851436f76038ea998b726193d1b10' '5c93b20f6de4478e1fbcfb38eb46738bca74180e' '42b144cb6a2d87385fa0b124c975d6cf1e3ec630' 'e1101373df5cd7672d988bb4e9cdd5eb97003165' 'e80b8e5c53c30df1cba45258d10b04872b7eea67' '9da195880f167ab7c2d595388decf783c9920121' '83f37ba7b76ab17e029ab4127ec64ccccce64c00' '45e02edd8422b6c4a511f38403dbd805cd139733' '6cf5df1040ba0694aea6a5edc6f31811a442ea36' '64fb5af1d1bbcf1b808e9bb092b22fa1b691ae63' '996bf834d0b61cb5a1389356c1ed7db1230139d7' 'd0252b0b945ec67fd09fc764dcadf445fb7757ee' '187150671d83324f1ca56f7ab5e00f16a3b9f2a9' 'fcb754602724fa2a1d0db72f13ddc3ef0306f911' '43d6140cedad9f031b47dfde6f85856e007b3f04' '31e3100d5e1fe69f944f84867be0cbfa5fd380c8' '491628388005a26c02d6827e649284357daec213' '1c35755f46423150e19ff57448786b4bb48fdb46' '0b6914a0121b4c9fc8f575b60a5dd43b74612908' '0eb8f83c055cb3461734710d1b1ce2dd4f01806e' '852c0b7204ded184924c41ab99b2ac7a70ad4dab' '3898b189079c85735f57759b0d407518c01c745e' 'c878d5c1a525b88807d9d79888fe8340bcbf1aa3' '4b36a47e2d989b98953dbfb1e97da0f0169f5086' 'fde277dbcf53be685d0b9976d636366c80a74da8' '91f505dc3a94c04421a2a51e8c40acf7ea67ecbc' '552f66c40134542f15d4302837e7d581a0b8e217' '638ad2bdb2f994c8bd99cc40e0c4796a8617ccf3' '4bb5b6f13fd83b32c8a93fbd399e7558415d1ce0' 'e2ceac2f323625632f12dd5333092976298a0cde' '0fa0843db17ccd427fc7a23d313aafa88fc89e04' '7c0ea26c57b0bb72d503fe27d6533f5addc5e3a3' 'f1e91acacf86fb2cd7478af490326cb9aa63e8ae' '0a27b2d7a224326fab543ca586d501fe1857b655' '6547577e94ae3d9f8ff30d3267fe7ec394e3b20d' '605aab3b3ca83f58681841b2dd16d4a7baefde6c' '4516be370ced14c4fb454fd6cc016e47bffe109e' 'db746fff89a14419379226ce0df8b94f472cf38c' 'a23ff143804d3b8c27157ffa19e48b4e22939115' 'f0703ce627a25b4a1307d8a92cfd6d6bf7e27e7a' '5585e342e8d38cc598279bdb87f235f8b954dd5a' 'f2d161e5804d8da070988624b9edd179ef31b478' '6b8f162bd3fa82c3c1b3653100d04172c1dbd8a5' '46ab7d80ed4f378e02cb249bd49a76026a2d683f' 'cb161c333927142818d6bf22a4da2b023fb2b8c9' '96dd187c93afe0ae0535276a92ed488759ace5a2' '153dbf4adad0082d030c30d20541df2b1af52db6' '861e232e15c278d6cfc5a675efe393b4838b1773' '5ea46b4360791345bd0bf4c7bf8fff5151374ea1' '0e9a970d7b2cb98d741bc0e32ad8c8f30c009c63' '0a7c85b516830c0bb088b0bdb2f2c50c76fc531a' '315c2f0b53ba2645062627443a12cea73f3dad9c' '2466b62268c020606d20b45e007c166399e639ee' '583348bd65ceaf4a5067a6267dd236929e1b4b37' 'ecfcee245cc99def0f6bf84ac75ac372f8ab65eb' 'a0ef5b4b101424b8a666ed56bf1717dafe2d37f5' '4c7518062d638837cea915e0ffe30f846780639a' '3f78762d17701f0435ad958b2821dc3243ff34b3' '9bbbf33a5ab84c0f3643f43350b0f473b60af5b8' '062b7ef6b103dcbcb3c084e8ace8e74e260b2346' 'c06c4f7cbea1d8dc71485bfddef2849a1b721e67' '943116ba2a6ab472e8ad2d1e57a3f10f13485cc2' '7796c97df6b1b2206681a07f3c80f6023a6593d5' '78e66dd5f32a1a8e5ee6decadd4e4dffa7d2c40d' '61eac5f7f6439e8fe99b5fb29406acb0fd7b83c6' '860693187c597645b28a421d8acb26428b8afd3f' '2d7395b23dbf4c2d60be49b73e4c4705fc446662' 'be61cd4242e4a53f5cf989ee7573121d041444bc' '72826381215e2f9d2bd2f32f63f76a80942b7fdf' '4d2ea16576c8aa1437048cf436bff85653f139fe' '169ec0a541aac8afb215ab591b0fd53276686014' '74a0ca4c7f19f1b273d665b3b53f7ae8af879658' '8d83282e53185ec257a4ce08812e8fabee2c7212' '43ca2463df9de2c192b03a0f4dc964e6ba7d7993' 'b3d993c7566fed1c027c5c18f3ef482ba8e6307a' '215705db51eb23052c73126d2efb6acbc2db0424' 'c108905a7423d44237d17374f845fc5bb9cb9728' '185ac20a7b055e025027d303b63dab456b4f5d5e' '3f75771987f32a9f512c8944e70e343f8c6d71c1' '6603c5133daadbb3277fbd93be0d0d5b8ec928e8' '678681828bf4abfd3c31f36390d2097682141d11' '25fac20edd09b60651eabcc57c187b1277f43d08' '991d98f17d31644826977e49477544987000a08a' '78d9ee370ed33cd8b662981fe1f47cff7b4f0e43' 'e27c125040b1e1f26d910b46daabbe55e67fdf3b' 'c2a756660324fceca26780a50950e6d91dfdc210' '8478dadc8148af311c3d43d4867cfb6632686ede' 'e3cd85963a20d2b92e77046a8d9f0777815f1f71' '652ffad172d089acb1a20e5fde1b66e687832b06' 'b2f10aa2eb18d289e48097e0ed973e714322175b' 'fb6ec1d27608c008bfe1ab0dfec3720990eb2451' '1a4a5a752fcd60797ed2cb7c06253c6433d13f63' 'e92f042642aed6f6206caace892d9df2d0166841' '4a91fe4c0d683c56044579fb263c660f5d18efac' '79ebb596201c86712fe38b0ef73d25d07b932664' 'f0173cbe7fa79eafbdf32eed32337209f84ddacd' 'cbe37a4d2b3c25d2e2a94097e09b6d87461b8833' '320155a61f7fc810a915644e9e2a451bdcea90b1' 'e995c51903384be1c7aead246dc30cb5244179ac' '7d92a38d67e5d937b64b20aa4fd14451ee1772f3' '6eab7034579917f207ca6d8e3f4e11e85e0ab7d5' '856366dc924a9561dae39f252b45dfd6cc6895ce' '3c32a4386909e8023b3c49253fec33d267be16bb' '299ce4beaf714abe76e3ad106f2e745748f693e9' 'a05143a8f713d9ae6abc41141dac52c66fca8b06' '26a756fc10fac6f133ef47f12362a39769dfe24d' 'dc561ab16d8be9cbe8f07a49a7b2f5428fbcfeea' 'c9e9aa80022c6db71bc097a621a6145f39aa0ade' 'b9fb91692af881736f8fa1741fa0dbadf07d99ee' '4343af66b8e1df1d3a2e6f1f8612506cb45b2afd' 'f9a5c4b6afc79073491acdab7f1e943ee3a19fbb' 'b5ec74c2aec76fbdff9bc16951455602e11902bf' 'c73be62caabbec6629689c705aea65e5ce364d5d' '9b32c86e40da792544c53076f5ec43f115e56687' 'd61009bd578ee7381a3cce5c506190ecb8f9d6e8' '7ed1b265021dd13ce5619501b388e489ddc8e204' 'c1ac98492d1584d31f335d233a5cd7a4d4116e5a' '5a6a461079decea452fdcae955bccecf92e07e97' 'd2ead60d853189f8e5ec6b301fac1e60e0b4b47d' 'f5aab0438ef17f01c5ecd25e61ae6a03f82a4586' '19d022d67d7353f0e6e9ba255435d3de93862ac4' '02d4a97ce30c0494ce6a614cd54d583caa0f8016' '3ce6f4f943ddd9edc03e450a2a0d89cb025b165b' '89785306453ce6d949e783f6936821a0b7649ee2' 'f9cbf56b0a1966d977df87d15a5bdbff2c342062' '5b4288792ff246cf2bda0c81cebcc02d1f631ca3' '995cf0e014b0144edf1125668a97c252c5ab775e' 'ba54629287f58b22c1d37f80f1875373e4b51ea6' 'aefadf03b3e319fe5c406a6e41a9eecd90ac423c' '3566784817aeb1a733c95953998a29adc386d2ff' '589c30de062eb4029f84ba4064209b4db153ac95' '9fbf78b6d6cecc2e9833c2f74eb2edc027c9b4cb' '5dcf8655cc80a48065ba0a224e794106c147c14b' '7e17e80c3a7eb2734795f66ba946f933412d597f' '9871e6af43db3892811f5a4ed0ed2e2d7cf6cf3c'
# bad: [8936cec5cb6e27649b86fabf383d7ce4113bba49] Add linux-next specific files for 20250219
git bisect bad 8936cec5cb6e27649b86fabf383d7ce4113bba49
# good: [4aa591507214c82976992e1810d5ac121a8545d2] Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git
git bisect good 4aa591507214c82976992e1810d5ac121a8545d2
# good: [38f28c2c14f7b6a204097792474f3f3fe8f87cd4] Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
git bisect good 38f28c2c14f7b6a204097792474f3f3fe8f87cd4
# bad: [f300530bbb82416019ae01536ad40532d574bff0] Merge branch 'next' of https://github.com/kvm-x86/linux.git
git bisect bad f300530bbb82416019ae01536ad40532d574bff0
# bad: [5e8357bc3db2c901b02c62cfe7ff29831865440a] Merge branch into tip/master: 'x86/misc'
git bisect bad 5e8357bc3db2c901b02c62cfe7ff29831865440a
# good: [ce68de08a2cc95dc2cb6018a22673beed52f25c3] ASoC: fsl: imx-pcm-fiq: Switch to use hrtimer_setup()
git bisect good ce68de08a2cc95dc2cb6018a22673beed52f25c3
# bad: [4e3434bf99d811d00ece73028c77d6a81779557f] Merge branch into tip/master: 'timers/core'
git bisect bad 4e3434bf99d811d00ece73028c77d6a81779557f
# bad: [96bda1071c815489bd6678eb38670c4fec7e37ce] Merge branch into tip/master: 'irq/drivers'
git bisect bad 96bda1071c815489bd6678eb38670c4fec7e37ce
# good: [999f458c1771354371ba367dd84f55f9a62a4233] irqchip/riscv-imsic: Set irq_set_affinity() for IMSIC base
git bisect good 999f458c1771354371ba367dd84f55f9a62a4233
# bad: [213ea5f92da586fe137dfa55004ed0f7706cfae5] RISC-V: Select CONFIG_GENERIC_PENDING_IRQ
git bisect bad 213ea5f92da586fe137dfa55004ed0f7706cfae5
# bad: [44b70d9abe4c83a04804975f50fdf7c5594cb443] irqchip/riscv-imsic: Move to common MSI library
git bisect bad 44b70d9abe4c83a04804975f50fdf7c5594cb443
# bad: [1eb4e8fdac707e9e7766c6e1cd1f7cbaaee4eac4] irqchip/irq-msi-lib: Optionally set default irq_eoi()/irq_ack()
git bisect bad 1eb4e8fdac707e9e7766c6e1cd1f7cbaaee4eac4
# first bad commit: [1eb4e8fdac707e9e7766c6e1cd1f7cbaaee4eac4] irqchip/irq-msi-lib: Optionally set default irq_eoi()/irq_ack()

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v6 02/10] irqchip/irq-msi-lib: Optionally set default irq_eoi/irq_ack
  2025-02-19 14:41   ` Mark Brown
@ 2025-02-20 13:54     ` Thomas Gleixner
  2025-02-20 14:21       ` Thomas Gleixner
  0 siblings, 1 reply; 18+ messages in thread
From: Thomas Gleixner @ 2025-02-20 13:54 UTC (permalink / raw)
  To: Mark Brown, Anup Patel
  Cc: Ingo Molnar, Borislav Petkov, Dave Hansen, x86, hpa, Marc Zyngier,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Palmer Dabbelt,
	Paul Walmsley, Atish Patra, Andrew Jones, Sunil V L, Anup Patel,
	linux-riscv, linux-arm-kernel, linux-kernel, imx

On Wed, Feb 19 2025 at 14:41, Mark Brown wrote:
> On Mon, Feb 17, 2025 at 02:26:48PM +0530, Anup Patel wrote:
> I'm seeing boot regressions with qemu on arm64 in -next which bisect
> down to this patch.  We hit a NULL pointer dereference:
>
> <6>[    0.898900] virtio_blk virtio1: 1/0/0 default/read/poll queues
> <5>[    0.910197] virtio_blk virtio1: [vda] 3906250 512-byte logical blocks (2.00 GB/1.86 GiB)
> <1>[    0.924459] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
> <1>[    0.924508] Mem abort info:
> <1>[    0.924521]   ESR = 0x000000008600002b
> <1>[    0.924559]   EC = 0x21: IABT (current EL), IL = 32 bits
> <1>[    0.924580]   SET = 0, FnV = 0
> <1>[    0.924597]   EA = 0, S1PTW = 0
> <1>[    0.924616]   FSC = 0x2b: level -1 translation fault
> <1>[    0.924667] [0000000000000000] user address but active_mm is swapper
> <0>[    0.924833] Internal error: Oops: 000000008600002b [#1] PREEMPT
> SMP

Uuurg. I wish I had double checked that the final submitted patch covers
_ALL_ incarnations of this. The below delta patch should address it.

Thanks,

        tglx
---
diff --git a/drivers/irqchip/irq-gic-v3-its-msi-parent.c b/drivers/irqchip/irq-gic-v3-its-msi-parent.c
index e150365fbe89..bdb04c808148 100644
--- a/drivers/irqchip/irq-gic-v3-its-msi-parent.c
+++ b/drivers/irqchip/irq-gic-v3-its-msi-parent.c
@@ -203,6 +203,7 @@ static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
 const struct msi_parent_ops gic_v3_its_msi_parent_ops = {
 	.supported_flags	= ITS_MSI_FLAGS_SUPPORTED,
 	.required_flags		= ITS_MSI_FLAGS_REQUIRED,
+	.chip_flags		= MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK,
 	.bus_select_token	= DOMAIN_BUS_NEXUS,
 	.bus_select_mask	= MATCH_PCI_MSI | MATCH_PLATFORM_MSI,
 	.prefix			= "ITS-",
diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c
index 3fe870f8ee17..3e1d8a1cda5e 100644
--- a/drivers/irqchip/irq-gic-v3-mbi.c
+++ b/drivers/irqchip/irq-gic-v3-mbi.c
@@ -201,6 +201,7 @@ static bool mbi_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
 static const struct msi_parent_ops gic_v3_mbi_msi_parent_ops = {
 	.supported_flags	= MBI_MSI_FLAGS_SUPPORTED,
 	.required_flags		= MBI_MSI_FLAGS_REQUIRED,
+	.chip_flags		= MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK,
 	.bus_select_token	= DOMAIN_BUS_NEXUS,
 	.bus_select_mask	= MATCH_PCI_MSI | MATCH_PLATFORM_MSI,
 	.prefix			= "MBI-",
diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c
index bd337ecddb40..9c62108b3ad5 100644
--- a/drivers/irqchip/irq-loongson-pch-msi.c
+++ b/drivers/irqchip/irq-loongson-pch-msi.c
@@ -146,6 +146,7 @@ static const struct irq_domain_ops pch_msi_middle_domain_ops = {
 static struct msi_parent_ops pch_msi_parent_ops = {
 	.required_flags		= PCH_MSI_FLAGS_REQUIRED,
 	.supported_flags	= PCH_MSI_FLAGS_SUPPORTED,
+	.chip_flags		= MSI_CHIP_FLAG_SET_EOI | MSI_CHIP_FLAG_SET_ACK,
 	.bus_select_mask	= MATCH_PCI_MSI,
 	.bus_select_token	= DOMAIN_BUS_NEXUS,
 	.prefix			= "PCH-",





^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v6 02/10] irqchip/irq-msi-lib: Optionally set default irq_eoi/irq_ack
  2025-02-20 13:54     ` Thomas Gleixner
@ 2025-02-20 14:21       ` Thomas Gleixner
  0 siblings, 0 replies; 18+ messages in thread
From: Thomas Gleixner @ 2025-02-20 14:21 UTC (permalink / raw)
  To: Mark Brown, Anup Patel
  Cc: Ingo Molnar, Borislav Petkov, Dave Hansen, x86, hpa, Marc Zyngier,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Andrew Lunn,
	Gregory Clement, Sebastian Hesselbarth, Palmer Dabbelt,
	Paul Walmsley, Atish Patra, Andrew Jones, Sunil V L, Anup Patel,
	linux-riscv, linux-arm-kernel, linux-kernel, imx

On Thu, Feb 20 2025 at 14:54, Thomas Gleixner wrote:
> On Wed, Feb 19 2025 at 14:41, Mark Brown wrote:
>> On Mon, Feb 17, 2025 at 02:26:48PM +0530, Anup Patel wrote:
>> I'm seeing boot regressions with qemu on arm64 in -next which bisect
>> down to this patch.  We hit a NULL pointer dereference:
>>
>> <6>[    0.898900] virtio_blk virtio1: 1/0/0 default/read/poll queues
>> <5>[    0.910197] virtio_blk virtio1: [vda] 3906250 512-byte logical blocks (2.00 GB/1.86 GiB)
>> <1>[    0.924459] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
>> <1>[    0.924508] Mem abort info:
>> <1>[    0.924521]   ESR = 0x000000008600002b
>> <1>[    0.924559]   EC = 0x21: IABT (current EL), IL = 32 bits
>> <1>[    0.924580]   SET = 0, FnV = 0
>> <1>[    0.924597]   EA = 0, S1PTW = 0
>> <1>[    0.924616]   FSC = 0x2b: level -1 translation fault
>> <1>[    0.924667] [0000000000000000] user address but active_mm is swapper
>> <0>[    0.924833] Internal error: Oops: 000000008600002b [#1] PREEMPT
>> SMP
>
> Uuurg. I wish I had double checked that the final submitted patch covers
> _ALL_ incarnations of this. The below delta patch should address it.

I'll redo the branch accordingly.

Thanks,

         tglx


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v6 04/10] genirq: Introduce common irq_force_complete_move() implementation
  2025-02-17  8:56 ` [PATCH v6 04/10] genirq: Introduce common irq_force_complete_move() implementation Anup Patel
@ 2025-04-03 13:13   ` Frank Scheiner
  2025-04-03 15:03     ` Thomas Gleixner
  0 siblings, 1 reply; 18+ messages in thread
From: Frank Scheiner @ 2025-04-03 13:13 UTC (permalink / raw)
  To: apatel
  Cc: ajones, andrew, anup, atishp, bp, dave.hansen, gregory.clement,
	hpa, imx, kernel, linux-arm-kernel, linux-kernel, linux-riscv,
	maz, mingo, palmer, paul.walmsley, s.hauer, sebastian.hesselbarth,
	shawnguo, sunilvl, tglx, x86, linux-ia64

Hi there,

this change, specfically the introduction of irq_force_complete_move()
to `kernel/irq/migration.c`, strangely breaks our builds for the hp-sim
platform (i.e. Linux/ia64 for Ski):

```
  CC      kernel/irq/affinity.o
kernel/irq/migration.c: In function 'irq_force_complete_move':
kernel/irq/migration.c:40:72: error: 'struct irq_data' has no member named 'parent_data'
   40 |         for (struct irq_data *d = irq_desc_get_irq_data(desc); d; d = d->parent_data) {
      |                                                                        ^~
make[4]: *** [scripts/Makefile.build:207: kernel/irq/migration.o] Error 1
```

The reason seems to be that "d->parent_data" (i.e.
"irq_data.parent_data") is used unguarded in this function:

```
void irq_force_complete_move(struct irq_desc *desc)
{
    for (struct irq_data *d = irq_desc_get_irq_data(desc); d; d = d->parent_data) {
        if (d->chip && d->chip->irq_force_complete_move) {
            d->chip->irq_force_complete_move(d);
            return;
        }
    }
}
```

...but "parent_data" is only present in `include/linux/irq.h` if
`CONFIG_IRQ_DOMAIN_HIERARCHY` was selected.

```
struct irq_data {
    u32            mask;
    unsigned int        irq;
    irq_hw_number_t        hwirq;
    struct irq_common_data    *common;
    struct irq_chip        *chip;
    struct irq_domain    *domain;
#ifdef    CONFIG_IRQ_DOMAIN_HIERARCHY
    struct irq_data        *parent_data;
#endif
    void            *chip_data;
};
```

So I guess, either the requirement in `linux/include/linux/irq.h` needs
to go, or the use of "d->parent_data" or the whole of
irq_force_complete_move() and its use needs to be guarded as well.

Cheers,
Frank



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v6 04/10] genirq: Introduce common irq_force_complete_move() implementation
  2025-04-03 13:13   ` Frank Scheiner
@ 2025-04-03 15:03     ` Thomas Gleixner
  2025-04-03 17:46       ` Frank Scheiner
  0 siblings, 1 reply; 18+ messages in thread
From: Thomas Gleixner @ 2025-04-03 15:03 UTC (permalink / raw)
  To: Frank Scheiner, apatel
  Cc: ajones, andrew, anup, atishp, bp, dave.hansen, gregory.clement,
	hpa, imx, kernel, linux-arm-kernel, linux-kernel, linux-riscv,
	maz, mingo, palmer, paul.walmsley, s.hauer, sebastian.hesselbarth,
	shawnguo, sunilvl, x86, linux-ia64

On Thu, Apr 03 2025 at 15:13, Frank Scheiner wrote:
> this change, specfically the introduction of irq_force_complete_move()
> to `kernel/irq/migration.c`, strangely breaks our builds for the hp-sim
> platform (i.e. Linux/ia64 for Ski):

arch/itanic has hit the iceberg and sank with the release of v6.7...

> So I guess, either the requirement in `linux/include/linux/irq.h` needs
> to go, or the use of "d->parent_data" or the whole of
> irq_force_complete_move() and its use needs to be guarded as well.

Guessing is not a really good approach to solve a technical problem :)

Thanks,

        tglx
---
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -37,7 +37,7 @@ bool irq_fixup_move_pending(struct irq_d
 
 void irq_force_complete_move(struct irq_desc *desc)
 {
-	for (struct irq_data *d = irq_desc_get_irq_data(desc); d; d = d->parent_data) {
+	for (struct irq_data *d = irq_desc_get_irq_data(desc); d; d = irqd_get_parent_data(d)) {
 		if (d->chip && d->chip->irq_force_complete_move) {
 			d->chip->irq_force_complete_move(d);
 			return;






^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH v6 04/10] genirq: Introduce common irq_force_complete_move() implementation
  2025-04-03 15:03     ` Thomas Gleixner
@ 2025-04-03 17:46       ` Frank Scheiner
  2025-04-04 14:51         ` [PATCH] genirq/migration: Use irqd_get_parent_data() in irq_force_complete_move() Thomas Gleixner
  0 siblings, 1 reply; 18+ messages in thread
From: Frank Scheiner @ 2025-04-03 17:46 UTC (permalink / raw)
  To: Thomas Gleixner, apatel
  Cc: ajones, andrew, anup, atishp, bp, dave.hansen, gregory.clement,
	hpa, imx, kernel, linux-arm-kernel, linux-kernel, linux-riscv,
	maz, mingo, palmer, paul.walmsley, s.hauer, sebastian.hesselbarth,
	shawnguo, sunilvl, x86, linux-ia64

On 03.04.25 17:03, Thomas Gleixner wrote:
> On Thu, Apr 03 2025 at 15:13, Frank Scheiner wrote:
>> this change, specfically the introduction of irq_force_complete_move()
>> to `kernel/irq/migration.c`, strangely breaks our builds for the hp-sim
>> platform (i.e. Linux/ia64 for Ski):
>
> arch/itanic has hit the iceberg and sank with the release of v6.7...

Ha, ha, not in our waters. :-) Still I'm glad I could help finding
errors in Linux by building for ia64.


>> So I guess, either the requirement in `linux/include/linux/irq.h` needs
>> to go, or the use of "d->parent_data" or the whole of
>> irq_force_complete_move() and its use needs to be guarded as well.
>
> Guessing is not a really good approach to solve a technical problem :)

Thanks for the advice, though guessing was not involved here. It's just
a way to say that I'm not sure what the right solution might be in this
case. And then I'd rather leave such fixes to the experts in the
specific field.

> ---
> --- a/kernel/irq/migration.c
> +++ b/kernel/irq/migration.c
> @@ -37,7 +37,7 @@ bool irq_fixup_move_pending(struct irq_d
>
>  void irq_force_complete_move(struct irq_desc *desc)
>  {
> -	for (struct irq_data *d = irq_desc_get_irq_data(desc); d; d = d->parent_data) {
> +	for (struct irq_data *d = irq_desc_get_irq_data(desc); d; d = irqd_get_parent_data(d)) {
>  		if (d->chip && d->chip->irq_force_complete_move) {
>  			d->chip->irq_force_complete_move(d);
>  			return;
>

This fxes the build for me for that file. Much obliged.
```
  CC      kernel/irq/migration.o
```

Cheers,
Frank


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH] genirq/migration: Use irqd_get_parent_data() in irq_force_complete_move()
  2025-04-03 17:46       ` Frank Scheiner
@ 2025-04-04 14:51         ` Thomas Gleixner
  0 siblings, 0 replies; 18+ messages in thread
From: Thomas Gleixner @ 2025-04-04 14:51 UTC (permalink / raw)
  To: Frank Scheiner, apatel
  Cc: ajones, andrew, anup, atishp, bp, dave.hansen, gregory.clement,
	hpa, imx, kernel, linux-arm-kernel, linux-kernel, linux-riscv,
	maz, mingo, palmer, paul.walmsley, s.hauer, sebastian.hesselbarth,
	shawnguo, sunilvl, x86, linux-ia64

Frank reported, that the common irq_force_complete_move() breaks the out of
tree build of ia64. The reason is that ia64 uses the migration code, but
does not have hierarchical interrupt domains enabled.

This went unnoticed in mainline as both x86 and RISC-V have hierarchical
domains enabled. Not that it matters for mainline, but it's still
inconsistent.

Use irqd_get_parent_data() instead of accessing the parent_data field
directly. The helper returns NULL when hierarchical domains are disabled
otherwise it accesses the parent_data field of the domain.

No functional change.

Fixes: 751dc837dabd ("genirq: Introduce common irq_force_complete_move() implementation")
Reported-by: Frank Scheiner <frank.scheiner@web.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Frank Scheiner <frank.scheiner@web.de>

--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -37,7 +37,7 @@ bool irq_fixup_move_pending(struct irq_d
 
 void irq_force_complete_move(struct irq_desc *desc)
 {
-	for (struct irq_data *d = irq_desc_get_irq_data(desc); d; d = d->parent_data) {
+	for (struct irq_data *d = irq_desc_get_irq_data(desc); d; d = irqd_get_parent_data(d)) {
 		if (d->chip && d->chip->irq_force_complete_move) {
 			d->chip->irq_force_complete_move(d);
 			return;






^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2025-04-04 14:59 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-17  8:56 [PATCH v6 00/10] RISC-V IMSIC driver improvements Anup Patel
2025-02-17  8:56 ` [PATCH v6 01/10] irqchip/riscv-imsic: Set irq_set_affinity for IMSIC base Anup Patel
2025-02-17  8:56 ` [PATCH v6 02/10] irqchip/irq-msi-lib: Optionally set default irq_eoi/irq_ack Anup Patel
2025-02-19 14:41   ` Mark Brown
2025-02-20 13:54     ` Thomas Gleixner
2025-02-20 14:21       ` Thomas Gleixner
2025-02-17  8:56 ` [PATCH v6 03/10] irqchip/riscv-imsic: Move to common MSI lib Anup Patel
2025-02-17  8:56 ` [PATCH v6 04/10] genirq: Introduce common irq_force_complete_move() implementation Anup Patel
2025-04-03 13:13   ` Frank Scheiner
2025-04-03 15:03     ` Thomas Gleixner
2025-04-03 17:46       ` Frank Scheiner
2025-04-04 14:51         ` [PATCH] genirq/migration: Use irqd_get_parent_data() in irq_force_complete_move() Thomas Gleixner
2025-02-17  8:56 ` [PATCH v6 05/10] genirq: Introduce irq_can_move_in_process_context() Anup Patel
2025-02-17  8:56 ` [PATCH v6 06/10] RISC-V: Select GENERIC_PENDING_IRQ Anup Patel
2025-02-17  8:56 ` [PATCH v6 07/10] irqchip/riscv-imsic: Separate next and previous pointers in IMSIC vector Anup Patel
2025-02-17  8:56 ` [PATCH v6 08/10] irqchip/riscv-imsic: Implement irq_force_complete_move() for IMSIC Anup Patel
2025-02-17  8:56 ` [PATCH v6 09/10] irqchip/riscv-imsic: Replace hwirq with irq in the IMSIC vector Anup Patel
2025-02-17  8:56 ` [PATCH v6 10/10] irqchip/riscv-imsic: Special handling for non-atomic device MSI update Anup Patel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).