diff options
Diffstat (limited to 'pkgs/patches-linux-5.15/0066-irqchip-armada-370-xp-Add-support-for-32-MSI-interru.patch')
-rw-r--r-- | pkgs/patches-linux-5.15/0066-irqchip-armada-370-xp-Add-support-for-32-MSI-interru.patch | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/pkgs/patches-linux-5.15/0066-irqchip-armada-370-xp-Add-support-for-32-MSI-interru.patch b/pkgs/patches-linux-5.15/0066-irqchip-armada-370-xp-Add-support-for-32-MSI-interru.patch new file mode 100644 index 0000000..0eefb9a --- /dev/null +++ b/pkgs/patches-linux-5.15/0066-irqchip-armada-370-xp-Add-support-for-32-MSI-interru.patch @@ -0,0 +1,181 @@ +From adf4ef16f1869c4f8a35bfb95ce95e0d418f72b9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org> +Date: Thu, 11 Aug 2022 13:16:26 +0200 +Subject: [PATCH 66/90] irqchip/armada-370-xp: Add support for 32 MSI + interrupts on non-IPI platforms +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently only upper 16 MSI interrupts on non-IPI platforms are used. +Low 16 MSI interrupts on non-IPI platforms are mapped into IPI registers. +Implement support also for low 16 MSI interrupts which allow increase +number of MSI interrupts on non-IPI platforms from 16 to 32. + +Signed-off-by: Pali Rohár <pali@kernel.org> +--- + drivers/irqchip/irq-armada-370-xp.c | 54 +++++++++++++++++++++-------- + 1 file changed, 40 insertions(+), 14 deletions(-) + +diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c +index 397bacf638a2..8abc70ed30c1 100644 +--- a/drivers/irqchip/irq-armada-370-xp.c ++++ b/drivers/irqchip/irq-armada-370-xp.c +@@ -135,6 +135,7 @@ + + #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 +@@ -143,6 +144,12 @@ + #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) ++#define PCI_MSI_FULL_DOORBELL_NR (32) ++#define PCI_MSI_FULL_DOORBELL_END (32) ++#define PCI_MSI_FULL_DOORBELL_MASK (0xFFFFFFFF) ++ + static void __iomem *per_cpu_int_base; + static void __iomem *main_int_base; + static struct irq_domain *armada_370_xp_mpic_domain; +@@ -151,7 +158,7 @@ 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 DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR); ++static DECLARE_BITMAP(msi_used, PCI_MSI_FULL_DOORBELL_NR); + static DEFINE_MUTEX(msi_used_lock); + static phys_addr_t msi_doorbell_addr; + #endif +@@ -209,9 +216,10 @@ static struct msi_domain_info armada_370_xp_msi_domain_info = { + + static void armada_370_xp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) + { ++ u32 msi_start = (parent_irq <= 0) ? PCI_MSI_DOORBELL_START : PCI_MSI_FULL_DOORBELL_START; + msg->address_lo = lower_32_bits(msi_doorbell_addr); + msg->address_hi = upper_32_bits(msi_doorbell_addr); +- msg->data = 0xf00 | (data->hwirq + PCI_MSI_DOORBELL_START); ++ msg->data = 0xf00 | (data->hwirq + msi_start); + } + + static int armada_370_xp_msi_set_affinity(struct irq_data *irq_data, +@@ -229,10 +237,11 @@ 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) + { ++ unsigned int msi_nr = (parent_irq <= 0) ? PCI_MSI_DOORBELL_NR : PCI_MSI_FULL_DOORBELL_NR; + int hwirq, i; + + mutex_lock(&msi_used_lock); +- hwirq = bitmap_find_free_region(msi_used, PCI_MSI_DOORBELL_NR, ++ hwirq = bitmap_find_free_region(msi_used, msi_nr, + order_base_2(nr_irqs)); + mutex_unlock(&msi_used_lock); + +@@ -267,13 +276,15 @@ static const struct irq_domain_ops armada_370_xp_msi_domain_ops = { + static int armada_370_xp_msi_init(struct device_node *node, + phys_addr_t main_int_phys_base) + { ++ unsigned int msi_nr = (parent_irq <= 0) ? PCI_MSI_DOORBELL_NR : PCI_MSI_FULL_DOORBELL_NR; ++ u32 msi_mask = (parent_irq <= 0) ? PCI_MSI_DOORBELL_MASK: PCI_MSI_FULL_DOORBELL_MASK; + u32 reg; + + msi_doorbell_addr = main_int_phys_base + + ARMADA_370_XP_SW_TRIG_INT_OFFS; + + armada_370_xp_msi_inner_domain = +- irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR, ++ irq_domain_add_linear(NULL, msi_nr, + &armada_370_xp_msi_domain_ops, NULL); + if (!armada_370_xp_msi_inner_domain) + return -ENOMEM; +@@ -288,7 +299,7 @@ static int armada_370_xp_msi_init(struct device_node *node, + } + + reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS) +- | PCI_MSI_DOORBELL_MASK; ++ | msi_mask; + + writel(reg, per_cpu_int_base + + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); +@@ -296,6 +307,10 @@ static int armada_370_xp_msi_init(struct device_node *node, + /* Unmask MSI interrupt */ + writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); + ++ /* Unmask low 16 MSI irqs on non-IPI platforms */ ++ if (parent_irq > 0) ++ writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); ++ + return 0; + } + #else +@@ -586,23 +601,25 @@ static const struct irq_domain_ops armada_370_xp_mpic_irq_ops = { + #ifdef CONFIG_PCI_MSI + static void armada_370_xp_handle_msi_irq(struct pt_regs *regs, bool is_chained) + { ++ u32 msi_start = (parent_irq <= 0) ? PCI_MSI_DOORBELL_START : PCI_MSI_FULL_DOORBELL_START; ++ u32 msi_end = (parent_irq <= 0) ? PCI_MSI_DOORBELL_END : PCI_MSI_FULL_DOORBELL_END; ++ u32 msi_mask = (parent_irq <= 0) ? PCI_MSI_DOORBELL_MASK: PCI_MSI_FULL_DOORBELL_MASK; + u32 msimask, msinr; + + msimask = readl_relaxed(per_cpu_int_base + + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS) +- & PCI_MSI_DOORBELL_MASK; ++ & msi_mask; + + writel(~msimask, per_cpu_int_base + + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); + +- for (msinr = PCI_MSI_DOORBELL_START; +- msinr < PCI_MSI_DOORBELL_END; msinr++) { ++ for (msinr = msi_start; msinr < msi_end; msinr++) { + unsigned int irq; + + if (!(msimask & BIT(msinr))) + continue; + +- irq = msinr - PCI_MSI_DOORBELL_START; ++ irq = msinr - msi_start; + + if (is_chained) + generic_handle_domain_irq(armada_370_xp_msi_inner_domain, +@@ -636,7 +653,7 @@ static void armada_370_xp_mpic_handle_cascade_irq(struct irq_desc *desc) + if (!(irqsrc & ARMADA_370_XP_INT_IRQ_FIQ_MASK(cpuid))) + continue; + +- if (irqn == 1) { ++ if (irqn == 0 || irqn == 1) { + armada_370_xp_handle_msi_irq(NULL, true); + continue; + } +@@ -737,10 +754,19 @@ static void armada_370_xp_mpic_resume(void) + writel(doorbell_mask_reg, + per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS); + /* IPI is used only when we do not have parent irq */ +- if (parent_irq <= 0 && (doorbell_mask_reg & IPI_DOORBELL_MASK)) +- writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); +- if (doorbell_mask_reg & PCI_MSI_DOORBELL_MASK) +- writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); ++ if (parent_irq <= 0) { ++ /* On IPI platforms is source 0 used for IPI and source 1 for MSI */ ++ if (doorbell_mask_reg & IPI_DOORBELL_MASK) ++ writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); ++ if (doorbell_mask_reg & PCI_MSI_DOORBELL_MASK) ++ writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); ++ } else { ++ /* On non-IPI platforms is source 0 used for MSI 0-15 and 1 for MSI 16-31 */ ++ if (doorbell_mask_reg & GENMASK(15, 0)) ++ writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); ++ if (doorbell_mask_reg & GENMASK(31, 16)) ++ writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); ++ } + + /* IPI is used only when we do not have parent irq */ + if (parent_irq <= 0) +-- +2.34.1 + |