linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/12] armada-370-xp irqchip updates round 5
@ 2024-08-07 16:40 Marek Behún
  2024-08-07 16:40 ` [PATCH v2 01/12] irqchip/armada-370-xp: Drop IPI_DOORBELL_START and rename IPI_DOORBELL_END Marek Behún
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:40 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

Hi Thomas, Andrew, Ilpo et al.,

This is v2 of the last round of updates for armada-370-xp irqchip before
I send the one patch adding support for SoC Error interrupts.

I have addressed the issues pointed out by Thomas in v1, which you can
see at
  https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=871321

This series can be applied on tip/irq/core.

Marek

Marek Behún (12):
  irqchip/armada-370-xp: Drop IPI_DOORBELL_START and rename
    IPI_DOORBELL_END
  irqchip/armada-370-xp: Drop msi_doorbell_end()
  irqchip/armada-370-xp: Add the __init attribute to mpic_msi_init()
  irqchip/armada-370-xp: Put __init attribute after return type in
    mpic_ipi_init()
  irqchip/armada-370-xp: Put static variables into driver private
    structure
  irqchip/armada-370-xp: Put MSI doorbell limits into the mpic structure
  irqchip/armada-370-xp: Pass around the driver private structure
  irqchip/armada-370-xp: Dynamically allocate the driver private
    structure
  irqchip/armada-370-xp: Correct reenabling last per-CPU interrupt
  irqchip/armada-370-xp: Iterate only valid bits of the per-CPU
    interrupt cause register
  irqchip/armada-370-xp: Allow mapping only per-CPU interrupts
  irqchip/armada-370-xp: Use the mpic_is_ipi_available() helper in one
    more case

 drivers/irqchip/irq-armada-370-xp.c | 407 ++++++++++++++++------------
 1 file changed, 229 insertions(+), 178 deletions(-)

-- 
2.44.2



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

* [PATCH v2 01/12] irqchip/armada-370-xp: Drop IPI_DOORBELL_START and rename IPI_DOORBELL_END
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
@ 2024-08-07 16:40 ` Marek Behún
  2024-08-07 16:40 ` [PATCH v2 02/12] irqchip/armada-370-xp: Drop msi_doorbell_end() Marek Behún
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:40 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

Drop IPI_DOORBELL_START since it is not used and rename IPI_DOORBELL_END
to IPI_DOORBELL_NR.

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 drivers/irqchip/irq-armada-370-xp.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index b11612acec78..9a431d04ed19 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -136,8 +136,7 @@
 #define MPIC_MAX_PER_CPU_IRQS			28
 
 /* IPI and MSI interrupt definitions for IPI platforms */
-#define IPI_DOORBELL_START			0
-#define IPI_DOORBELL_END			8
+#define IPI_DOORBELL_NR				8
 #define IPI_DOORBELL_MASK			GENMASK(7, 0)
 #define PCI_MSI_DOORBELL_START			16
 #define PCI_MSI_DOORBELL_NR			16
@@ -452,7 +451,7 @@ static const struct irq_domain_ops mpic_ipi_domain_ops = {
 
 static void mpic_ipi_resume(void)
 {
-	for (irq_hw_number_t i = 0; i < IPI_DOORBELL_END; i++) {
+	for (irq_hw_number_t i = 0; i < IPI_DOORBELL_NR; i++) {
 		unsigned int virq = irq_find_mapping(mpic_ipi_domain, i);
 		struct irq_data *d;
 
@@ -468,17 +467,17 @@ static __init int mpic_ipi_init(struct device_node *node)
 {
 	int base_ipi;
 
-	mpic_ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node), IPI_DOORBELL_END,
+	mpic_ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node), IPI_DOORBELL_NR,
 						   &mpic_ipi_domain_ops, NULL);
 	if (WARN_ON(!mpic_ipi_domain))
 		return -ENOMEM;
 
 	irq_domain_update_bus_token(mpic_ipi_domain, DOMAIN_BUS_IPI);
-	base_ipi = irq_domain_alloc_irqs(mpic_ipi_domain, IPI_DOORBELL_END, NUMA_NO_NODE, NULL);
+	base_ipi = irq_domain_alloc_irqs(mpic_ipi_domain, IPI_DOORBELL_NR, NUMA_NO_NODE, NULL);
 	if (WARN_ON(!base_ipi))
 		return -ENOMEM;
 
-	set_smp_ipi_range(base_ipi, IPI_DOORBELL_END);
+	set_smp_ipi_range(base_ipi, IPI_DOORBELL_NR);
 
 	return 0;
 }
@@ -627,7 +626,7 @@ static void mpic_handle_ipi_irq(void)
 	cause = readl_relaxed(per_cpu_int_base + MPIC_IN_DRBEL_CAUSE);
 	cause &= IPI_DOORBELL_MASK;
 
-	for_each_set_bit(i, &cause, IPI_DOORBELL_END)
+	for_each_set_bit(i, &cause, IPI_DOORBELL_NR)
 		generic_handle_domain_irq(mpic_ipi_domain, i);
 }
 #else
-- 
2.44.2



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

* [PATCH v2 02/12] irqchip/armada-370-xp: Drop msi_doorbell_end()
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
  2024-08-07 16:40 ` [PATCH v2 01/12] irqchip/armada-370-xp: Drop IPI_DOORBELL_START and rename IPI_DOORBELL_END Marek Behún
@ 2024-08-07 16:40 ` Marek Behún
  2024-08-07 16:40 ` [PATCH v2 03/12] irqchip/armada-370-xp: Add the __init attribute to mpic_msi_init() Marek Behún
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:40 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

Drop the msi_doorbell_end() function and related constants, it is not
used anymore.

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 drivers/irqchip/irq-armada-370-xp.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 9a431d04ed19..fcfc5f86fbff 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -140,13 +140,11 @@
 #define IPI_DOORBELL_MASK			GENMASK(7, 0)
 #define PCI_MSI_DOORBELL_START			16
 #define PCI_MSI_DOORBELL_NR			16
-#define PCI_MSI_DOORBELL_END			32
 #define PCI_MSI_DOORBELL_MASK			GENMASK(31, 16)
 
 /* MSI interrupt definitions for non-IPI platforms */
 #define PCI_MSI_FULL_DOORBELL_START		0
 #define PCI_MSI_FULL_DOORBELL_NR		32
-#define PCI_MSI_FULL_DOORBELL_END		32
 #define PCI_MSI_FULL_DOORBELL_MASK		GENMASK(31, 0)
 #define PCI_MSI_FULL_DOORBELL_SRC0_MASK		GENMASK(15, 0)
 #define PCI_MSI_FULL_DOORBELL_SRC1_MASK		GENMASK(31, 16)
@@ -190,11 +188,6 @@ static inline unsigned int msi_doorbell_size(void)
 	return mpic_is_ipi_available() ? PCI_MSI_DOORBELL_NR : PCI_MSI_FULL_DOORBELL_NR;
 }
 
-static inline unsigned int msi_doorbell_end(void)
-{
-	return mpic_is_ipi_available() ? PCI_MSI_DOORBELL_END : PCI_MSI_FULL_DOORBELL_END;
-}
-
 static inline bool mpic_is_percpu_irq(irq_hw_number_t hwirq)
 {
 	return hwirq <= MPIC_MAX_PER_CPU_IRQS;
-- 
2.44.2



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

* [PATCH v2 03/12] irqchip/armada-370-xp: Add the __init attribute to mpic_msi_init()
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
  2024-08-07 16:40 ` [PATCH v2 01/12] irqchip/armada-370-xp: Drop IPI_DOORBELL_START and rename IPI_DOORBELL_END Marek Behún
  2024-08-07 16:40 ` [PATCH v2 02/12] irqchip/armada-370-xp: Drop msi_doorbell_end() Marek Behún
@ 2024-08-07 16:40 ` Marek Behún
  2024-08-07 16:40 ` [PATCH v2 04/12] irqchip/armada-370-xp: Put __init attribute after return type in mpic_ipi_init() Marek Behún
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:40 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

Add the __init attribute to the mpic_msi_init() function. It is only
called from the device initializer, and so can be dropped after boot is
complete.

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 drivers/irqchip/irq-armada-370-xp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index fcfc5f86fbff..f5a693745785 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -314,7 +314,7 @@ static void mpic_msi_reenable_percpu(void)
 	writel(1, per_cpu_int_base + MPIC_INT_CLEAR_MASK);
 }
 
-static int mpic_msi_init(struct device_node *node, phys_addr_t main_int_phys_base)
+static int __init mpic_msi_init(struct device_node *node, phys_addr_t main_int_phys_base)
 {
 	msi_doorbell_addr = main_int_phys_base + MPIC_SW_TRIG_INT;
 
-- 
2.44.2



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

* [PATCH v2 04/12] irqchip/armada-370-xp: Put __init attribute after return type in mpic_ipi_init()
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
                   ` (2 preceding siblings ...)
  2024-08-07 16:40 ` [PATCH v2 03/12] irqchip/armada-370-xp: Add the __init attribute to mpic_msi_init() Marek Behún
@ 2024-08-07 16:40 ` Marek Behún
  2024-08-07 16:40 ` [PATCH v2 05/12] irqchip/armada-370-xp: Put static variables into driver private structure Marek Behún
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:40 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

For consistency with the rest of the driver, put the __init attribute
after the return type of the mpic_ipi_init() function.

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 drivers/irqchip/irq-armada-370-xp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index f5a693745785..07004ecec165 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -456,7 +456,7 @@ static void mpic_ipi_resume(void)
 	}
 }
 
