aboutsummaryrefslogtreecommitdiff
path: root/pkgs/patches-linux-5.15/0066-irqchip-armada-370-xp-Add-support-for-32-MSI-interru.patch
diff options
context:
space:
mode:
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.patch181
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
+