From 5e389e9868878c8aeb3ed60789eb62242506c9f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 8 Jul 2024 17:17:52 +0200 Subject: [PATCH 01/73] irqchip/armada-370-xp: Drop _OFFS suffix from some register constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some register constants have the _OFFS suffix and some do not. Drop it to be more consistent. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240708151801.11592-2-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 105 +++++++++++++--------------- 1 file changed, 48 insertions(+), 57 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index dce2b80bf439..66d6a2ebc8a5 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -66,15 +66,14 @@ * device * * The "global interrupt mask/unmask" is modified using the - * ARMADA_370_XP_INT_SET_ENABLE_OFFS and - * ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS registers, which are relative - * to "main_int_base". + * ARMADA_370_XP_INT_SET_ENABLE and ARMADA_370_XP_INT_CLEAR_ENABLE + * registers, which are relative to "main_int_base". * * The "per-CPU mask/unmask" is modified using the - * ARMADA_370_XP_INT_SET_MASK_OFFS and - * ARMADA_370_XP_INT_CLEAR_MASK_OFFS registers, which are relative to - * "per_cpu_int_base". This base address points to a special address, - * which automatically accesses the registers of the current CPU. + * ARMADA_370_XP_INT_SET_MASK and ARMADA_370_XP_INT_CLEAR_MASK + * registers, which are relative to "per_cpu_int_base". 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 * per-interrupt ARMADA_370_XP_INT_SOURCE_CTL register, which we use @@ -118,21 +117,21 @@ /* Registers relative to main_int_base */ #define ARMADA_370_XP_INT_CONTROL (0x00) -#define ARMADA_370_XP_SW_TRIG_INT_OFFS (0x04) -#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) -#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34) +#define ARMADA_370_XP_SW_TRIG_INT (0x04) +#define ARMADA_370_XP_INT_SET_ENABLE (0x30) +#define ARMADA_370_XP_INT_CLEAR_ENABLE (0x34) #define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) #define ARMADA_370_XP_INT_SOURCE_CPU_MASK 0xF #define ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid) ((BIT(0) | BIT(8)) << cpuid) /* Registers relative to per_cpu_int_base */ -#define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x08) -#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0x0c) +#define ARMADA_370_XP_IN_DRBEL_CAUSE (0x08) +#define ARMADA_370_XP_IN_DRBEL_MSK (0x0c) #define ARMADA_375_PPI_CAUSE (0x10) -#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) -#define ARMADA_370_XP_INT_SET_MASK_OFFS (0x48) -#define ARMADA_370_XP_INT_CLEAR_MASK_OFFS (0x4C) -#define ARMADA_370_XP_INT_FABRIC_MASK_OFFS (0x54) +#define ARMADA_370_XP_CPU_INTACK (0x44) +#define ARMADA_370_XP_INT_SET_MASK (0x48) +#define ARMADA_370_XP_INT_CLEAR_MASK (0x4C) +#define ARMADA_370_XP_INT_FABRIC_MASK (0x54) #define ARMADA_370_XP_INT_CAUSE_PERF(cpu) (1 << cpu) #define ARMADA_370_XP_MAX_PER_CPU_IRQS (28) @@ -220,11 +219,9 @@ static void armada_370_xp_irq_mask(struct irq_data *d) irq_hw_number_t hwirq = irqd_to_hwirq(d); if (!is_percpu_irq(hwirq)) - writel(hwirq, main_int_base + - ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS); + writel(hwirq, main_int_base + ARMADA_370_XP_INT_CLEAR_ENABLE); else - writel(hwirq, per_cpu_int_base + - ARMADA_370_XP_INT_SET_MASK_OFFS); + writel(hwirq, per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK); } static void armada_370_xp_irq_unmask(struct irq_data *d) @@ -232,11 +229,9 @@ static void armada_370_xp_irq_unmask(struct irq_data *d) irq_hw_number_t hwirq = irqd_to_hwirq(d); if (!is_percpu_irq(hwirq)) - writel(hwirq, main_int_base + - ARMADA_370_XP_INT_SET_ENABLE_OFFS); + writel(hwirq, main_int_base + ARMADA_370_XP_INT_SET_ENABLE); else - writel(hwirq, per_cpu_int_base + - ARMADA_370_XP_INT_CLEAR_MASK_OFFS); + writel(hwirq, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); } #ifdef CONFIG_PCI_MSI @@ -329,19 +324,18 @@ static void armada_370_xp_msi_reenable_percpu(void) u32 reg; /* Enable MSI doorbell mask and combined cpu local interrupt */ - reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); reg |= msi_doorbell_mask(); - writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); /* Unmask local doorbell interrupt */ - writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); + writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); } static int armada_370_xp_msi_init(struct device_node *node, phys_addr_t main_int_phys_base) { - msi_doorbell_addr = main_int_phys_base + - ARMADA_370_XP_SW_TRIG_INT_OFFS; + msi_doorbell_addr = main_int_phys_base + ARMADA_370_XP_SW_TRIG_INT; armada_370_xp_msi_inner_domain = irq_domain_add_linear(NULL, msi_doorbell_size(), @@ -362,7 +356,7 @@ static int armada_370_xp_msi_init(struct device_node *node, /* Unmask low 16 MSI irqs on non-IPI platforms */ if (!is_ipi_available()) - writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); + writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); return 0; } @@ -391,7 +385,7 @@ static void armada_xp_mpic_perf_init(void) /* Enable Performance Counter Overflow interrupts */ writel(ARMADA_370_XP_INT_CAUSE_PERF(cpuid), - per_cpu_int_base + ARMADA_370_XP_INT_FABRIC_MASK_OFFS); + per_cpu_int_base + ARMADA_370_XP_INT_FABRIC_MASK); } #ifdef CONFIG_SMP @@ -400,17 +394,17 @@ static struct irq_domain *ipi_domain; static void armada_370_xp_ipi_mask(struct irq_data *d) { u32 reg; - reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); reg &= ~BIT(d->hwirq); - writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); } static void armada_370_xp_ipi_unmask(struct irq_data *d) { u32 reg; - reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); reg |= BIT(d->hwirq); - writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); } static void armada_370_xp_ipi_send_mask(struct irq_data *d, @@ -431,12 +425,12 @@ static void armada_370_xp_ipi_send_mask(struct irq_data *d, /* submit softirq */ writel((map << 8) | d->hwirq, main_int_base + - ARMADA_370_XP_SW_TRIG_INT_OFFS); + ARMADA_370_XP_SW_TRIG_INT); } static void armada_370_xp_ipi_ack(struct irq_data *d) { - writel(~BIT(d->hwirq), per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); + writel(~BIT(d->hwirq), per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE); } static struct irq_chip ipi_irqchip = { @@ -539,19 +533,19 @@ static void armada_xp_mpic_smp_cpu_init(void) nr_irqs = (control >> 2) & 0x3ff; for (i = 0; i < nr_irqs; i++) - writel(i, per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS); + writel(i, per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK); if (!is_ipi_available()) return; /* Disable all IPIs */ - writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); /* Clear pending IPIs */ - writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); + writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE); /* Unmask IPI interrupt */ - writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); + writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); } static void armada_xp_mpic_reenable_percpu(void) @@ -622,9 +616,9 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h, armada_370_xp_irq_mask(irq_get_irq_data(virq)); if (!is_percpu_irq(hw)) writel(hw, per_cpu_int_base + - ARMADA_370_XP_INT_CLEAR_MASK_OFFS); + ARMADA_370_XP_INT_CLEAR_MASK); else - writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS); + writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE); irq_set_status_flags(virq, IRQ_LEVEL); if (is_percpu_irq(hw)) { @@ -651,12 +645,10 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained) { u32 msimask, msinr; - msimask = readl_relaxed(per_cpu_int_base + - ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); + msimask = readl_relaxed(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE); msimask &= msi_doorbell_mask(); - writel(~msimask, per_cpu_int_base + - ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); + writel(~msimask, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE); for (msinr = msi_doorbell_start(); msinr < msi_doorbell_end(); msinr++) { @@ -712,7 +704,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs) do { irqstat = readl_relaxed(per_cpu_int_base + - ARMADA_370_XP_CPU_INTACK_OFFS); + ARMADA_370_XP_CPU_INTACK); irqnr = irqstat & 0x3FF; if (irqnr > 1022) @@ -735,7 +727,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs) int ipi; ipimask = readl_relaxed(per_cpu_int_base + - ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS) + ARMADA_370_XP_IN_DRBEL_CAUSE) & IPI_DOORBELL_MASK; for_each_set_bit(ipi, &ipimask, IPI_DOORBELL_END) @@ -748,8 +740,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs) static int armada_370_xp_mpic_suspend(void) { - doorbell_mask_reg = readl(per_cpu_int_base + - ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + doorbell_mask_reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); return 0; } @@ -774,13 +765,13 @@ static void armada_370_xp_mpic_resume(void) if (!is_percpu_irq(irq)) { /* Non per-CPU interrupts */ writel(irq, per_cpu_int_base + - ARMADA_370_XP_INT_CLEAR_MASK_OFFS); + ARMADA_370_XP_INT_CLEAR_MASK); if (!irqd_irq_disabled(data)) armada_370_xp_irq_unmask(data); } else { /* Per-CPU interrupts */ writel(irq, main_int_base + - ARMADA_370_XP_INT_SET_ENABLE_OFFS); + ARMADA_370_XP_INT_SET_ENABLE); /* * Re-enable on the current CPU, @@ -794,7 +785,7 @@ static void armada_370_xp_mpic_resume(void) /* Reconfigure doorbells for IPIs and MSIs */ writel(doorbell_mask_reg, - per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); if (is_ipi_available()) { src0 = doorbell_mask_reg & IPI_DOORBELL_MASK; @@ -805,9 +796,9 @@ static void armada_370_xp_mpic_resume(void) } if (src0) - writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); + writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); if (src1) - writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); + writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); if (is_ipi_available()) ipi_resume(); @@ -847,7 +838,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, nr_irqs = (control >> 2) & 0x3ff; for (i = 0; i < nr_irqs; i++) - writel(i, main_int_base + ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS); + writel(i, main_int_base + ARMADA_370_XP_INT_CLEAR_ENABLE); armada_370_xp_mpic_domain = irq_domain_add_linear(node, nr_irqs, From 9fa3e59a003bb82977ade5011ca6255f5ec83c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 8 Jul 2024 17:17:53 +0200 Subject: [PATCH 02/73] irqchip/armada-370-xp: Change register constant suffix from _MSK to _MASK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is one occurrence of suffix _MSK in register constants, others have _MASK instead. Change the one to _MASK for consistency. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240708151801.11592-3-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 66d6a2ebc8a5..588a9e2e1887 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -126,7 +126,7 @@ /* Registers relative to per_cpu_int_base */ #define ARMADA_370_XP_IN_DRBEL_CAUSE (0x08) -#define ARMADA_370_XP_IN_DRBEL_MSK (0x0c) +#define ARMADA_370_XP_IN_DRBEL_MASK (0x0c) #define ARMADA_375_PPI_CAUSE (0x10) #define ARMADA_370_XP_CPU_INTACK (0x44) #define ARMADA_370_XP_INT_SET_MASK (0x48) @@ -324,9 +324,9 @@ static void armada_370_xp_msi_reenable_percpu(void) u32 reg; /* Enable MSI doorbell mask and combined cpu local interrupt */ - reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); + reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); reg |= msi_doorbell_mask(); - writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); + writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); /* Unmask local doorbell interrupt */ writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); @@ -394,17 +394,17 @@ static struct irq_domain *ipi_domain; static void armada_370_xp_ipi_mask(struct irq_data *d) { u32 reg; - reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); + reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); reg &= ~BIT(d->hwirq); - writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); + writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); } static void armada_370_xp_ipi_unmask(struct irq_data *d) { u32 reg; - reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); + reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); reg |= BIT(d->hwirq); - writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); + writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); } static void armada_370_xp_ipi_send_mask(struct irq_data *d, @@ -539,7 +539,7 @@ static void armada_xp_mpic_smp_cpu_init(void) return; /* Disable all IPIs */ - writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); + writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); /* Clear pending IPIs */ writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE); @@ -740,7 +740,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs) static int armada_370_xp_mpic_suspend(void) { - doorbell_mask_reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); + doorbell_mask_reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); return 0; } @@ -785,7 +785,7 @@ static void armada_370_xp_mpic_resume(void) /* Reconfigure doorbells for IPIs and MSIs */ writel(doorbell_mask_reg, - per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK); + per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); if (is_ipi_available()) { src0 = doorbell_mask_reg & IPI_DOORBELL_MASK; From f04ef167b350722f1623308c085c3ce119894035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 8 Jul 2024 17:17:54 +0200 Subject: [PATCH 03/73] irqchip/armada-370-xp: Change spaces to tabs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change spaces to tabs in register constants definitions. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240708151801.11592-4-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 588a9e2e1887..427ba5fd6adc 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -137,13 +137,13 @@ #define ARMADA_370_XP_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_MASK 0xFF -#define PCI_MSI_DOORBELL_START (16) -#define PCI_MSI_DOORBELL_NR (16) -#define PCI_MSI_DOORBELL_END (32) -#define PCI_MSI_DOORBELL_MASK 0xFFFF0000 +#define IPI_DOORBELL_START (0) +#define IPI_DOORBELL_END (8) +#define IPI_DOORBELL_MASK 0xFF +#define PCI_MSI_DOORBELL_START (16) +#define PCI_MSI_DOORBELL_NR (16) +#define PCI_MSI_DOORBELL_END (32) +#define PCI_MSI_DOORBELL_MASK 0xFFFF0000 /* MSI interrupt definitions for non-IPI platforms */ #define PCI_MSI_FULL_DOORBELL_START 0 From 2613b94d2dc5fc6b80ea8175ac3dbf579e6e1bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 8 Jul 2024 17:17:55 +0200 Subject: [PATCH 04/73] irqchip/armada-370-xp: Use BIT() and GENMASK() macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the BIT() and GENMASK() macros where appropriate. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/all/20240708151801.11592-5-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 427ba5fd6adc..18aca9b5d3b3 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -121,7 +121,7 @@ #define ARMADA_370_XP_INT_SET_ENABLE (0x30) #define ARMADA_370_XP_INT_CLEAR_ENABLE (0x34) #define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) -#define ARMADA_370_XP_INT_SOURCE_CPU_MASK 0xF +#define ARMADA_370_XP_INT_SOURCE_CPU_MASK GENMASK(3, 0) #define ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid) ((BIT(0) | BIT(8)) << cpuid) /* Registers relative to per_cpu_int_base */ @@ -132,18 +132,18 @@ #define ARMADA_370_XP_INT_SET_MASK (0x48) #define ARMADA_370_XP_INT_CLEAR_MASK (0x4C) #define ARMADA_370_XP_INT_FABRIC_MASK (0x54) -#define ARMADA_370_XP_INT_CAUSE_PERF(cpu) (1 << cpu) +#define ARMADA_370_XP_INT_CAUSE_PERF(cpu) BIT(cpu) #define ARMADA_370_XP_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_MASK 0xFF +#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 0xFFFF0000 +#define PCI_MSI_DOORBELL_MASK GENMASK(31, 16) /* MSI interrupt definitions for non-IPI platforms */ #define PCI_MSI_FULL_DOORBELL_START 0 @@ -415,7 +415,7 @@ static void armada_370_xp_ipi_send_mask(struct irq_data *d, /* Convert our logical CPU mask into a physical one. */ for_each_cpu(cpu, mask) - map |= 1 << cpu_logical_map(cpu); + map |= BIT(cpu_logical_map(cpu)); /* * Ensure that stores to Normal memory are visible to the From 9236717b97e3f5f0a5c77e40a85b8355b6025311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 8 Jul 2024 17:17:56 +0200 Subject: [PATCH 05/73] irqchip/armada-370-xp: Cosmetic fix parentheses in register constant definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop parentheses where not needed and add them where it makes sense in register constant definitions. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240708151801.11592-6-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 38 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 18aca9b5d3b3..14d213e9b0d2 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -116,33 +116,33 @@ */ /* Registers relative to main_int_base */ -#define ARMADA_370_XP_INT_CONTROL (0x00) -#define ARMADA_370_XP_SW_TRIG_INT (0x04) -#define ARMADA_370_XP_INT_SET_ENABLE (0x30) -#define ARMADA_370_XP_INT_CLEAR_ENABLE (0x34) -#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4) +#define ARMADA_370_XP_INT_CONTROL 0x00 +#define ARMADA_370_XP_SW_TRIG_INT 0x04 +#define ARMADA_370_XP_INT_SET_ENABLE 0x30 +#define ARMADA_370_XP_INT_CLEAR_ENABLE 0x34 +#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + (irq) * 4) #define ARMADA_370_XP_INT_SOURCE_CPU_MASK GENMASK(3, 0) -#define ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid) ((BIT(0) | BIT(8)) << cpuid) +#define ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid) ((BIT(0) | BIT(8)) << (cpuid)) /* Registers relative to per_cpu_int_base */ -#define ARMADA_370_XP_IN_DRBEL_CAUSE (0x08) -#define ARMADA_370_XP_IN_DRBEL_MASK (0x0c) -#define ARMADA_375_PPI_CAUSE (0x10) -#define ARMADA_370_XP_CPU_INTACK (0x44) -#define ARMADA_370_XP_INT_SET_MASK (0x48) -#define ARMADA_370_XP_INT_CLEAR_MASK (0x4C) -#define ARMADA_370_XP_INT_FABRIC_MASK (0x54) +#define ARMADA_370_XP_IN_DRBEL_CAUSE 0x08 +#define ARMADA_370_XP_IN_DRBEL_MASK 0x0c +#define ARMADA_375_PPI_CAUSE 0x10 +#define ARMADA_370_XP_CPU_INTACK 0x44 +#define ARMADA_370_XP_INT_SET_MASK 0x48 +#define ARMADA_370_XP_INT_CLEAR_MASK 0x4C +#define ARMADA_370_XP_INT_FABRIC_MASK 0x54 #define ARMADA_370_XP_INT_CAUSE_PERF(cpu) BIT(cpu) -#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28) +#define ARMADA_370_XP_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_START 0 +#define IPI_DOORBELL_END 8 #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_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 */ From e812dd60b6cca3211e7d83528c8bf077a51730b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 8 Jul 2024 17:17:57 +0200 Subject: [PATCH 06/73] irqchip/armada-370-xp: Change register constants prefix to MPIC_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the long ARMADA_370_XP_ prefix in register constants (ARMADA_375_ in one case) to MPIC_. The rationale is that it is shorter and more generic (this controller is called MPIC and is also used on Armada 38x and 39x). Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/all/20240708151801.11592-7-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 148 +++++++++++++--------------- 1 file changed, 69 insertions(+), 79 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 14d213e9b0d2..8f52de6d8921 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -66,18 +66,17 @@ * device * * The "global interrupt mask/unmask" is modified using the - * ARMADA_370_XP_INT_SET_ENABLE and ARMADA_370_XP_INT_CLEAR_ENABLE + * MPIC_INT_SET_ENABLE and MPIC_INT_CLEAR_ENABLE * registers, which are relative to "main_int_base". * - * The "per-CPU mask/unmask" is modified using the - * ARMADA_370_XP_INT_SET_MASK and ARMADA_370_XP_INT_CLEAR_MASK - * registers, which are relative to "per_cpu_int_base". This base - * address points to a special address, which automatically accesses - * the registers of the current CPU. + * 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, + * which automatically accesses the registers of the current CPU. * * The per-CPU mask/unmask can also be adjusted using the global - * per-interrupt ARMADA_370_XP_INT_SOURCE_CTL register, which we use - * to configure interrupt affinity. + * per-interrupt MPIC_INT_SOURCE_CTL register, which we use to + * configure interrupt affinity. * * Due to this model, all interrupts need to be mask/unmasked at two * different levels: at the global level and at the per-CPU level. @@ -91,9 +90,8 @@ * the current CPU, running the ->map() code. This allows to have * the interrupt unmasked at this level in non-SMP * configurations. In SMP configurations, the ->set_affinity() - * callback is called, which using the - * ARMADA_370_XP_INT_SOURCE_CTL() readjusts the per-CPU mask/unmask - * for the interrupt. + * callback is called, which using the MPIC_INT_SOURCE_CTL() + * readjusts the per-CPU mask/unmask for the interrupt. * * The ->mask() and ->unmask() operations only mask/unmask the * interrupt at the "global" level. @@ -116,25 +114,25 @@ */ /* Registers relative to main_int_base */ -#define ARMADA_370_XP_INT_CONTROL 0x00 -#define ARMADA_370_XP_SW_TRIG_INT 0x04 -#define ARMADA_370_XP_INT_SET_ENABLE 0x30 -#define ARMADA_370_XP_INT_CLEAR_ENABLE 0x34 -#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + (irq) * 4) -#define ARMADA_370_XP_INT_SOURCE_CPU_MASK GENMASK(3, 0) -#define ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid) ((BIT(0) | BIT(8)) << (cpuid)) +#define MPIC_INT_CONTROL 0x00 +#define MPIC_SW_TRIG_INT 0x04 +#define MPIC_INT_SET_ENABLE 0x30 +#define MPIC_INT_CLEAR_ENABLE 0x34 +#define MPIC_INT_SOURCE_CTL(irq) (0x100 + (irq) * 4) +#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 */ -#define ARMADA_370_XP_IN_DRBEL_CAUSE 0x08 -#define ARMADA_370_XP_IN_DRBEL_MASK 0x0c -#define ARMADA_375_PPI_CAUSE 0x10 -#define ARMADA_370_XP_CPU_INTACK 0x44 -#define ARMADA_370_XP_INT_SET_MASK 0x48 -#define ARMADA_370_XP_INT_CLEAR_MASK 0x4C -#define ARMADA_370_XP_INT_FABRIC_MASK 0x54 -#define ARMADA_370_XP_INT_CAUSE_PERF(cpu) BIT(cpu) +#define MPIC_IN_DRBEL_CAUSE 0x08 +#define MPIC_IN_DRBEL_MASK 0x0c +#define MPIC_PPI_CAUSE 0x10 +#define MPIC_CPU_INTACK 0x44 +#define MPIC_INT_SET_MASK 0x48 +#define MPIC_INT_CLEAR_MASK 0x4C +#define MPIC_INT_FABRIC_MASK 0x54 +#define MPIC_INT_CAUSE_PERF(cpu) BIT(cpu) -#define ARMADA_370_XP_MAX_PER_CPU_IRQS 28 +#define MPIC_MAX_PER_CPU_IRQS 28 /* IPI and MSI interrupt definitions for IPI platforms */ #define IPI_DOORBELL_START 0 @@ -203,7 +201,7 @@ static inline unsigned int msi_doorbell_end(void) static inline bool is_percpu_irq(irq_hw_number_t irq) { - if (irq <= ARMADA_370_XP_MAX_PER_CPU_IRQS) + if (irq <= MPIC_MAX_PER_CPU_IRQS) return true; return false; @@ -219,9 +217,9 @@ static void armada_370_xp_irq_mask(struct irq_data *d) irq_hw_number_t hwirq = irqd_to_hwirq(d); if (!is_percpu_irq(hwirq)) - writel(hwirq, main_int_base + ARMADA_370_XP_INT_CLEAR_ENABLE); + writel(hwirq, main_int_base + MPIC_INT_CLEAR_ENABLE); else - writel(hwirq, per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK); + writel(hwirq, per_cpu_int_base + MPIC_INT_SET_MASK); } static void armada_370_xp_irq_unmask(struct irq_data *d) @@ -229,9 +227,9 @@ static void armada_370_xp_irq_unmask(struct irq_data *d) irq_hw_number_t hwirq = irqd_to_hwirq(d); if (!is_percpu_irq(hwirq)) - writel(hwirq, main_int_base + ARMADA_370_XP_INT_SET_ENABLE); + writel(hwirq, main_int_base + MPIC_INT_SET_ENABLE); else - writel(hwirq, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); + writel(hwirq, per_cpu_int_base + MPIC_INT_CLEAR_MASK); } #ifdef CONFIG_PCI_MSI @@ -324,18 +322,18 @@ static void armada_370_xp_msi_reenable_percpu(void) u32 reg; /* Enable MSI doorbell mask and combined cpu local interrupt */ - reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); + reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK); reg |= msi_doorbell_mask(); - writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); + writel(reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK); /* Unmask local doorbell interrupt */ - writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); + writel(1, per_cpu_int_base + MPIC_INT_CLEAR_MASK); } static int armada_370_xp_msi_init(struct device_node *node, phys_addr_t main_int_phys_base) { - msi_doorbell_addr = main_int_phys_base + ARMADA_370_XP_SW_TRIG_INT; + msi_doorbell_addr = main_int_phys_base + MPIC_SW_TRIG_INT; armada_370_xp_msi_inner_domain = irq_domain_add_linear(NULL, msi_doorbell_size(), @@ -356,7 +354,7 @@ static int armada_370_xp_msi_init(struct device_node *node, /* Unmask low 16 MSI irqs on non-IPI platforms */ if (!is_ipi_available()) - writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); + writel(0, per_cpu_int_base + MPIC_INT_CLEAR_MASK); return 0; } @@ -384,8 +382,8 @@ static void armada_xp_mpic_perf_init(void) cpuid = cpu_logical_map(smp_processor_id()); /* Enable Performance Counter Overflow interrupts */ - writel(ARMADA_370_XP_INT_CAUSE_PERF(cpuid), - per_cpu_int_base + ARMADA_370_XP_INT_FABRIC_MASK); + writel(MPIC_INT_CAUSE_PERF(cpuid), + per_cpu_int_base + MPIC_INT_FABRIC_MASK); } #ifdef CONFIG_SMP @@ -394,17 +392,17 @@ static struct irq_domain *ipi_domain; static void armada_370_xp_ipi_mask(struct irq_data *d) { u32 reg; - reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); + reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK); reg &= ~BIT(d->hwirq); - writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); + writel(reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK); } static void armada_370_xp_ipi_unmask(struct irq_data *d) { u32 reg; - reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); + reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK); reg |= BIT(d->hwirq); - writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); + writel(reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK); } static void armada_370_xp_ipi_send_mask(struct irq_data *d, @@ -424,13 +422,12 @@ static void armada_370_xp_ipi_send_mask(struct irq_data *d, dsb(); /* submit softirq */ - writel((map << 8) | d->hwirq, main_int_base + - ARMADA_370_XP_SW_TRIG_INT); + writel((map << 8) | d->hwirq, main_int_base + MPIC_SW_TRIG_INT); } static void armada_370_xp_ipi_ack(struct irq_data *d) { - writel(~BIT(d->hwirq), per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE); + writel(~BIT(d->hwirq), per_cpu_int_base + MPIC_IN_DRBEL_CAUSE); } static struct irq_chip ipi_irqchip = { @@ -515,9 +512,8 @@ static int armada_xp_set_affinity(struct irq_data *d, /* 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 + ARMADA_370_XP_INT_SOURCE_CTL(hwirq), - ARMADA_370_XP_INT_SOURCE_CPU_MASK, - BIT(cpu_logical_map(cpu))); + atomic_io_modify(main_int_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)); @@ -529,23 +525,23 @@ static void armada_xp_mpic_smp_cpu_init(void) u32 control; int nr_irqs, i; - control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL); + control = readl(main_int_base + MPIC_INT_CONTROL); nr_irqs = (control >> 2) & 0x3ff; for (i = 0; i < nr_irqs; i++) - writel(i, per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK); + writel(i, per_cpu_int_base + MPIC_INT_SET_MASK); if (!is_ipi_available()) return; /* Disable all IPIs */ - writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); + writel(0, per_cpu_int_base + MPIC_IN_DRBEL_MASK); /* Clear pending IPIs */ - writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE); + writel(0, per_cpu_int_base + MPIC_IN_DRBEL_CAUSE); /* Unmask IPI interrupt */ - writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); + writel(0, per_cpu_int_base + MPIC_INT_CLEAR_MASK); } static void armada_xp_mpic_reenable_percpu(void) @@ -553,7 +549,7 @@ static void armada_xp_mpic_reenable_percpu(void) unsigned int irq; /* Re-enable per-CPU interrupts that were enabled before suspend */ - for (irq = 0; irq < ARMADA_370_XP_MAX_PER_CPU_IRQS; irq++) { + for (irq = 0; irq < MPIC_MAX_PER_CPU_IRQS; irq++) { struct irq_data *data; int virq; @@ -615,10 +611,9 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h, armada_370_xp_irq_mask(irq_get_irq_data(virq)); if (!is_percpu_irq(hw)) - writel(hw, per_cpu_int_base + - ARMADA_370_XP_INT_CLEAR_MASK); + writel(hw, per_cpu_int_base + MPIC_INT_CLEAR_MASK); else - writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE); + writel(hw, main_int_base + MPIC_INT_SET_ENABLE); irq_set_status_flags(virq, IRQ_LEVEL); if (is_percpu_irq(hw)) { @@ -645,10 +640,10 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained) { u32 msimask, msinr; - msimask = readl_relaxed(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE); + msimask = readl_relaxed(per_cpu_int_base + MPIC_IN_DRBEL_CAUSE); msimask &= msi_doorbell_mask(); - writel(~msimask, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE); + writel(~msimask, per_cpu_int_base + MPIC_IN_DRBEL_CAUSE); for (msinr = msi_doorbell_start(); msinr < msi_doorbell_end(); msinr++) { @@ -673,17 +668,16 @@ static void armada_370_xp_mpic_handle_cascade_irq(struct irq_desc *desc) chained_irq_enter(chip, desc); - irqmap = readl_relaxed(per_cpu_int_base + ARMADA_375_PPI_CAUSE); + irqmap = readl_relaxed(per_cpu_int_base + MPIC_PPI_CAUSE); cpuid = cpu_logical_map(smp_processor_id()); for_each_set_bit(irqn, &irqmap, BITS_PER_LONG) { - irqsrc = readl_relaxed(main_int_base + - ARMADA_370_XP_INT_SOURCE_CTL(irqn)); + irqsrc = readl_relaxed(main_int_base + MPIC_INT_SOURCE_CTL(irqn)); /* Check if the interrupt is not masked on current CPU. * Test IRQ (0-1) and FIQ (8-9) mask bits. */ - if (!(irqsrc & ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid))) + if (!(irqsrc & MPIC_INT_IRQ_FIQ_MASK(cpuid))) continue; if (irqn == 0 || irqn == 1) { @@ -703,8 +697,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs) u32 irqstat, irqnr; do { - irqstat = readl_relaxed(per_cpu_int_base + - ARMADA_370_XP_CPU_INTACK); + irqstat = readl_relaxed(per_cpu_int_base + MPIC_CPU_INTACK); irqnr = irqstat & 0x3FF; if (irqnr > 1022) @@ -727,7 +720,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs) int ipi; ipimask = readl_relaxed(per_cpu_int_base + - ARMADA_370_XP_IN_DRBEL_CAUSE) + MPIC_IN_DRBEL_CAUSE) & IPI_DOORBELL_MASK; for_each_set_bit(ipi, &ipimask, IPI_DOORBELL_END) @@ -740,7 +733,7 @@ armada_370_xp_handle_irq(struct pt_regs *regs) static int armada_370_xp_mpic_suspend(void) { - doorbell_mask_reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); + doorbell_mask_reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK); return 0; } @@ -751,7 +744,7 @@ static void armada_370_xp_mpic_resume(void) irq_hw_number_t irq; /* Re-enable interrupts */ - nirqs = (readl(main_int_base + ARMADA_370_XP_INT_CONTROL) >> 2) & 0x3ff; + nirqs = (readl(main_int_base + MPIC_INT_CONTROL) >> 2) & 0x3ff; for (irq = 0; irq < nirqs; irq++) { struct irq_data *data; int virq; @@ -764,14 +757,12 @@ static void armada_370_xp_mpic_resume(void) if (!is_percpu_irq(irq)) { /* Non per-CPU interrupts */ - writel(irq, per_cpu_int_base + - ARMADA_370_XP_INT_CLEAR_MASK); + writel(irq, per_cpu_int_base + MPIC_INT_CLEAR_MASK); if (!irqd_irq_disabled(data)) armada_370_xp_irq_unmask(data); } else { /* Per-CPU interrupts */ - writel(irq, main_int_base + - ARMADA_370_XP_INT_SET_ENABLE); + writel(irq, main_int_base + MPIC_INT_SET_ENABLE); /* * Re-enable on the current CPU, @@ -784,8 +775,7 @@ static void armada_370_xp_mpic_resume(void) } /* Reconfigure doorbells for IPIs and MSIs */ - writel(doorbell_mask_reg, - per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MASK); + writel(doorbell_mask_reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK); if (is_ipi_available()) { src0 = doorbell_mask_reg & IPI_DOORBELL_MASK; @@ -796,9 +786,9 @@ static void armada_370_xp_mpic_resume(void) } if (src0) - writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); + writel(0, per_cpu_int_base + MPIC_INT_CLEAR_MASK); if (src1) - writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK); + writel(1, per_cpu_int_base + MPIC_INT_CLEAR_MASK); if (is_ipi_available()) ipi_resume(); @@ -834,11 +824,11 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, resource_size(&per_cpu_int_res)); BUG_ON(!per_cpu_int_base); - control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL); + control = readl(main_int_base + MPIC_INT_CONTROL); nr_irqs = (control >> 2) & 0x3ff; for (i = 0; i < nr_irqs; i++) - writel(i, main_int_base + ARMADA_370_XP_INT_CLEAR_ENABLE); + writel(i, main_int_base + MPIC_INT_CLEAR_ENABLE); armada_370_xp_mpic_domain = irq_domain_add_linear(node, nr_irqs, From 0cbbf7c15d197ac370387c08d900abe142153cd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 8 Jul 2024 17:17:58 +0200 Subject: [PATCH 07/73] irqchip/armada-370-xp: Use correct type for cpu variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use unsigned int instead of int for variable storing the cpu number. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/all/20240708151801.11592-8-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 8f52de6d8921..b9631cc25c0b 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -409,7 +409,7 @@ static void armada_370_xp_ipi_send_mask(struct irq_data *d, const struct cpumask *mask) { unsigned long map = 0; - int cpu; + unsigned int cpu; /* Convert our logical CPU mask into a physical one. */ for_each_cpu(cpu, mask) @@ -507,7 +507,7 @@ static int armada_xp_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { irq_hw_number_t hwirq = irqd_to_hwirq(d); - int cpu; + unsigned int cpu; /* Select a single core from the affinity mask which is online */ cpu = cpumask_any_and(mask_val, cpu_online_mask); From ccef3a991b7c972cccce4aee8e62f70e3a706e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 8 Jul 2024 17:17:59 +0200 Subject: [PATCH 08/73] irqchip/armada-370-xp: Simplify is_percpu_irq() code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Simplify the code in the is_percpu_irq() function. Instead of if (condition) return true; return false; simply return condition. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240708151801.11592-9-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index b9631cc25c0b..cfd6dc803150 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -201,10 +201,7 @@ static inline unsigned int msi_doorbell_end(void) static inline bool is_percpu_irq(irq_hw_number_t irq) { - if (irq <= MPIC_MAX_PER_CPU_IRQS) - return true; - - return false; + return irq <= MPIC_MAX_PER_CPU_IRQS; } /* From 045c4bb864489fda99309dfa902346570d576a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 8 Jul 2024 17:18:00 +0200 Subject: [PATCH 09/73] irqchip/armada-370-xp: Change to SPDX license identifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the license identifier to SPDX style. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/all/20240708151801.11592-10-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index cfd6dc803150..3d15d0bb7605 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Marvell Armada 370 and Armada XP SoC IRQ handling * @@ -7,10 +8,6 @@ * Gregory CLEMENT * Thomas Petazzoni * Ben Dooks - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. */ #include From 644799f920c906666b5393c33dcf3008ace1ef6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Mon, 8 Jul 2024 17:18:01 +0200 Subject: [PATCH 10/73] irqchip/armada-370-xp: Declare iterators in for loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Where possible, declare iterators in for cycle. This is possible since kernel uses -std=gnu11. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Link: https://lore.kernel.org/all/20240708151801.11592-11-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 3d15d0bb7605..22e1a493abae 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -276,7 +276,7 @@ static struct irq_chip armada_370_xp_msi_bottom_irq_chip = { static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, void *args) { - int hwirq, i; + int hwirq; mutex_lock(&msi_used_lock); hwirq = bitmap_find_free_region(msi_used, msi_doorbell_size(), @@ -286,7 +286,7 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, if (hwirq < 0) return -ENOSPC; - for (i = 0; i < nr_irqs; i++) { + for (int i = 0; i < nr_irqs; i++) { irq_domain_set_info(domain, virq + i, hwirq + i, &armada_370_xp_msi_bottom_irq_chip, domain->host_data, handle_simple_irq, @@ -436,9 +436,7 @@ static int armada_370_xp_ipi_alloc(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs, void *args) { - int i; - - for (i = 0; i < nr_irqs; i++) { + for (int i = 0; i < nr_irqs; i++) { irq_set_percpu_devid(virq + i); irq_domain_set_info(d, virq + i, i, &ipi_irqchip, d->host_data, @@ -463,9 +461,7 @@ static const struct irq_domain_ops ipi_domain_ops = { static void ipi_resume(void) { - int i; - - for (i = 0; i < IPI_DOORBELL_END; i++) { + for (int i = 0; i < IPI_DOORBELL_END; i++) { int irq; irq = irq_find_mapping(ipi_domain, i); @@ -517,12 +513,12 @@ static int armada_xp_set_affinity(struct irq_data *d, static void armada_xp_mpic_smp_cpu_init(void) { u32 control; - int nr_irqs, i; + int nr_irqs; control = readl(main_int_base + MPIC_INT_CONTROL); nr_irqs = (control >> 2) & 0x3ff; - for (i = 0; i < nr_irqs; i++) + for (int i = 0; i < nr_irqs; i++) writel(i, per_cpu_int_base + MPIC_INT_SET_MASK); if (!is_ipi_available()) @@ -540,10 +536,8 @@ static void armada_xp_mpic_smp_cpu_init(void) static void armada_xp_mpic_reenable_percpu(void) { - unsigned int irq; - /* Re-enable per-CPU interrupts that were enabled before suspend */ - for (irq = 0; irq < MPIC_MAX_PER_CPU_IRQS; irq++) { + for (unsigned int irq = 0; irq < MPIC_MAX_PER_CPU_IRQS; irq++) { struct irq_data *data; int virq; @@ -735,11 +729,10 @@ static void armada_370_xp_mpic_resume(void) { bool src0, src1; int nirqs; - irq_hw_number_t irq; /* Re-enable interrupts */ nirqs = (readl(main_int_base + MPIC_INT_CONTROL) >> 2) & 0x3ff; - for (irq = 0; irq < nirqs; irq++) { + for (irq_hw_number_t irq = 0; irq < nirqs; irq++) { struct irq_data *data; int virq; @@ -797,7 +790,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, struct device_node *parent) { struct resource main_int_res, per_cpu_int_res; - int nr_irqs, i; + int nr_irqs; u32 control; BUG_ON(of_address_to_resource(node, 0, &main_int_res)); @@ -821,7 +814,7 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, control = readl(main_int_base + MPIC_INT_CONTROL); nr_irqs = (control >> 2) & 0x3ff; - for (i = 0; i < nr_irqs; i++) + for (int i = 0; i < nr_irqs; i++) writel(i, main_int_base + MPIC_INT_CLEAR_ENABLE); armada_370_xp_mpic_domain = From 55689986d7eaed09b6569b1e06b29044cd3cb590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 13:57:39 +0200 Subject: [PATCH 11/73] irqchip/armada-370-xp: Rename variable for consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the irq variable to virq in the ipi_resume() function for consistency with the rest of the code. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240711115748.30268-2-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 22e1a493abae..7016b206bddd 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -462,14 +462,14 @@ static const struct irq_domain_ops ipi_domain_ops = { static void ipi_resume(void) { for (int i = 0; i < IPI_DOORBELL_END; i++) { - int irq; + int virq; - irq = irq_find_mapping(ipi_domain, i); - if (irq <= 0) + virq = irq_find_mapping(ipi_domain, i); + if (virq <= 0) continue; - if (irq_percpu_is_enabled(irq)) { + if (irq_percpu_is_enabled(virq)) { struct irq_data *d; - d = irq_domain_get_irq_data(ipi_domain, irq); + d = irq_domain_get_irq_data(ipi_domain, virq); armada_370_xp_ipi_unmask(d); } } From e4cd7c553a00e2904689cac543e314b1962c6a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 13:57:40 +0200 Subject: [PATCH 12/73] irqchip/armada-370-xp: Use unsigned int type for virqs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The return type of irq_find_mapping() and irq_linear_revmap() is unsigned int. Use the unsigned int type for the variables storing the return value. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240711115748.30268-3-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 7016b206bddd..b29f3bbfb1c3 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -462,10 +462,10 @@ static const struct irq_domain_ops ipi_domain_ops = { static void ipi_resume(void) { for (int i = 0; i < IPI_DOORBELL_END; i++) { - int virq; + unsigned int virq; virq = irq_find_mapping(ipi_domain, i); - if (virq <= 0) + if (!virq) continue; if (irq_percpu_is_enabled(virq)) { struct irq_data *d; @@ -539,7 +539,7 @@ static void armada_xp_mpic_reenable_percpu(void) /* Re-enable per-CPU interrupts that were enabled before suspend */ for (unsigned int irq = 0; irq < MPIC_MAX_PER_CPU_IRQS; irq++) { struct irq_data *data; - int virq; + unsigned int virq; virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq); if (virq == 0) @@ -734,7 +734,7 @@ static void armada_370_xp_mpic_resume(void) nirqs = (readl(main_int_base + MPIC_INT_CONTROL) >> 2) & 0x3ff; for (irq_hw_number_t irq = 0; irq < nirqs; irq++) { struct irq_data *data; - int virq; + unsigned int virq; virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq); if (virq == 0) From 88d49ee30ca52ba9a0dd593860a1323426791710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 13:57:41 +0200 Subject: [PATCH 13/73] irqchip/armada-370-xp: Use !virq instead of virq == 0 in condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use !virq instead of virq == 0 when checking for availability of the virq. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240711115748.30268-4-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index b29f3bbfb1c3..c007610413fe 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -542,7 +542,7 @@ static void armada_xp_mpic_reenable_percpu(void) unsigned int virq; virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq); - if (virq == 0) + if (!virq) continue; data = irq_get_irq_data(virq); @@ -737,7 +737,7 @@ static void armada_370_xp_mpic_resume(void) unsigned int virq; virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq); - if (virq == 0) + if (!virq) continue; data = irq_get_irq_data(virq); From 0381be072f301088637ab6b01f2c8f0e5745e0e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 13:57:42 +0200 Subject: [PATCH 14/73] irqchip/armada-370-xp: Simplify ipi_resume() code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor the ipi_resume() function to drop one indentation level. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240711115748.30268-5-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index c007610413fe..316c27c97951 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -462,16 +462,14 @@ static const struct irq_domain_ops ipi_domain_ops = { static void ipi_resume(void) { for (int i = 0; i < IPI_DOORBELL_END; i++) { - unsigned int virq; + unsigned int virq = irq_find_mapping(ipi_domain, i); + struct irq_data *d; - virq = irq_find_mapping(ipi_domain, i); - if (!virq) + if (!virq || !irq_percpu_is_enabled(virq)) continue; - if (irq_percpu_is_enabled(virq)) { - struct irq_data *d; - d = irq_domain_get_irq_data(ipi_domain, virq); - armada_370_xp_ipi_unmask(d); - } + + d = irq_domain_get_irq_data(ipi_domain, virq); + armada_370_xp_ipi_unmask(d); } } From 5302e767ebfc1c297bf76f6ef65888249b831a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 13:57:43 +0200 Subject: [PATCH 15/73] irqchip/armada-370-xp: Improve indentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add some blank lines and other indentation improvements. Checkpatch now stops complaining. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240711115748.30268-6-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 56 ++++++++++++++--------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 316c27c97951..a66d3459f7fa 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -229,9 +229,9 @@ static void armada_370_xp_irq_unmask(struct irq_data *d) #ifdef CONFIG_PCI_MSI static struct irq_chip armada_370_xp_msi_irq_chip = { - .name = "MPIC MSI", - .irq_mask = pci_msi_mask_irq, - .irq_unmask = pci_msi_unmask_irq, + .name = "MPIC MSI", + .irq_mask = pci_msi_mask_irq, + .irq_unmask = pci_msi_unmask_irq, }; static struct msi_domain_info armada_370_xp_msi_domain_info = { @@ -386,6 +386,7 @@ static struct irq_domain *ipi_domain; static void armada_370_xp_ipi_mask(struct irq_data *d) { u32 reg; + reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK); reg &= ~BIT(d->hwirq); writel(reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK); @@ -394,6 +395,7 @@ static void armada_370_xp_ipi_mask(struct irq_data *d) static void armada_370_xp_ipi_unmask(struct irq_data *d) { u32 reg; + reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK); reg |= BIT(d->hwirq); writel(reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK); @@ -432,24 +434,20 @@ static struct irq_chip ipi_irqchip = { .ipi_send_mask = armada_370_xp_ipi_send_mask, }; -static int armada_370_xp_ipi_alloc(struct irq_domain *d, - unsigned int virq, - unsigned int nr_irqs, void *args) +static int armada_370_xp_ipi_alloc(struct irq_domain *d, unsigned int virq, + unsigned int nr_irqs, void *args) { for (int i = 0; i < nr_irqs; i++) { irq_set_percpu_devid(virq + i); - irq_domain_set_info(d, virq + i, i, &ipi_irqchip, - d->host_data, - handle_percpu_devid_irq, - NULL, NULL); + irq_domain_set_info(d, virq + i, i, &ipi_irqchip, d->host_data, + handle_percpu_devid_irq, NULL, NULL); } return 0; } -static void armada_370_xp_ipi_free(struct irq_domain *d, - unsigned int virq, - unsigned int nr_irqs) +static void armada_370_xp_ipi_free(struct irq_domain *d, unsigned int virq, + unsigned int nr_irqs) { /* Not freeing IPIs */ } @@ -477,8 +475,7 @@ static __init void armada_xp_ipi_init(struct device_node *node) { int base_ipi; - ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node), - IPI_DOORBELL_END, + ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node), IPI_DOORBELL_END, &ipi_domain_ops, NULL); if (WARN_ON(!ipi_domain)) return; @@ -562,6 +559,7 @@ static int armada_xp_mpic_starting_cpu(unsigned int cpu) armada_xp_mpic_perf_init(); armada_xp_mpic_smp_cpu_init(); armada_xp_mpic_reenable_percpu(); + return 0; } @@ -570,6 +568,7 @@ static int mpic_cascaded_starting_cpu(unsigned int cpu) armada_xp_mpic_perf_init(); armada_xp_mpic_reenable_percpu(); enable_percpu_irq(parent_irq, IRQ_TYPE_NONE); + return 0; } #else @@ -579,9 +578,9 @@ static void ipi_resume(void) {} static struct irq_chip armada_370_xp_irq_chip = { .name = "MPIC", - .irq_mask = armada_370_xp_irq_mask, - .irq_mask_ack = armada_370_xp_irq_mask, - .irq_unmask = armada_370_xp_irq_unmask, + .irq_mask = armada_370_xp_irq_mask, + .irq_mask_ack = armada_370_xp_irq_mask, + .irq_unmask = armada_370_xp_irq_unmask, #ifdef CONFIG_SMP .irq_set_affinity = armada_xp_set_affinity, #endif @@ -605,10 +604,9 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h, if (is_percpu_irq(hw)) { irq_set_percpu_devid(virq); irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, - handle_percpu_devid_irq); + handle_percpu_devid_irq); } else { - irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, - handle_level_irq); + irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, handle_level_irq); irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); } irq_set_probe(virq); @@ -617,8 +615,8 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h, } static const struct irq_domain_ops armada_370_xp_mpic_irq_ops = { - .map = armada_370_xp_mpic_irq_map, - .xlate = irq_domain_xlate_onecell, + .map = armada_370_xp_mpic_irq_map, + .xlate = irq_domain_xlate_onecell, }; #ifdef CONFIG_PCI_MSI @@ -705,21 +703,20 @@ armada_370_xp_handle_irq(struct pt_regs *regs) unsigned long ipimask; int ipi; - ipimask = readl_relaxed(per_cpu_int_base + - MPIC_IN_DRBEL_CAUSE) - & IPI_DOORBELL_MASK; + ipimask = readl_relaxed(per_cpu_int_base + MPIC_IN_DRBEL_CAUSE) & + IPI_DOORBELL_MASK; for_each_set_bit(ipi, &ipimask, IPI_DOORBELL_END) generic_handle_domain_irq(ipi_domain, ipi); } #endif - } while (1); } static int armada_370_xp_mpic_suspend(void) { doorbell_mask_reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK); + return 0; } @@ -815,9 +812,8 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, for (int i = 0; i < nr_irqs; i++) writel(i, main_int_base + MPIC_INT_CLEAR_ENABLE); - armada_370_xp_mpic_domain = - irq_domain_add_linear(node, nr_irqs, - &armada_370_xp_mpic_irq_ops, NULL); + armada_370_xp_mpic_domain = irq_domain_add_linear(node, nr_irqs, + &armada_370_xp_mpic_irq_ops, NULL); BUG_ON(!armada_370_xp_mpic_domain); irq_domain_update_bus_token(armada_370_xp_mpic_domain, DOMAIN_BUS_WIRED); From f63f54a2b8ff0815788d0c73cbbd5a96a3d467eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 13:57:44 +0200 Subject: [PATCH 16/73] irqchip/armada-370-xp: Change symbol prefixes to mpic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change symbol prefixes from armada_370_xp_ or others to mpic_. The rationale is that it is shorter and more generic (this controller is called MPIC and is also used on Armada 38x and 39x). Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240711115748.30268-7-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 305 +++++++++++++--------------- 1 file changed, 142 insertions(+), 163 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index a66d3459f7fa..27588347189e 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -150,18 +150,18 @@ static void __iomem *per_cpu_int_base; static void __iomem *main_int_base; -static struct irq_domain *armada_370_xp_mpic_domain; +static struct irq_domain *mpic_domain; static u32 doorbell_mask_reg; static int parent_irq; #ifdef CONFIG_PCI_MSI -static struct irq_domain *armada_370_xp_msi_domain; -static struct irq_domain *armada_370_xp_msi_inner_domain; +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; #endif -static inline bool is_ipi_available(void) +static inline bool mpic_is_ipi_available(void) { /* * We distinguish IPI availability in the IC by the IC not having a @@ -174,29 +174,25 @@ static inline bool is_ipi_available(void) static inline u32 msi_doorbell_mask(void) { - return is_ipi_available() ? PCI_MSI_DOORBELL_MASK : - PCI_MSI_FULL_DOORBELL_MASK; + return mpic_is_ipi_available() ? PCI_MSI_DOORBELL_MASK : PCI_MSI_FULL_DOORBELL_MASK; } static inline unsigned int msi_doorbell_start(void) { - return is_ipi_available() ? PCI_MSI_DOORBELL_START : - PCI_MSI_FULL_DOORBELL_START; + return mpic_is_ipi_available() ? PCI_MSI_DOORBELL_START : PCI_MSI_FULL_DOORBELL_START; } static inline unsigned int msi_doorbell_size(void) { - return is_ipi_available() ? PCI_MSI_DOORBELL_NR : - PCI_MSI_FULL_DOORBELL_NR; + return mpic_is_ipi_available() ? PCI_MSI_DOORBELL_NR : PCI_MSI_FULL_DOORBELL_NR; } static inline unsigned int msi_doorbell_end(void) { - return is_ipi_available() ? PCI_MSI_DOORBELL_END : - PCI_MSI_FULL_DOORBELL_END; + return mpic_is_ipi_available() ? PCI_MSI_DOORBELL_END : PCI_MSI_FULL_DOORBELL_END; } -static inline bool is_percpu_irq(irq_hw_number_t irq) +static inline bool mpic_is_percpu_irq(irq_hw_number_t irq) { return irq <= MPIC_MAX_PER_CPU_IRQS; } @@ -206,21 +202,21 @@ static inline bool is_percpu_irq(irq_hw_number_t irq) * For shared global interrupts, mask/unmask global enable bit * For CPU interrupts, mask/unmask the calling CPU's bit */ -static void armada_370_xp_irq_mask(struct irq_data *d) +static void mpic_irq_mask(struct irq_data *d) { irq_hw_number_t hwirq = irqd_to_hwirq(d); - if (!is_percpu_irq(hwirq)) + if (!mpic_is_percpu_irq(hwirq)) writel(hwirq, main_int_base + MPIC_INT_CLEAR_ENABLE); else writel(hwirq, per_cpu_int_base + MPIC_INT_SET_MASK); } -static void armada_370_xp_irq_unmask(struct irq_data *d) +static void mpic_irq_unmask(struct irq_data *d) { irq_hw_number_t hwirq = irqd_to_hwirq(d); - if (!is_percpu_irq(hwirq)) + if (!mpic_is_percpu_irq(hwirq)) writel(hwirq, main_int_base + MPIC_INT_SET_ENABLE); else writel(hwirq, per_cpu_int_base + MPIC_INT_CLEAR_MASK); @@ -228,19 +224,19 @@ static void armada_370_xp_irq_unmask(struct irq_data *d) #ifdef CONFIG_PCI_MSI -static struct irq_chip armada_370_xp_msi_irq_chip = { +static struct irq_chip mpic_msi_irq_chip = { .name = "MPIC MSI", .irq_mask = pci_msi_mask_irq, .irq_unmask = pci_msi_unmask_irq, }; -static struct msi_domain_info armada_370_xp_msi_domain_info = { +static struct msi_domain_info mpic_msi_domain_info = { .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX), - .chip = &armada_370_xp_msi_irq_chip, + .chip = &mpic_msi_irq_chip, }; -static void armada_370_xp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) +static void mpic_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) { unsigned int cpu = cpumask_first(irq_data_get_effective_affinity_mask(data)); @@ -249,8 +245,7 @@ static void armada_370_xp_compose_msi_msg(struct irq_data *data, struct msi_msg msg->data = BIT(cpu + 8) | (data->hwirq + msi_doorbell_start()); } -static int armada_370_xp_msi_set_affinity(struct irq_data *irq_data, - const struct cpumask *mask, bool force) +static int mpic_msi_set_affinity(struct irq_data *irq_data, const struct cpumask *mask, bool force) { unsigned int cpu; @@ -267,14 +262,14 @@ static int armada_370_xp_msi_set_affinity(struct irq_data *irq_data, return IRQ_SET_MASK_OK; } -static struct irq_chip armada_370_xp_msi_bottom_irq_chip = { +static struct irq_chip mpic_msi_bottom_irq_chip = { .name = "MPIC MSI", - .irq_compose_msi_msg = armada_370_xp_compose_msi_msg, - .irq_set_affinity = armada_370_xp_msi_set_affinity, + .irq_compose_msi_msg = mpic_compose_msi_msg, + .irq_set_affinity = mpic_msi_set_affinity, }; -static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, - unsigned int nr_irqs, void *args) +static int mpic_msi_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, + void *args) { int hwirq; @@ -288,7 +283,7 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, for (int i = 0; i < nr_irqs; i++) { irq_domain_set_info(domain, virq + i, hwirq + i, - &armada_370_xp_msi_bottom_irq_chip, + &mpic_msi_bottom_irq_chip, domain->host_data, handle_simple_irq, NULL, NULL); } @@ -296,8 +291,7 @@ static int armada_370_xp_msi_alloc(struct irq_domain *domain, unsigned int virq, return 0; } -static void armada_370_xp_msi_free(struct irq_domain *domain, - unsigned int virq, unsigned int nr_irqs) +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); @@ -306,12 +300,12 @@ static void armada_370_xp_msi_free(struct irq_domain *domain, mutex_unlock(&msi_used_lock); } -static const struct irq_domain_ops armada_370_xp_msi_domain_ops = { - .alloc = armada_370_xp_msi_alloc, - .free = armada_370_xp_msi_free, +static const struct irq_domain_ops mpic_msi_domain_ops = { + .alloc = mpic_msi_alloc, + .free = mpic_msi_free, }; -static void armada_370_xp_msi_reenable_percpu(void) +static void mpic_msi_reenable_percpu(void) { u32 reg; @@ -324,45 +318,41 @@ static void armada_370_xp_msi_reenable_percpu(void) writel(1, per_cpu_int_base + MPIC_INT_CLEAR_MASK); } -static int armada_370_xp_msi_init(struct device_node *node, - phys_addr_t main_int_phys_base) +static int 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; - armada_370_xp_msi_inner_domain = - irq_domain_add_linear(NULL, msi_doorbell_size(), - &armada_370_xp_msi_domain_ops, NULL); - if (!armada_370_xp_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; - armada_370_xp_msi_domain = - pci_msi_create_irq_domain(of_node_to_fwnode(node), - &armada_370_xp_msi_domain_info, - armada_370_xp_msi_inner_domain); - if (!armada_370_xp_msi_domain) { - irq_domain_remove(armada_370_xp_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; } - armada_370_xp_msi_reenable_percpu(); + mpic_msi_reenable_percpu(); /* Unmask low 16 MSI irqs on non-IPI platforms */ - if (!is_ipi_available()) + if (!mpic_is_ipi_available()) writel(0, per_cpu_int_base + MPIC_INT_CLEAR_MASK); return 0; } #else -static __maybe_unused void armada_370_xp_msi_reenable_percpu(void) {} +static __maybe_unused void mpic_msi_reenable_percpu(void) {} -static inline int armada_370_xp_msi_init(struct device_node *node, - phys_addr_t main_int_phys_base) +static inline int mpic_msi_init(struct device_node *node, + phys_addr_t main_int_phys_base) { return 0; } #endif -static void armada_xp_mpic_perf_init(void) +static void mpic_perf_init(void) { unsigned long cpuid; @@ -381,9 +371,9 @@ static void armada_xp_mpic_perf_init(void) } #ifdef CONFIG_SMP -static struct irq_domain *ipi_domain; +static struct irq_domain *mpic_ipi_domain; -static void armada_370_xp_ipi_mask(struct irq_data *d) +static void mpic_ipi_mask(struct irq_data *d) { u32 reg; @@ -392,7 +382,7 @@ static void armada_370_xp_ipi_mask(struct irq_data *d) writel(reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK); } -static void armada_370_xp_ipi_unmask(struct irq_data *d) +static void mpic_ipi_unmask(struct irq_data *d) { u32 reg; @@ -401,8 +391,7 @@ static void armada_370_xp_ipi_unmask(struct irq_data *d) writel(reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK); } -static void armada_370_xp_ipi_send_mask(struct irq_data *d, - const struct cpumask *mask) +static void mpic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask) { unsigned long map = 0; unsigned int cpu; @@ -421,75 +410,73 @@ static void armada_370_xp_ipi_send_mask(struct irq_data *d, writel((map << 8) | d->hwirq, main_int_base + MPIC_SW_TRIG_INT); } -static void armada_370_xp_ipi_ack(struct irq_data *d) +static void mpic_ipi_ack(struct irq_data *d) { writel(~BIT(d->hwirq), per_cpu_int_base + MPIC_IN_DRBEL_CAUSE); } -static struct irq_chip ipi_irqchip = { +static struct irq_chip mpic_ipi_irqchip = { .name = "IPI", - .irq_ack = armada_370_xp_ipi_ack, - .irq_mask = armada_370_xp_ipi_mask, - .irq_unmask = armada_370_xp_ipi_unmask, - .ipi_send_mask = armada_370_xp_ipi_send_mask, + .irq_ack = mpic_ipi_ack, + .irq_mask = mpic_ipi_mask, + .irq_unmask = mpic_ipi_unmask, + .ipi_send_mask = mpic_ipi_send_mask, }; -static int armada_370_xp_ipi_alloc(struct irq_domain *d, unsigned int virq, - unsigned int nr_irqs, void *args) +static int mpic_ipi_alloc(struct irq_domain *d, unsigned int virq, + unsigned int nr_irqs, void *args) { for (int i = 0; i < nr_irqs; i++) { irq_set_percpu_devid(virq + i); - irq_domain_set_info(d, virq + i, i, &ipi_irqchip, d->host_data, + irq_domain_set_info(d, virq + i, i, &mpic_ipi_irqchip, d->host_data, handle_percpu_devid_irq, NULL, NULL); } return 0; } -static void armada_370_xp_ipi_free(struct irq_domain *d, unsigned int virq, - unsigned int nr_irqs) +static void mpic_ipi_free(struct irq_domain *d, unsigned int virq, + unsigned int nr_irqs) { /* Not freeing IPIs */ } -static const struct irq_domain_ops ipi_domain_ops = { - .alloc = armada_370_xp_ipi_alloc, - .free = armada_370_xp_ipi_free, +static const struct irq_domain_ops mpic_ipi_domain_ops = { + .alloc = mpic_ipi_alloc, + .free = mpic_ipi_free, }; -static void ipi_resume(void) +static void mpic_ipi_resume(void) { for (int i = 0; i < IPI_DOORBELL_END; i++) { - unsigned int virq = irq_find_mapping(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(ipi_domain, virq); - armada_370_xp_ipi_unmask(d); + d = irq_domain_get_irq_data(mpic_ipi_domain, virq); + mpic_ipi_unmask(d); } } -static __init void armada_xp_ipi_init(struct device_node *node) +static __init void mpic_ipi_init(struct device_node *node) { int base_ipi; - ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node), IPI_DOORBELL_END, - &ipi_domain_ops, NULL); - if (WARN_ON(!ipi_domain)) + mpic_ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node), IPI_DOORBELL_END, + &mpic_ipi_domain_ops, NULL); + if (WARN_ON(!mpic_ipi_domain)) return; - irq_domain_update_bus_token(ipi_domain, DOMAIN_BUS_IPI); - base_ipi = irq_domain_alloc_irqs(ipi_domain, IPI_DOORBELL_END, 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_END, NUMA_NO_NODE, NULL); if (WARN_ON(!base_ipi)) return; - set_smp_ipi_range(base_ipi, IPI_DOORBELL_END); } -static int armada_xp_set_affinity(struct irq_data *d, - const struct cpumask *mask_val, bool force) +static int mpic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) { irq_hw_number_t hwirq = irqd_to_hwirq(d); unsigned int cpu; @@ -505,7 +492,7 @@ static int armada_xp_set_affinity(struct irq_data *d, return IRQ_SET_MASK_OK; } -static void armada_xp_mpic_smp_cpu_init(void) +static void mpic_smp_cpu_init(void) { u32 control; int nr_irqs; @@ -516,7 +503,7 @@ static void armada_xp_mpic_smp_cpu_init(void) for (int i = 0; i < nr_irqs; i++) writel(i, per_cpu_int_base + MPIC_INT_SET_MASK); - if (!is_ipi_available()) + if (!mpic_is_ipi_available()) return; /* Disable all IPIs */ @@ -529,14 +516,14 @@ static void armada_xp_mpic_smp_cpu_init(void) writel(0, per_cpu_int_base + MPIC_INT_CLEAR_MASK); } -static void armada_xp_mpic_reenable_percpu(void) +static void mpic_reenable_percpu(void) { /* Re-enable per-CPU interrupts that were enabled before suspend */ for (unsigned int irq = 0; irq < MPIC_MAX_PER_CPU_IRQS; irq++) { struct irq_data *data; unsigned int virq; - virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq); + virq = irq_linear_revmap(mpic_domain, irq); if (!virq) continue; @@ -545,82 +532,80 @@ static void armada_xp_mpic_reenable_percpu(void) if (!irq_percpu_is_enabled(virq)) continue; - armada_370_xp_irq_unmask(data); + mpic_irq_unmask(data); } - if (is_ipi_available()) - ipi_resume(); + if (mpic_is_ipi_available()) + mpic_ipi_resume(); - armada_370_xp_msi_reenable_percpu(); + mpic_msi_reenable_percpu(); } -static int armada_xp_mpic_starting_cpu(unsigned int cpu) +static int mpic_starting_cpu(unsigned int cpu) { - armada_xp_mpic_perf_init(); - armada_xp_mpic_smp_cpu_init(); - armada_xp_mpic_reenable_percpu(); + mpic_perf_init(); + mpic_smp_cpu_init(); + mpic_reenable_percpu(); return 0; } static int mpic_cascaded_starting_cpu(unsigned int cpu) { - armada_xp_mpic_perf_init(); - armada_xp_mpic_reenable_percpu(); + mpic_perf_init(); + mpic_reenable_percpu(); enable_percpu_irq(parent_irq, IRQ_TYPE_NONE); return 0; } #else -static void armada_xp_mpic_smp_cpu_init(void) {} -static void ipi_resume(void) {} +static void mpic_smp_cpu_init(void) {} +static void mpic_ipi_resume(void) {} #endif -static struct irq_chip armada_370_xp_irq_chip = { +static struct irq_chip mpic_irq_chip = { .name = "MPIC", - .irq_mask = armada_370_xp_irq_mask, - .irq_mask_ack = armada_370_xp_irq_mask, - .irq_unmask = armada_370_xp_irq_unmask, + .irq_mask = mpic_irq_mask, + .irq_mask_ack = mpic_irq_mask, + .irq_unmask = mpic_irq_unmask, #ifdef CONFIG_SMP - .irq_set_affinity = armada_xp_set_affinity, + .irq_set_affinity = mpic_set_affinity, #endif .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND, }; -static int armada_370_xp_mpic_irq_map(struct irq_domain *h, - unsigned int virq, irq_hw_number_t hw) +static int mpic_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) { /* IRQs 0 and 1 cannot be mapped, they are handled internally */ if (hw <= 1) return -EINVAL; - armada_370_xp_irq_mask(irq_get_irq_data(virq)); - if (!is_percpu_irq(hw)) + mpic_irq_mask(irq_get_irq_data(virq)); + if (!mpic_is_percpu_irq(hw)) writel(hw, per_cpu_int_base + MPIC_INT_CLEAR_MASK); else writel(hw, main_int_base + MPIC_INT_SET_ENABLE); irq_set_status_flags(virq, IRQ_LEVEL); - if (is_percpu_irq(hw)) { + if (mpic_is_percpu_irq(hw)) { irq_set_percpu_devid(virq); - irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, - handle_percpu_devid_irq); + irq_set_chip_and_handler(virq, &mpic_irq_chip, handle_percpu_devid_irq); } else { - irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, handle_level_irq); + irq_set_chip_and_handler(virq, &mpic_irq_chip, handle_level_irq); irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); } irq_set_probe(virq); - return 0; } -static const struct irq_domain_ops armada_370_xp_mpic_irq_ops = { - .map = armada_370_xp_mpic_irq_map, +static const struct irq_domain_ops mpic_irq_ops = { + .map = mpic_irq_map, .xlate = irq_domain_xlate_onecell, }; #ifdef CONFIG_PCI_MSI -static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained) +static void mpic_handle_msi_irq(struct pt_regs *regs, bool is_chained) { u32 msimask, msinr; @@ -638,14 +623,14 @@ static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained) irq = msinr - msi_doorbell_start(); - generic_handle_domain_irq(armada_370_xp_msi_inner_domain, irq); + generic_handle_domain_irq(mpic_msi_inner_domain, irq); } } #else -static void armada_370_xp_handle_msi_irq(struct pt_regs *r, bool b) {} +static void mpic_handle_msi_irq(struct pt_regs *r, bool b) {} #endif -static void armada_370_xp_mpic_handle_cascade_irq(struct irq_desc *desc) +static void mpic_handle_cascade_irq(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); unsigned long irqmap, irqn, irqsrc, cpuid; @@ -665,18 +650,17 @@ static void armada_370_xp_mpic_handle_cascade_irq(struct irq_desc *desc) continue; if (irqn == 0 || irqn == 1) { - armada_370_xp_handle_msi_irq(NULL, true); + mpic_handle_msi_irq(NULL, true); continue; } - generic_handle_domain_irq(armada_370_xp_mpic_domain, irqn); + generic_handle_domain_irq(mpic_domain, irqn); } chained_irq_exit(chip, desc); } -static void __exception_irq_entry -armada_370_xp_handle_irq(struct pt_regs *regs) +static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs) { u32 irqstat, irqnr; @@ -688,14 +672,13 @@ armada_370_xp_handle_irq(struct pt_regs *regs) break; if (irqnr > 1) { - generic_handle_domain_irq(armada_370_xp_mpic_domain, - irqnr); + generic_handle_domain_irq(mpic_domain, irqnr); continue; } /* MSI handling */ if (irqnr == 1) - armada_370_xp_handle_msi_irq(regs, false); + mpic_handle_msi_irq(regs, false); #ifdef CONFIG_SMP /* IPI Handling */ @@ -704,62 +687,60 @@ armada_370_xp_handle_irq(struct pt_regs *regs) int ipi; ipimask = readl_relaxed(per_cpu_int_base + MPIC_IN_DRBEL_CAUSE) & - IPI_DOORBELL_MASK; + IPI_DOORBELL_MASK; for_each_set_bit(ipi, &ipimask, IPI_DOORBELL_END) - generic_handle_domain_irq(ipi_domain, ipi); + generic_handle_domain_irq(mpic_ipi_domain, ipi); } #endif } while (1); } -static int armada_370_xp_mpic_suspend(void) +static int mpic_suspend(void) { doorbell_mask_reg = readl(per_cpu_int_base + MPIC_IN_DRBEL_MASK); return 0; } -static void armada_370_xp_mpic_resume(void) +static void mpic_resume(void) { bool src0, src1; int nirqs; - /* Re-enable interrupts */ nirqs = (readl(main_int_base + MPIC_INT_CONTROL) >> 2) & 0x3ff; for (irq_hw_number_t irq = 0; irq < nirqs; irq++) { struct irq_data *data; unsigned int virq; - virq = irq_linear_revmap(armada_370_xp_mpic_domain, irq); + virq = irq_linear_revmap(mpic_domain, irq); if (!virq) continue; data = irq_get_irq_data(virq); - if (!is_percpu_irq(irq)) { + if (!mpic_is_percpu_irq(irq)) { /* Non per-CPU interrupts */ writel(irq, per_cpu_int_base + MPIC_INT_CLEAR_MASK); if (!irqd_irq_disabled(data)) - armada_370_xp_irq_unmask(data); + mpic_irq_unmask(data); } else { /* Per-CPU interrupts */ writel(irq, main_int_base + MPIC_INT_SET_ENABLE); /* - * Re-enable on the current CPU, - * armada_xp_mpic_reenable_percpu() will take - * care of secondary CPUs when they come up. + * Re-enable on the current CPU, mpic_reenable_percpu() + * will take care of secondary CPUs when they come up. */ if (irq_percpu_is_enabled(virq)) - armada_370_xp_irq_unmask(data); + mpic_irq_unmask(data); } } /* Reconfigure doorbells for IPIs and MSIs */ writel(doorbell_mask_reg, per_cpu_int_base + MPIC_IN_DRBEL_MASK); - if (is_ipi_available()) { + if (mpic_is_ipi_available()) { src0 = doorbell_mask_reg & IPI_DOORBELL_MASK; src1 = doorbell_mask_reg & PCI_MSI_DOORBELL_MASK; } else { @@ -772,17 +753,17 @@ static void armada_370_xp_mpic_resume(void) if (src1) writel(1, per_cpu_int_base + MPIC_INT_CLEAR_MASK); - if (is_ipi_available()) - ipi_resume(); + if (mpic_is_ipi_available()) + mpic_ipi_resume(); } -static struct syscore_ops armada_370_xp_mpic_syscore_ops = { - .suspend = armada_370_xp_mpic_suspend, - .resume = armada_370_xp_mpic_resume, +static struct syscore_ops mpic_syscore_ops = { + .suspend = mpic_suspend, + .resume = mpic_resume, }; -static int __init armada_370_xp_mpic_of_init(struct device_node *node, - struct device_node *parent) +static int __init mpic_of_init(struct device_node *node, + struct device_node *parent) { struct resource main_int_res, per_cpu_int_res; int nr_irqs; @@ -812,10 +793,9 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, for (int i = 0; i < nr_irqs; i++) writel(i, main_int_base + MPIC_INT_CLEAR_ENABLE); - armada_370_xp_mpic_domain = irq_domain_add_linear(node, nr_irqs, - &armada_370_xp_mpic_irq_ops, NULL); - BUG_ON(!armada_370_xp_mpic_domain); - irq_domain_update_bus_token(armada_370_xp_mpic_domain, DOMAIN_BUS_WIRED); + mpic_domain = irq_domain_add_linear(node, nr_irqs, &mpic_irq_ops, NULL); + BUG_ON(!mpic_domain); + irq_domain_update_bus_token(mpic_domain, DOMAIN_BUS_WIRED); /* * Initialize parent_irq before calling any other functions, since it is @@ -824,19 +804,19 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, parent_irq = irq_of_parse_and_map(node, 0); /* Setup for the boot CPU */ - armada_xp_mpic_perf_init(); - armada_xp_mpic_smp_cpu_init(); + mpic_perf_init(); + mpic_smp_cpu_init(); - armada_370_xp_msi_init(node, main_int_res.start); + mpic_msi_init(node, main_int_res.start); if (parent_irq <= 0) { - irq_set_default_host(armada_370_xp_mpic_domain); - set_handle_irq(armada_370_xp_handle_irq); + irq_set_default_host(mpic_domain); + set_handle_irq(mpic_handle_irq); #ifdef CONFIG_SMP - armada_xp_ipi_init(node); + mpic_ipi_init(node); cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_ARMADA_XP_STARTING, "irqchip/armada/ipi:starting", - armada_xp_mpic_starting_cpu, NULL); + mpic_starting_cpu, NULL); #endif } else { #ifdef CONFIG_SMP @@ -844,13 +824,12 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, "irqchip/armada/cascade:starting", mpic_cascaded_starting_cpu, NULL); #endif - irq_set_chained_handler(parent_irq, - armada_370_xp_mpic_handle_cascade_irq); + irq_set_chained_handler(parent_irq, mpic_handle_cascade_irq); } - register_syscore_ops(&armada_370_xp_mpic_syscore_ops); + register_syscore_ops(&mpic_syscore_ops); return 0; } -IRQCHIP_DECLARE(armada_370_xp_mpic, "marvell,mpic", armada_370_xp_mpic_of_init); +IRQCHIP_DECLARE(marvell_mpic, "marvell,mpic", mpic_of_init); From 5ecafc9a640f7c1e5690375cf3a82848d669abb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 13:57:45 +0200 Subject: [PATCH 17/73] irqchip/armada-370-xp: Don't read number of supported interrupts multiple times MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use mpic_domain::hwirq_max at runtime instead of reading the same value over and over from the MPIC_INT_CONTROL register. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240711115748.30268-8-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 27588347189e..e43eb26ab6e7 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -494,13 +494,7 @@ static int mpic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, static void mpic_smp_cpu_init(void) { - u32 control; - int nr_irqs; - - control = readl(main_int_base + MPIC_INT_CONTROL); - nr_irqs = (control >> 2) & 0x3ff; - - for (int i = 0; i < nr_irqs; i++) + for (int i = 0; i < mpic_domain->hwirq_max; i++) writel(i, per_cpu_int_base + MPIC_INT_SET_MASK); if (!mpic_is_ipi_available()) @@ -706,10 +700,9 @@ static int mpic_suspend(void) static void mpic_resume(void) { bool src0, src1; - int nirqs; + /* Re-enable interrupts */ - nirqs = (readl(main_int_base + MPIC_INT_CONTROL) >> 2) & 0x3ff; - for (irq_hw_number_t irq = 0; irq < nirqs; irq++) { + for (irq_hw_number_t irq = 0; irq < mpic_domain->hwirq_max; irq++) { struct irq_data *data; unsigned int virq; From 92128c74e41868e42e6944f83d9d2130c9aa8a22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 13:57:46 +0200 Subject: [PATCH 18/73] irqchip/armada-370-xp: Use FIELD_GET() and named register constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use FIELD_GET() and named register mask constant when reading the number of supported interrupts / current interrupt. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240711115748.30268-9-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index e43eb26ab6e7..179a30a4a128 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -10,6 +10,7 @@ * Ben Dooks */ +#include #include #include #include @@ -112,6 +113,7 @@ /* Registers relative to main_int_base */ #define MPIC_INT_CONTROL 0x00 +#define MPIC_INT_CONTROL_NUMINT_MASK GENMASK(12, 2) #define MPIC_SW_TRIG_INT 0x04 #define MPIC_INT_SET_ENABLE 0x30 #define MPIC_INT_CLEAR_ENABLE 0x34 @@ -124,6 +126,7 @@ #define MPIC_IN_DRBEL_MASK 0x0c #define MPIC_PPI_CAUSE 0x10 #define MPIC_CPU_INTACK 0x44 +#define MPIC_CPU_INTACK_IID_MASK GENMASK(9, 0) #define MPIC_INT_SET_MASK 0x48 #define MPIC_INT_CLEAR_MASK 0x4C #define MPIC_INT_FABRIC_MASK 0x54 @@ -660,7 +663,7 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs) do { irqstat = readl_relaxed(per_cpu_int_base + MPIC_CPU_INTACK); - irqnr = irqstat & 0x3FF; + irqnr = FIELD_GET(MPIC_CPU_INTACK_IID_MASK, irqstat); if (irqnr > 1022) break; @@ -759,8 +762,7 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *parent) { struct resource main_int_res, per_cpu_int_res; - int nr_irqs; - u32 control; + unsigned int nr_irqs; BUG_ON(of_address_to_resource(node, 0, &main_int_res)); BUG_ON(of_address_to_resource(node, 1, &per_cpu_int_res)); @@ -780,8 +782,7 @@ static int __init mpic_of_init(struct device_node *node, resource_size(&per_cpu_int_res)); BUG_ON(!per_cpu_int_base); - control = readl(main_int_base + MPIC_INT_CONTROL); - nr_irqs = (control >> 2) & 0x3ff; + nr_irqs = FIELD_GET(MPIC_INT_CONTROL_NUMINT_MASK, readl(main_int_base + MPIC_INT_CONTROL)); for (int i = 0; i < nr_irqs; i++) writel(i, main_int_base + MPIC_INT_CLEAR_ENABLE); From 63697bc7199ee2bacc8324b59951046a7b3ea991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 13:57:47 +0200 Subject: [PATCH 19/73] irqchip/armada-370-xp: Refactor mpic_handle_msi_irq() code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor the mpic_handle_msi_irq() function to make it simpler: - drop the function arguments, they are not needed - rename the variable holding the doorbell cause register to "cause" - rename the iterating variable to "i" - use for_each_set_bit() (requires retyping "cause" to unsigned long) Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240711115748.30268-10-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 32 +++++++++++------------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 179a30a4a128..5c2631f6f7b0 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -602,29 +602,21 @@ static const struct irq_domain_ops mpic_irq_ops = { }; #ifdef CONFIG_PCI_MSI -static void mpic_handle_msi_irq(struct pt_regs *regs, bool is_chained) +static void mpic_handle_msi_irq(void) { - u32 msimask, msinr; + unsigned long cause; + unsigned int i; - msimask = readl_relaxed(per_cpu_int_base + MPIC_IN_DRBEL_CAUSE); - msimask &= msi_doorbell_mask(); + cause = readl_relaxed(per_cpu_int_base + MPIC_IN_DRBEL_CAUSE); + cause &= msi_doorbell_mask(); + writel(~cause, per_cpu_int_base + MPIC_IN_DRBEL_CAUSE); - writel(~msimask, per_cpu_int_base + MPIC_IN_DRBEL_CAUSE); - - for (msinr = msi_doorbell_start(); - msinr < msi_doorbell_end(); msinr++) { - unsigned int irq; - - if (!(msimask & BIT(msinr))) - continue; - - irq = msinr - msi_doorbell_start(); - - generic_handle_domain_irq(mpic_msi_inner_domain, irq); - } + for_each_set_bit(i, &cause, BITS_PER_LONG) + generic_handle_domain_irq(mpic_msi_inner_domain, + i - msi_doorbell_start()); } #else -static void mpic_handle_msi_irq(struct pt_regs *r, bool b) {} +static void mpic_handle_msi_irq(void) {} #endif static void mpic_handle_cascade_irq(struct irq_desc *desc) @@ -647,7 +639,7 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc) continue; if (irqn == 0 || irqn == 1) { - mpic_handle_msi_irq(NULL, true); + mpic_handle_msi_irq(); continue; } @@ -675,7 +667,7 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs) /* MSI handling */ if (irqnr == 1) - mpic_handle_msi_irq(regs, false); + mpic_handle_msi_irq(); #ifdef CONFIG_SMP /* IPI Handling */ From baf01c726b7f99b72f2abfa54e249d766cbd59a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 13:57:48 +0200 Subject: [PATCH 20/73] irqchip/armada-370-xp: Refactor handling IPI interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor the handling of IPI interrupts - put into own function mpic_handle_ipi_irq(), similar to mpic_handle_msi_irq() - rename the variable holding the doorbell cause register to "cause" - retype and rename the variable holding the IPI HW IRQ number to "irq_hw_number_t i" Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Reviewed-by: Andrew Lunn Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/all/20240711115748.30268-11-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 30 +++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 5c2631f6f7b0..d42c7a1750ac 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -619,6 +619,22 @@ static void mpic_handle_msi_irq(void) static void mpic_handle_msi_irq(void) {} #endif +#ifdef CONFIG_SMP +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 &= IPI_DOORBELL_MASK; + + for_each_set_bit(i, &cause, IPI_DOORBELL_END) + generic_handle_domain_irq(mpic_ipi_domain, i); +} +#else +static inline void mpic_handle_ipi_irq(void) {} +#endif + static void mpic_handle_cascade_irq(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); @@ -669,19 +685,9 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs) if (irqnr == 1) mpic_handle_msi_irq(); -#ifdef CONFIG_SMP /* IPI Handling */ - if (irqnr == 0) { - unsigned long ipimask; - int ipi; - - ipimask = readl_relaxed(per_cpu_int_base + MPIC_IN_DRBEL_CAUSE) & - IPI_DOORBELL_MASK; - - for_each_set_bit(ipi, &ipimask, IPI_DOORBELL_END) - generic_handle_domain_irq(mpic_ipi_domain, ipi); - } -#endif + if (irqnr == 0) + mpic_handle_ipi_irq(); } while (1); } From 66fc31034f96cbdef7687b1c55d600367e70287e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 18:08:58 +0200 Subject: [PATCH 21/73] irqchip/armada-370-xp: Use consistent variable names for hwirqs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use consistent variable names for hwirqs: when iterating, use "i", otherwise use "hwirq". Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240711160907.31012-2-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 56 ++++++++++++++--------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index d42c7a1750ac..8f95da0977d7 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -117,7 +117,7 @@ #define MPIC_SW_TRIG_INT 0x04 #define MPIC_INT_SET_ENABLE 0x30 #define MPIC_INT_CLEAR_ENABLE 0x34 -#define MPIC_INT_SOURCE_CTL(irq) (0x100 + (irq) * 4) +#define MPIC_INT_SOURCE_CTL(hwirq) (0x100 + (hwirq) * 4) #define MPIC_INT_SOURCE_CPU_MASK GENMASK(3, 0) #define MPIC_INT_IRQ_FIQ_MASK(cpuid) ((BIT(0) | BIT(8)) << (cpuid)) @@ -195,9 +195,9 @@ 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 irq) +static inline bool mpic_is_percpu_irq(irq_hw_number_t hwirq) { - return irq <= MPIC_MAX_PER_CPU_IRQS; + return hwirq <= MPIC_MAX_PER_CPU_IRQS; } /* @@ -516,11 +516,11 @@ static void mpic_smp_cpu_init(void) static void mpic_reenable_percpu(void) { /* Re-enable per-CPU interrupts that were enabled before suspend */ - for (unsigned int irq = 0; irq < MPIC_MAX_PER_CPU_IRQS; irq++) { + for (unsigned int i = 0; i < MPIC_MAX_PER_CPU_IRQS; i++) { struct irq_data *data; unsigned int virq; - virq = irq_linear_revmap(mpic_domain, irq); + virq = irq_linear_revmap(mpic_domain, i); if (!virq) continue; @@ -572,20 +572,20 @@ static struct irq_chip mpic_irq_chip = { }; static int mpic_irq_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw) + irq_hw_number_t hwirq) { /* IRQs 0 and 1 cannot be mapped, they are handled internally */ - if (hw <= 1) + if (hwirq <= 1) return -EINVAL; mpic_irq_mask(irq_get_irq_data(virq)); - if (!mpic_is_percpu_irq(hw)) - writel(hw, per_cpu_int_base + MPIC_INT_CLEAR_MASK); + if (!mpic_is_percpu_irq(hwirq)) + writel(hwirq, per_cpu_int_base + MPIC_INT_CLEAR_MASK); else - writel(hw, main_int_base + MPIC_INT_SET_ENABLE); + writel(hwirq, main_int_base + MPIC_INT_SET_ENABLE); irq_set_status_flags(virq, IRQ_LEVEL); - if (mpic_is_percpu_irq(hw)) { + if (mpic_is_percpu_irq(hwirq)) { irq_set_percpu_devid(virq); irq_set_chip_and_handler(virq, &mpic_irq_chip, handle_percpu_devid_irq); } else { @@ -638,15 +638,15 @@ static inline void mpic_handle_ipi_irq(void) {} static void mpic_handle_cascade_irq(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); - unsigned long irqmap, irqn, irqsrc, cpuid; + unsigned long irqmap, i, irqsrc, cpuid; chained_irq_enter(chip, desc); irqmap = readl_relaxed(per_cpu_int_base + MPIC_PPI_CAUSE); cpuid = cpu_logical_map(smp_processor_id()); - for_each_set_bit(irqn, &irqmap, BITS_PER_LONG) { - irqsrc = readl_relaxed(main_int_base + MPIC_INT_SOURCE_CTL(irqn)); + for_each_set_bit(i, &irqmap, BITS_PER_LONG) { + irqsrc = readl_relaxed(main_int_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. @@ -654,12 +654,12 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc) if (!(irqsrc & MPIC_INT_IRQ_FIQ_MASK(cpuid))) continue; - if (irqn == 0 || irqn == 1) { + if (i == 0 || i == 1) { mpic_handle_msi_irq(); continue; } - generic_handle_domain_irq(mpic_domain, irqn); + generic_handle_domain_irq(mpic_domain, i); } chained_irq_exit(chip, desc); @@ -667,26 +667,26 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc) static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs) { - u32 irqstat, irqnr; + u32 irqstat, i; do { irqstat = readl_relaxed(per_cpu_int_base + MPIC_CPU_INTACK); - irqnr = FIELD_GET(MPIC_CPU_INTACK_IID_MASK, irqstat); + i = FIELD_GET(MPIC_CPU_INTACK_IID_MASK, irqstat); - if (irqnr > 1022) + if (i > 1022) break; - if (irqnr > 1) { - generic_handle_domain_irq(mpic_domain, irqnr); + if (i > 1) { + generic_handle_domain_irq(mpic_domain, i); continue; } /* MSI handling */ - if (irqnr == 1) + if (i == 1) mpic_handle_msi_irq(); /* IPI Handling */ - if (irqnr == 0) + if (i == 0) mpic_handle_ipi_irq(); } while (1); } @@ -703,24 +703,24 @@ static void mpic_resume(void) bool src0, src1; /* Re-enable interrupts */ - for (irq_hw_number_t irq = 0; irq < mpic_domain->hwirq_max; irq++) { + for (irq_hw_number_t i = 0; i < mpic_domain->hwirq_max; i++) { struct irq_data *data; unsigned int virq; - virq = irq_linear_revmap(mpic_domain, irq); + virq = irq_linear_revmap(mpic_domain, i); if (!virq) continue; data = irq_get_irq_data(virq); - if (!mpic_is_percpu_irq(irq)) { + if (!mpic_is_percpu_irq(i)) { /* Non per-CPU interrupts */ - writel(irq, per_cpu_int_base + MPIC_INT_CLEAR_MASK); + writel(i, per_cpu_int_base + MPIC_INT_CLEAR_MASK); if (!irqd_irq_disabled(data)) mpic_irq_unmask(data); } else { /* Per-CPU interrupts */ - writel(irq, main_int_base + MPIC_INT_SET_ENABLE); + writel(i, main_int_base + MPIC_INT_SET_ENABLE); /* * Re-enable on the current CPU, mpic_reenable_percpu() From a5d32b7475fffe2506fa374b1d6b4a74fa13020c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 18:08:59 +0200 Subject: [PATCH 22/73] irqchip/armada-370-xp: Use consistent types when iterating interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When iterating, use either the irq_hw_number_t type or the unsigned int type for the iterator variable, depending on whether the variable represents HW IRQ number or whether it is added to a IRQ number. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240711160907.31012-3-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 8f95da0977d7..db9594b1024f 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -284,7 +284,7 @@ static int mpic_msi_alloc(struct irq_domain *domain, unsigned int virq, unsigned if (hwirq < 0) return -ENOSPC; - for (int i = 0; i < nr_irqs; i++) { + for (unsigned int i = 0; i < nr_irqs; i++) { irq_domain_set_info(domain, virq + i, hwirq + i, &mpic_msi_bottom_irq_chip, domain->host_data, handle_simple_irq, @@ -429,7 +429,7 @@ static struct irq_chip mpic_ipi_irqchip = { static int mpic_ipi_alloc(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs, void *args) { - for (int i = 0; i < nr_irqs; i++) { + for (unsigned int i = 0; i < nr_irqs; i++) { irq_set_percpu_devid(virq + i); irq_domain_set_info(d, virq + i, i, &mpic_ipi_irqchip, d->host_data, handle_percpu_devid_irq, NULL, NULL); @@ -451,7 +451,7 @@ static const struct irq_domain_ops mpic_ipi_domain_ops = { static void mpic_ipi_resume(void) { - for (int i = 0; i < IPI_DOORBELL_END; i++) { + for (irq_hw_number_t i = 0; i < IPI_DOORBELL_END; i++) { unsigned int virq = irq_find_mapping(mpic_ipi_domain, i); struct irq_data *d; @@ -497,7 +497,7 @@ static int mpic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, static void mpic_smp_cpu_init(void) { - for (int i = 0; i < mpic_domain->hwirq_max; i++) + for (irq_hw_number_t i = 0; i < mpic_domain->hwirq_max; i++) writel(i, per_cpu_int_base + MPIC_INT_SET_MASK); if (!mpic_is_ipi_available()) @@ -516,7 +516,7 @@ static void mpic_smp_cpu_init(void) static void mpic_reenable_percpu(void) { /* Re-enable per-CPU interrupts that were enabled before suspend */ - for (unsigned int i = 0; i < MPIC_MAX_PER_CPU_IRQS; i++) { + for (irq_hw_number_t i = 0; i < MPIC_MAX_PER_CPU_IRQS; i++) { struct irq_data *data; unsigned int virq; @@ -638,7 +638,8 @@ static inline void mpic_handle_ipi_irq(void) {} static void mpic_handle_cascade_irq(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); - unsigned long irqmap, i, irqsrc, cpuid; + unsigned long irqmap, irqsrc, cpuid; + irq_hw_number_t i; chained_irq_enter(chip, desc); @@ -667,7 +668,8 @@ static void mpic_handle_cascade_irq(struct irq_desc *desc) static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs) { - u32 irqstat, i; + irq_hw_number_t i; + u32 irqstat; do { irqstat = readl_relaxed(per_cpu_int_base + MPIC_CPU_INTACK); @@ -782,7 +784,7 @@ static int __init mpic_of_init(struct device_node *node, nr_irqs = FIELD_GET(MPIC_INT_CONTROL_NUMINT_MASK, readl(main_int_base + MPIC_INT_CONTROL)); - for (int i = 0; i < nr_irqs; i++) + for (irq_hw_number_t i = 0; i < nr_irqs; i++) writel(i, main_int_base + MPIC_INT_CLEAR_ENABLE); mpic_domain = irq_domain_add_linear(node, nr_irqs, &mpic_irq_ops, NULL); From 0d4b1fcd378ea61ff76bedf0d484eac69c028c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 18:09:00 +0200 Subject: [PATCH 23/73] irqchip/armada-370-xp: Use consistent name for struct irq_data variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always use variable name "d" for struct irq_data *, for consistency. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240711160907.31012-4-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index db9594b1024f..98f90a3d62d8 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -239,16 +239,16 @@ static struct msi_domain_info mpic_msi_domain_info = { .chip = &mpic_msi_irq_chip, }; -static void mpic_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) +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(data)); + 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->data = BIT(cpu + 8) | (data->hwirq + msi_doorbell_start()); + msg->data = BIT(cpu + 8) | (d->hwirq + msi_doorbell_start()); } -static int mpic_msi_set_affinity(struct irq_data *irq_data, const struct cpumask *mask, bool force) +static int mpic_msi_set_affinity(struct irq_data *d, const struct cpumask *mask, bool force) { unsigned int cpu; @@ -260,7 +260,7 @@ static int mpic_msi_set_affinity(struct irq_data *irq_data, const struct cpumask if (cpu >= nr_cpu_ids) return -EINVAL; - irq_data_update_effective_affinity(irq_data, cpumask_of(cpu)); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); return IRQ_SET_MASK_OK; } @@ -517,19 +517,19 @@ 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++) { - struct irq_data *data; + struct irq_data *d; unsigned int virq; virq = irq_linear_revmap(mpic_domain, i); if (!virq) continue; - data = irq_get_irq_data(virq); + d = irq_get_irq_data(virq); if (!irq_percpu_is_enabled(virq)) continue; - mpic_irq_unmask(data); + mpic_irq_unmask(d); } if (mpic_is_ipi_available()) @@ -706,20 +706,20 @@ static void mpic_resume(void) /* Re-enable interrupts */ for (irq_hw_number_t i = 0; i < mpic_domain->hwirq_max; i++) { - struct irq_data *data; + struct irq_data *d; unsigned int virq; virq = irq_linear_revmap(mpic_domain, i); if (!virq) continue; - data = irq_get_irq_data(virq); + d = irq_get_irq_data(virq); if (!mpic_is_percpu_irq(i)) { /* Non per-CPU interrupts */ writel(i, per_cpu_int_base + MPIC_INT_CLEAR_MASK); - if (!irqd_irq_disabled(data)) - mpic_irq_unmask(data); + if (!irqd_irq_disabled(d)) + mpic_irq_unmask(d); } else { /* Per-CPU interrupts */ writel(i, main_int_base + MPIC_INT_SET_ENABLE); @@ -729,7 +729,7 @@ static void mpic_resume(void) * will take care of secondary CPUs when they come up. */ if (irq_percpu_is_enabled(virq)) - mpic_irq_unmask(data); + mpic_irq_unmask(d); } } From 15a50eeaadc169243b00ec90087f689a8a28848e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 18:09:01 +0200 Subject: [PATCH 24/73] irqchip/armada-370-xp: Simplify mpic_reenable_percpu() and mpic_resume() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor the mpic_reenable_percpu() and mpic_resume() functions to make them a little bit simpler. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240711160907.31012-5-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 98f90a3d62d8..66e14f1183d1 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -517,18 +517,13 @@ 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); struct irq_data *d; - unsigned int virq; - virq = irq_linear_revmap(mpic_domain, i); - if (!virq) + if (!virq || !irq_percpu_is_enabled(virq)) continue; d = irq_get_irq_data(virq); - - if (!irq_percpu_is_enabled(virq)) - continue; - mpic_irq_unmask(d); } @@ -706,10 +701,9 @@ static void mpic_resume(void) /* 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); struct irq_data *d; - unsigned int virq; - virq = irq_linear_revmap(mpic_domain, i); if (!virq) continue; From 081b64cc872707f80a23e41f0ab12852716551b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 18:09:03 +0200 Subject: [PATCH 25/73] irqchip/armada-370-xp: Drop redundant continue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop redundant continue from mpic_handle_irq(). Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240711160907.31012-7-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 66e14f1183d1..4abe0eac184e 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -673,10 +673,8 @@ static void __exception_irq_entry mpic_handle_irq(struct pt_regs *regs) if (i > 1022) break; - if (i > 1) { + if (i > 1) generic_handle_domain_irq(mpic_domain, i); - continue; - } /* MSI handling */ if (i == 1) From ac0ae59db6f521223b477677d2ff51e26815b114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 18:09:04 +0200 Subject: [PATCH 26/73] irqchip/armada-370-xp: Rename variable for consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the variable holding the cause register to "cause" in mpic_handle_cascade_irq(). Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240711160907.31012-8-kabel@kernel.org --- 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 4abe0eac184e..5cde229c9e39 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -633,15 +633,15 @@ static inline void mpic_handle_ipi_irq(void) {} static void mpic_handle_cascade_irq(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); - unsigned long irqmap, irqsrc, cpuid; + unsigned long cause, irqsrc, cpuid; irq_hw_number_t i; chained_irq_enter(chip, desc); - irqmap = readl_relaxed(per_cpu_int_base + MPIC_PPI_CAUSE); + cause = readl_relaxed(per_cpu_int_base + MPIC_PPI_CAUSE); cpuid = cpu_logical_map(smp_processor_id()); - for_each_set_bit(i, &irqmap, BITS_PER_LONG) { + for_each_set_bit(i, &cause, BITS_PER_LONG) { irqsrc = readl_relaxed(main_int_base + MPIC_INT_SOURCE_CTL(i)); /* Check if the interrupt is not masked on current CPU. From 625f0582f05d1f496ecd598323df1c8bfcdcbd6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 18:09:05 +0200 Subject: [PATCH 27/73] irqchip/armada-370-xp: Use u32 type instead of unsigned long where possieble MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency across the driver, use the u32 type instead of unsigned long for holding register values and return value of cpu_logical_map(). One exception is when the variable is referenced for passing into for_each_set_bit(), in which case it has to be unsigned long. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240711160907.31012-9-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 5cde229c9e39..8b28188953b0 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -357,7 +357,7 @@ static inline int mpic_msi_init(struct device_node *node, static void mpic_perf_init(void) { - unsigned long cpuid; + u32 cpuid; /* * This Performance Counter Overflow interrupt is specific for @@ -396,8 +396,8 @@ static void mpic_ipi_unmask(struct irq_data *d) static void mpic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask) { - unsigned long map = 0; unsigned int cpu; + u32 map = 0; /* Convert our logical CPU mask into a physical one. */ for_each_cpu(cpu, mask) @@ -633,7 +633,8 @@ static inline void mpic_handle_ipi_irq(void) {} static void mpic_handle_cascade_irq(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); - unsigned long cause, irqsrc, cpuid; + unsigned long cause; + u32 irqsrc, cpuid; irq_hw_number_t i; chained_irq_enter(chip, desc); From 654caa9db6649dbecdfa55ea29c9cbf4603fb402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 18:09:06 +0200 Subject: [PATCH 28/73] irqchip/armada-370-xp: Refactor initial memory regions mapping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor the initial memory regions mapping: - put into its own function - return error numbers on failure - use WARN_ON() instead of BUG_ON() Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240711160907.31012-10-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 62 +++++++++++++++++++---------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 8b28188953b0..9c66c251cee5 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -751,29 +752,50 @@ static struct syscore_ops mpic_syscore_ops = { .resume = mpic_resume, }; -static int __init mpic_of_init(struct device_node *node, - struct device_node *parent) +static int __init mpic_map_region(struct device_node *np, int index, + void __iomem **base, phys_addr_t *phys_base) { - struct resource main_int_res, per_cpu_int_res; + struct resource res; + int err; + + err = of_address_to_resource(np, index, &res); + if (WARN_ON(err)) + goto fail; + + if (WARN_ON(!request_mem_region(res.start, resource_size(&res), np->full_name))) { + err = -EBUSY; + goto fail; + } + + *base = ioremap(res.start, resource_size(&res)); + if (WARN_ON(!*base)) { + err = -ENOMEM; + goto fail; + } + + if (phys_base) + *phys_base = res.start; + + return 0; + +fail: + pr_err("%pOF: Unable to map resource %d: %pE\n", np, index, ERR_PTR(err)); + return err; +} + +static int __init mpic_of_init(struct device_node *node, struct device_node *parent) +{ + phys_addr_t phys_base; unsigned int nr_irqs; + int err; - BUG_ON(of_address_to_resource(node, 0, &main_int_res)); - BUG_ON(of_address_to_resource(node, 1, &per_cpu_int_res)); + err = mpic_map_region(node, 0, &main_int_base, &phys_base); + if (err) + return err; - BUG_ON(!request_mem_region(main_int_res.start, - resource_size(&main_int_res), - node->full_name)); - BUG_ON(!request_mem_region(per_cpu_int_res.start, - resource_size(&per_cpu_int_res), - node->full_name)); - - main_int_base = ioremap(main_int_res.start, - resource_size(&main_int_res)); - BUG_ON(!main_int_base); - - per_cpu_int_base = ioremap(per_cpu_int_res.start, - resource_size(&per_cpu_int_res)); - BUG_ON(!per_cpu_int_base); + err = mpic_map_region(node, 1, &per_cpu_int_base, NULL); + if (err) + return err; nr_irqs = FIELD_GET(MPIC_INT_CONTROL_NUMINT_MASK, readl(main_int_base + MPIC_INT_CONTROL)); @@ -794,7 +816,7 @@ static int __init mpic_of_init(struct device_node *node, mpic_perf_init(); mpic_smp_cpu_init(); - mpic_msi_init(node, main_int_res.start); + mpic_msi_init(node, phys_base); if (parent_irq <= 0) { irq_set_default_host(mpic_domain); From 1d07c9a3e71c97ee1bbc1f119e104bf3746c51f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 11 Jul 2024 18:09:07 +0200 Subject: [PATCH 29/73] irqchip/armada-370-xp: Print error and return error code on initialization failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print error and return error code on main / IPI / MSI domain initialization failure. Use WARN_ON() instead of BUG_ON(). Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240711160907.31012-11-kabel@kernel.org --- drivers/irqchip/irq-armada-370-xp.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 9c66c251cee5..b11612acec78 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -464,20 +464,23 @@ static void mpic_ipi_resume(void) } } -static __init void mpic_ipi_init(struct device_node *node) +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_ops, NULL); if (WARN_ON(!mpic_ipi_domain)) - return; + 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); if (WARN_ON(!base_ipi)) - return; + return -ENOMEM; + set_smp_ipi_range(base_ipi, IPI_DOORBELL_END); + + return 0; } static int mpic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force) @@ -803,7 +806,11 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par writel(i, main_int_base + MPIC_INT_CLEAR_ENABLE); mpic_domain = irq_domain_add_linear(node, nr_irqs, &mpic_irq_ops, NULL); - BUG_ON(!mpic_domain); + 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); /* @@ -816,13 +823,22 @@ static int __init mpic_of_init(struct device_node *node, struct device_node *par mpic_perf_init(); mpic_smp_cpu_init(); - mpic_msi_init(node, phys_base); + err = mpic_msi_init(node, phys_base); + if (err) { + pr_err("%pOF: Unable to initialize MSI domain\n", node); + return err; + } if (parent_irq <= 0) { irq_set_default_host(mpic_domain); set_handle_irq(mpic_handle_irq); #ifdef CONFIG_SMP - mpic_ipi_init(node); + err = mpic_ipi_init(node); + if (err) { + pr_err("%pOF: Unable to initialize IPI domain\n", node); + return err; + } + cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_ARMADA_XP_STARTING, "irqchip/armada/ipi:starting", mpic_starting_cpu, NULL); From b8fb82e4ffec3da153a6100d4cd6229fbfd3a22c Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Mon, 29 Jul 2024 19:26:06 +0800 Subject: [PATCH 30/73] irqchip: Remove asmlinkage for handlers registered with set_handle_irq() All architectures with use set_handle_irq() to set the root chip interrupt handler call that handler from C code, so there's no need for these handlers to be marked asmlinkage. Remove asmlinkage for all handlers registered with set_handle_irq(). Suggested-by: Thomas Gleixner Signed-off-by: Jinjie Ruan Signed-off-by: Thomas Gleixner Acked-by: Mark Rutland Link: https://lore.kernel.org/all/20240729112606.1581732-1-ruanjinjie@huawei.com --- drivers/irqchip/irq-atmel-aic.c | 3 +-- drivers/irqchip/irq-atmel-aic5.c | 3 +-- drivers/irqchip/irq-clps711x.c | 2 +- drivers/irqchip/irq-davinci-cp-intc.c | 3 +-- drivers/irqchip/irq-ftintc010.c | 2 +- drivers/irqchip/irq-gic-v3.c | 2 +- drivers/irqchip/irq-ixp4xx.c | 3 +-- drivers/irqchip/irq-omap-intc.c | 3 +-- drivers/irqchip/irq-sa11x0.c | 3 +-- drivers/irqchip/irq-versatile-fpga.c | 2 +- 10 files changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c index 4631f6847953..3839ad79ad31 100644 --- a/drivers/irqchip/irq-atmel-aic.c +++ b/drivers/irqchip/irq-atmel-aic.c @@ -57,8 +57,7 @@ static struct irq_domain *aic_domain; -static asmlinkage void __exception_irq_entry -aic_handle(struct pt_regs *regs) +static void __exception_irq_entry aic_handle(struct pt_regs *regs) { struct irq_domain_chip_generic *dgc = aic_domain->gc; struct irq_chip_generic *gc = dgc->gc[0]; diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c index 145535bd7560..c0f55dc7b050 100644 --- a/drivers/irqchip/irq-atmel-aic5.c +++ b/drivers/irqchip/irq-atmel-aic5.c @@ -67,8 +67,7 @@ static struct irq_domain *aic5_domain; -static asmlinkage void __exception_irq_entry -aic5_handle(struct pt_regs *regs) +static void __exception_irq_entry aic5_handle(struct pt_regs *regs) { struct irq_chip_generic *bgc = irq_get_domain_generic_chip(aic5_domain, 0); u32 irqnr; diff --git a/drivers/irqchip/irq-clps711x.c b/drivers/irqchip/irq-clps711x.c index e731e0784f7e..806ebb1de201 100644 --- a/drivers/irqchip/irq-clps711x.c +++ b/drivers/irqchip/irq-clps711x.c @@ -69,7 +69,7 @@ static struct { struct irq_domain_ops ops; } *clps711x_intc; -static asmlinkage void __exception_irq_entry clps711x_irqh(struct pt_regs *regs) +static void __exception_irq_entry clps711x_irqh(struct pt_regs *regs) { u32 irqstat; diff --git a/drivers/irqchip/irq-davinci-cp-intc.c b/drivers/irqchip/irq-davinci-cp-intc.c index 7482c8ed34b2..f4f8e9fadbbf 100644 --- a/drivers/irqchip/irq-davinci-cp-intc.c +++ b/drivers/irqchip/irq-davinci-cp-intc.c @@ -116,8 +116,7 @@ static struct irq_chip davinci_cp_intc_irq_chip = { .flags = IRQCHIP_SKIP_SET_WAKE, }; -static asmlinkage void __exception_irq_entry -davinci_cp_intc_handle_irq(struct pt_regs *regs) +static void __exception_irq_entry davinci_cp_intc_handle_irq(struct pt_regs *regs) { int gpir, irqnr, none; diff --git a/drivers/irqchip/irq-ftintc010.c b/drivers/irqchip/irq-ftintc010.c index 359efc1d1be7..b91c358ea6db 100644 --- a/drivers/irqchip/irq-ftintc010.c +++ b/drivers/irqchip/irq-ftintc010.c @@ -125,7 +125,7 @@ static struct irq_chip ft010_irq_chip = { /* Local static for the IRQ entry call */ static struct ft010_irq_data firq; -static asmlinkage void __exception_irq_entry ft010_irqchip_handle_irq(struct pt_regs *regs) +static void __exception_irq_entry ft010_irqchip_handle_irq(struct pt_regs *regs) { struct ft010_irq_data *f = &firq; int irq; diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index c19083bfb943..0efa3443c323 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -930,7 +930,7 @@ static void __gic_handle_irq_from_irqsoff(struct pt_regs *regs) __gic_handle_nmi(irqnr, regs); } -static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) +static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) { if (unlikely(gic_supports_nmi() && !interrupts_enabled(regs))) __gic_handle_irq_from_irqsoff(regs); diff --git a/drivers/irqchip/irq-ixp4xx.c b/drivers/irqchip/irq-ixp4xx.c index 5fba907b9052..f23b02f62a5c 100644 --- a/drivers/irqchip/irq-ixp4xx.c +++ b/drivers/irqchip/irq-ixp4xx.c @@ -105,8 +105,7 @@ static void ixp4xx_irq_unmask(struct irq_data *d) } } -static asmlinkage void __exception_irq_entry -ixp4xx_handle_irq(struct pt_regs *regs) +static void __exception_irq_entry ixp4xx_handle_irq(struct pt_regs *regs) { struct ixp4xx_irq *ixi = &ixirq; unsigned long status; diff --git a/drivers/irqchip/irq-omap-intc.c b/drivers/irqchip/irq-omap-intc.c index dc82162ba763..ad84a2f03368 100644 --- a/drivers/irqchip/irq-omap-intc.c +++ b/drivers/irqchip/irq-omap-intc.c @@ -325,8 +325,7 @@ static int __init omap_init_irq(u32 base, struct device_node *node) return ret; } -static asmlinkage void __exception_irq_entry -omap_intc_handle_irq(struct pt_regs *regs) +static void __exception_irq_entry omap_intc_handle_irq(struct pt_regs *regs) { extern unsigned long irq_err_count; u32 irqnr; diff --git a/drivers/irqchip/irq-sa11x0.c b/drivers/irqchip/irq-sa11x0.c index 31c202a1ae62..9d0b80271949 100644 --- a/drivers/irqchip/irq-sa11x0.c +++ b/drivers/irqchip/irq-sa11x0.c @@ -127,8 +127,7 @@ static int __init sa1100irq_init_devicefs(void) device_initcall(sa1100irq_init_devicefs); -static asmlinkage void __exception_irq_entry -sa1100_handle_irq(struct pt_regs *regs) +static void __exception_irq_entry sa1100_handle_irq(struct pt_regs *regs) { uint32_t icip, icmr, mask; diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c index 5018a06060e6..ca471c6fee99 100644 --- a/drivers/irqchip/irq-versatile-fpga.c +++ b/drivers/irqchip/irq-versatile-fpga.c @@ -128,7 +128,7 @@ static int handle_one_fpga(struct fpga_irq_data *f, struct pt_regs *regs) * Keep iterating over all registered FPGA IRQ controllers until there are * no pending interrupts. */ -static asmlinkage void __exception_irq_entry fpga_handle_irq(struct pt_regs *regs) +static void __exception_irq_entry fpga_handle_irq(struct pt_regs *regs) { int i, handled; From bb4531976523c6e394188c4f4a7eeaf5e9efdd48 Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Fri, 2 Aug 2024 14:26:01 +0530 Subject: [PATCH 31/73] irqchip/gic-v4.1: Replace bare number with ID_AA64PFR0_EL1_GIC_V4P1 Use ID_AA64PFR0_EL1_GIC_V4P1 instead of '3' in gic_cpuif_has_vsgi() to check for the GIC version. Signed-off-by: Anshuman Khandual Signed-off-by: Thomas Gleixner Reviewed-by: Zenghui Yu Acked-by: Marc Zyngier Link: https://lore.kernel.org/all/20240802085601.1824057-1-anshuman.khandual@arm.com --- drivers/irqchip/irq-gic-v4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c index ca32ac19d284..58c28895f8c4 100644 --- a/drivers/irqchip/irq-gic-v4.c +++ b/drivers/irqchip/irq-gic-v4.c @@ -97,7 +97,7 @@ bool gic_cpuif_has_vsgi(void) fld = cpuid_feature_extract_unsigned_field(reg, ID_AA64PFR0_EL1_GIC_SHIFT); - return fld >= 0x3; + return fld >= ID_AA64PFR0_EL1_GIC_V4P1; } #else bool gic_cpuif_has_vsgi(void) From 3431392d5e8a7d420c06048260d521c1dd08e931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:40:53 +0200 Subject: [PATCH 32/73] irqchip/armada-370-xp: Drop IPI_DOORBELL_START and rename IPI_DOORBELL_END MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop IPI_DOORBELL_START since it is not used and rename IPI_DOORBELL_END to IPI_DOORBELL_NR. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner --- 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 From 0dbf9b6025e3d6092ad883541c090118e5361d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:40:54 +0200 Subject: [PATCH 33/73] irqchip/armada-370-xp: Drop msi_doorbell_end() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the msi_doorbell_end() function and related constants, it is not used anymore. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner --- 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; From 37e130c224fd0da168570003355fcbd091a87030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:40:55 +0200 Subject: [PATCH 34/73] irqchip/armada-370-xp: Add the __init attribute to mpic_msi_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Thomas Gleixner --- 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; From a4d4d4a642da83d869d2851c8c3732c699cbc08e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:40:56 +0200 Subject: [PATCH 35/73] irqchip/armada-370-xp: Put __init attribute after return type in mpic_ipi_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Thomas Gleixner --- 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; From 68fe2c59853611e2551370f0ab4b80b04a0748ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:40:57 +0200 Subject: [PATCH 36/73] irqchip/armada-370-xp: Put static variables into driver private structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Thomas Gleixner --- drivers/irqchip/irq-armada-370-xp.c | 225 +++++++++++++++------------- 1 file changed, 123 insertions(+), 102 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; -#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 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 + 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; - mpic_msi_inner_domain = irq_domain_add_linear(NULL, msi_doorbell_size(), - &mpic_msi_domain_ops, NULL); - if (!mpic_msi_inner_domain) + 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) 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); From ee5d09cf14a10010af163ac98e21aa282de6c4cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:40:58 +0200 Subject: [PATCH 37/73] irqchip/armada-370-xp: Put MSI doorbell limits into the mpic structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Thomas Gleixner --- 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) {} From 77eef29b642f07f56af28a7126b5666f705ca8d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:40:59 +0200 Subject: [PATCH 38/73] irqchip/armada-370-xp: Pass around the driver private structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Thomas Gleixner --- 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 @@ fail: 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); From 6abd809a543936ca005fd37efa32906c78409aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:41:00 +0200 Subject: [PATCH 39/73] irqchip/armada-370-xp: Dynamically allocate the driver private structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dynamically allocate the driver private structure. This concludes the conversion of this driver to modern style. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner --- 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 @@ fail: 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; From 2793f68749c1fb035e255cdffb10108ef023f608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:41:01 +0200 Subject: [PATCH 40/73] irqchip/armada-370-xp: Fix reenabling last per-CPU interrupt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. Fixes: 0fa4ce746d1d ("irqchip/armada-370-xp: Re-enable per-CPU interrupts at resume time") Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner Cc: # The 29th interrupt is not used in any device-tree --- 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; From 4042a965a5e62c8d298d642cbf72b14f41687319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:41:02 +0200 Subject: [PATCH 41/73] irqchip/armada-370-xp: Iterate only valid bits of the per-CPU interrupt cause register MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Thomas Gleixner --- 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. From d6ca3f440239fb4fa85228ead4c5e8b286645b7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:41:03 +0200 Subject: [PATCH 42/73] irqchip/armada-370-xp: Allow mapping only per-CPU interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 interrupt 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 Signed-off-by: Thomas Gleixner --- 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); From b77c6a73e10ae16b19999bebc6ca1413739dfe86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Wed, 7 Aug 2024 18:41:04 +0200 Subject: [PATCH 43/73] irqchip/armada-370-xp: Use mpic_is_ipi_available() in mpic_of_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mpic_of_init() contains the last case where the open coded IPI support condition needs to be replaced with mpic_is_ipi_available() to keep the code consistent. Signed-off-by: Marek Behún Signed-off-by: Thomas Gleixner --- 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 From 76bee035c6add05841addc3f31b41cd726b912c4 Mon Sep 17 00:00:00 2001 From: Zhang Zekun Date: Thu, 8 Aug 2024 11:15:52 +0800 Subject: [PATCH 44/73] irqchip/mbigen: Simplify code logic with for_each_child_of_node_scoped() for_each_child_of_node_scoped() handles the device_node automaticlly, so switching over to it removes the device node cleanups and allows to return directly from the loop. Signed-off-by: Zhang Zekun Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240808031552.3156-1-zhangzekun11@huawei.com --- drivers/irqchip/irq-mbigen.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c index 093fd42893a7..12919836dadb 100644 --- a/drivers/irqchip/irq-mbigen.c +++ b/drivers/irqchip/irq-mbigen.c @@ -222,37 +222,27 @@ static int mbigen_of_create_domain(struct platform_device *pdev, struct mbigen_device *mgn_chip) { struct platform_device *child; - struct device_node *np; u32 num_pins; - int ret = 0; - for_each_child_of_node(pdev->dev.of_node, np) { + for_each_child_of_node_scoped(pdev->dev.of_node, np) { if (!of_property_read_bool(np, "interrupt-controller")) continue; child = of_platform_device_create(np, NULL, NULL); - if (!child) { - ret = -ENOMEM; - break; - } + if (!child) + return -ENOMEM; if (of_property_read_u32(child->dev.of_node, "num-pins", &num_pins) < 0) { dev_err(&pdev->dev, "No num-pins property\n"); - ret = -EINVAL; - break; + return -EINVAL; } - if (!mbigen_create_device_domain(&child->dev, num_pins, mgn_chip)) { - ret = -ENOMEM; - break; - } + if (!mbigen_create_device_domain(&child->dev, num_pins, mgn_chip)) + return -ENOMEM; } - if (ret) - of_node_put(np); - - return ret; + return 0; } #ifdef CONFIG_ACPI From 15e46124ec937bb0ab530634dce4550947f53133 Mon Sep 17 00:00:00 2001 From: "Jiri Slaby (SUSE)" Date: Thu, 8 Aug 2024 12:41:16 +0200 Subject: [PATCH 45/73] genirq/irq_sim: Remove unused irq_sim_work_ctx:: Irq_base Since commit 337cbeb2c13e ("genirq/irq_sim: Simplify the API"), irq_sim_work_ctx::irq_base is unused. Drop it. Found by https://github.com/jirislaby/clang-struct. Signed-off-by: Jiri Slaby (SUSE) Signed-off-by: Thomas Gleixner Acked-by: Bartosz Golaszewski Link: https://lore.kernel.org/all/20240808104118.430670-1-jirislaby@kernel.org --- kernel/irq/irq_sim.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel/irq/irq_sim.c b/kernel/irq/irq_sim.c index 3d4036db15ac..1a3d483548e2 100644 --- a/kernel/irq/irq_sim.c +++ b/kernel/irq/irq_sim.c @@ -13,7 +13,6 @@ struct irq_sim_work_ctx { struct irq_work work; - int irq_base; unsigned int irq_count; unsigned long *pending; struct irq_domain *domain; From a09cdb8f564613769142a60400bb5160864c3269 Mon Sep 17 00:00:00 2001 From: "Jiri Slaby (SUSE)" Date: Thu, 8 Aug 2024 12:41:17 +0200 Subject: [PATCH 46/73] genirq: Remove unused irq_chip_generic:: {type,polarity}_cache The type_cache and polarity_cache members of struct irq_chip_generic are unused. Remove them both along with their kernel-doc. Found by https://github.com/jirislaby/clang-struct. Signed-off-by: Jiri Slaby (SUSE) Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240808104118.430670-2-jirislaby@kernel.org --- include/linux/irq.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index 1f5dbf1f92c9..00490d6ead65 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -1040,8 +1040,6 @@ struct irq_chip_type { * @irq_base: Interrupt base nr for this chip * @irq_cnt: Number of interrupts handled by this chip * @mask_cache: Cached mask register shared between all chip types - * @type_cache: Cached type register - * @polarity_cache: Cached polarity register * @wake_enabled: Interrupt can wakeup from suspend * @wake_active: Interrupt is marked as an wakeup from suspend source * @num_ct: Number of available irq_chip_type instances (usually 1) @@ -1068,8 +1066,6 @@ struct irq_chip_generic { unsigned int irq_base; unsigned int irq_cnt; u32 mask_cache; - u32 type_cache; - u32 polarity_cache; u32 wake_enabled; u32 wake_active; unsigned int num_ct; From 60029162a0458832ab2bcfc6fd4986bfd9ca0f55 Mon Sep 17 00:00:00 2001 From: "Jiri Slaby (SUSE)" Date: Thu, 8 Aug 2024 12:41:18 +0200 Subject: [PATCH 47/73] genirq: Remove irq_chip_regs:: Polarity The polarity member of struct irq_chip_regs is unused. Remove it along with its kernel-doc. Found by https://github.com/jirislaby/clang-struct. Signed-off-by: Jiri Slaby (SUSE) Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240808104118.430670-3-jirislaby@kernel.org --- include/linux/irq.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/irq.h b/include/linux/irq.h index 00490d6ead65..fa711f80957b 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -991,7 +991,6 @@ void irq_init_desc(unsigned int irq); * @ack: Ack register offset to reg_base * @eoi: Eoi register offset to reg_base * @type: Type configuration register offset to reg_base - * @polarity: Polarity configuration register offset to reg_base */ struct irq_chip_regs { unsigned long enable; @@ -1000,7 +999,6 @@ struct irq_chip_regs { unsigned long ack; unsigned long eoi; unsigned long type; - unsigned long polarity; }; /** From 70114e7f7585ef078c2b7033ee14218f95f55e22 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Thu, 8 Aug 2024 15:34:02 +0300 Subject: [PATCH 48/73] irqdomain: Simplify simple and legacy domain creation irq_domain_create_simple() and irq_domain_create_legacy() use __irq_domain_instantiate(), but have extra handling of allocating interrupt descriptors and associating interrupts in them. Some of that is duplicated. There are also call sites which have conditonals to invoke different interrupt domain creator functions, where one of them is usually irq_domain_create_legacy(). Alternatively they associate the interrupts for the legacy case after creating the domain. Moving the extra logic of irq_domain_create_simple()/legacy() into __irq_domain_instantiate() allows to consolidate that. Introduce hwirq_base and virq_base members in the irq_domain_info structure, which allows to transport the required information and add the conditional interrupt descriptor allocation and interrupt association into __irq_domain_instantiate(). This reduces irq_domain_create_legacy() and irq_domain_create_simple() to trivial wrappers which fill in the info structure and allows call sites which must support the legacy case along with more modern mechanism to select the domain type via the parameters of the info struct. [ tglx: Massaged change log ] Suggested-by: Thomas Gleixner Signed-off-by: Matti Vaittinen Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/32d07bd79eb2b5416e24da9e9e8fe5955423dcf9.1723120028.git.mazziesaccount@gmail.com --- include/linux/irqdomain.h | 5 +++ kernel/irq/irqdomain.c | 74 ++++++++++++++++++++++----------------- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index de6105f68fec..bfcffa2c7047 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -291,6 +291,9 @@ struct irq_domain_chip_generic_info; * @hwirq_max: Maximum number of interrupts supported by controller * @direct_max: Maximum value of direct maps; * Use ~0 for no limit; 0 for no direct mapping + * @hwirq_base: The first hardware interrupt number (legacy domains only) + * @virq_base: The first Linux interrupt number for legacy domains to + * immediately associate the interrupts after domain creation * @bus_token: Domain bus token * @ops: Domain operation callbacks * @host_data: Controller private data pointer @@ -307,6 +310,8 @@ struct irq_domain_info { unsigned int size; irq_hw_number_t hwirq_max; int direct_max; + unsigned int hwirq_base; + unsigned int virq_base; enum irq_domain_bus_token bus_token; const struct irq_domain_ops *ops; void *host_data; diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index cea8f6874b1f..7625e424f85a 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -267,13 +267,20 @@ static void irq_domain_free(struct irq_domain *domain) kfree(domain); } -/** - * irq_domain_instantiate() - Instantiate a new irq domain data structure - * @info: Domain information pointer pointing to the information for this domain - * - * Return: A pointer to the instantiated irq domain or an ERR_PTR value. - */ -struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info) +static void irq_domain_instantiate_descs(const struct irq_domain_info *info) +{ + if (!IS_ENABLED(CONFIG_SPARSE_IRQ)) + return; + + if (irq_alloc_descs(info->virq_base, info->virq_base, info->size, + of_node_to_nid(to_of_node(info->fwnode))) < 0) { + pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", + info->virq_base); + } +} + +static struct irq_domain *__irq_domain_instantiate(const struct irq_domain_info *info, + bool cond_alloc_descs) { struct irq_domain *domain; int err; @@ -306,6 +313,15 @@ struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info) __irq_domain_publish(domain); + if (cond_alloc_descs && info->virq_base > 0) + irq_domain_instantiate_descs(info); + + /* Legacy interrupt domains have a fixed Linux interrupt number */ + if (info->virq_base > 0) { + irq_domain_associate_many(domain, info->virq_base, info->hwirq_base, + info->size - info->hwirq_base); + } + return domain; err_domain_gc_remove: @@ -315,6 +331,17 @@ err_domain_free: irq_domain_free(domain); return ERR_PTR(err); } + +/** + * irq_domain_instantiate() - Instantiate a new irq domain data structure + * @info: Domain information pointer pointing to the information for this domain + * + * Return: A pointer to the instantiated irq domain or an ERR_PTR value. + */ +struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info) +{ + return __irq_domain_instantiate(info, false); +} EXPORT_SYMBOL_GPL(irq_domain_instantiate); /** @@ -413,28 +440,13 @@ struct irq_domain *irq_domain_create_simple(struct fwnode_handle *fwnode, .fwnode = fwnode, .size = size, .hwirq_max = size, + .virq_base = first_irq, .ops = ops, .host_data = host_data, }; - struct irq_domain *domain; + struct irq_domain *domain = __irq_domain_instantiate(&info, true); - domain = irq_domain_instantiate(&info); - if (IS_ERR(domain)) - return NULL; - - if (first_irq > 0) { - if (IS_ENABLED(CONFIG_SPARSE_IRQ)) { - /* attempt to allocated irq_descs */ - int rc = irq_alloc_descs(first_irq, first_irq, size, - of_node_to_nid(to_of_node(fwnode))); - if (rc < 0) - pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", - first_irq); - } - irq_domain_associate_many(domain, first_irq, 0, size); - } - - return domain; + return IS_ERR(domain) ? NULL : domain; } EXPORT_SYMBOL_GPL(irq_domain_create_simple); @@ -476,18 +488,14 @@ struct irq_domain *irq_domain_create_legacy(struct fwnode_handle *fwnode, .fwnode = fwnode, .size = first_hwirq + size, .hwirq_max = first_hwirq + size, + .hwirq_base = first_hwirq, + .virq_base = first_irq, .ops = ops, .host_data = host_data, }; - struct irq_domain *domain; + struct irq_domain *domain = irq_domain_instantiate(&info); - domain = irq_domain_instantiate(&info); - if (IS_ERR(domain)) - return NULL; - - irq_domain_associate_many(domain, first_irq, first_hwirq, size); - - return domain; + return IS_ERR(domain) ? NULL : domain; } EXPORT_SYMBOL_GPL(irq_domain_create_legacy); From 1bf2c92829274e7c815d06d7b3196a967ff70917 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 8 Aug 2024 22:19:41 +0200 Subject: [PATCH 49/73] irqdomain: Cleanup domain name allocation irq_domain_set_name() is truly unreadable gunk. Clean it up before adding more. Signed-off-by: Thomas Gleixner Reviewed-by: Matti Vaittinen Link: https://lore.kernel.org/all/874j7uvkbm.ffs@tglx --- kernel/irq/irqdomain.c | 106 +++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 7625e424f85a..72ab60187103 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -128,72 +128,76 @@ void irq_domain_free_fwnode(struct fwnode_handle *fwnode) } EXPORT_SYMBOL_GPL(irq_domain_free_fwnode); -static int irq_domain_set_name(struct irq_domain *domain, - const struct fwnode_handle *fwnode, - enum irq_domain_bus_token bus_token) +static int alloc_name(struct irq_domain *domain, char *base, enum irq_domain_bus_token bus_token) +{ + domain->name = bus_token ? kasprintf(GFP_KERNEL, "%s-%d", base, bus_token) : + kasprintf(GFP_KERNEL, "%s", base); + if (!domain->name) + return -ENOMEM; + + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; + return 0; +} + +static int alloc_fwnode_name(struct irq_domain *domain, const struct fwnode_handle *fwnode, + enum irq_domain_bus_token bus_token) +{ + char *name = bus_token ? kasprintf(GFP_KERNEL, "%pfw-%d", fwnode, bus_token) : + kasprintf(GFP_KERNEL, "%pfw", fwnode); + + if (!name) + return -ENOMEM; + + /* + * fwnode paths contain '/', which debugfs is legitimately unhappy + * about. Replace them with ':', which does the trick and is not as + * offensive as '\'... + */ + domain->name = strreplace(name, '/', ':'); + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; + return 0; +} + +static int alloc_unknown_name(struct irq_domain *domain, enum irq_domain_bus_token bus_token) { static atomic_t unknown_domains; - struct irqchip_fwid *fwid; + int id = atomic_inc_return(&unknown_domains); + domain->name = bus_token ? kasprintf(GFP_KERNEL, "unknown-%d-%d", id, bus_token) : + kasprintf(GFP_KERNEL, "unknown-%d", id); + + if (!domain->name) + return -ENOMEM; + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; + return 0; +} + +static int irq_domain_set_name(struct irq_domain *domain, const struct fwnode_handle *fwnode, + enum irq_domain_bus_token bus_token) +{ if (is_fwnode_irqchip(fwnode)) { - fwid = container_of(fwnode, struct irqchip_fwid, fwnode); + struct irqchip_fwid *fwid = container_of(fwnode, struct irqchip_fwid, fwnode); switch (fwid->type) { case IRQCHIP_FWNODE_NAMED: case IRQCHIP_FWNODE_NAMED_ID: - domain->name = bus_token ? - kasprintf(GFP_KERNEL, "%s-%d", - fwid->name, bus_token) : - kstrdup(fwid->name, GFP_KERNEL); - if (!domain->name) - return -ENOMEM; - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; - break; + return alloc_name(domain, fwid->name, bus_token); default: domain->name = fwid->name; - if (bus_token) { - domain->name = kasprintf(GFP_KERNEL, "%s-%d", - fwid->name, bus_token); - if (!domain->name) - return -ENOMEM; - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; - } - break; + if (bus_token) + return alloc_name(domain, fwid->name, bus_token); } - } else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || - is_software_node(fwnode)) { - char *name; - /* - * fwnode paths contain '/', which debugfs is legitimately - * unhappy about. Replace them with ':', which does - * the trick and is not as offensive as '\'... - */ - name = bus_token ? - kasprintf(GFP_KERNEL, "%pfw-%d", fwnode, bus_token) : - kasprintf(GFP_KERNEL, "%pfw", fwnode); - if (!name) - return -ENOMEM; - - domain->name = strreplace(name, '/', ':'); - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; + } else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || is_software_node(fwnode)) { + return alloc_fwnode_name(domain, fwnode, bus_token); } - if (!domain->name) { - if (fwnode) - pr_err("Invalid fwnode type for irqdomain\n"); - domain->name = bus_token ? - kasprintf(GFP_KERNEL, "unknown-%d-%d", - atomic_inc_return(&unknown_domains), - bus_token) : - kasprintf(GFP_KERNEL, "unknown-%d", - atomic_inc_return(&unknown_domains)); - if (!domain->name) - return -ENOMEM; - domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; - } + if (domain->name) + return 0; - return 0; + if (fwnode) + pr_err("Invalid fwnode type for irqdomain\n"); + return alloc_unknown_name(domain, bus_token); } static struct irq_domain *__irq_domain_create(const struct irq_domain_info *info) From 1e7c05292531e5b6bebe409cd531ed4ec0b2ff56 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Thu, 8 Aug 2024 22:23:06 +0200 Subject: [PATCH 50/73] irqdomain: Allow giving name suffix for domain Devices can provide multiple interrupt lines. One reason for this is that a device has multiple subfunctions, each providing its own interrupt line. Another reason is that a device can be designed to be used (also) on a system where some of the interrupts can be routed to another processor. A line often further acts as a demultiplex for specific interrupts and has it's respective set of interrupt (status, mask, ack, ...) registers. Regmap supports the handling of these registers and demultiplexing interrupts, but the interrupt domain code ends up assigning the same name for the per interrupt line domains. This causes a naming collision in the debugFS code and leads to confusion, as /proc/interrupts shows two separate interrupts with the same domain name and hardware interrupt number. Instead of adding a workaround in regmap or driver code, allow giving a name suffix for the domain name when the domain is created. Add a name_suffix field in the irq_domain_info structure and make irq_domain_instantiate() use this suffix if it is given when a domain is created. [ tglx: Adopt it to the cleanup patch and fixup the invalid NULL return ] Signed-off-by: Matti Vaittinen Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/871q2yvk5x.ffs@tglx --- include/linux/irqdomain.h | 3 +++ kernel/irq/irqdomain.c | 30 +++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index bfcffa2c7047..e432b6a12a32 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -295,6 +295,8 @@ struct irq_domain_chip_generic_info; * @virq_base: The first Linux interrupt number for legacy domains to * immediately associate the interrupts after domain creation * @bus_token: Domain bus token + * @name_suffix: Optional name suffix to avoid collisions when multiple + * domains are added using same fwnode * @ops: Domain operation callbacks * @host_data: Controller private data pointer * @dgc_info: Geneneric chip information structure pointer used to @@ -313,6 +315,7 @@ struct irq_domain_info { unsigned int hwirq_base; unsigned int virq_base; enum irq_domain_bus_token bus_token; + const char *name_suffix; const struct irq_domain_ops *ops; void *host_data; #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 72ab60187103..01001eb615ec 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -140,11 +140,14 @@ static int alloc_name(struct irq_domain *domain, char *base, enum irq_domain_bus } static int alloc_fwnode_name(struct irq_domain *domain, const struct fwnode_handle *fwnode, - enum irq_domain_bus_token bus_token) + enum irq_domain_bus_token bus_token, const char *suffix) { - char *name = bus_token ? kasprintf(GFP_KERNEL, "%pfw-%d", fwnode, bus_token) : - kasprintf(GFP_KERNEL, "%pfw", fwnode); + const char *sep = suffix ? "-" : ""; + const char *suf = suffix ? : ""; + char *name; + name = bus_token ? kasprintf(GFP_KERNEL, "%pfw-%s%s%d", fwnode, suf, sep, bus_token) : + kasprintf(GFP_KERNEL, "%pfw-%s", fwnode, suf); if (!name) return -ENOMEM; @@ -172,12 +175,25 @@ static int alloc_unknown_name(struct irq_domain *domain, enum irq_domain_bus_tok return 0; } -static int irq_domain_set_name(struct irq_domain *domain, const struct fwnode_handle *fwnode, - enum irq_domain_bus_token bus_token) +static int irq_domain_set_name(struct irq_domain *domain, const struct irq_domain_info *info) { + enum irq_domain_bus_token bus_token = info->bus_token; + const struct fwnode_handle *fwnode = info->fwnode; + if (is_fwnode_irqchip(fwnode)) { struct irqchip_fwid *fwid = container_of(fwnode, struct irqchip_fwid, fwnode); + /* + * The name_suffix is only intended to be used to avoid a name + * collision when multiple domains are created for a single + * device and the name is picked using a real device node. + * (Typical use-case is regmap-IRQ controllers for devices + * providing more than one physical IRQ.) There should be no + * need to use name_suffix with irqchip-fwnode. + */ + if (info->name_suffix) + return -EINVAL; + switch (fwid->type) { case IRQCHIP_FWNODE_NAMED: case IRQCHIP_FWNODE_NAMED_ID: @@ -189,7 +205,7 @@ static int irq_domain_set_name(struct irq_domain *domain, const struct fwnode_ha } } else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) || is_software_node(fwnode)) { - return alloc_fwnode_name(domain, fwnode, bus_token); + return alloc_fwnode_name(domain, fwnode, bus_token, info->name_suffix); } if (domain->name) @@ -215,7 +231,7 @@ static struct irq_domain *__irq_domain_create(const struct irq_domain_info *info if (!domain) return ERR_PTR(-ENOMEM); - err = irq_domain_set_name(domain, info->fwnode, info->bus_token); + err = irq_domain_set_name(domain, info); if (err) { kfree(domain); return ERR_PTR(err); From c0ece64497992473aabbcbb007e2afecc8d750a2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 12 Aug 2024 22:29:39 +0300 Subject: [PATCH 51/73] irqdomain: Clarify checks for bus_token The code uses if (bus_token) and if (bus_token == DOMAIN_BUS_ANY). Since bus_token is an enum, the latter is more robust against changes. Convert all !bus_token checks to explicitely check for DOMAIN_BUS_ANY. Signed-off-by: Andy Shevchenko Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240812193101.1266625-2-andriy.shevchenko@linux.intel.com --- kernel/irq/irqdomain.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 01001eb615ec..18d253e10e87 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -130,8 +130,10 @@ EXPORT_SYMBOL_GPL(irq_domain_free_fwnode); static int alloc_name(struct irq_domain *domain, char *base, enum irq_domain_bus_token bus_token) { - domain->name = bus_token ? kasprintf(GFP_KERNEL, "%s-%d", base, bus_token) : - kasprintf(GFP_KERNEL, "%s", base); + if (bus_token == DOMAIN_BUS_ANY) + domain->name = kasprintf(GFP_KERNEL, "%s", base); + else + domain->name = kasprintf(GFP_KERNEL, "%s-%d", base, bus_token); if (!domain->name) return -ENOMEM; @@ -146,8 +148,10 @@ static int alloc_fwnode_name(struct irq_domain *domain, const struct fwnode_hand const char *suf = suffix ? : ""; char *name; - name = bus_token ? kasprintf(GFP_KERNEL, "%pfw-%s%s%d", fwnode, suf, sep, bus_token) : - kasprintf(GFP_KERNEL, "%pfw-%s", fwnode, suf); + if (bus_token == DOMAIN_BUS_ANY) + name = kasprintf(GFP_KERNEL, "%pfw-%s", fwnode, suf); + else + name = kasprintf(GFP_KERNEL, "%pfw-%s%s%d", fwnode, suf, sep, bus_token); if (!name) return -ENOMEM; @@ -166,11 +170,13 @@ static int alloc_unknown_name(struct irq_domain *domain, enum irq_domain_bus_tok static atomic_t unknown_domains; int id = atomic_inc_return(&unknown_domains); - domain->name = bus_token ? kasprintf(GFP_KERNEL, "unknown-%d-%d", id, bus_token) : - kasprintf(GFP_KERNEL, "unknown-%d", id); - + if (bus_token == DOMAIN_BUS_ANY) + domain->name = kasprintf(GFP_KERNEL, "unknown-%d", id); + else + domain->name = kasprintf(GFP_KERNEL, "unknown-%d-%d", id, bus_token); if (!domain->name) return -ENOMEM; + domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED; return 0; } @@ -200,7 +206,7 @@ static int irq_domain_set_name(struct irq_domain *domain, const struct irq_domai return alloc_name(domain, fwid->name, bus_token); default: domain->name = fwid->name; - if (bus_token) + if (bus_token != DOMAIN_BUS_ANY) return alloc_name(domain, fwid->name, bus_token); } From 7b9414cb2d370b7c5149b37f585b077af2ae211b Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 12 Aug 2024 22:29:40 +0300 Subject: [PATCH 52/73] irqdomain: Remove stray '-' in the domain name When the domain suffix is not supplied alloc_fwnode_name() unconditionally adds a separator. Fix the format strings to get rid of the stray '-' separator. Fixes: 1e7c05292531 ("irqdomain: Allow giving name suffix for domain") Signed-off-by: Andy Shevchenko Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240812193101.1266625-3-andriy.shevchenko@linux.intel.com --- kernel/irq/irqdomain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 18d253e10e87..1acc5308fcb7 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -149,9 +149,9 @@ static int alloc_fwnode_name(struct irq_domain *domain, const struct fwnode_hand char *name; if (bus_token == DOMAIN_BUS_ANY) - name = kasprintf(GFP_KERNEL, "%pfw-%s", fwnode, suf); + name = kasprintf(GFP_KERNEL, "%pfw%s%s", fwnode, sep, suf); else - name = kasprintf(GFP_KERNEL, "%pfw-%s%s%d", fwnode, suf, sep, bus_token); + name = kasprintf(GFP_KERNEL, "%pfw%s%s-%d", fwnode, sep, suf, bus_token); if (!name) return -ENOMEM; From 24d02c4e53e2f02da16b2ae8a1bc92553110ca25 Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Tue, 13 Aug 2024 14:34:27 +0300 Subject: [PATCH 53/73] irqdomain: Always associate interrupts for legacy domains The unification of irq_domain_create_legacy() missed the fact that interrupts must be associated even when the Linux interrupt number provided in the first_irq argument is 0. This breaks all call sites of irq_domain_create_legacy() which supply 0 as the first_irq argument. Enforce the association for legacy domains in __irq_domain_instantiate() to cure this. [ tglx: Massaged it slightly. ] Fixes: 70114e7f7585 ("irqdomain: Simplify simple and legacy domain creation") Reported-by: Jiaxun Yang Signed-off-by Matti Vaittinen Signed-off-by: Thomas Gleixner Tested-by: Jiaxun Yang Link: https://lore.kernel.org/all/c3379142-10bc-4f14-b8ac-a46927aeac38@gmail.com --- kernel/irq/irqdomain.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 1acc5308fcb7..5df8780100bb 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -306,7 +306,7 @@ static void irq_domain_instantiate_descs(const struct irq_domain_info *info) } static struct irq_domain *__irq_domain_instantiate(const struct irq_domain_info *info, - bool cond_alloc_descs) + bool cond_alloc_descs, bool force_associate) { struct irq_domain *domain; int err; @@ -342,8 +342,12 @@ static struct irq_domain *__irq_domain_instantiate(const struct irq_domain_info if (cond_alloc_descs && info->virq_base > 0) irq_domain_instantiate_descs(info); - /* Legacy interrupt domains have a fixed Linux interrupt number */ - if (info->virq_base > 0) { + /* + * Legacy interrupt domains have a fixed Linux interrupt number + * associated. Other interrupt domains can request association by + * providing a Linux interrupt number > 0. + */ + if (force_associate || info->virq_base > 0) { irq_domain_associate_many(domain, info->virq_base, info->hwirq_base, info->size - info->hwirq_base); } @@ -366,7 +370,7 @@ err_domain_free: */ struct irq_domain *irq_domain_instantiate(const struct irq_domain_info *info) { - return __irq_domain_instantiate(info, false); + return __irq_domain_instantiate(info, false, false); } EXPORT_SYMBOL_GPL(irq_domain_instantiate); @@ -470,7 +474,7 @@ struct irq_domain *irq_domain_create_simple(struct fwnode_handle *fwnode, .ops = ops, .host_data = host_data, }; - struct irq_domain *domain = __irq_domain_instantiate(&info, true); + struct irq_domain *domain = __irq_domain_instantiate(&info, true, false); return IS_ERR(domain) ? NULL : domain; } @@ -519,7 +523,7 @@ struct irq_domain *irq_domain_create_legacy(struct fwnode_handle *fwnode, .ops = ops, .host_data = host_data, }; - struct irq_domain *domain = irq_domain_instantiate(&info); + struct irq_domain *domain = __irq_domain_instantiate(&info, false, true); return IS_ERR(domain) ? NULL : domain; } From e68ac2b488495fa4d127d6105ce633849859957a Mon Sep 17 00:00:00 2001 From: Caleb Sander Mateos Date: Thu, 15 Aug 2024 11:15:40 -0600 Subject: [PATCH 54/73] softirq: Remove unused 'action' parameter from action callback When soft interrupt actions are called, they are passed a pointer to the struct softirq action which contains the action's function pointer. This pointer isn't useful, as the action callback already knows what function it is. And since each callback handles a specific soft interrupt, the callback also knows which soft interrupt number is running. No soft interrupt action callback actually uses this parameter, so remove it from the function pointer signature. This clarifies that soft interrupt actions are global routines and makes it slightly cheaper to call them. Signed-off-by: Caleb Sander Mateos Signed-off-by: Thomas Gleixner Reviewed-by: Jens Axboe Link: https://lore.kernel.org/all/20240815171549.3260003-1-csander@purestorage.com --- block/blk-mq.c | 2 +- include/linux/interrupt.h | 4 ++-- kernel/rcu/tiny.c | 2 +- kernel/rcu/tree.c | 2 +- kernel/sched/fair.c | 2 +- kernel/softirq.c | 15 +++++++-------- kernel/time/hrtimer.c | 2 +- kernel/time/timer.c | 2 +- lib/irq_poll.c | 2 +- net/core/dev.c | 4 ++-- 10 files changed, 18 insertions(+), 19 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index e3c3c0c21b55..aa28157b1aaf 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1128,7 +1128,7 @@ static void blk_complete_reqs(struct llist_head *list) rq->q->mq_ops->complete(rq); } -static __latent_entropy void blk_done_softirq(struct softirq_action *h) +static __latent_entropy void blk_done_softirq(void) { blk_complete_reqs(this_cpu_ptr(&blk_cpu_done)); } diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 3f30c88e0b4c..694de61e0b38 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -594,7 +594,7 @@ extern const char * const softirq_to_name[NR_SOFTIRQS]; struct softirq_action { - void (*action)(struct softirq_action *); + void (*action)(void); }; asmlinkage void do_softirq(void); @@ -609,7 +609,7 @@ static inline void do_softirq_post_smp_call_flush(unsigned int unused) } #endif -extern void open_softirq(int nr, void (*action)(struct softirq_action *)); +extern void open_softirq(int nr, void (*action)(void)); extern void softirq_init(void); extern void __raise_softirq_irqoff(unsigned int nr); diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c index 4402d6f5f857..b3b3ce34df63 100644 --- a/kernel/rcu/tiny.c +++ b/kernel/rcu/tiny.c @@ -105,7 +105,7 @@ static inline bool rcu_reclaim_tiny(struct rcu_head *head) } /* Invoke the RCU callbacks whose grace period has elapsed. */ -static __latent_entropy void rcu_process_callbacks(struct softirq_action *unused) +static __latent_entropy void rcu_process_callbacks(void) { struct rcu_head *next, *list; unsigned long flags; diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index e641cc681901..93bd665637c0 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -2855,7 +2855,7 @@ static __latent_entropy void rcu_core(void) queue_work_on(rdp->cpu, rcu_gp_wq, &rdp->strict_work); } -static void rcu_core_si(struct softirq_action *h) +static void rcu_core_si(void) { rcu_core(); } diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 9057584ec06d..8dc9385f6da4 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -12483,7 +12483,7 @@ out: * - indirectly from a remote scheduler_tick() for NOHZ idle balancing * through the SMP cross-call nohz_csd_func() */ -static __latent_entropy void sched_balance_softirq(struct softirq_action *h) +static __latent_entropy void sched_balance_softirq(void) { struct rq *this_rq = this_rq(); enum cpu_idle_type idle = this_rq->idle_balance; diff --git a/kernel/softirq.c b/kernel/softirq.c index 02582017759a..d082e7840f88 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -551,7 +551,7 @@ restart: kstat_incr_softirqs_this_cpu(vec_nr); trace_softirq_entry(vec_nr); - h->action(h); + h->action(); trace_softirq_exit(vec_nr); if (unlikely(prev_count != preempt_count())) { pr_err("huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?\n", @@ -700,7 +700,7 @@ void __raise_softirq_irqoff(unsigned int nr) or_softirq_pending(1UL << nr); } -void open_softirq(int nr, void (*action)(struct softirq_action *)) +void open_softirq(int nr, void (*action)(void)) { softirq_vec[nr].action = action; } @@ -760,8 +760,7 @@ static bool tasklet_clear_sched(struct tasklet_struct *t) return false; } -static void tasklet_action_common(struct softirq_action *a, - struct tasklet_head *tl_head, +static void tasklet_action_common(struct tasklet_head *tl_head, unsigned int softirq_nr) { struct tasklet_struct *list; @@ -805,16 +804,16 @@ static void tasklet_action_common(struct softirq_action *a, } } -static __latent_entropy void tasklet_action(struct softirq_action *a) +static __latent_entropy void tasklet_action(void) { workqueue_softirq_action(false); - tasklet_action_common(a, this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ); + tasklet_action_common(this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ); } -static __latent_entropy void tasklet_hi_action(struct softirq_action *a) +static __latent_entropy void tasklet_hi_action(void) { workqueue_softirq_action(true); - tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ); + tasklet_action_common(this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ); } void tasklet_setup(struct tasklet_struct *t, diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index b8ee320208d4..836157e09e25 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1757,7 +1757,7 @@ static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now, } } -static __latent_entropy void hrtimer_run_softirq(struct softirq_action *h) +static __latent_entropy void hrtimer_run_softirq(void) { struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases); unsigned long flags; diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 64b0d8a0aa0f..760bbeb1f331 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -2440,7 +2440,7 @@ static void run_timer_base(int index) /* * This function runs timers and the timer-tq in bottom half context. */ -static __latent_entropy void run_timer_softirq(struct softirq_action *h) +static __latent_entropy void run_timer_softirq(void) { run_timer_base(BASE_LOCAL); if (IS_ENABLED(CONFIG_NO_HZ_COMMON)) { diff --git a/lib/irq_poll.c b/lib/irq_poll.c index 2d5329a42105..08b242bbdbdf 100644 --- a/lib/irq_poll.c +++ b/lib/irq_poll.c @@ -75,7 +75,7 @@ void irq_poll_complete(struct irq_poll *iop) } EXPORT_SYMBOL(irq_poll_complete); -static void __latent_entropy irq_poll_softirq(struct softirq_action *h) +static void __latent_entropy irq_poll_softirq(void) { struct list_head *list = this_cpu_ptr(&blk_cpu_iopoll); int rearm = 0, budget = irq_poll_budget; diff --git a/net/core/dev.c b/net/core/dev.c index 6ea1d20676fb..e24a3bcb496d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5247,7 +5247,7 @@ int netif_rx(struct sk_buff *skb) } EXPORT_SYMBOL(netif_rx); -static __latent_entropy void net_tx_action(struct softirq_action *h) +static __latent_entropy void net_tx_action(void) { struct softnet_data *sd = this_cpu_ptr(&softnet_data); @@ -6920,7 +6920,7 @@ static int napi_threaded_poll(void *data) return 0; } -static __latent_entropy void net_rx_action(struct softirq_action *h) +static __latent_entropy void net_rx_action(void) { struct softnet_data *sd = this_cpu_ptr(&softnet_data); unsigned long time_limit = jiffies + From 0b3af7591dbfd16ca45740cd90eb34be8b9a7175 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Thu, 15 Aug 2024 19:26:07 +0800 Subject: [PATCH 55/73] irqchip/loongson-pch-msi: Switch to MSI parent domains Remove the global PCI/MSI irqdomain implementation and provide the required MSI parent functionality by filling in msi_parent_ops, so the PCI/MSI code can detect the new parent and setup per-device MSI domains. Signed-off-by: Huacai Chen Signed-off-by: Tianyang Zhang Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240815112608.26925-2-zhangtianyang@loongson.cn --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-loongson-pch-msi.c | 58 ++++++++++---------------- 2 files changed, 24 insertions(+), 35 deletions(-) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index d078bdc48c38..341cd9ca5a05 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -685,6 +685,7 @@ config LOONGSON_PCH_MSI depends on PCI default MACH_LOONGSON64 select IRQ_DOMAIN_HIERARCHY + select IRQ_MSI_LIB select PCI_MSI help Support for the Loongson PCH MSI Controller. diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c index dd4d699170f4..2242f63c66fc 100644 --- a/drivers/irqchip/irq-loongson-pch-msi.c +++ b/drivers/irqchip/irq-loongson-pch-msi.c @@ -15,6 +15,8 @@ #include #include +#include "irq-msi-lib.h" + static int nr_pics; struct pch_msi_data { @@ -27,26 +29,6 @@ struct pch_msi_data { static struct fwnode_handle *pch_msi_handle[MAX_IO_PICS]; -static void pch_msi_mask_msi_irq(struct irq_data *d) -{ - pci_msi_mask_irq(d); - irq_chip_mask_parent(d); -} - -static void pch_msi_unmask_msi_irq(struct irq_data *d) -{ - irq_chip_unmask_parent(d); - pci_msi_unmask_irq(d); -} - -static struct irq_chip pch_msi_irq_chip = { - .name = "PCH PCI MSI", - .irq_mask = pch_msi_mask_msi_irq, - .irq_unmask = pch_msi_unmask_msi_irq, - .irq_ack = irq_chip_ack_parent, - .irq_set_affinity = irq_chip_set_affinity_parent, -}; - static int pch_msi_allocate_hwirq(struct pch_msi_data *priv, int num_req) { int first; @@ -85,12 +67,6 @@ static void pch_msi_compose_msi_msg(struct irq_data *data, msg->data = data->hwirq; } -static struct msi_domain_info pch_msi_domain_info = { - .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX, - .chip = &pch_msi_irq_chip, -}; - static struct irq_chip middle_irq_chip = { .name = "PCH MSI", .irq_mask = irq_chip_mask_parent, @@ -155,13 +131,31 @@ static void pch_msi_middle_domain_free(struct irq_domain *domain, static const struct irq_domain_ops pch_msi_middle_domain_ops = { .alloc = pch_msi_middle_domain_alloc, .free = pch_msi_middle_domain_free, + .select = msi_lib_irq_domain_select, +}; + +#define PCH_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ + MSI_FLAG_USE_DEF_CHIP_OPS | \ + MSI_FLAG_PCI_MSI_MASK_PARENT) + +#define PCH_MSI_FLAGS_SUPPORTED (MSI_GENERIC_FLAGS_MASK | \ + MSI_FLAG_PCI_MSIX | \ + MSI_FLAG_MULTI_PCI_MSI) + +static struct msi_parent_ops pch_msi_parent_ops = { + .required_flags = PCH_MSI_FLAGS_REQUIRED, + .supported_flags = PCH_MSI_FLAGS_SUPPORTED, + .bus_select_mask = MATCH_PCI_MSI, + .bus_select_token = DOMAIN_BUS_NEXUS, + .prefix = "PCH-", + .init_dev_msi_info = msi_lib_init_dev_msi_info, }; static int pch_msi_init_domains(struct pch_msi_data *priv, struct irq_domain *parent, struct fwnode_handle *domain_handle) { - struct irq_domain *middle_domain, *msi_domain; + struct irq_domain *middle_domain; middle_domain = irq_domain_create_hierarchy(parent, 0, priv->num_irqs, domain_handle, @@ -174,14 +168,8 @@ static int pch_msi_init_domains(struct pch_msi_data *priv, irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS); - msi_domain = pci_msi_create_irq_domain(domain_handle, - &pch_msi_domain_info, - middle_domain); - if (!msi_domain) { - pr_err("Failed to create PCI MSI domain\n"); - irq_domain_remove(middle_domain); - return -ENOMEM; - } + middle_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; + middle_domain->msi_parent_ops = &pch_msi_parent_ops; return 0; } From 06fac729a6d54e2c6650b38734f84383aafb3acc Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Fri, 23 Aug 2024 18:39:32 +0800 Subject: [PATCH 56/73] LoongArch: Move irqchip function prototypes to irq-loongson.h Some irqchip functions are only for internal use by irqchip drivers, so move their prototypes from asm/irq.h to drivers/irqchip/irq-loongson.h. All related driver files include the new irq-loongson.h. Signed-off-by: Huacai Chen Signed-off-by: Tianyang Zhang Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240823103936.25092-1-zhangtianyang@loongson.cn --- arch/loongarch/include/asm/irq.h | 14 -------------- drivers/irqchip/irq-loongarch-cpu.c | 2 ++ drivers/irqchip/irq-loongson-eiointc.c | 2 ++ drivers/irqchip/irq-loongson-htvec.c | 2 ++ drivers/irqchip/irq-loongson-liointc.c | 2 ++ drivers/irqchip/irq-loongson-pch-lpc.c | 2 ++ drivers/irqchip/irq-loongson-pch-msi.c | 1 + drivers/irqchip/irq-loongson-pch-pic.c | 2 ++ drivers/irqchip/irq-loongson.h | 25 +++++++++++++++++++++++++ 9 files changed, 38 insertions(+), 14 deletions(-) create mode 100644 drivers/irqchip/irq-loongson.h diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index 480418bc5071..65503c9eb529 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -88,20 +88,6 @@ struct acpi_madt_bio_pic; struct acpi_madt_msi_pic; struct acpi_madt_lpc_pic; -int liointc_acpi_init(struct irq_domain *parent, - struct acpi_madt_lio_pic *acpi_liointc); -int eiointc_acpi_init(struct irq_domain *parent, - struct acpi_madt_eio_pic *acpi_eiointc); - -int htvec_acpi_init(struct irq_domain *parent, - struct acpi_madt_ht_pic *acpi_htvec); -int pch_lpc_acpi_init(struct irq_domain *parent, - struct acpi_madt_lpc_pic *acpi_pchlpc); -int pch_msi_acpi_init(struct irq_domain *parent, - struct acpi_madt_msi_pic *acpi_pchmsi); -int pch_pic_acpi_init(struct irq_domain *parent, - struct acpi_madt_bio_pic *acpi_pchpic); -int find_pch_pic(u32 gsi); struct fwnode_handle *get_pch_msi_handle(int pci_segment); extern struct acpi_madt_lio_pic *acpi_liointc; diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c index 9d8f2c406043..83f7492290a8 100644 --- a/drivers/irqchip/irq-loongarch-cpu.c +++ b/drivers/irqchip/irq-loongarch-cpu.c @@ -13,6 +13,8 @@ #include #include +#include "irq-loongson.h" + static struct irq_domain *irq_domain; struct fwnode_handle *cpuintc_handle; diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index b1f2080be2be..34b5ca2f5e62 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -17,6 +17,8 @@ #include #include +#include "irq-loongson.h" + #define EIOINTC_REG_NODEMAP 0x14a0 #define EIOINTC_REG_IPMAP 0x14c0 #define EIOINTC_REG_ENABLE 0x1600 diff --git a/drivers/irqchip/irq-loongson-htvec.c b/drivers/irqchip/irq-loongson-htvec.c index 0bff728b25e3..5da02c7ad0b3 100644 --- a/drivers/irqchip/irq-loongson-htvec.c +++ b/drivers/irqchip/irq-loongson-htvec.c @@ -17,6 +17,8 @@ #include #include +#include "irq-loongson.h" + /* Registers */ #define HTVEC_EN_OFF 0x20 #define HTVEC_MAX_PARENT_IRQ 8 diff --git a/drivers/irqchip/irq-loongson-liointc.c b/drivers/irqchip/irq-loongson-liointc.c index 7c4fe7ab4b83..2b1bd4a96665 100644 --- a/drivers/irqchip/irq-loongson-liointc.c +++ b/drivers/irqchip/irq-loongson-liointc.c @@ -22,6 +22,8 @@ #include #endif +#include "irq-loongson.h" + #define LIOINTC_CHIP_IRQ 32 #define LIOINTC_NUM_PARENT 4 #define LIOINTC_NUM_CORES 4 diff --git a/drivers/irqchip/irq-loongson-pch-lpc.c b/drivers/irqchip/irq-loongson-pch-lpc.c index 9b35492fb6be..2d4c3ec128b8 100644 --- a/drivers/irqchip/irq-loongson-pch-lpc.c +++ b/drivers/irqchip/irq-loongson-pch-lpc.c @@ -15,6 +15,8 @@ #include #include +#include "irq-loongson.h" + /* Registers */ #define LPC_INT_CTL 0x00 #define LPC_INT_ENA 0x04 diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c index 2242f63c66fc..d43731878800 100644 --- a/drivers/irqchip/irq-loongson-pch-msi.c +++ b/drivers/irqchip/irq-loongson-pch-msi.c @@ -16,6 +16,7 @@ #include #include "irq-msi-lib.h" +#include "irq-loongson.h" static int nr_pics; diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c index cbaef65e804c..69efda35a8e7 100644 --- a/drivers/irqchip/irq-loongson-pch-pic.c +++ b/drivers/irqchip/irq-loongson-pch-pic.c @@ -17,6 +17,8 @@ #include #include +#include "irq-loongson.h" + /* Registers */ #define PCH_PIC_MASK 0x20 #define PCH_PIC_HTMSI_EN 0x40 diff --git a/drivers/irqchip/irq-loongson.h b/drivers/irqchip/irq-loongson.h new file mode 100644 index 000000000000..b155f1258ed5 --- /dev/null +++ b/drivers/irqchip/irq-loongson.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2024 Loongson Technology Corporation Limited + */ + +#ifndef _DRIVERS_IRQCHIP_IRQ_LOONGSON_H +#define _DRIVERS_IRQCHIP_IRQ_LOONGSON_H + +int find_pch_pic(u32 gsi); + +int liointc_acpi_init(struct irq_domain *parent, + struct acpi_madt_lio_pic *acpi_liointc); +int eiointc_acpi_init(struct irq_domain *parent, + struct acpi_madt_eio_pic *acpi_eiointc); + +int htvec_acpi_init(struct irq_domain *parent, + struct acpi_madt_ht_pic *acpi_htvec); +int pch_lpc_acpi_init(struct irq_domain *parent, + struct acpi_madt_lpc_pic *acpi_pchlpc); +int pch_pic_acpi_init(struct irq_domain *parent, + struct acpi_madt_bio_pic *acpi_pchpic); +int pch_msi_acpi_init(struct irq_domain *parent, + struct acpi_madt_msi_pic *acpi_pchmsi); + +#endif /* _DRIVERS_IRQCHIP_IRQ_LOONGSON_H */ From 843ed9317be1d0c3f4245418644fc7e55f465419 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Fri, 23 Aug 2024 18:39:33 +0800 Subject: [PATCH 57/73] LoongArch: Architectural preparation for AVEC irqchip Add architectural preparation for AVEC irqchip, including: 1. CPUCFG feature bits definition for AVEC; 2. Detection of AVEC irqchip in cpu_probe(); 3. New IPI type definition (IPI_CLEAR_VECTOR) for AVEC; 4. Provide arch_probe_nr_irqs() for large NR_IRQS; 5. Other related changes about the number of interrupts. Signed-off-by: Huacai Chen Signed-off-by: Tianyang Zhang Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240823103936.25092-2-zhangtianyang@loongson.cn --- arch/loongarch/include/asm/cpu-features.h | 1 + arch/loongarch/include/asm/cpu.h | 2 ++ arch/loongarch/include/asm/hardirq.h | 3 ++- arch/loongarch/include/asm/irq.h | 15 +++++++++++++-- arch/loongarch/include/asm/loongarch.h | 18 ++++++++++++++---- arch/loongarch/include/asm/smp.h | 2 ++ arch/loongarch/kernel/cpu-probe.c | 3 ++- arch/loongarch/kernel/irq.c | 12 ++++++++++++ 8 files changed, 48 insertions(+), 8 deletions(-) diff --git a/arch/loongarch/include/asm/cpu-features.h b/arch/loongarch/include/asm/cpu-features.h index 2eafe6a6aca8..16a716f88a5c 100644 --- a/arch/loongarch/include/asm/cpu-features.h +++ b/arch/loongarch/include/asm/cpu-features.h @@ -65,5 +65,6 @@ #define cpu_has_guestid cpu_opt(LOONGARCH_CPU_GUESTID) #define cpu_has_hypervisor cpu_opt(LOONGARCH_CPU_HYPERVISOR) #define cpu_has_ptw cpu_opt(LOONGARCH_CPU_PTW) +#define cpu_has_avecint cpu_opt(LOONGARCH_CPU_AVECINT) #endif /* __ASM_CPU_FEATURES_H */ diff --git a/arch/loongarch/include/asm/cpu.h b/arch/loongarch/include/asm/cpu.h index 48b9f7168bcc..843f9c4ec980 100644 --- a/arch/loongarch/include/asm/cpu.h +++ b/arch/loongarch/include/asm/cpu.h @@ -99,6 +99,7 @@ enum cpu_type_enum { #define CPU_FEATURE_GUESTID 24 /* CPU has GuestID feature */ #define CPU_FEATURE_HYPERVISOR 25 /* CPU has hypervisor (running in VM) */ #define CPU_FEATURE_PTW 26 /* CPU has hardware page table walker */ +#define CPU_FEATURE_AVECINT 27 /* CPU has avec interrupt */ #define LOONGARCH_CPU_CPUCFG BIT_ULL(CPU_FEATURE_CPUCFG) #define LOONGARCH_CPU_LAM BIT_ULL(CPU_FEATURE_LAM) @@ -127,5 +128,6 @@ enum cpu_type_enum { #define LOONGARCH_CPU_GUESTID BIT_ULL(CPU_FEATURE_GUESTID) #define LOONGARCH_CPU_HYPERVISOR BIT_ULL(CPU_FEATURE_HYPERVISOR) #define LOONGARCH_CPU_PTW BIT_ULL(CPU_FEATURE_PTW) +#define LOONGARCH_CPU_AVECINT BIT_ULL(CPU_FEATURE_AVECINT) #endif /* _ASM_CPU_H */ diff --git a/arch/loongarch/include/asm/hardirq.h b/arch/loongarch/include/asm/hardirq.h index 1d7feb719515..10da8d6961cb 100644 --- a/arch/loongarch/include/asm/hardirq.h +++ b/arch/loongarch/include/asm/hardirq.h @@ -12,12 +12,13 @@ extern void ack_bad_irq(unsigned int irq); #define ack_bad_irq ack_bad_irq -#define NR_IPI 3 +#define NR_IPI 4 enum ipi_msg_type { IPI_RESCHEDULE, IPI_CALL_FUNCTION, IPI_IRQ_WORK, + IPI_CLEAR_VECTOR, }; typedef struct { diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index 65503c9eb529..c4835800c8b9 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -39,11 +39,22 @@ void spurious_interrupt(void); #define NR_IRQS_LEGACY 16 +/* + * 256 Vectors Mapping for AVECINTC: + * + * 0 - 15: Mapping classic IPs, e.g. IP0-12. + * 16 - 255: Mapping vectors for external IRQ. + * + */ +#define NR_VECTORS 256 +#define NR_LEGACY_VECTORS 16 +#define IRQ_MATRIX_BITS NR_VECTORS + #define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace void arch_trigger_cpumask_backtrace(const struct cpumask *mask, int exclude_cpu); #define MAX_IO_PICS 2 -#define NR_IRQS (64 + (256 * MAX_IO_PICS)) +#define NR_IRQS (64 + NR_VECTORS * (NR_CPUS + MAX_IO_PICS)) struct acpi_vector_group { int node; @@ -65,7 +76,7 @@ extern struct acpi_vector_group msi_group[MAX_IO_PICS]; #define LOONGSON_LPC_LAST_IRQ (LOONGSON_LPC_IRQ_BASE + 15) #define LOONGSON_CPU_IRQ_BASE 16 -#define LOONGSON_CPU_LAST_IRQ (LOONGSON_CPU_IRQ_BASE + 14) +#define LOONGSON_CPU_LAST_IRQ (LOONGSON_CPU_IRQ_BASE + 15) #define LOONGSON_PCH_IRQ_BASE 64 #define LOONGSON_PCH_ACPI_IRQ (LOONGSON_PCH_IRQ_BASE + 47) diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h index 04a78010fc72..631d249b3ef2 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -253,8 +253,8 @@ #define CSR_ESTAT_EXC_WIDTH 6 #define CSR_ESTAT_EXC (_ULCAST_(0x3f) << CSR_ESTAT_EXC_SHIFT) #define CSR_ESTAT_IS_SHIFT 0 -#define CSR_ESTAT_IS_WIDTH 14 -#define CSR_ESTAT_IS (_ULCAST_(0x3fff) << CSR_ESTAT_IS_SHIFT) +#define CSR_ESTAT_IS_WIDTH 15 +#define CSR_ESTAT_IS (_ULCAST_(0x7fff) << CSR_ESTAT_IS_SHIFT) #define LOONGARCH_CSR_ERA 0x6 /* ERA */ @@ -649,6 +649,13 @@ #define LOONGARCH_CSR_CTAG 0x98 /* TagLo + TagHi */ +#define LOONGARCH_CSR_ISR0 0xa0 +#define LOONGARCH_CSR_ISR1 0xa1 +#define LOONGARCH_CSR_ISR2 0xa2 +#define LOONGARCH_CSR_ISR3 0xa3 + +#define LOONGARCH_CSR_IRR 0xa4 + #define LOONGARCH_CSR_PRID 0xc0 /* Shadow MCSR : 0xc0 ~ 0xff */ @@ -1011,7 +1018,7 @@ /* * CSR_ECFG IM */ -#define ECFG0_IM 0x00001fff +#define ECFG0_IM 0x00005fff #define ECFGB_SIP0 0 #define ECFGF_SIP0 (_ULCAST_(1) << ECFGB_SIP0) #define ECFGB_SIP1 1 @@ -1054,6 +1061,7 @@ #define IOCSRF_EIODECODE BIT_ULL(9) #define IOCSRF_FLATMODE BIT_ULL(10) #define IOCSRF_VM BIT_ULL(11) +#define IOCSRF_AVEC BIT_ULL(15) #define LOONGARCH_IOCSR_VENDOR 0x10 @@ -1065,6 +1073,7 @@ #define IOCSR_MISC_FUNC_SOFT_INT BIT_ULL(10) #define IOCSR_MISC_FUNC_TIMER_RESET BIT_ULL(21) #define IOCSR_MISC_FUNC_EXT_IOI_EN BIT_ULL(48) +#define IOCSR_MISC_FUNC_AVEC_EN BIT_ULL(51) #define LOONGARCH_IOCSR_CPUTEMP 0x428 @@ -1387,9 +1396,10 @@ __BUILD_CSR_OP(tlbidx) #define INT_TI 11 /* Timer */ #define INT_IPI 12 #define INT_NMI 13 +#define INT_AVEC 14 /* ExcCodes corresponding to interrupts */ -#define EXCCODE_INT_NUM (INT_NMI + 1) +#define EXCCODE_INT_NUM (INT_AVEC + 1) #define EXCCODE_INT_START 64 #define EXCCODE_INT_END (EXCCODE_INT_START + EXCCODE_INT_NUM - 1) diff --git a/arch/loongarch/include/asm/smp.h b/arch/loongarch/include/asm/smp.h index 50db503f44e3..3383c9d24e94 100644 --- a/arch/loongarch/include/asm/smp.h +++ b/arch/loongarch/include/asm/smp.h @@ -70,10 +70,12 @@ extern int __cpu_logical_map[NR_CPUS]; #define ACTION_RESCHEDULE 1 #define ACTION_CALL_FUNCTION 2 #define ACTION_IRQ_WORK 3 +#define ACTION_CLEAR_VECTOR 4 #define SMP_BOOT_CPU BIT(ACTION_BOOT_CPU) #define SMP_RESCHEDULE BIT(ACTION_RESCHEDULE) #define SMP_CALL_FUNCTION BIT(ACTION_CALL_FUNCTION) #define SMP_IRQ_WORK BIT(ACTION_IRQ_WORK) +#define SMP_CLEAR_VECTOR BIT(ACTION_CLEAR_VECTOR) struct secondary_data { unsigned long stack; diff --git a/arch/loongarch/kernel/cpu-probe.c b/arch/loongarch/kernel/cpu-probe.c index 55320813ee08..14f0449f5452 100644 --- a/arch/loongarch/kernel/cpu-probe.c +++ b/arch/loongarch/kernel/cpu-probe.c @@ -106,7 +106,6 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c) elf_hwcap |= HWCAP_LOONGARCH_CRC32; } - config = read_cpucfg(LOONGARCH_CPUCFG2); if (config & CPUCFG2_LAM) { c->options |= LOONGARCH_CPU_LAM; @@ -174,6 +173,8 @@ static void cpu_probe_common(struct cpuinfo_loongarch *c) c->options |= LOONGARCH_CPU_FLATMODE; if (config & IOCSRF_EIODECODE) c->options |= LOONGARCH_CPU_EIODECODE; + if (config & IOCSRF_AVEC) + c->options |= LOONGARCH_CPU_AVECINT; if (config & IOCSRF_VM) c->options |= LOONGARCH_CPU_HYPERVISOR; diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index f4991c03514f..414f5249d70a 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -87,6 +87,18 @@ static void __init init_vec_parent_group(void) acpi_table_parse(ACPI_SIG_MCFG, early_pci_mcfg_parse); } +int __init arch_probe_nr_irqs(void) +{ + int nr_io_pics = bitmap_weight(loongson_sysconf.cores_io_master, NR_CPUS); + + if (!cpu_has_avecint) + nr_irqs = (64 + NR_VECTORS * nr_io_pics); + else + nr_irqs = (64 + NR_VECTORS * (nr_cpu_ids + nr_io_pics)); + + return NR_IRQS_LEGACY; +} + void __init init_IRQ(void) { int i; From 9e83dd3ebb14fadccb936308b7b101c75da76324 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Fri, 23 Aug 2024 18:39:34 +0800 Subject: [PATCH 58/73] irqchip/loongson-eiointc: Rename CPUHP_AP_IRQ_LOONGARCH_STARTING Rename CPUHP_AP_IRQ_LOONGARCH_STARTING to CPUHP_AP_IRQ_EIOINTC_STARTING because the upcoming AVECINTC irqchip driver will introduce a new state and so both are clearly identifiable. Signed-off-by: Huacai Chen Signed-off-by: Tianyang Zhang Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240823103936.25092-3-zhangtianyang@loongson.cn --- drivers/irqchip/irq-loongson-eiointc.c | 4 ++-- include/linux/cpuhotplug.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index 34b5ca2f5e62..c756b7aa8055 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -398,8 +398,8 @@ static int __init eiointc_init(struct eiointc_priv *priv, int parent_irq, if (nr_pics == 1) { register_syscore_ops(&eiointc_syscore_ops); - cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, - "irqchip/loongarch/intc:starting", + cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_EIOINTC_STARTING, + "irqchip/loongarch/eiointc:starting", eiointc_router_init, NULL); } diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 51ba681b915a..e49807f7805c 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -145,7 +145,7 @@ enum cpuhp_state { CPUHP_AP_IRQ_ARMADA_XP_STARTING, CPUHP_AP_IRQ_BCM2836_STARTING, CPUHP_AP_IRQ_MIPS_GIC_STARTING, - CPUHP_AP_IRQ_LOONGARCH_STARTING, + CPUHP_AP_IRQ_EIOINTC_STARTING, CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING, CPUHP_AP_IRQ_RISCV_IMSIC_STARTING, CPUHP_AP_ARM_MVEBU_COHERENCY, From a1d4646d34c6642194a421ca9afbd060b0f9aa00 Mon Sep 17 00:00:00 2001 From: Tianyang Zhang Date: Fri, 23 Aug 2024 18:43:36 +0800 Subject: [PATCH 59/73] irqchip/loongson-pch-msi: Prepare get_pch_msi_handle() for AVECINTC On Loongson-3C6000 and higher systems with AVECINTC irqchip, there may be multiple PCI segments, but only one PCH-MSI irq domain. In this case, let get_pch_msi_handle() return the first domain handle. Co-developed-by: Jianmin Lv Signed-off-by: Jianmin Lv Co-developed-by: Liupu Wang Signed-off-by: Liupu Wang Co-developed-by: Huacai Chen Signed-off-by: Huacai Chen Signed-off-by: Tianyang Zhang Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240823104337.25577-1-zhangtianyang@loongson.cn --- drivers/irqchip/irq-loongson-pch-msi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c index d43731878800..0dc14550791d 100644 --- a/drivers/irqchip/irq-loongson-pch-msi.c +++ b/drivers/irqchip/irq-loongson-pch-msi.c @@ -255,17 +255,17 @@ IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_of_init); #ifdef CONFIG_ACPI struct fwnode_handle *get_pch_msi_handle(int pci_segment) { - int i; + if (cpu_has_avecint) + return pch_msi_handle[0]; - for (i = 0; i < MAX_IO_PICS; i++) { + for (int i = 0; i < MAX_IO_PICS; i++) { if (msi_group[i].pci_segment == pci_segment) return pch_msi_handle[i]; } - return NULL; + return pch_msi_handle[0]; } -int __init pch_msi_acpi_init(struct irq_domain *parent, - struct acpi_madt_msi_pic *acpi_pchmsi) +int __init pch_msi_acpi_init(struct irq_domain *parent, struct acpi_madt_msi_pic *acpi_pchmsi) { int ret; struct fwnode_handle *domain_handle; From ae16f05c928a1336d5d9d19fd805d7bf29c3f0c8 Mon Sep 17 00:00:00 2001 From: Tianyang Zhang Date: Fri, 23 Aug 2024 18:43:37 +0800 Subject: [PATCH 60/73] irqchip/loongarch-avec: Add AVEC irqchip support Introduce the advanced extended interrupt controllers (AVECINTC). This feature will allow each core to have 256 independent interrupt vectors and MSI interrupts can be independently routed to any vector on any CPU. The whole topology of irqchips in LoongArch machines looks like this if AVECINTC is supported: +-----+ +-----------------------+ +-------+ | IPI | --> | CPUINTC | <-- | Timer | +-----+ +-----------------------+ +-------+ ^ ^ ^ | | | +---------+ +----------+ +---------+ +-------+ | EIOINTC | | AVECINTC | | LIOINTC | <-- | UARTs | +---------+ +----------+ +---------+ +-------+ ^ ^ | | +---------+ +---------+ | PCH-PIC | | PCH-MSI | +---------+ +---------+ ^ ^ ^ | | | +---------+ +---------+ +---------+ | Devices | | PCH-LPC | | Devices | +---------+ +---------+ +---------+ ^ | +---------+ | Devices | +---------+ Co-developed-by: Jianmin Lv Signed-off-by: Jianmin Lv Co-developed-by: Liupu Wang Signed-off-by: Liupu Wang Co-developed-by: Huacai Chen Signed-off-by: Huacai Chen Signed-off-by: Tianyang Zhang Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240823104337.25577-2-zhangtianyang@loongson.cn --- arch/loongarch/Kconfig | 1 + arch/loongarch/include/asm/irq.h | 2 + arch/loongarch/kernel/paravirt.c | 5 + arch/loongarch/kernel/smp.c | 6 + drivers/irqchip/Makefile | 2 +- drivers/irqchip/irq-loongarch-avec.c | 425 +++++++++++++++++++++++++ drivers/irqchip/irq-loongarch-cpu.c | 5 +- drivers/irqchip/irq-loongson-eiointc.c | 3 + drivers/irqchip/irq-loongson-pch-msi.c | 14 + drivers/irqchip/irq-loongson.h | 2 + include/linux/cpuhotplug.h | 1 + 11 files changed, 464 insertions(+), 2 deletions(-) create mode 100644 drivers/irqchip/irq-loongarch-avec.c diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index 70f169210b52..0e3abf7b0bd3 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -85,6 +85,7 @@ config LOONGARCH select GENERIC_ENTRY select GENERIC_GETTIMEOFDAY select GENERIC_IOREMAP if !ARCH_IOREMAP + select GENERIC_IRQ_MATRIX_ALLOCATOR select GENERIC_IRQ_MULTI_HANDLER select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index c4835800c8b9..9c2ca785faa9 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -99,6 +99,8 @@ struct acpi_madt_bio_pic; struct acpi_madt_msi_pic; struct acpi_madt_lpc_pic; +void complete_irq_moving(void); + struct fwnode_handle *get_pch_msi_handle(int pci_segment); extern struct acpi_madt_lio_pic *acpi_liointc; diff --git a/arch/loongarch/kernel/paravirt.c b/arch/loongarch/kernel/paravirt.c index 9c9b75b76f62..4d736a4e488d 100644 --- a/arch/loongarch/kernel/paravirt.c +++ b/arch/loongarch/kernel/paravirt.c @@ -134,6 +134,11 @@ static irqreturn_t pv_ipi_interrupt(int irq, void *dev) info->ipi_irqs[IPI_IRQ_WORK]++; } + if (action & SMP_CLEAR_VECTOR) { + complete_irq_moving(); + info->ipi_irqs[IPI_CLEAR_VECTOR]++; + } + return IRQ_HANDLED; } diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index ca405ab86aae..4adbbef3450a 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -72,6 +72,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { [IPI_RESCHEDULE] = "Rescheduling interrupts", [IPI_CALL_FUNCTION] = "Function call interrupts", [IPI_IRQ_WORK] = "IRQ work interrupts", + [IPI_CLEAR_VECTOR] = "Clear vector interrupts", }; void show_ipi_list(struct seq_file *p, int prec) @@ -248,6 +249,11 @@ static irqreturn_t loongson_ipi_interrupt(int irq, void *dev) per_cpu(irq_stat, cpu).ipi_irqs[IPI_IRQ_WORK]++; } + if (action & SMP_CLEAR_VECTOR) { + complete_irq_moving(); + per_cpu(irq_stat, cpu).ipi_irqs[IPI_CLEAR_VECTOR]++; + } + return IRQ_HANDLED; } diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 15635812b2d6..e3679ec2b9f7 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -110,7 +110,7 @@ obj-$(CONFIG_LS1X_IRQ) += irq-ls1x.o obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) += irq-ti-sci-intr.o obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) += irq-ti-sci-inta.o obj-$(CONFIG_TI_PRUSS_INTC) += irq-pruss-intc.o -obj-$(CONFIG_IRQ_LOONGARCH_CPU) += irq-loongarch-cpu.o +obj-$(CONFIG_IRQ_LOONGARCH_CPU) += irq-loongarch-cpu.o irq-loongarch-avec.o obj-$(CONFIG_LOONGSON_LIOINTC) += irq-loongson-liointc.o obj-$(CONFIG_LOONGSON_EIOINTC) += irq-loongson-eiointc.o obj-$(CONFIG_LOONGSON_HTPIC) += irq-loongson-htpic.o diff --git a/drivers/irqchip/irq-loongarch-avec.c b/drivers/irqchip/irq-loongarch-avec.c new file mode 100644 index 000000000000..0f6e465dd309 --- /dev/null +++ b/drivers/irqchip/irq-loongarch-avec.c @@ -0,0 +1,425 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020-2024 Loongson Technologies, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "irq-msi-lib.h" +#include "irq-loongson.h" + +#define VECTORS_PER_REG 64 +#define IRR_VECTOR_MASK 0xffUL +#define IRR_INVALID_MASK 0x80000000UL +#define AVEC_MSG_OFFSET 0x100000 + +#ifdef CONFIG_SMP +struct pending_list { + struct list_head head; +}; + +static struct cpumask intersect_mask; +static DEFINE_PER_CPU(struct pending_list, pending_list); +#endif + +static DEFINE_PER_CPU(struct irq_desc * [NR_VECTORS], irq_map); + +struct avecintc_chip { + raw_spinlock_t lock; + struct fwnode_handle *fwnode; + struct irq_domain *domain; + struct irq_matrix *vector_matrix; + phys_addr_t msi_base_addr; +}; + +static struct avecintc_chip loongarch_avec; + +struct avecintc_data { + struct list_head entry; + unsigned int cpu; + unsigned int vec; + unsigned int prev_cpu; + unsigned int prev_vec; + unsigned int moving; +}; + +static inline void avecintc_ack_irq(struct irq_data *d) +{ +} + +static inline void avecintc_mask_irq(struct irq_data *d) +{ +} + +static inline void avecintc_unmask_irq(struct irq_data *d) +{ +} + +#ifdef CONFIG_SMP +static inline void pending_list_init(int cpu) +{ + struct pending_list *plist = per_cpu_ptr(&pending_list, cpu); + + INIT_LIST_HEAD(&plist->head); +} + +static void avecintc_sync(struct avecintc_data *adata) +{ + struct pending_list *plist; + + if (cpu_online(adata->prev_cpu)) { + plist = per_cpu_ptr(&pending_list, adata->prev_cpu); + list_add_tail(&adata->entry, &plist->head); + adata->moving = 1; + mp_ops.send_ipi_single(adata->prev_cpu, ACTION_CLEAR_VECTOR); + } +} + +static int avecintc_set_affinity(struct irq_data *data, const struct cpumask *dest, bool force) +{ + int cpu, ret, vector; + struct avecintc_data *adata; + + scoped_guard(raw_spinlock, &loongarch_avec.lock) { + adata = irq_data_get_irq_chip_data(data); + + if (adata->moving) + return -EBUSY; + + if (cpu_online(adata->cpu) && cpumask_test_cpu(adata->cpu, dest)) + return 0; + + cpumask_and(&intersect_mask, dest, cpu_online_mask); + + ret = irq_matrix_alloc(loongarch_avec.vector_matrix, &intersect_mask, false, &cpu); + if (ret < 0) + return ret; + + vector = ret; + adata->cpu = cpu; + adata->vec = vector; + per_cpu_ptr(irq_map, adata->cpu)[adata->vec] = irq_data_to_desc(data); + avecintc_sync(adata); + } + + irq_data_update_effective_affinity(data, cpumask_of(cpu)); + + return IRQ_SET_MASK_OK; +} + +static int avecintc_cpu_online(unsigned int cpu) +{ + if (!loongarch_avec.vector_matrix) + return 0; + + guard(raw_spinlock)(&loongarch_avec.lock); + + irq_matrix_online(loongarch_avec.vector_matrix); + + pending_list_init(cpu); + + return 0; +} + +static int avecintc_cpu_offline(unsigned int cpu) +{ + struct pending_list *plist = per_cpu_ptr(&pending_list, cpu); + + if (!loongarch_avec.vector_matrix) + return 0; + + guard(raw_spinlock)(&loongarch_avec.lock); + + if (!list_empty(&plist->head)) + pr_warn("CPU#%d vector is busy\n", cpu); + + irq_matrix_offline(loongarch_avec.vector_matrix); + + return 0; +} + +void complete_irq_moving(void) +{ + struct pending_list *plist = this_cpu_ptr(&pending_list); + struct avecintc_data *adata, *tdata; + int cpu, vector, bias; + uint64_t isr; + + guard(raw_spinlock)(&loongarch_avec.lock); + + list_for_each_entry_safe(adata, tdata, &plist->head, entry) { + cpu = adata->prev_cpu; + vector = adata->prev_vec; + bias = vector / VECTORS_PER_REG; + switch (bias) { + case 0: + isr = csr_read64(LOONGARCH_CSR_ISR0); + break; + case 1: + isr = csr_read64(LOONGARCH_CSR_ISR1); + break; + case 2: + isr = csr_read64(LOONGARCH_CSR_ISR2); + break; + case 3: + isr = csr_read64(LOONGARCH_CSR_ISR3); + break; + } + + if (isr & (1UL << (vector % VECTORS_PER_REG))) { + mp_ops.send_ipi_single(cpu, ACTION_CLEAR_VECTOR); + continue; + } + list_del(&adata->entry); + irq_matrix_free(loongarch_avec.vector_matrix, cpu, vector, false); + this_cpu_write(irq_map[vector], NULL); + adata->moving = 0; + adata->prev_cpu = adata->cpu; + adata->prev_vec = adata->vec; + } +} +#endif + +static void avecintc_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) +{ + struct avecintc_data *adata = irq_data_get_irq_chip_data(d); + + msg->address_hi = 0x0; + msg->address_lo = (loongarch_avec.msi_base_addr | (adata->vec & 0xff) << 4) + | ((cpu_logical_map(adata->cpu & 0xffff)) << 12); + msg->data = 0x0; +} + +static struct irq_chip avec_irq_controller = { + .name = "AVECINTC", + .irq_ack = avecintc_ack_irq, + .irq_mask = avecintc_mask_irq, + .irq_unmask = avecintc_unmask_irq, +#ifdef CONFIG_SMP + .irq_set_affinity = avecintc_set_affinity, +#endif + .irq_compose_msi_msg = avecintc_compose_msi_msg, +}; + +static void avecintc_irq_dispatch(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct irq_desc *d; + + chained_irq_enter(chip, desc); + + while (true) { + unsigned long vector = csr_read64(LOONGARCH_CSR_IRR); + if (vector & IRR_INVALID_MASK) + break; + + vector &= IRR_VECTOR_MASK; + + d = this_cpu_read(irq_map[vector]); + if (d) { + generic_handle_irq_desc(d); + } else { + spurious_interrupt(); + pr_warn("Unexpected IRQ occurs on CPU#%d [vector %ld]\n", smp_processor_id(), vector); + } + } + + chained_irq_exit(chip, desc); +} + +static int avecintc_alloc_vector(struct irq_data *irqd, struct avecintc_data *adata) +{ + int cpu, ret; + + guard(raw_spinlock_irqsave)(&loongarch_avec.lock); + + ret = irq_matrix_alloc(loongarch_avec.vector_matrix, cpu_online_mask, false, &cpu); + if (ret < 0) + return ret; + + adata->prev_cpu = adata->cpu = cpu; + adata->prev_vec = adata->vec = ret; + per_cpu_ptr(irq_map, adata->cpu)[adata->vec] = irq_data_to_desc(irqd); + + return 0; +} + +static int avecintc_domain_alloc(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs, void *arg) +{ + for (unsigned int i = 0; i < nr_irqs; i++) { + struct irq_data *irqd = irq_domain_get_irq_data(domain, virq + i); + struct avecintc_data *adata = kzalloc(sizeof(*adata), GFP_KERNEL); + int ret; + + if (!adata) + return -ENOMEM; + + ret = avecintc_alloc_vector(irqd, adata); + if (ret < 0) { + kfree(adata); + return ret; + } + + irq_domain_set_info(domain, virq + i, virq + i, &avec_irq_controller, + adata, handle_edge_irq, NULL, NULL); + irqd_set_single_target(irqd); + irqd_set_affinity_on_activate(irqd); + } + + return 0; +} + +static void avecintc_free_vector(struct irq_data *irqd, struct avecintc_data *adata) +{ + guard(raw_spinlock_irqsave)(&loongarch_avec.lock); + + per_cpu(irq_map, adata->cpu)[adata->vec] = NULL; + irq_matrix_free(loongarch_avec.vector_matrix, adata->cpu, adata->vec, false); + +#ifdef CONFIG_SMP + if (!adata->moving) + return; + + per_cpu(irq_map, adata->prev_cpu)[adata->prev_vec] = NULL; + irq_matrix_free(loongarch_avec.vector_matrix, adata->prev_cpu, adata->prev_vec, false); + list_del_init(&adata->entry); +#endif +} + +static void avecintc_domain_free(struct irq_domain *domain, unsigned int virq, + unsigned int nr_irqs) +{ + for (unsigned int i = 0; i < nr_irqs; i++) { + struct irq_data *d = irq_domain_get_irq_data(domain, virq + i); + + if (d) { + struct avecintc_data *adata = irq_data_get_irq_chip_data(d); + + avecintc_free_vector(d, adata); + irq_domain_reset_irq_data(d); + kfree(adata); + } + } +} + +static const struct irq_domain_ops avecintc_domain_ops = { + .alloc = avecintc_domain_alloc, + .free = avecintc_domain_free, + .select = msi_lib_irq_domain_select, +}; + +static int __init irq_matrix_init(void) +{ + loongarch_avec.vector_matrix = irq_alloc_matrix(NR_VECTORS, 0, NR_VECTORS); + if (!loongarch_avec.vector_matrix) + return -ENOMEM; + + for (int i = 0; i < NR_LEGACY_VECTORS; i++) + irq_matrix_assign_system(loongarch_avec.vector_matrix, i, false); + + irq_matrix_online(loongarch_avec.vector_matrix); + + return 0; +} + +static int __init avecintc_init(struct irq_domain *parent) +{ + int ret, parent_irq; + unsigned long value; + + raw_spin_lock_init(&loongarch_avec.lock); + + loongarch_avec.fwnode = irq_domain_alloc_named_fwnode("AVECINTC"); + if (!loongarch_avec.fwnode) { + pr_err("Unable to allocate domain handle\n"); + ret = -ENOMEM; + goto out; + } + + loongarch_avec.domain = irq_domain_create_tree(loongarch_avec.fwnode, + &avecintc_domain_ops, NULL); + if (!loongarch_avec.domain) { + pr_err("Unable to create IRQ domain\n"); + ret = -ENOMEM; + goto out_free_handle; + } + + parent_irq = irq_create_mapping(parent, INT_AVEC); + if (!parent_irq) { + pr_err("Failed to mapping hwirq\n"); + ret = -EINVAL; + goto out_remove_domain; + } + + ret = irq_matrix_init(); + if (ret < 0) { + pr_err("Failed to init irq matrix\n"); + goto out_remove_domain; + } + irq_set_chained_handler_and_data(parent_irq, avecintc_irq_dispatch, NULL); + +#ifdef CONFIG_SMP + pending_list_init(0); + cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_AVECINTC_STARTING, + "irqchip/loongarch/avecintc:starting", + avecintc_cpu_online, avecintc_cpu_offline); +#endif + value = iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC); + value |= IOCSR_MISC_FUNC_AVEC_EN; + iocsr_write64(value, LOONGARCH_IOCSR_MISC_FUNC); + + return ret; + +out_remove_domain: + irq_domain_remove(loongarch_avec.domain); +out_free_handle: + irq_domain_free_fwnode(loongarch_avec.fwnode); +out: + return ret; +} + +static int __init pch_msi_parse_madt(union acpi_subtable_headers *header, + const unsigned long end) +{ + struct acpi_madt_msi_pic *pchmsi_entry = (struct acpi_madt_msi_pic *)header; + + loongarch_avec.msi_base_addr = pchmsi_entry->msg_address - AVEC_MSG_OFFSET; + + return pch_msi_acpi_init_avec(loongarch_avec.domain); +} + +static inline int __init acpi_cascade_irqdomain_init(void) +{ + return acpi_table_parse_madt(ACPI_MADT_TYPE_MSI_PIC, pch_msi_parse_madt, 1); +} + +int __init avecintc_acpi_init(struct irq_domain *parent) +{ + int ret = avecintc_init(parent); + if (ret < 0) { + pr_err("Failed to init IRQ domain\n"); + return ret; + } + + ret = acpi_cascade_irqdomain_init(); + if (ret < 0) { + pr_err("Failed to init cascade IRQ domain\n"); + return ret; + } + + return ret; +} diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c index 83f7492290a8..bcbd7fd33178 100644 --- a/drivers/irqchip/irq-loongarch-cpu.c +++ b/drivers/irqchip/irq-loongarch-cpu.c @@ -140,7 +140,10 @@ static int __init acpi_cascade_irqdomain_init(void) if (r < 0) return r; - return 0; + if (cpu_has_avecint) + r = avecintc_acpi_init(irq_domain); + + return r; } static int __init cpuintc_acpi_init(union acpi_subtable_headers *header, diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index c756b7aa8055..e24db71a8783 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -362,6 +362,9 @@ static int __init acpi_cascade_irqdomain_init(void) if (r < 0) return r; + if (cpu_has_avecint) + return 0; + r = acpi_table_parse_madt(ACPI_MADT_TYPE_MSI_PIC, pch_msi_parse_madt, 1); if (r < 0) return r; diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c index 0dc14550791d..bd337ecddb40 100644 --- a/drivers/irqchip/irq-loongson-pch-msi.c +++ b/drivers/irqchip/irq-loongson-pch-msi.c @@ -278,4 +278,18 @@ int __init pch_msi_acpi_init(struct irq_domain *parent, struct acpi_madt_msi_pic return ret; } + +int __init pch_msi_acpi_init_avec(struct irq_domain *parent) +{ + if (pch_msi_handle[0]) + return 0; + + pch_msi_handle[0] = parent->fwnode; + irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS); + + parent->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; + parent->msi_parent_ops = &pch_msi_parent_ops; + + return 0; +} #endif diff --git a/drivers/irqchip/irq-loongson.h b/drivers/irqchip/irq-loongson.h index b155f1258ed5..11fa138d1f44 100644 --- a/drivers/irqchip/irq-loongson.h +++ b/drivers/irqchip/irq-loongson.h @@ -12,6 +12,7 @@ int liointc_acpi_init(struct irq_domain *parent, struct acpi_madt_lio_pic *acpi_liointc); int eiointc_acpi_init(struct irq_domain *parent, struct acpi_madt_eio_pic *acpi_eiointc); +int avecintc_acpi_init(struct irq_domain *parent); int htvec_acpi_init(struct irq_domain *parent, struct acpi_madt_ht_pic *acpi_htvec); @@ -21,5 +22,6 @@ int pch_pic_acpi_init(struct irq_domain *parent, struct acpi_madt_bio_pic *acpi_pchpic); int pch_msi_acpi_init(struct irq_domain *parent, struct acpi_madt_msi_pic *acpi_pchmsi); +int pch_msi_acpi_init_avec(struct irq_domain *parent); #endif /* _DRIVERS_IRQCHIP_IRQ_LOONGSON_H */ diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index e49807f7805c..55a726d317d4 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -146,6 +146,7 @@ enum cpuhp_state { CPUHP_AP_IRQ_BCM2836_STARTING, CPUHP_AP_IRQ_MIPS_GIC_STARTING, CPUHP_AP_IRQ_EIOINTC_STARTING, + CPUHP_AP_IRQ_AVECINTC_STARTING, CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING, CPUHP_AP_IRQ_RISCV_IMSIC_STARTING, CPUHP_AP_ARM_MVEBU_COHERENCY, From 17e28a9aeae40d2de3c1ea3b94819ed94bfd6392 Mon Sep 17 00:00:00 2001 From: Costa Shulyupin Date: Thu, 22 Aug 2024 15:31:58 +0300 Subject: [PATCH 61/73] genirq: Fix typo in struct comment Remove redundant "e" in "assign(e)ments". Signed-off-by: Costa Shulyupin Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240822123205.2186221-1-costa.shul@redhat.com --- include/linux/interrupt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 694de61e0b38..457151f9f263 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -276,7 +276,7 @@ struct irq_affinity_notify { #define IRQ_AFFINITY_MAX_SETS 4 /** - * struct irq_affinity - Description for automatic irq affinity assignements + * struct irq_affinity - Description for automatic irq affinity assignments * @pre_vectors: Don't apply affinity to @pre_vectors at beginning of * the MSI(-X) vector space * @post_vectors: Don't apply affinity to @post_vectors at end of From 64b6d1d7a84538de34c22a6fc92a7dcc2b196b64 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 26 Aug 2024 09:06:18 +0100 Subject: [PATCH 62/73] genirq: Get rid of global lock in irq_do_set_affinity() Kunkun Jiang reports that for a workload involving the simultaneous startup of a large number of VMs (for a total of about 200 vcpus), a lot of CPU time gets spent on spinning on the tmp_mask_lock that exists as a static raw spinlock in irq_do_set_affinity(). This lock protects a global cpumask (tmp_mask) that is used as a temporary variable to compute the resulting affinity. While this is triggered by KVM issuing a irq_set_affinity() call each time a vcpu is about to execute, it is obvious that having a single global resource is not very scalable. Since a cpumask can be a fairly large structure on systems with a high core count, a stack allocation is not really appropriate. Instead, turn the global cpumask into a per-CPU variable, removing the need for locking altogether as the code is executed with preemption and interrupts disabled. [ tglx: Moved the per CPU variable declaration outside of the function ] Reported-by: Kunkun Jiang Suggested-by: Thomas Gleixner Signed-off-by: Marc Zyngier Signed-off-by: Thomas Gleixner Tested-by: Kunkun Jiang Link: https://lore.kernel.org/all/20240826080618.3886694-1-maz@kernel.org Link: https://lore.kernel.org/all/a7fc58e4-64c2-77fc-c1dc-f5eb78dbbb01@huawei.com --- kernel/irq/manage.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index dd53298ef1a5..f0803d6bd296 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -218,21 +218,20 @@ static void irq_validate_effective_affinity(struct irq_data *data) static inline void irq_validate_effective_affinity(struct irq_data *data) { } #endif +static DEFINE_PER_CPU(struct cpumask, __tmp_mask); + int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) { + struct cpumask *tmp_mask = this_cpu_ptr(&__tmp_mask); struct irq_desc *desc = irq_data_to_desc(data); struct irq_chip *chip = irq_data_get_irq_chip(data); const struct cpumask *prog_mask; int ret; - static DEFINE_RAW_SPINLOCK(tmp_mask_lock); - static struct cpumask tmp_mask; - if (!chip || !chip->irq_set_affinity) return -EINVAL; - raw_spin_lock(&tmp_mask_lock); /* * If this is a managed interrupt and housekeeping is enabled on * it check whether the requested affinity mask intersects with @@ -258,11 +257,11 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, hk_mask = housekeeping_cpumask(HK_TYPE_MANAGED_IRQ); - cpumask_and(&tmp_mask, mask, hk_mask); - if (!cpumask_intersects(&tmp_mask, cpu_online_mask)) + cpumask_and(tmp_mask, mask, hk_mask); + if (!cpumask_intersects(tmp_mask, cpu_online_mask)) prog_mask = mask; else - prog_mask = &tmp_mask; + prog_mask = tmp_mask; } else { prog_mask = mask; } @@ -272,16 +271,14 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, * unless we are being asked to force the affinity (in which * case we do as we are told). */ - cpumask_and(&tmp_mask, prog_mask, cpu_online_mask); - if (!force && !cpumask_empty(&tmp_mask)) - ret = chip->irq_set_affinity(data, &tmp_mask, force); + cpumask_and(tmp_mask, prog_mask, cpu_online_mask); + if (!force && !cpumask_empty(tmp_mask)) + ret = chip->irq_set_affinity(data, tmp_mask, force); else if (force) ret = chip->irq_set_affinity(data, mask, force); else ret = -EINVAL; - raw_spin_unlock(&tmp_mask_lock); - switch (ret) { case IRQ_SET_MASK_OK: case IRQ_SET_MASK_OK_DONE: From c7718e5c76d49b5bb394265383ae51f766d5dd3a Mon Sep 17 00:00:00 2001 From: Jeff Xie Date: Sun, 25 Aug 2024 21:19:11 +0800 Subject: [PATCH 63/73] genirq/proc: Correctly set file permissions for affinity control files The kernel already knows at the time of interrupt allocation whether affinity of an interrupt can be controlled by userspace or not. It still creates all related procfs control files with read/write permissions. That's inconsistent and non-intuitive for system administrators and tools. Therefore set the file permissions to read-only for such interrupts. [ tglx: Massage change log, fixed UP build ] Signed-off-by: Jeff Xie Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240825131911.107119-1-jeff.xie@linux.dev --- kernel/irq/proc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 8cccdf40725a..9b3b12ad5dda 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -362,8 +362,13 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc) goto out_unlock; #ifdef CONFIG_SMP + umode_t umode = S_IRUGO; + + if (irq_can_set_affinity_usr(desc->irq_data.irq)) + umode |= S_IWUSR; + /* create /proc/irq//smp_affinity */ - proc_create_data("smp_affinity", 0644, desc->dir, + proc_create_data("smp_affinity", umode, desc->dir, &irq_affinity_proc_ops, irqp); /* create /proc/irq//affinity_hint */ @@ -371,7 +376,7 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc) irq_affinity_hint_proc_show, irqp); /* create /proc/irq//smp_affinity_list */ - proc_create_data("smp_affinity_list", 0644, desc->dir, + proc_create_data("smp_affinity_list", umode, desc->dir, &irq_affinity_list_proc_ops, irqp); proc_create_single_data("node", 0444, desc->dir, irq_node_proc_show, From 9012f84e1c5b653c282b7a6cca81454ecf7c5a0a Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Thu, 29 Aug 2024 19:15:22 +0800 Subject: [PATCH 64/73] genirq/proc: Use irq_move_pending() in show_irq_affinity() irq_move_pending() encapsulates irqd_is_setaffinity_pending() depending on CONFIG_GENERIC_PENDING_IRQ. Replace the open coded #ifdeffery with it. Signed-off-by: Jinjie Ruan Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240829111522.230595-1-ruanjinjie@huawei.com --- kernel/irq/proc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 9b3b12ad5dda..d98fb9c2c667 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -52,10 +52,8 @@ static int show_irq_affinity(int type, struct seq_file *m) case AFFINITY: case AFFINITY_LIST: mask = desc->irq_common_data.affinity; -#ifdef CONFIG_GENERIC_PENDING_IRQ - if (irqd_is_setaffinity_pending(&desc->irq_data)) - mask = desc->pending_mask; -#endif + if (irq_move_pending(&desc->irq_data)) + mask = irq_desc_get_pending_mask(desc); break; case EFFECTIVE: case EFFECTIVE_LIST: From eb29369fa543e7d5557c19ebecf072244bb14815 Mon Sep 17 00:00:00 2001 From: Jeff Xie Date: Mon, 26 Aug 2024 22:58:05 +0800 Subject: [PATCH 65/73] genirq/proc: Change the return value for set affinity permission error Currently, when the affinity of an irq cannot be set due to lack of permission, the write_irq_affinity() returns the error code -EIO. Change the return value to -EPERM as that reflects the cause of error correctly. Signed-off-by: Jeff Xie Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240826145805.5938-1-jeff.xie@linux.dev --- kernel/irq/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index d98fb9c2c667..9081ada81c3d 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -140,7 +140,7 @@ static ssize_t write_irq_affinity(int type, struct file *file, int err; if (!irq_can_set_affinity_usr(irq) || no_irq_affinity) - return -EIO; + return -EPERM; if (!zalloc_cpumask_var(&new_value, GFP_KERNEL)) return -ENOMEM; From bf1e0fb69a15fac4d6ee71d0e1c715147add986a Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Wed, 28 Aug 2024 15:22:19 +0800 Subject: [PATCH 66/73] genirq/msi: Use kmemdup_array() instead of kmemdup() Let kmemdup_array() take care about sizing instead of doing it open coded. Signed-off-by: Jinjie Ruan Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240828072219.1249250-1-ruanjinjie@huawei.com --- kernel/irq/msi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 5fa0547ece0c..1c7e5159064c 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -82,7 +82,7 @@ static struct msi_desc *msi_alloc_desc(struct device *dev, int nvec, desc->dev = dev; desc->nvec_used = nvec; if (affinity) { - desc->affinity = kmemdup(affinity, nvec * sizeof(*desc->affinity), GFP_KERNEL); + desc->affinity = kmemdup_array(affinity, nvec, sizeof(*desc->affinity), GFP_KERNEL); if (!desc->affinity) { kfree(desc); return NULL; From 4609c6eab67bb1785a5337ddafb5c74c796bcd35 Mon Sep 17 00:00:00 2001 From: Hongbo Li Date: Wed, 28 Aug 2024 20:27:24 +0800 Subject: [PATCH 67/73] irqdomain: Use IS_ERR_OR_NULL() in irq_domain_trim_hierarchy() Use IS_ERR_OR_NULL() instead of open-coding a NULL and a error pointer check. Signed-off-by: Hongbo Li Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240828122724.3697447-1-lihongbo22@huawei.com --- kernel/irq/irqdomain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 5df8780100bb..e0bff21f30e0 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1403,7 +1403,7 @@ static int irq_domain_trim_hierarchy(unsigned int virq) tail = NULL; /* The first entry must have a valid irqchip */ - if (!irq_data->chip || IS_ERR(irq_data->chip)) + if (IS_ERR_OR_NULL(irq_data->chip)) return -EINVAL; /* From 9e65863194ad253f1de48bb9000a586e6caa5eed Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sun, 1 Sep 2024 11:40:04 +0800 Subject: [PATCH 68/73] dt-bindings: apple,aic: Document A7-A11 compatibles Document and describe the compatibles for Apple A7-A11 SoCs. There are three feature levels: - apple,aic: No fast IPI, for A7-A10 - apple,t8015-aic: fast IPI, global only, for A11 - apple,t8103-aic: fast IPI with local and global support, for M1 Each feature level is an extension of the previous, for example, M1 will also work with the A7 feature level. All of A7-M1 gets its own SoC-specific compatible, and the "apple,aic" compatible as a fallback. Signed-off-by: Nick Chan Signed-off-by: Thomas Gleixner Reviewed-by: Sven Peter Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/all/20240901034143.12731-2-towinchenmi@gmail.com --- .../bindings/interrupt-controller/apple,aic.yaml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml index 698588e9aa86..4be9b596a790 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml @@ -31,13 +31,25 @@ description: | This device also represents the FIQ interrupt sources on platforms using AIC, which do not go through a discrete interrupt controller. + IPIs may be performed via MMIO registers on all variants of AIC. Starting + from A11, system registers may also be used for "fast" IPIs. Starting from + M1, even faster IPIs within the same cluster may be achieved by writing to + a "local" fast IPI register as opposed to using the "global" fast IPI + register. + allOf: - $ref: /schemas/interrupt-controller.yaml# properties: compatible: items: - - const: apple,t8103-aic + - enum: + - apple,s5l8960x-aic + - apple,t7000-aic + - apple,s8000-aic + - apple,t8010-aic + - apple,t8015-aic + - apple,t8103-aic - const: apple,aic interrupt-controller: true From 5527b06c96715518bc58d1ebb29efc3653f66c5e Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sun, 1 Sep 2024 11:40:05 +0800 Subject: [PATCH 69/73] irqchip/apple-aic: Skip unnecessary enabling of use_fast_ipi use_fast_ipi is true by default and there is no need to "enable" it. Signed-off-by: Nick Chan Signed-off-by: Thomas Gleixner Reviewed-by: Sven Peter Link: https://lore.kernel.org/all/20240901034143.12731-3-towinchenmi@gmail.com --- drivers/irqchip/irq-apple-aic.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index 5c534d9fd2b0..8d81d5fb3c50 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -987,9 +987,7 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p off += sizeof(u32) * (irqc->max_irq >> 5); /* MASK_CLR */ off += sizeof(u32) * (irqc->max_irq >> 5); /* HW_STATE */ - if (irqc->info.fast_ipi) - static_branch_enable(&use_fast_ipi); - else + if (!irqc->info.fast_ipi) static_branch_disable(&use_fast_ipi); irqc->info.die_stride = off - start_off; From a845342e6e5fb4937564f93cc88e00c732286fe3 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sun, 1 Sep 2024 11:40:06 +0800 Subject: [PATCH 70/73] irqchip/apple-aic: Add a new "Global fast IPIs only" feature level Starting with the A11 (T8015) SoC, Apple began using arm64 sysregs for fast IPIs. However, on A11, there is no such things as "Local" fast IPIs, as the SYS_IMP_APL_IPI_RR_LOCAL_EL1 register does not seem to exist. Add a new feature level, used by the compatible "apple,t8015-aic", controlled by a static branch key named use_local_fast_ipi. When use_fast_ipi is true and use_local_fast_ipi is false, fast IPIs are used but all IPIs goes through the register SYS_IMP_APL_IPI_RR_GLOBAL_EL1, as "global" IPIs. Signed-off-by: Nick Chan Signed-off-by: Thomas Gleixner Reviewed-by: Sven Peter Link: https://lore.kernel.org/all/20240901034143.12731-4-towinchenmi@gmail.com --- drivers/irqchip/irq-apple-aic.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index 8d81d5fb3c50..90126908f0ba 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -235,6 +235,8 @@ enum fiq_hwirq { }; static DEFINE_STATIC_KEY_TRUE(use_fast_ipi); +/* True if SYS_IMP_APL_IPI_RR_LOCAL_EL1 exists for local fast IPIs (M1+) */ +static DEFINE_STATIC_KEY_TRUE(use_local_fast_ipi); struct aic_info { int version; @@ -252,6 +254,7 @@ struct aic_info { /* Features */ bool fast_ipi; + bool local_fast_ipi; }; static const struct aic_info aic1_info __initconst = { @@ -270,17 +273,32 @@ static const struct aic_info aic1_fipi_info __initconst = { .fast_ipi = true, }; +static const struct aic_info aic1_local_fipi_info __initconst = { + .version = 1, + + .event = AIC_EVENT, + .target_cpu = AIC_TARGET_CPU, + + .fast_ipi = true, + .local_fast_ipi = true, +}; + static const struct aic_info aic2_info __initconst = { .version = 2, .irq_cfg = AIC2_IRQ_CFG, .fast_ipi = true, + .local_fast_ipi = true, }; static const struct of_device_id aic_info_match[] = { { .compatible = "apple,t8103-aic", + .data = &aic1_local_fipi_info, + }, + { + .compatible = "apple,t8015-aic", .data = &aic1_fipi_info, }, { @@ -750,12 +768,12 @@ static void aic_ipi_send_fast(int cpu) u64 cluster = MPIDR_CLUSTER(mpidr); u64 idx = MPIDR_CPU(mpidr); - if (MPIDR_CLUSTER(my_mpidr) == cluster) - write_sysreg_s(FIELD_PREP(IPI_RR_CPU, idx), - SYS_IMP_APL_IPI_RR_LOCAL_EL1); - else + if (static_branch_likely(&use_local_fast_ipi) && MPIDR_CLUSTER(my_mpidr) == cluster) { + write_sysreg_s(FIELD_PREP(IPI_RR_CPU, idx), SYS_IMP_APL_IPI_RR_LOCAL_EL1); + } else { write_sysreg_s(FIELD_PREP(IPI_RR_CPU, idx) | FIELD_PREP(IPI_RR_CLUSTER, cluster), SYS_IMP_APL_IPI_RR_GLOBAL_EL1); + } isb(); } @@ -990,6 +1008,9 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p if (!irqc->info.fast_ipi) static_branch_disable(&use_fast_ipi); + if (!irqc->info.local_fast_ipi) + static_branch_disable(&use_local_fast_ipi); + irqc->info.die_stride = off - start_off; irqc->hw_domain = irq_domain_create_tree(of_node_to_fwnode(node), From 59fc20ba70294d2c5f620ad6206aa661ce7718d6 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sun, 1 Sep 2024 11:40:07 +0800 Subject: [PATCH 71/73] irqchip/apple-aic: Only access system registers on SoCs which provide them Starting from the A11 (T8015) SoC, Apple introuced system registers for fast IPI and UNCORE PMC control. These sysregs do not exist on earlier A7-A10 SoCs and trying to access them results in an instant crash. Restrict sysreg access within the AIC driver to configurations where use_fast_ipi is true to allow AIC to function properly on A7-A10 SoCs. Co-developed-by: Nick Chan Signed-off-by: Konrad Dybcio Signed-off-by: Nick Chan Signed-off-by: Thomas Gleixner Reviewed-by: Sven Peter Link: https://lore.kernel.org/all/20240901034143.12731-5-towinchenmi@gmail.com --- drivers/irqchip/irq-apple-aic.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/irqchip/irq-apple-aic.c b/drivers/irqchip/irq-apple-aic.c index 90126908f0ba..da5250f0155c 100644 --- a/drivers/irqchip/irq-apple-aic.c +++ b/drivers/irqchip/irq-apple-aic.c @@ -234,6 +234,7 @@ enum fiq_hwirq { AIC_NR_FIQ }; +/* True if UNCORE/UNCORE2 and Sn_... IPI registers are present and used (A11+) */ static DEFINE_STATIC_KEY_TRUE(use_fast_ipi); /* True if SYS_IMP_APL_IPI_RR_LOCAL_EL1 exists for local fast IPIs (M1+) */ static DEFINE_STATIC_KEY_TRUE(use_local_fast_ipi); @@ -550,14 +551,9 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs) * we check for everything here, even things we don't support yet. */ - if (read_sysreg_s(SYS_IMP_APL_IPI_SR_EL1) & IPI_SR_PENDING) { - if (static_branch_likely(&use_fast_ipi)) { - aic_handle_ipi(regs); - } else { - pr_err_ratelimited("Fast IPI fired. Acking.\n"); - write_sysreg_s(IPI_SR_PENDING, SYS_IMP_APL_IPI_SR_EL1); - } - } + if (static_branch_likely(&use_fast_ipi) && + (read_sysreg_s(SYS_IMP_APL_IPI_SR_EL1) & IPI_SR_PENDING)) + aic_handle_ipi(regs); if (TIMER_FIRING(read_sysreg(cntp_ctl_el0))) generic_handle_domain_irq(aic_irqc->hw_domain, @@ -592,8 +588,9 @@ static void __exception_irq_entry aic_handle_fiq(struct pt_regs *regs) AIC_FIQ_HWIRQ(irq)); } - if (FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ && - (read_sysreg_s(SYS_IMP_APL_UPMSR_EL1) & UPMSR_IACT)) { + if (static_branch_likely(&use_fast_ipi) && + (FIELD_GET(UPMCR0_IMODE, read_sysreg_s(SYS_IMP_APL_UPMCR0_EL1)) == UPMCR0_IMODE_FIQ) && + (read_sysreg_s(SYS_IMP_APL_UPMSR_EL1) & UPMSR_IACT)) { /* Same story with uncore PMCs */ pr_err_ratelimited("Uncore PMC FIQ fired. Masking.\n"); sysreg_clear_set_s(SYS_IMP_APL_UPMCR0_EL1, UPMCR0_IMODE, @@ -829,7 +826,8 @@ static int aic_init_cpu(unsigned int cpu) /* Mask all hard-wired per-CPU IRQ/FIQ sources */ /* Pending Fast IPI FIQs */ - write_sysreg_s(IPI_SR_PENDING, SYS_IMP_APL_IPI_SR_EL1); + if (static_branch_likely(&use_fast_ipi)) + write_sysreg_s(IPI_SR_PENDING, SYS_IMP_APL_IPI_SR_EL1); /* Timer FIQs */ sysreg_clear_set(cntp_ctl_el0, 0, ARCH_TIMER_CTRL_IT_MASK); @@ -850,8 +848,10 @@ static int aic_init_cpu(unsigned int cpu) FIELD_PREP(PMCR0_IMODE, PMCR0_IMODE_OFF)); /* Uncore PMC FIQ */ - sysreg_clear_set_s(SYS_IMP_APL_UPMCR0_EL1, UPMCR0_IMODE, - FIELD_PREP(UPMCR0_IMODE, UPMCR0_IMODE_OFF)); + if (static_branch_likely(&use_fast_ipi)) { + sysreg_clear_set_s(SYS_IMP_APL_UPMCR0_EL1, UPMCR0_IMODE, + FIELD_PREP(UPMCR0_IMODE, UPMCR0_IMODE_OFF)); + } /* Commit all of the above */ isb(); From 87b5a153b862b7d937fc1dd499368297a1feae87 Mon Sep 17 00:00:00 2001 From: Costa Shulyupin Date: Wed, 4 Sep 2024 16:48:23 +0300 Subject: [PATCH 72/73] genirq/cpuhotplug: Use cpumask_intersects() Replace `cpumask_any_and(a, b) >= nr_cpu_ids` with the more readable `!cpumask_intersects(a, b)`. [ tglx: Massaged change log ] Signed-off-by: Costa Shulyupin Signed-off-by: Thomas Gleixner Reviewed-by: Ming Lei Link: https://lore.kernel.org/all/20240904134823.777623-2-costa.shul@redhat.com --- kernel/irq/cpuhotplug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c index eb8628390156..15a7654eff68 100644 --- a/kernel/irq/cpuhotplug.c +++ b/kernel/irq/cpuhotplug.c @@ -37,7 +37,7 @@ static inline bool irq_needs_fixup(struct irq_data *d) * has been removed from the online mask already. */ if (cpumask_any_but(m, cpu) < nr_cpu_ids && - cpumask_any_and(m, cpu_online_mask) >= nr_cpu_ids) { + !cpumask_intersects(m, cpu_online_mask)) { /* * If this happens then there was a missed IRQ fixup at some * point. Warn about it and enforce fixup. @@ -110,7 +110,7 @@ static bool migrate_one_irq(struct irq_desc *desc) if (maskchip && chip->irq_mask) chip->irq_mask(d); - if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { + if (!cpumask_intersects(affinity, cpu_online_mask)) { /* * If the interrupt is managed, then shut it down and leave * the affinity untouched. From a6fe30d1e3657991c832702cecb44576128d7fa3 Mon Sep 17 00:00:00 2001 From: Costa Shulyupin Date: Fri, 6 Sep 2024 20:01:40 +0300 Subject: [PATCH 73/73] genirq: Use cpumask_intersects() Replace `cpumask_any_and(a, b) >= nr_cpu_ids` and `cpumask_any_and(a, b) < nr_cpu_ids` with the more readable `!cpumask_intersects(a, b)` and `cpumask_intersects(a, b)` Signed-off-by: Costa Shulyupin Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/all/20240906170142.1135207-1-costa.shul@redhat.com --- kernel/irq/chip.c | 2 +- kernel/irq/migration.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index dc94e0bf2c94..271e9139de77 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -198,7 +198,7 @@ __irq_startup_managed(struct irq_desc *desc, const struct cpumask *aff, irqd_clr_managed_shutdown(d); - if (cpumask_any_and(aff, cpu_online_mask) >= nr_cpu_ids) { + if (!cpumask_intersects(aff, cpu_online_mask)) { /* * Catch code which fiddles with enable_irq() on a managed * and potentially shutdown IRQ. Chained interrupt diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index 61ca924ef4b4..eb150afd671f 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c @@ -26,7 +26,7 @@ bool irq_fixup_move_pending(struct irq_desc *desc, bool force_clear) * The outgoing CPU might be the last online target in a pending * interrupt move. If that's the case clear the pending move bit. */ - if (cpumask_any_and(desc->pending_mask, cpu_online_mask) >= nr_cpu_ids) { + if (!cpumask_intersects(desc->pending_mask, cpu_online_mask)) { irqd_clr_move_pending(data); return false; } @@ -74,7 +74,7 @@ void irq_move_masked_irq(struct irq_data *idata) * For correct operation this depends on the caller * masking the irqs. */ - if (cpumask_any_and(desc->pending_mask, cpu_online_mask) < nr_cpu_ids) { + if (cpumask_intersects(desc->pending_mask, cpu_online_mask)) { int ret; ret = irq_do_set_affinity(data, desc->pending_mask, false);