-static __init int mpic_ipi_init(struct device_node *node)
+static int __init mpic_ipi_init(struct device_node *node)
 {
 	int base_ipi;
 
-- 
2.44.2



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

* [PATCH v2 05/12] irqchip/armada-370-xp: Put static variables into driver private structure
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
                   ` (3 preceding siblings ...)
  2024-08-07 16:40 ` [PATCH v2 04/12] irqchip/armada-370-xp: Put __init attribute after return type in mpic_ipi_init() Marek Behún
@ 2024-08-07 16:40 ` Marek Behún
  2024-08-07 16:40 ` [PATCH v2 06/12] irqchip/armada-370-xp: Put MSI doorbell limits into the mpic structure Marek Behún
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:40 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

In preparation for converting the driver to modern style put all the
interrupt controller private static variables into driver private
structure.

Access to these variables changes as:
  main_int_base		mpic->base
  per_cpu_int_base	mpic->per_cpu
  mpic_domain		mpic->domain
  parent_irq		mpic->parent_irq
  ...

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 drivers/irqchip/irq-armada-370-xp.c | 223 +++++++++++++++-------------
 1 file changed, 122 insertions(+), 101 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 07004ecec165..00f38428d2ba 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -66,11 +66,11 @@
  *
  * The "global interrupt mask/unmask" is modified using the
  * MPIC_INT_SET_ENABLE and MPIC_INT_CLEAR_ENABLE
- * registers, which are relative to "main_int_base".
+ * registers, which are relative to "mpic->base".
  *
  * The "per-CPU mask/unmask" is modified using the MPIC_INT_SET_MASK
  * and MPIC_INT_CLEAR_MASK registers, which are relative to
- * "per_cpu_int_base". This base address points to a special address,
+ * "mpic->per_cpu". This base address points to a special address,
  * which automatically accesses the registers of the current CPU.
  *
  * The per-CPU mask/unmask can also be adjusted using the global
@@ -112,7 +112,7 @@
  *    at the per-CPU level.
  */
 
-/* Registers relative to main_int_base */
+/* Registers relative to mpic->base */
 #define MPIC_INT_CONTROL			0x00
 #define MPIC_INT_CONTROL_NUMINT_MASK		GENMASK(12, 2)
 #define MPIC_SW_TRIG_INT			0x04
@@ -122,7 +122,7 @@
 #define MPIC_INT_SOURCE_CPU_MASK		GENMASK(3, 0)
 #define MPIC_INT_IRQ_FIQ_MASK(cpuid)		((BIT(0) | BIT(8)) << (cpuid))
 
-/* Registers relative to per_cpu_int_base */
+/* Registers relative to mpic->per_cpu */
 #define MPIC_IN_DRBEL_CAUSE			0x08
 #define MPIC_IN_DRBEL_MASK			0x0c
 #define MPIC_PPI_CAUSE				0x10
@@ -149,18 +149,40 @@
 #define PCI_MSI_FULL_DOORBELL_SRC0_MASK		GENMASK(15, 0)
 #define PCI_MSI_FULL_DOORBELL_SRC1_MASK		GENMASK(31, 16)
 
-static void __iomem *per_cpu_int_base;
-static void __iomem *main_int_base;
-static struct irq_domain *mpic_domain;
-static u32 doorbell_mask_reg;
-static int parent_irq;
+/**
+ * struct mpic - MPIC private data structure
+ * @base:		MPIC registers base address
+ * @per_cpu:		per-CPU registers base address
+ * @parent_irq:		parent IRQ if MPIC is not top-level interrupt controller
+ * @domain:		MPIC main interrupt domain
+ * @ipi_domain:		IPI domain
+ * @msi_domain:		MSI domain
+ * @msi_inner_domain:	MSI inner domain
+ * @msi_used:		bitmap of used MSI numbers
+ * @msi_lock:		mutex serializing access to @msi_used
+ * @msi_doorbell_addr:	physical address of MSI doorbell register
+ * @doorbell_mask:	doorbell mask of MSIs and IPIs, stored on suspend, restored on resume
+ */
+struct mpic {
+	void __iomem *base;
+	void __iomem *per_cpu;
+	int parent_irq;
+	struct irq_domain *domain;
+#ifdef CONFIG_SMP
+	struct irq_domain *ipi_domain;
+#endif
 #ifdef CONFIG_PCI_MSI
-static struct irq_domain *mpic_msi_domain;
-static struct irq_domain *mpic_msi_inner_domain;
-static DECLARE_BITMAP(msi_used, PCI_MSI_FULL_DOORBELL_NR);
-static DEFINE_MUTEX(msi_used_lock);
-static phys_addr_t msi_doorbell_addr;
+	struct irq_domain *msi_domain;
+	struct irq_domain *msi_inner_domain;
+	DECLARE_BITMAP(msi_used, PCI_MSI_FULL_DOORBELL_NR);
+	struct mutex msi_lock;
+	phys_addr_t msi_doorbell_addr;
 #endif
+	u32 doorbell_mask;
+};
+
+static struct mpic mpic_data;
+static struct mpic * const mpic = &mpic_data;
 
 static inline bool mpic_is_ipi_available(void)
 {
@@ -170,7 +192,7 @@ static inline bool mpic_is_ipi_available(void)
 	 * interrupt controller (e.g. GIC) that takes care of inter-processor
 	 * interrupts.
 	 */
-	return parent_irq <= 0;
+	return mpic->parent_irq <= 0;
 }
 
 static inline u32 msi_doorbell_mask(void)
@@ -203,9 +225,9 @@ static void mpic_irq_mask(struct irq_data *d)
 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
 	if (!mpic_is_percpu_irq(hwirq))
-		writel(hwirq, main_int_base + MPIC_INT_CLEAR_ENABLE);
+		writel(hwirq, mpic->base + MPIC_INT_CLEAR_ENABLE);
 	else
-		writel(hwirq, per_cpu_int_base + MPIC_INT_SET_MASK);
+		writel(hwirq, mpic->per_cpu + MPIC_INT_SET_MASK);
 }
 
 static void mpic_irq_unmask(struct irq_data *d)
@@ -213,9 +235,9 @@ static void mpic_irq_unmask(struct irq_data *d)
 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
 	if (!mpic_is_percpu_irq(hwirq))
-		writel(hwirq, main_int_base + MPIC_INT_SET_ENABLE);
+		writel(hwirq, mpic->base + MPIC_INT_SET_ENABLE);
 	else
-		writel(hwirq, per_cpu_int_base + MPIC_INT_CLEAR_MASK);
+		writel(hwirq, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 }
 
 #ifdef CONFIG_PCI_MSI
@@ -236,8 +258,8 @@ static void mpic_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
 {
 	unsigned int cpu = cpumask_first(irq_data_get_effective_affinity_mask(d));
 
-	msg->address_lo = lower_32_bits(msi_doorbell_addr);
-	msg->address_hi = upper_32_bits(msi_doorbell_addr);
+	msg->address_lo = lower_32_bits(mpic->msi_doorbell_addr);
+	msg->address_hi = upper_32_bits(mpic->msi_doorbell_addr);
 	msg->data = BIT(cpu + 8) | (d->hwirq + msi_doorbell_start());
 }
 
@@ -269,10 +291,10 @@ static int mpic_msi_alloc(struct irq_domain *domain, unsigned int virq, unsigned
 {
 	int hwirq;
 
-	mutex_lock(&msi_used_lock);
-	hwirq = bitmap_find_free_region(msi_used, msi_doorbell_size(),
+	mutex_lock(&mpic->msi_lock);
+	hwirq = bitmap_find_free_region(mpic->msi_used, msi_doorbell_size(),
 					order_base_2(nr_irqs));
-	mutex_unlock(&msi_used_lock);
+	mutex_unlock(&mpic->msi_lock);
 
 	if (hwirq < 0)
 		return -ENOSPC;
@@ -291,9 +313,9 @@ static void mpic_msi_free(struct irq_domain *domain, unsigned int virq, unsigned
 {
 	struct irq_data *d = irq_domain_get_irq_data(domain, virq);
 
-	mutex_lock(&msi_used_lock);
-	bitmap_release_region(msi_used, d->hwirq, order_base_2(nr_irqs));
-	mutex_unlock(&msi_used_lock);
+	mutex_lock(&mpic->msi_lock);
+	bitmap_release_region(mpic->msi_used, d->hwirq, order_base_2(nr_irqs));
+	mutex_unlock(&mpic->msi_lock);
 }
 
 static const struct irq_domain_ops mpic_msi_domain_ops = {
@@ -306,27 +328,29 @@ static void mpic_msi_reenable_percpu(void)
 	u32 reg;
 
 	/* Enable MSI doorbell mask and combined cpu local interrupt */
-	reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK);
+	reg = readl(mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 	reg |= msi_doorbell_mask();
-	writel(reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK);
+	writel(reg, mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 
 	/* Unmask local doorbell interrupt */
-	writel(1, per_cpu_int_base + MPIC_INT_CLEAR_MASK);
+	writel(1, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 }
 
 static int __init mpic_msi_init(struct device_node *node, phys_addr_t main_int_phys_base)
 {
-	msi_doorbell_addr = main_int_phys_base + MPIC_SW_TRIG_INT;
+	mpic->msi_doorbell_addr = main_int_phys_base + MPIC_SW_TRIG_INT;
+
+	mutex_init(&mpic->msi_lock);
 
-	mpic_msi_inner_domain = irq_domain_add_linear(NULL, msi_doorbell_size(),
-						      &mpic_msi_domain_ops, NULL);
-	if (!mpic_msi_inner_domain)
+	mpic->msi_inner_domain = irq_domain_add_linear(NULL, msi_doorbell_size(),
+						       &mpic_msi_domain_ops, NULL);
+	if (!mpic->msi_inner_domain)
 		return -ENOMEM;
 
-	mpic_msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), &mpic_msi_domain_info,
-						    mpic_msi_inner_domain);
-	if (!mpic_msi_domain) {
-		irq_domain_remove(mpic_msi_inner_domain);
+	mpic->msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), &mpic_msi_domain_info,
+						     mpic->msi_inner_domain);
+	if (!mpic->msi_domain) {
+		irq_domain_remove(mpic->msi_inner_domain);
 		return -ENOMEM;
 	}
 
@@ -334,7 +358,7 @@ static int __init mpic_msi_init(struct device_node *node, phys_addr_t main_int_p
 
 	/* Unmask low 16 MSI irqs on non-IPI platforms */
 	if (!mpic_is_ipi_available())
-		writel(0, per_cpu_int_base + MPIC_INT_CLEAR_MASK);
+		writel(0, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 
 	return 0;
 }
@@ -362,29 +386,26 @@ static void mpic_perf_init(void)
 	cpuid = cpu_logical_map(smp_processor_id());
 
 	/* Enable Performance Counter Overflow interrupts */
-	writel(MPIC_INT_CAUSE_PERF(cpuid),
-	       per_cpu_int_base + MPIC_INT_FABRIC_MASK);
+	writel(MPIC_INT_CAUSE_PERF(cpuid), mpic->per_cpu + MPIC_INT_FABRIC_MASK);
 }
 
 #ifdef CONFIG_SMP
-static struct irq_domain *mpic_ipi_domain;
-
 static void mpic_ipi_mask(struct irq_data *d)
 {
 	u32 reg;
 
-	reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK);
+	reg = readl(mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 	reg &= ~BIT(d->hwirq);
-	writel(reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK);
+	writel(reg, mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 }
 
 static void mpic_ipi_unmask(struct irq_data *d)
 {
 	u32 reg;
 
-	reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK);
+	reg = readl(mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 	reg |= BIT(d->hwirq);
-	writel(reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK);
+	writel(reg, mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 }
 
 static void mpic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)
@@ -403,12 +424,12 @@ static void mpic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)
 	dsb();
 
 	/* submit softirq */
-	writel((map << 8) | d->hwirq, main_int_base + MPIC_SW_TRIG_INT);
+	writel((map << 8) | d->hwirq, mpic->base + MPIC_SW_TRIG_INT);
 }
 
 static void mpic_ipi_ack(struct irq_data *d)
 {
-	writel(~BIT(d->hwirq), per_cpu_int_base + MPIC_IN_DRBEL_CAUSE);
+	writel(~BIT(d->hwirq), mpic->per_cpu + MPIC_IN_DRBEL_CAUSE);
 }
 
 static struct irq_chip mpic_ipi_irqchip = {
@@ -445,13 +466,13 @@ static const struct irq_domain_ops mpic_ipi_domain_ops = {
 static void mpic_ipi_resume(void)
 {
 	for (irq_hw_number_t i = 0; i < IPI_DOORBELL_NR; i++) {
-		unsigned int virq = irq_find_mapping(mpic_ipi_domain, i);
+		unsigned int virq = irq_find_mapping(mpic->ipi_domain, i);
 		struct irq_data *d;
 
 		if (!virq || !irq_percpu_is_enabled(virq))
 			continue;
 
-		d = irq_domain_get_irq_data(mpic_ipi_domain, virq);
+		d = irq_domain_get_irq_data(mpic->ipi_domain, virq);
 		mpic_ipi_unmask(d);
 	}
 }
@@ -460,13 +481,13 @@ static int __init mpic_ipi_init(struct device_node *node)
 {
 	int base_ipi;
 
-	mpic_ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node), IPI_DOORBELL_NR,
-						   &mpic_ipi_domain_ops, NULL);
-	if (WARN_ON(!mpic_ipi_domain))
+	mpic->ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node), IPI_DOORBELL_NR,
+						    &mpic_ipi_domain_ops, NULL);
+	if (WARN_ON(!mpic->ipi_domain))
 		return -ENOMEM;
 
-	irq_domain_update_bus_token(mpic_ipi_domain, DOMAIN_BUS_IPI);
-	base_ipi = irq_domain_alloc_irqs(mpic_ipi_domain, IPI_DOORBELL_NR, NUMA_NO_NODE, NULL);
+	irq_domain_update_bus_token(mpic->ipi_domain, DOMAIN_BUS_IPI);
+	base_ipi = irq_domain_alloc_irqs(mpic->ipi_domain, IPI_DOORBELL_NR, NUMA_NO_NODE, NULL);
 	if (WARN_ON(!base_ipi))
 		return -ENOMEM;
 
@@ -483,7 +504,7 @@ static int mpic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 	/* Select a single core from the affinity mask which is online */
 	cpu = cpumask_any_and(mask_val, cpu_online_mask);
 
-	atomic_io_modify(main_int_base + MPIC_INT_SOURCE_CTL(hwirq),
+	atomic_io_modify(mpic->base + MPIC_INT_SOURCE_CTL(hwirq),
 			 MPIC_INT_SOURCE_CPU_MASK, BIT(cpu_logical_map(cpu)));
 
 	irq_data_update_effective_affinity(d, cpumask_of(cpu));
@@ -493,27 +514,27 @@ static int mpic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 
 static void mpic_smp_cpu_init(void)
 {
-	for (irq_hw_number_t i = 0; i < mpic_domain->hwirq_max; i++)
-		writel(i, per_cpu_int_base + MPIC_INT_SET_MASK);
+	for (irq_hw_number_t i = 0; i < mpic->domain->hwirq_max; i++)
+		writel(i, mpic->per_cpu + MPIC_INT_SET_MASK);
 
 	if (!mpic_is_ipi_available())
 		return;
 
 	/* Disable all IPIs */
-	writel(0, per_cpu_int_base + MPIC_IN_DRBEL_MASK);
+	writel(0, mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 
 	/* Clear pending IPIs */
-	writel(0, per_cpu_int_base + MPIC_IN_DRBEL_CAUSE);
+	writel(0, mpic->per_cpu + MPIC_IN_DRBEL_CAUSE);
 
 	/* Unmask IPI interrupt */
-	writel(0, per_cpu_int_base + MPIC_INT_CLEAR_MASK);
+	writel(0, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 }
 
 static void mpic_reenable_percpu(void)
 {
 	/* Re-enable per-CPU interrupts that were enabled before suspend */
 	for (irq_hw_number_t i = 0; i < MPIC_MAX_PER_CPU_IRQS; i++) {
-		unsigned int virq = irq_linear_revmap(mpic_domain, i);
+		unsigned int virq = irq_linear_revmap(mpic->domain, i);
 		struct irq_data *d;
 
 		if (!virq || !irq_percpu_is_enabled(virq))
@@ -542,7 +563,7 @@ static int mpic_cascaded_starting_cpu(unsigned int cpu)
 {
 	mpic_perf_init();
 	mpic_reenable_percpu();
-	enable_percpu_irq(parent_irq, IRQ_TYPE_NONE);
+	enable_percpu_irq(mpic->parent_irq, IRQ_TYPE_NONE);
 
 	return 0;
 }
@@ -571,9 +592,9 @@ static int mpic_irq_map(struct irq_domain *h, unsigned int virq,
 
 	mpic_irq_mask(irq_get_irq_data(virq));
 	if (!mpic_is_percpu_irq(hwirq))
-		writel(hwirq, per_cpu_int_base + MPIC_INT_CLEAR_MASK);
+		writel(hwirq, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 	else
-		writel(hwirq, main_int_base + MPIC_INT_SET_ENABLE);
+		writel(hwirq, mpic->base + MPIC_INT_SET_ENABLE);
 	irq_set_status_flags(virq, IRQ_LEVEL);
 
 	if (mpic_is_percpu_irq(hwirq)) {
@@ -598,12 +619,12 @@ static void mpic_handle_msi_irq(void)
 	unsigned long cause;
 	unsigned int i;
 
-	cause = readl_relaxed(per_cpu_int_base + MPIC_IN_DRBEL_CAUSE);
+	cause = readl_relaxed(mpic->per_cpu + MPIC_IN_DRBEL_CAUSE);
 	cause &= msi_doorbell_mask();
-	writel(~cause, per_cpu_int_base + MPIC_IN_DRBEL_CAUSE);
+	writel(~cause, mpic->per_cpu + MPIC_IN_DRBEL_CAUSE);
 
 	for_each_set_bit(i, &cause, BITS_PER_LONG)
-		generic_handle_domain_irq(mpic_msi_inner_domain,
+		generic_handle_domain_irq(mpic->msi_inner_domain,
 					  i - msi_doorbell_start());
 }
 #else
@@ -616,11 +637,11 @@ static void mpic_handle_ipi_irq(void)
 	unsigned long cause;
 	irq_hw_number_t i;
 
-	cause = readl_relaxed(per_cpu_int_base + MPIC_IN_DRBEL_CAUSE);
+	cause = readl_relaxed(mpic->per_cpu + MPIC_IN_DRBEL_CAUSE);
 	cause &= IPI_DOORBELL_MASK;
 
 	for_each_set_bit(i, &cause, IPI_DOORBELL_NR)
-		generic_handle_domain_irq(mpic_ipi_domain, i);
+		generic_handle_domain_irq(mpic->ipi_domain, i);
 }
 #else
 static inline void mpic_handle_ipi_irq(void) {}
@@ -635,11 +656,11 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc)
 
 	chained_irq_enter(chip, desc);
 
-	cause = readl_relaxed(per_cpu_int_base + MPIC_PPI_CAUSE);
+	cause = readl_relaxed(mpic->per_cpu + MPIC_PPI_CAUSE);
 	cpuid = cpu_logical_map(smp_processor_id());
 
 	for_each_set_bit(i, &cause, BITS_PER_LONG) {
-		irqsrc = readl_relaxed(main_int_base + MPIC_INT_SOURCE_CTL(i));
+		irqsrc = readl_relaxed(mpic->base + MPIC_INT_SOURCE_CTL(i));
 
 		/* Check if the interrupt is not masked on current CPU.
 		 * Test IRQ (0-1) and FIQ (8-9) mask bits.
@@ -652,7 +673,7 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc)
 			continue;
 		}
 
-		generic_handle_domain_irq(mpic_domain, i);
+		generic_handle_domain_irq(mpic->domain, i);
 	}
 
 	chained_irq_exit(chip, desc);
@@ -664,14 +685,14 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs)
 	u32 irqstat;
 
 	do {
-		irqstat = readl_relaxed(per_cpu_int_base + MPIC_CPU_INTACK);
+		irqstat = readl_relaxed(mpic->per_cpu + MPIC_CPU_INTACK);
 		i = FIELD_GET(MPIC_CPU_INTACK_IID_MASK, irqstat);
 
 		if (i > 1022)
 			break;
 
 		if (i > 1)
-			generic_handle_domain_irq(mpic_domain, i);
+			generic_handle_domain_irq(mpic->domain, i);
 
 		/* MSI handling */
 		if (i == 1)
@@ -685,7 +706,7 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs)
 
 static int mpic_suspend(void)
 {
-	doorbell_mask_reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK);
+	mpic->doorbell_mask = readl(mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 
 	return 0;
 }
@@ -695,8 +716,8 @@ static void mpic_resume(void)
 	bool src0, src1;
 
 	/* Re-enable interrupts */
-	for (irq_hw_number_t i = 0; i < mpic_domain->hwirq_max; i++) {
-		unsigned int virq = irq_linear_revmap(mpic_domain, i);
+	for (irq_hw_number_t i = 0; i < mpic->domain->hwirq_max; i++) {
+		unsigned int virq = irq_linear_revmap(mpic->domain, i);
 		struct irq_data *d;
 
 		if (!virq)
@@ -706,12 +727,12 @@ static void mpic_resume(void)
 
 		if (!mpic_is_percpu_irq(i)) {
 			/* Non per-CPU interrupts */
-			writel(i, per_cpu_int_base + MPIC_INT_CLEAR_MASK);
+			writel(i, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 			if (!irqd_irq_disabled(d))
 				mpic_irq_unmask(d);
 		} else {
 			/* Per-CPU interrupts */
-			writel(i, main_int_base + MPIC_INT_SET_ENABLE);
+			writel(i, mpic->base + MPIC_INT_SET_ENABLE);
 
 			/*
 			 * Re-enable on the current CPU, mpic_reenable_percpu()
@@ -723,20 +744,20 @@ static void mpic_resume(void)
 	}
 
 	/* Reconfigure doorbells for IPIs and MSIs */
-	writel(doorbell_mask_reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK);
+	writel(mpic->doorbell_mask, mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 
 	if (mpic_is_ipi_available()) {
-		src0 = doorbell_mask_reg & IPI_DOORBELL_MASK;
-		src1 = doorbell_mask_reg & PCI_MSI_DOORBELL_MASK;
+		src0 = mpic->doorbell_mask & IPI_DOORBELL_MASK;
+		src1 = mpic->doorbell_mask & PCI_MSI_DOORBELL_MASK;
 	} else {
-		src0 = doorbell_mask_reg & PCI_MSI_FULL_DOORBELL_SRC0_MASK;
-		src1 = doorbell_mask_reg & PCI_MSI_FULL_DOORBELL_SRC1_MASK;
+		src0 = mpic->doorbell_mask & PCI_MSI_FULL_DOORBELL_SRC0_MASK;
+		src1 = mpic->doorbell_mask & PCI_MSI_FULL_DOORBELL_SRC1_MASK;
 	}
 
 	if (src0)
-		writel(0, per_cpu_int_base + MPIC_INT_CLEAR_MASK);
+		writel(0, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 	if (src1)
-		writel(1, per_cpu_int_base + MPIC_INT_CLEAR_MASK);
+		writel(1, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 
 	if (mpic_is_ipi_available())
 		mpic_ipi_resume();
@@ -784,32 +805,32 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par
 	unsigned int nr_irqs;
 	int err;
 
-	err = mpic_map_region(node, 0, &main_int_base, &phys_base);
+	err = mpic_map_region(node, 0, &mpic->base, &phys_base);
 	if (err)
 		return err;
 
-	err = mpic_map_region(node, 1, &per_cpu_int_base, NULL);
+	err = mpic_map_region(node, 1, &mpic->per_cpu, NULL);
 	if (err)
 		return err;
 
-	nr_irqs = FIELD_GET(MPIC_INT_CONTROL_NUMINT_MASK, readl(main_int_base + MPIC_INT_CONTROL));
+	nr_irqs = FIELD_GET(MPIC_INT_CONTROL_NUMINT_MASK, readl(mpic->base + MPIC_INT_CONTROL));
 
 	for (irq_hw_number_t i = 0; i < nr_irqs; i++)
-		writel(i, main_int_base + MPIC_INT_CLEAR_ENABLE);
+		writel(i, mpic->base + MPIC_INT_CLEAR_ENABLE);
 
-	mpic_domain = irq_domain_add_linear(node, nr_irqs, &mpic_irq_ops, NULL);
-	if (!mpic_domain) {
+	mpic->domain = irq_domain_add_linear(node, nr_irqs, &mpic_irq_ops, NULL);
+	if (!mpic->domain) {
 		pr_err("%pOF: Unable to add IRQ domain\n", node);
 		return -ENOMEM;
 	}
 
-	irq_domain_update_bus_token(mpic_domain, DOMAIN_BUS_WIRED);
+	irq_domain_update_bus_token(mpic->domain, DOMAIN_BUS_WIRED);
 
 	/*
-	 * Initialize parent_irq before calling any other functions, since it is
-	 * used to distinguish between IPI and non-IPI platforms.
+	 * Initialize mpic->parent_irq before calling any other functions, since
+	 * it is used to distinguish between IPI and non-IPI platforms.
 	 */
-	parent_irq = irq_of_parse_and_map(node, 0);
+	mpic->parent_irq = irq_of_parse_and_map(node, 0);
 
 	/* Setup for the boot CPU */
 	mpic_perf_init();
@@ -821,8 +842,8 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par
 		return err;
 	}
 
-	if (parent_irq <= 0) {
-		irq_set_default_host(mpic_domain);
+	if (mpic->parent_irq <= 0) {
+		irq_set_default_host(mpic->domain);
 		set_handle_irq(mpic_handle_irq);
 #ifdef CONFIG_SMP
 		err = mpic_ipi_init(node);
@@ -841,7 +862,7 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par
 					  "irqchip/armada/cascade:starting",
 					  mpic_cascaded_starting_cpu, NULL);
 #endif
-		irq_set_chained_handler(parent_irq, mpic_handle_cascade_irq);
+		irq_set_chained_handler(mpic->parent_irq, mpic_handle_cascade_irq);
 	}
 
 	register_syscore_ops(&mpic_syscore_ops);
-- 
2.44.2



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

* [PATCH v2 06/12] irqchip/armada-370-xp: Put MSI doorbell limits into the mpic structure
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
                   ` (4 preceding siblings ...)
  2024-08-07 16:40 ` [PATCH v2 05/12] irqchip/armada-370-xp: Put static variables into driver private structure Marek Behún
@ 2024-08-07 16:40 ` Marek Behún
  2024-08-07 16:40 ` [PATCH v2 07/12] irqchip/armada-370-xp: Pass around the driver private structure Marek Behún
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:40 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

Put the MSI doorbell limits msi_doorbell_start, msi_doorbell_size and
msi_doorbell_mask into the driver private structure and get rid of the
corresponding functions.

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 drivers/irqchip/irq-armada-370-xp.c | 44 ++++++++++++++---------------
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 00f38428d2ba..1c95a61c18cb 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -161,6 +161,10 @@
  * @msi_used:		bitmap of used MSI numbers
  * @msi_lock:		mutex serializing access to @msi_used
  * @msi_doorbell_addr:	physical address of MSI doorbell register
+ * @msi_doorbell_mask:	mask of available doorbell bits for MSIs (either PCI_MSI_DOORBELL_MASK or
+ *			PCI_MSI_FULL_DOORBELL_MASK)
+ * @msi_doorbell_start:	first set bit in @msi_doorbell_mask
+ * @msi_doorbell_size:	number of set bits in @msi_doorbell_mask
  * @doorbell_mask:	doorbell mask of MSIs and IPIs, stored on suspend, restored on resume
  */
 struct mpic {
@@ -177,6 +181,8 @@ struct mpic {
 	DECLARE_BITMAP(msi_used, PCI_MSI_FULL_DOORBELL_NR);
 	struct mutex msi_lock;
 	phys_addr_t msi_doorbell_addr;
+	u32 msi_doorbell_mask;
+	unsigned int msi_doorbell_start, msi_doorbell_size;
 #endif
 	u32 doorbell_mask;
 };
@@ -195,21 +201,6 @@ static inline bool mpic_is_ipi_available(void)
 	return mpic->parent_irq <= 0;
 }
 
-static inline u32 msi_doorbell_mask(void)
-{
-	return mpic_is_ipi_available() ? PCI_MSI_DOORBELL_MASK : PCI_MSI_FULL_DOORBELL_MASK;
-}
-
-static inline unsigned int msi_doorbell_start(void)
-{
-	return mpic_is_ipi_available() ? PCI_MSI_DOORBELL_START : PCI_MSI_FULL_DOORBELL_START;
-}
-
-static inline unsigned int msi_doorbell_size(void)
-{
-	return mpic_is_ipi_available() ? PCI_MSI_DOORBELL_NR : PCI_MSI_FULL_DOORBELL_NR;
-}
-
 static inline bool mpic_is_percpu_irq(irq_hw_number_t hwirq)
 {
 	return hwirq <= MPIC_MAX_PER_CPU_IRQS;
@@ -260,7 +251,7 @@ static void mpic_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
 
 	msg->address_lo = lower_32_bits(mpic->msi_doorbell_addr);
 	msg->address_hi = upper_32_bits(mpic->msi_doorbell_addr);
-	msg->data = BIT(cpu + 8) | (d->hwirq + msi_doorbell_start());
+	msg->data = BIT(cpu + 8) | (d->hwirq + mpic->msi_doorbell_start);
 }
 
 static int mpic_msi_set_affinity(struct irq_data *d, const struct cpumask *mask, bool force)
@@ -292,7 +283,7 @@ static int mpic_msi_alloc(struct irq_domain *domain, unsigned int virq, unsigned
 	int hwirq;
 
 	mutex_lock(&mpic->msi_lock);
-	hwirq = bitmap_find_free_region(mpic->msi_used, msi_doorbell_size(),
+	hwirq = bitmap_find_free_region(mpic->msi_used, mpic->msi_doorbell_size,
 					order_base_2(nr_irqs));
 	mutex_unlock(&mpic->msi_lock);
 
@@ -329,7 +320,7 @@ static void mpic_msi_reenable_percpu(void)
 
 	/* Enable MSI doorbell mask and combined cpu local interrupt */
 	reg = readl(mpic->per_cpu + MPIC_IN_DRBEL_MASK);
-	reg |= msi_doorbell_mask();
+	reg |= mpic->msi_doorbell_mask;
 	writel(reg, mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 
 	/* Unmask local doorbell interrupt */
@@ -342,7 +333,17 @@ static int __init mpic_msi_init(struct device_node *node, phys_addr_t main_int_p
 
 	mutex_init(&mpic->msi_lock);
 
-	mpic->msi_inner_domain = irq_domain_add_linear(NULL, msi_doorbell_size(),
+	if (mpic_is_ipi_available()) {
+		mpic->msi_doorbell_start = PCI_MSI_DOORBELL_START;
+		mpic->msi_doorbell_size = PCI_MSI_DOORBELL_NR;
+		mpic->msi_doorbell_mask = PCI_MSI_DOORBELL_MASK;
+	} else {
+		mpic->msi_doorbell_start = PCI_MSI_FULL_DOORBELL_START;
+		mpic->msi_doorbell_size = PCI_MSI_FULL_DOORBELL_NR;
+		mpic->msi_doorbell_mask = PCI_MSI_FULL_DOORBELL_MASK;
+	}
+
+	mpic->msi_inner_domain = irq_domain_add_linear(NULL, mpic->msi_doorbell_size,
 						       &mpic_msi_domain_ops, NULL);
 	if (!mpic->msi_inner_domain)
 		return -ENOMEM;
@@ -620,12 +621,11 @@ static void mpic_handle_msi_irq(void)
 	unsigned int i;
 
 	cause = readl_relaxed(mpic->per_cpu + MPIC_IN_DRBEL_CAUSE);
-	cause &= msi_doorbell_mask();
+	cause &= mpic->msi_doorbell_mask;
 	writel(~cause, mpic->per_cpu + MPIC_IN_DRBEL_CAUSE);
 
 	for_each_set_bit(i, &cause, BITS_PER_LONG)
-		generic_handle_domain_irq(mpic->msi_inner_domain,
-					  i - msi_doorbell_start());
+		generic_handle_domain_irq(mpic->msi_inner_domain, i - mpic->msi_doorbell_start);
 }
 #else
 static void mpic_handle_msi_irq(void) {}
-- 
2.44.2



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

* [PATCH v2 07/12] irqchip/armada-370-xp: Pass around the driver private structure
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
                   ` (5 preceding siblings ...)
  2024-08-07 16:40 ` [PATCH v2 06/12] irqchip/armada-370-xp: Put MSI doorbell limits into the mpic structure Marek Behún
@ 2024-08-07 16:40 ` Marek Behún
  2024-08-07 16:41 ` [PATCH v2 08/12] irqchip/armada-370-xp: Dynamically allocate " Marek Behún
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:40 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

In continuation of converting the driver to modern style, drop the
global pointer to the driver private structure and instead pass it
around the functions and callbacks, wherever possible. (There are 3
cases where it is not possible: mpic_cascaded_starting_cpu() and the
syscore operations mpic_suspend() and mpic_resume()).

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 drivers/irqchip/irq-armada-370-xp.c | 115 +++++++++++++++++-----------
 1 file changed, 70 insertions(+), 45 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 1c95a61c18cb..5710ce206cca 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -188,9 +188,8 @@ struct mpic {
 };
 
 static struct mpic mpic_data;
-static struct mpic * const mpic = &mpic_data;
 
-static inline bool mpic_is_ipi_available(void)
+static inline bool mpic_is_ipi_available(struct mpic *mpic)
 {
 	/*
 	 * We distinguish IPI availability in the IC by the IC not having a
@@ -213,6 +212,7 @@ static inline bool mpic_is_percpu_irq(irq_hw_number_t hwirq)
  */
 static void mpic_irq_mask(struct irq_data *d)
 {
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
 	if (!mpic_is_percpu_irq(hwirq))
@@ -223,6 +223,7 @@ static void mpic_irq_mask(struct irq_data *d)
 
 static void mpic_irq_unmask(struct irq_data *d)
 {
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
 	if (!mpic_is_percpu_irq(hwirq))
@@ -248,6 +249,7 @@ static struct msi_domain_info mpic_msi_domain_info = {
 static void mpic_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
 {
 	unsigned int cpu = cpumask_first(irq_data_get_effective_affinity_mask(d));
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
 
 	msg->address_lo = lower_32_bits(mpic->msi_doorbell_addr);
 	msg->address_hi = upper_32_bits(mpic->msi_doorbell_addr);
@@ -280,6 +282,7 @@ static struct irq_chip mpic_msi_bottom_irq_chip = {
 static int mpic_msi_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs,
 			  void *args)
 {
+	struct mpic *mpic = domain->host_data;
 	int hwirq;
 
 	mutex_lock(&mpic->msi_lock);
@@ -303,6 +306,7 @@ static int mpic_msi_alloc(struct irq_domain *domain, unsigned int virq, unsigned
 static void mpic_msi_free(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs)
 {
 	struct irq_data *d = irq_domain_get_irq_data(domain, virq);
+	struct mpic *mpic = domain->host_data;
 
 	mutex_lock(&mpic->msi_lock);
 	bitmap_release_region(mpic->msi_used, d->hwirq, order_base_2(nr_irqs));
@@ -314,7 +318,7 @@ static const struct irq_domain_ops mpic_msi_domain_ops = {
 	.free	= mpic_msi_free,
 };
 
-static void mpic_msi_reenable_percpu(void)
+static void mpic_msi_reenable_percpu(struct mpic *mpic)
 {
 	u32 reg;
 
@@ -327,13 +331,14 @@ static void mpic_msi_reenable_percpu(void)
 	writel(1, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 }
 
-static int __init mpic_msi_init(struct device_node *node, phys_addr_t main_int_phys_base)
+static int __init mpic_msi_init(struct mpic *mpic, struct device_node *node,
+				phys_addr_t main_int_phys_base)
 {
 	mpic->msi_doorbell_addr = main_int_phys_base + MPIC_SW_TRIG_INT;
 
 	mutex_init(&mpic->msi_lock);
 
-	if (mpic_is_ipi_available()) {
+	if (mpic_is_ipi_available(mpic)) {
 		mpic->msi_doorbell_start = PCI_MSI_DOORBELL_START;
 		mpic->msi_doorbell_size = PCI_MSI_DOORBELL_NR;
 		mpic->msi_doorbell_mask = PCI_MSI_DOORBELL_MASK;
@@ -344,7 +349,7 @@ static int __init mpic_msi_init(struct device_node *node, phys_addr_t main_int_p
 	}
 
 	mpic->msi_inner_domain = irq_domain_add_linear(NULL, mpic->msi_doorbell_size,
-						       &mpic_msi_domain_ops, NULL);
+						       &mpic_msi_domain_ops, mpic);
 	if (!mpic->msi_inner_domain)
 		return -ENOMEM;
 
@@ -355,25 +360,25 @@ static int __init mpic_msi_init(struct device_node *node, phys_addr_t main_int_p
 		return -ENOMEM;
 	}
 
-	mpic_msi_reenable_percpu();
+	mpic_msi_reenable_percpu(mpic);
 
 	/* Unmask low 16 MSI irqs on non-IPI platforms */
-	if (!mpic_is_ipi_available())
+	if (!mpic_is_ipi_available(mpic))
 		writel(0, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 
 	return 0;
 }
 #else
-static __maybe_unused void mpic_msi_reenable_percpu(void) {}
+static __maybe_unused void mpic_msi_reenable_percpu(struct mpic *mpic) {}
 
-static inline int mpic_msi_init(struct device_node *node,
+static inline int mpic_msi_init(struct mpic *mpic, struct device_node *node,
 				phys_addr_t main_int_phys_base)
 {
 	return 0;
 }
 #endif
 
-static void mpic_perf_init(void)
+static void mpic_perf_init(struct mpic *mpic)
 {
 	u32 cpuid;
 
@@ -393,6 +398,7 @@ static void mpic_perf_init(void)
 #ifdef CONFIG_SMP
 static void mpic_ipi_mask(struct irq_data *d)
 {
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
 	u32 reg;
 
 	reg = readl(mpic->per_cpu + MPIC_IN_DRBEL_MASK);
@@ -402,6 +408,7 @@ static void mpic_ipi_mask(struct irq_data *d)
 
 static void mpic_ipi_unmask(struct irq_data *d)
 {
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
 	u32 reg;
 
 	reg = readl(mpic->per_cpu + MPIC_IN_DRBEL_MASK);
@@ -411,6 +418,7 @@ static void mpic_ipi_unmask(struct irq_data *d)
 
 static void mpic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)
 {
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
 	unsigned int cpu;
 	u32 map = 0;
 
@@ -430,6 +438,8 @@ static void mpic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)
 
 static void mpic_ipi_ack(struct irq_data *d)
 {
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
+
 	writel(~BIT(d->hwirq), mpic->per_cpu + MPIC_IN_DRBEL_CAUSE);
 }
 
@@ -464,7 +474,7 @@ static const struct irq_domain_ops mpic_ipi_domain_ops = {
 	.free	= mpic_ipi_free,
 };
 
-static void mpic_ipi_resume(void)
+static void mpic_ipi_resume(struct mpic *mpic)
 {
 	for (irq_hw_number_t i = 0; i < IPI_DOORBELL_NR; i++) {
 		unsigned int virq = irq_find_mapping(mpic->ipi_domain, i);
@@ -478,12 +488,12 @@ static void mpic_ipi_resume(void)
 	}
 }
 
-static int __init mpic_ipi_init(struct device_node *node)
+static int __init mpic_ipi_init(struct mpic *mpic, struct device_node *node)
 {
 	int base_ipi;
 
 	mpic->ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node), IPI_DOORBELL_NR,
-						    &mpic_ipi_domain_ops, NULL);
+						    &mpic_ipi_domain_ops, mpic);
 	if (WARN_ON(!mpic->ipi_domain))
 		return -ENOMEM;
 
@@ -499,6 +509,7 @@ static int __init mpic_ipi_init(struct device_node *node)
 
 static int mpic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force)
 {
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
 	unsigned int cpu;
 
@@ -513,12 +524,12 @@ static int mpic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 	return IRQ_SET_MASK_OK;
 }
 
-static void mpic_smp_cpu_init(void)
+static void mpic_smp_cpu_init(struct mpic *mpic)
 {
 	for (irq_hw_number_t i = 0; i < mpic->domain->hwirq_max; i++)
 		writel(i, mpic->per_cpu + MPIC_INT_SET_MASK);
 
-	if (!mpic_is_ipi_available())
+	if (!mpic_is_ipi_available(mpic))
 		return;
 
 	/* Disable all IPIs */
@@ -531,7 +542,7 @@ static void mpic_smp_cpu_init(void)
 	writel(0, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 }
 
-static void mpic_reenable_percpu(void)
+static void mpic_reenable_percpu(struct mpic *mpic)
 {
 	/* Re-enable per-CPU interrupts that were enabled before suspend */
 	for (irq_hw_number_t i = 0; i < MPIC_MAX_PER_CPU_IRQS; i++) {
@@ -545,32 +556,36 @@ static void mpic_reenable_percpu(void)
 		mpic_irq_unmask(d);
 	}
 
-	if (mpic_is_ipi_available())
-		mpic_ipi_resume();
+	if (mpic_is_ipi_available(mpic))
+		mpic_ipi_resume(mpic);
 
-	mpic_msi_reenable_percpu();
+	mpic_msi_reenable_percpu(mpic);
 }
 
 static int mpic_starting_cpu(unsigned int cpu)
 {
-	mpic_perf_init();
-	mpic_smp_cpu_init();
-	mpic_reenable_percpu();
+	struct mpic *mpic = irq_get_default_host()->host_data;
+
+	mpic_perf_init(mpic);
+	mpic_smp_cpu_init(mpic);
+	mpic_reenable_percpu(mpic);
 
 	return 0;
 }
 
 static int mpic_cascaded_starting_cpu(unsigned int cpu)
 {
-	mpic_perf_init();
-	mpic_reenable_percpu();
+	struct mpic *mpic = &mpic_data;
+
+	mpic_perf_init(mpic);
+	mpic_reenable_percpu(mpic);
 	enable_percpu_irq(mpic->parent_irq, IRQ_TYPE_NONE);
 
 	return 0;
 }
 #else
-static void mpic_smp_cpu_init(void) {}
-static void mpic_ipi_resume(void) {}
+static void mpic_smp_cpu_init(struct mpic *mpic) {}
+static void mpic_ipi_resume(struct mpic *mpic) {}
 #endif
 
 static struct irq_chip mpic_irq_chip = {
@@ -584,13 +599,16 @@ static struct irq_chip mpic_irq_chip = {
 	.flags		= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
 };
 
-static int mpic_irq_map(struct irq_domain *h, unsigned int virq,
-			irq_hw_number_t hwirq)
+static int mpic_irq_map(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq)
 {
+	struct mpic *mpic = domain->host_data;
+
 	/* IRQs 0 and 1 cannot be mapped, they are handled internally */
 	if (hwirq <= 1)
 		return -EINVAL;
 
+	irq_set_chip_data(virq, mpic);
+
 	mpic_irq_mask(irq_get_irq_data(virq));
 	if (!mpic_is_percpu_irq(hwirq))
 		writel(hwirq, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
@@ -615,7 +633,7 @@ static const struct irq_domain_ops mpic_irq_ops = {
 };
 
 #ifdef CONFIG_PCI_MSI
-static void mpic_handle_msi_irq(void)
+static void mpic_handle_msi_irq(struct mpic *mpic)
 {
 	unsigned long cause;
 	unsigned int i;
@@ -628,11 +646,11 @@ static void mpic_handle_msi_irq(void)
 		generic_handle_domain_irq(mpic->msi_inner_domain, i - mpic->msi_doorbell_start);
 }
 #else
-static void mpic_handle_msi_irq(void) {}
+static void mpic_handle_msi_irq(struct mpic *mpic) {}
 #endif
 
 #ifdef CONFIG_SMP
-static void mpic_handle_ipi_irq(void)
+static void mpic_handle_ipi_irq(struct mpic *mpic)
 {
 	unsigned long cause;
 	irq_hw_number_t i;
@@ -644,11 +662,12 @@ static void mpic_handle_ipi_irq(void)
 		generic_handle_domain_irq(mpic->ipi_domain, i);
 }
 #else
-static inline void mpic_handle_ipi_irq(void) {}
+static inline void mpic_handle_ipi_irq(struct mpic *mpic) {}
 #endif
 
 static void mpic_handle_cascade_irq(struct irq_desc *desc)
 {
+	struct mpic *mpic = irq_desc_get_handler_data(desc);
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned long cause;
 	u32 irqsrc, cpuid;
@@ -669,7 +688,7 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc)
 			continue;
 
 		if (i == 0 || i == 1) {
-			mpic_handle_msi_irq();
+			mpic_handle_msi_irq(mpic);
 			continue;
 		}
 
@@ -681,6 +700,7 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc)
 
 static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs)
 {
+	struct mpic *mpic = irq_get_default_host()->host_data;
 	irq_hw_number_t i;
 	u32 irqstat;
 
@@ -696,16 +716,18 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs)
 
 		/* MSI handling */
 		if (i == 1)
-			mpic_handle_msi_irq();
+			mpic_handle_msi_irq(mpic);
 
 		/* IPI Handling */
 		if (i == 0)
-			mpic_handle_ipi_irq();
+			mpic_handle_ipi_irq(mpic);
 	} while (1);
 }
 
 static int mpic_suspend(void)
 {
+	struct mpic *mpic = &mpic_data;
+
 	mpic->doorbell_mask = readl(mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 
 	return 0;
@@ -713,6 +735,7 @@ static int mpic_suspend(void)
 
 static void mpic_resume(void)
 {
+	struct mpic *mpic = &mpic_data;
 	bool src0, src1;
 
 	/* Re-enable interrupts */
@@ -746,7 +769,7 @@ static void mpic_resume(void)
 	/* Reconfigure doorbells for IPIs and MSIs */
 	writel(mpic->doorbell_mask, mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 
-	if (mpic_is_ipi_available()) {
+	if (mpic_is_ipi_available(mpic)) {
 		src0 = mpic->doorbell_mask & IPI_DOORBELL_MASK;
 		src1 = mpic->doorbell_mask & PCI_MSI_DOORBELL_MASK;
 	} else {
@@ -759,8 +782,8 @@ static void mpic_resume(void)
 	if (src1)
 		writel(1, mpic->per_cpu + MPIC_INT_CLEAR_MASK);
 
-	if (mpic_is_ipi_available())
-		mpic_ipi_resume();
+	if (mpic_is_ipi_available(mpic))
+		mpic_ipi_resume(mpic);
 }
 
 static struct syscore_ops mpic_syscore_ops = {
@@ -801,6 +824,7 @@ static int __init mpic_map_region(struct device_node *np, int index,
 
 static int __init mpic_of_init(struct device_node *node, struct device_node *parent)
 {
+	struct mpic *mpic = &mpic_data;
 	phys_addr_t phys_base;
 	unsigned int nr_irqs;
 	int err;
@@ -818,7 +842,7 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par
 	for (irq_hw_number_t i = 0; i < nr_irqs; i++)
 		writel(i, mpic->base + MPIC_INT_CLEAR_ENABLE);
 
-	mpic->domain = irq_domain_add_linear(node, nr_irqs, &mpic_irq_ops, NULL);
+	mpic->domain = irq_domain_add_linear(node, nr_irqs, &mpic_irq_ops, mpic);
 	if (!mpic->domain) {
 		pr_err("%pOF: Unable to add IRQ domain\n", node);
 		return -ENOMEM;
@@ -833,10 +857,10 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par
 	mpic->parent_irq = irq_of_parse_and_map(node, 0);
 
 	/* Setup for the boot CPU */
-	mpic_perf_init();
-	mpic_smp_cpu_init();
+	mpic_perf_init(mpic);
+	mpic_smp_cpu_init(mpic);
 
-	err = mpic_msi_init(node, phys_base);
+	err = mpic_msi_init(mpic, node, phys_base);
 	if (err) {
 		pr_err("%pOF: Unable to initialize MSI domain\n", node);
 		return err;
@@ -846,7 +870,7 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par
 		irq_set_default_host(mpic->domain);
 		set_handle_irq(mpic_handle_irq);
 #ifdef CONFIG_SMP
-		err = mpic_ipi_init(node);
+		err = mpic_ipi_init(mpic, node);
 		if (err) {
 			pr_err("%pOF: Unable to initialize IPI domain\n", node);
 			return err;
@@ -862,7 +886,8 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par
 					  "irqchip/armada/cascade:starting",
 					  mpic_cascaded_starting_cpu, NULL);
 #endif
-		irq_set_chained_handler(mpic->parent_irq, mpic_handle_cascade_irq);
+		irq_set_chained_handler_and_data(mpic->parent_irq,
+						 mpic_handle_cascade_irq, mpic);
 	}
 
 	register_syscore_ops(&mpic_syscore_ops);
-- 
2.44.2



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

* [PATCH v2 08/12] irqchip/armada-370-xp: Dynamically allocate the driver private structure
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
                   ` (6 preceding siblings ...)
  2024-08-07 16:40 ` [PATCH v2 07/12] irqchip/armada-370-xp: Pass around the driver private structure Marek Behún
@ 2024-08-07 16:41 ` Marek Behún
  2024-08-07 16:41 ` [PATCH v2 09/12] irqchip/armada-370-xp: Fix reenabling last per-CPU interrupt Marek Behún
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:41 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

Dynamically allocate the driver private structure. This concludes the
conversion of this driver to modern style.

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 drivers/irqchip/irq-armada-370-xp.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 5710ce206cca..f8658a232f21 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -187,7 +187,7 @@ struct mpic {
 	u32 doorbell_mask;
 };
 
-static struct mpic mpic_data;
+static struct mpic *mpic_data __ro_after_init;
 
 static inline bool mpic_is_ipi_available(struct mpic *mpic)
 {
@@ -575,7 +575,7 @@ static int mpic_starting_cpu(unsigned int cpu)
 
 static int mpic_cascaded_starting_cpu(unsigned int cpu)
 {
-	struct mpic *mpic = &mpic_data;
+	struct mpic *mpic = mpic_data;
 
 	mpic_perf_init(mpic);
 	mpic_reenable_percpu(mpic);
@@ -726,7 +726,7 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs)
 
 static int mpic_suspend(void)
 {
-	struct mpic *mpic = &mpic_data;
+	struct mpic *mpic = mpic_data;
 
 	mpic->doorbell_mask = readl(mpic->per_cpu + MPIC_IN_DRBEL_MASK);
 
@@ -735,7 +735,7 @@ static int mpic_suspend(void)
 
 static void mpic_resume(void)
 {
-	struct mpic *mpic = &mpic_data;
+	struct mpic *mpic = mpic_data;
 	bool src0, src1;
 
 	/* Re-enable interrupts */
@@ -824,11 +824,17 @@ static int __init mpic_map_region(struct device_node *np, int index,
 
 static int __init mpic_of_init(struct device_node *node, struct device_node *parent)
 {
-	struct mpic *mpic = &mpic_data;
 	phys_addr_t phys_base;
 	unsigned int nr_irqs;
+	struct mpic *mpic;
 	int err;
 
+	mpic = kzalloc(sizeof(*mpic), GFP_KERNEL);
+	if (WARN_ON(!mpic))
+		return -ENOMEM;
+
+	mpic_data = mpic;
+
 	err = mpic_map_region(node, 0, &mpic->base, &phys_base);
 	if (err)
 		return err;
-- 
2.44.2



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

* [PATCH v2 09/12] irqchip/armada-370-xp: Fix reenabling last per-CPU interrupt
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
                   ` (7 preceding siblings ...)
  2024-08-07 16:41 ` [PATCH v2 08/12] irqchip/armada-370-xp: Dynamically allocate " Marek Behún
@ 2024-08-07 16:41 ` Marek Behún
  2024-08-07 16:41 ` [PATCH v2 10/12] irqchip/armada-370-xp: Iterate only valid bits of the per-CPU interrupt cause register Marek Behún
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:41 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún, stable+noautosel

The number of per-CPU interrupts is 29 (0 to 28). This is described by
the constant MPIC_MAX_PER_CPU_IRQS, set to 28 (the maximum per-CPU
interrupt).

Commit 0fa4ce746d1d ("irqchip/armada-370-xp: Re-enable per-CPU
interrupts at resume time") used the constant incorrectly in the
for-loop, it used the operator < instead of <=, causing it to iterate
only the first 28 interrupts (0 to 27), ignoring the last, 28th,
per-CPU interrupt.

To avoid this kind of confusions, fix this issue by renaming the constant
to MPIC_PER_CPU_IRQS_NR and set it to 29, the number of per-CPU IRQs.
Update its use in mpic_is_percpu_irq() accordingly.

Cc: <stable+noautosel@kernel.org> # The 29th interrupt is not used in any device-tree
Fixes: 0fa4ce746d1d ("irqchip/armada-370-xp: Re-enable per-CPU interrupts at resume time")
Signed-off-by: Marek Behún <kabel@kernel.org>
---
Thomas, I have added the stable+noautosel Cc so that this patch won't be
autoselected for stable releases, as described in
Documentation/process/stable-kernel-rules.rst. This way I can keep the
Fixes tag.
---
 drivers/irqchip/irq-armada-370-xp.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index f8658a232f21..83afc3a27812 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -133,7 +133,7 @@
 #define MPIC_INT_FABRIC_MASK			0x54
 #define MPIC_INT_CAUSE_PERF(cpu)		BIT(cpu)
 
-#define MPIC_MAX_PER_CPU_IRQS			28
+#define MPIC_PER_CPU_IRQS_NR			29
 
 /* IPI and MSI interrupt definitions for IPI platforms */
 #define IPI_DOORBELL_NR				8
@@ -202,7 +202,7 @@ static inline bool mpic_is_ipi_available(struct mpic *mpic)
 
 static inline bool mpic_is_percpu_irq(irq_hw_number_t hwirq)
 {
-	return hwirq <= MPIC_MAX_PER_CPU_IRQS;
+	return hwirq < MPIC_PER_CPU_IRQS_NR;
 }
 
 /*
@@ -545,7 +545,7 @@ static void mpic_smp_cpu_init(struct mpic *mpic)
 static void mpic_reenable_percpu(struct mpic *mpic)
 {
 	/* Re-enable per-CPU interrupts that were enabled before suspend */
-	for (irq_hw_number_t i = 0; i < MPIC_MAX_PER_CPU_IRQS; i++) {
+	for (irq_hw_number_t i = 0; i < MPIC_PER_CPU_IRQS_NR; i++) {
 		unsigned int virq = irq_linear_revmap(mpic->domain, i);
 		struct irq_data *d;
 
-- 
2.44.2



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

* [PATCH v2 10/12] irqchip/armada-370-xp: Iterate only valid bits of the per-CPU interrupt cause register
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
                   ` (8 preceding siblings ...)
  2024-08-07 16:41 ` [PATCH v2 09/12] irqchip/armada-370-xp: Fix reenabling last per-CPU interrupt Marek Behún
@ 2024-08-07 16:41 ` Marek Behún
  2024-08-07 16:41 ` [PATCH v2 11/12] irqchip/armada-370-xp: Allow mapping only per-CPU interrupts Marek Behún
  2024-08-07 16:41 ` [PATCH v2 12/12] irqchip/armada-370-xp: Use the mpic_is_ipi_available() helper in one more case Marek Behún
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:41 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

Use MPIC_PER_CPU_IRQS_NR (29) bound instead of BITS_PER_LONG (32) when
iterating the bits of the per-CPU interrupt cause register, since there
are only 29 per-CPU interrupts. The top 3 bits are always zero anyway.

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 drivers/irqchip/irq-armada-370-xp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 83afc3a27812..36d1bac8a99f 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -678,7 +678,7 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc)
 	cause = readl_relaxed(mpic->per_cpu + MPIC_PPI_CAUSE);
 	cpuid = cpu_logical_map(smp_processor_id());
 
-	for_each_set_bit(i, &cause, BITS_PER_LONG) {
+	for_each_set_bit(i, &cause, MPIC_PER_CPU_IRQS_NR) {
 		irqsrc = readl_relaxed(mpic->base + MPIC_INT_SOURCE_CTL(i));
 
 		/* Check if the interrupt is not masked on current CPU.
-- 
2.44.2



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

* [PATCH v2 11/12] irqchip/armada-370-xp: Allow mapping only per-CPU interrupts
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
                   ` (9 preceding siblings ...)
  2024-08-07 16:41 ` [PATCH v2 10/12] irqchip/armada-370-xp: Iterate only valid bits of the per-CPU interrupt cause register Marek Behún
@ 2024-08-07 16:41 ` Marek Behún
  2024-08-07 16:41 ` [PATCH v2 12/12] irqchip/armada-370-xp: Use the mpic_is_ipi_available() helper in one more case Marek Behún
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:41 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

On platforms where MPIC is not the top-level interrupt controller the
driver currently only supports handling of the per-CPU interrupts (the
first 29 interrupts). This is obvious from the code of
mpic_handle_cascade_irq(), which reads only one cause register.

Bound the number of available interrupts in the IRQ domain to 29 for
these platforms.

The corresponding device-trees refer only to per-CPU interrupts via
MPIC, the other interrupts are referred to via GIC.

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 drivers/irqchip/irq-armada-370-xp.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 36d1bac8a99f..4f3f99af12b2 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -848,6 +848,19 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par
 	for (irq_hw_number_t i = 0; i < nr_irqs; i++)
 		writel(i, mpic->base + MPIC_INT_CLEAR_ENABLE);
 
+	/*
+	 * Initialize mpic->parent_irq before calling any other functions, since
+	 * it is used to distinguish between IPI and non-IPI platforms.
+	 */
+	mpic->parent_irq = irq_of_parse_and_map(node, 0);
+
+	/*
+	 * On non-IPI platforms the driver currently supports only the per-CPU
+	 * interrupts (the first 29 interrupts). See mpic_handle_cascade_irq().
+	 */
+	if (!mpic_is_ipi_available(mpic))
+		nr_irqs = MPIC_PER_CPU_IRQS_NR;
+
 	mpic->domain = irq_domain_add_linear(node, nr_irqs, &mpic_irq_ops, mpic);
 	if (!mpic->domain) {
 		pr_err("%pOF: Unable to add IRQ domain\n", node);
@@ -856,12 +869,6 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par
 
 	irq_domain_update_bus_token(mpic->domain, DOMAIN_BUS_WIRED);
 
-	/*
-	 * Initialize mpic->parent_irq before calling any other functions, since
-	 * it is used to distinguish between IPI and non-IPI platforms.
-	 */
-	mpic->parent_irq = irq_of_parse_and_map(node, 0);
-
 	/* Setup for the boot CPU */
 	mpic_perf_init(mpic);
 	mpic_smp_cpu_init(mpic);
-- 
2.44.2



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

* [PATCH v2 12/12] irqchip/armada-370-xp: Use the mpic_is_ipi_available() helper in one more case
  2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
                   ` (10 preceding siblings ...)
  2024-08-07 16:41 ` [PATCH v2 11/12] irqchip/armada-370-xp: Allow mapping only per-CPU interrupts Marek Behún
@ 2024-08-07 16:41 ` Marek Behún
  11 siblings, 0 replies; 13+ messages in thread
From: Marek Behún @ 2024-08-07 16:41 UTC (permalink / raw)
  To: Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
	Thomas Gleixner, linux-arm-kernel, arm, Andy Shevchenko,
	Hans de Goede, Ilpo Järvinen
  Cc: Marek Behún

There is one last case where we can use the helper function
mpic_is_ipi_available() instead of hardcoding the condition.

Signed-off-by: Marek Behún <kabel@kernel.org>
---
 drivers/irqchip/irq-armada-370-xp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 4f3f99af12b2..d7c5ef248474 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -879,7 +879,7 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par
 		return err;
 	}
 
-	if (mpic->parent_irq <= 0) {
+	if (mpic_is_ipi_available(mpic)) {
 		irq_set_default_host(mpic->domain);
 		set_handle_irq(mpic_handle_irq);
 #ifdef CONFIG_SMP
-- 
2.44.2



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

end of thread, other threads:[~2024-08-07 16:48 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-07 16:40 [PATCH v2 00/12] armada-370-xp irqchip updates round 5 Marek Behún
2024-08-07 16:40 ` [PATCH v2 01/12] irqchip/armada-370-xp: Drop IPI_DOORBELL_START and rename IPI_DOORBELL_END Marek Behún
2024-08-07 16:40 ` [PATCH v2 02/12] irqchip/armada-370-xp: Drop msi_doorbell_end() Marek Behún
2024-08-07 16:40 ` [PATCH v2 03/12] irqchip/armada-370-xp: Add the __init attribute to mpic_msi_init() Marek Behún
2024-08-07 16:40 ` [PATCH v2 04/12] irqchip/armada-370-xp: Put __init attribute after return type in mpic_ipi_init() Marek Behún
2024-08-07 16:40 ` [PATCH v2 05/12] irqchip/armada-370-xp: Put static variables into driver private structure Marek Behún
2024-08-07 16:40 ` [PATCH v2 06/12] irqchip/armada-370-xp: Put MSI doorbell limits into the mpic structure Marek Behún
2024-08-07 16:40 ` [PATCH v2 07/12] irqchip/armada-370-xp: Pass around the driver private structure Marek Behún
2024-08-07 16:41 ` [PATCH v2 08/12] irqchip/armada-370-xp: Dynamically allocate " Marek Behún
2024-08-07 16:41 ` [PATCH v2 09/12] irqchip/armada-370-xp: Fix reenabling last per-CPU interrupt Marek Behún
2024-08-07 16:41 ` [PATCH v2 10/12] irqchip/armada-370-xp: Iterate only valid bits of the per-CPU interrupt cause register Marek Behún
2024-08-07 16:41 ` [PATCH v2 11/12] irqchip/armada-370-xp: Allow mapping only per-CPU interrupts Marek Behún
2024-08-07 16:41 ` [PATCH v2 12/12] irqchip/armada-370-xp: Use the mpic_is_ipi_available() helper in one more case Marek Behún

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).