From: Marc Zyngier <maz@kernel.org>
To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org
Cc: Sumit Garg <sumit.garg@linaro.org>,
kernel-team@android.com, Russell King <linux@arm.linux.org.uk>,
Jason Cooper <jason@lakedaemon.net>,
Catalin Marinas <catalin.marinas@arm.com>,
Thomas Gleixner <tglx@linutronix.de>,
Will Deacon <will@kernel.org>
Subject: [PATCH 08/11] irqchip/gic: Configure SGIs as standard interrupts
Date: Tue, 19 May 2020 17:17:52 +0100 [thread overview]
Message-ID: <20200519161755.209565-9-maz@kernel.org> (raw)
In-Reply-To: <20200519161755.209565-1-maz@kernel.org>
Change the way we deal with GIC SGIs by turning them into proper
IRQs, and calling into the arch code to register the interrupt range
instead of a callback.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
drivers/irqchip/irq-gic.c | 113 +++++++++++++++++++++++++-------------
1 file changed, 74 insertions(+), 39 deletions(-)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index e289810e794c..8d146ac28c74 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -47,6 +47,8 @@
#include "irq-gic-common.h"
+#define GIC_IRQ_TYPE_SGI 0x561
+
#ifdef CONFIG_ARM64
#include <asm/cpufeature.h>
@@ -335,31 +337,22 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
irqnr = irqstat & GICC_IAR_INT_ID_MASK;
- if (likely(irqnr > 15 && irqnr < 1020)) {
- if (static_branch_likely(&supports_deactivate_key))
- writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
- isb();
- handle_domain_irq(gic->domain, irqnr, regs);
- continue;
- }
- if (irqnr < 16) {
+ if (unlikely(irqnr >= 1020))
+ break;
+
+ if (static_branch_likely(&supports_deactivate_key))
writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
- if (static_branch_likely(&supports_deactivate_key))
- writel_relaxed(irqstat, cpu_base + GIC_CPU_DEACTIVATE);
-#ifdef CONFIG_SMP
- /*
- * Ensure any shared data written by the CPU sending
- * the IPI is read after we've read the ACK register
- * on the GIC.
- *
- * Pairs with the write barrier in gic_raise_softirq
- */
+ isb();
+
+ /*
+ * Ensure any shared data written by the CPU sending the IPI
+ * is read after we've read the ACK register on the GIC.
+ *
+ * Pairs with the write barrier in gic_ipi_send_mask
+ */
+ if (irqnr <= 15)
smp_rmb();
- handle_IPI(irqnr, regs);
-#endif
- continue;
- }
- break;
+ handle_domain_irq(gic->domain, irqnr, regs);
} while (1);
}
@@ -801,14 +794,14 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
return IRQ_SET_MASK_OK_DONE;
}
-static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
+static void gic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)
{
int cpu;
unsigned long flags, map = 0;
if (unlikely(nr_cpu_ids == 1)) {
/* Only one CPU? let's do a self-IPI... */
- writel_relaxed(2 << 24 | irq,
+ writel_relaxed(2 << 24 | d->hwirq,
gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
return;
}
@@ -826,7 +819,7 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
dmb(ishst);
/* this always happens on GIC0 */
- writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+ writel_relaxed(map << 16 | d->hwirq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
gic_unlock_irqrestore(flags);
}
@@ -839,14 +832,40 @@ static int gic_starting_cpu(unsigned int cpu)
static __init void gic_smp_init(void)
{
- set_smp_cross_call(gic_raise_softirq);
+ struct irq_fwspec sgi_fwspec = {
+ .fwnode = gic_data[0].domain->fwnode,
+ };
+ int base_sgi;
+
cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING,
"irqchip/arm/gic:starting",
gic_starting_cpu, NULL);
+
+ if (is_of_node(gic_data[0].domain->fwnode)) {
+ /* DT */
+ sgi_fwspec.param_count = 3;
+ sgi_fwspec.param[0] = GIC_IRQ_TYPE_SGI;
+ sgi_fwspec.param[1] = 0;
+ sgi_fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+ } else {
+ /* ACPI */
+ sgi_fwspec.param_count = 2;
+ sgi_fwspec.param[0] = 0;
+ sgi_fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+ }
+
+ base_sgi = __irq_domain_alloc_irqs(gic_data[0].domain, -1, 8,
+ NUMA_NO_NODE, &sgi_fwspec,
+ false, NULL);
+ if (WARN_ON(base_sgi <= 0))
+ return;
+
+ set_smp_ipi_range(base_sgi, 8);
}
#else
#define gic_smp_init() do { } while(0)
#define gic_set_affinity NULL
+#define gic_ipi_send_mask NULL
#endif
#ifdef CONFIG_BL_SWITCHER
@@ -993,16 +1012,26 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
{
struct gic_chip_data *gic = d->host_data;
- if (hw < 32) {
+ switch (hw) {
+ case 0 ... 15:
+ irq_set_percpu_devid(irq);
+ irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
+ handle_percpu_devid_fasteoi_ipi,
+ NULL, NULL);
+ irq_set_status_flags(irq, IRQ_NOAUTOEN);
+ break;
+ case 16 ... 31:
irq_set_percpu_devid(irq);
irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
handle_percpu_devid_irq, NULL, NULL);
irq_set_status_flags(irq, IRQ_NOAUTOEN);
- } else {
+ break;
+ default:
irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
handle_fasteoi_irq, NULL, NULL);
irq_set_probe(irq);
irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
+ break;
}
return 0;
}
@@ -1020,15 +1049,19 @@ static int gic_irq_domain_translate(struct irq_domain *d,
if (fwspec->param_count < 3)
return -EINVAL;
- /* Get the interrupt number and add 16 to skip over SGIs */
- *hwirq = fwspec->param[1] + 16;
-
- /*
- * For SPIs, we need to add 16 more to get the GIC irq
- * ID number
- */
- if (!fwspec->param[0])
- *hwirq += 16;
+ switch (fwspec->param[0]) {
+ case 0: /* SPI */
+ *hwirq = fwspec->param[1] + 32;
+ break;
+ case 1: /* PPI */
+ *hwirq = fwspec->param[1] + 16;
+ break;
+ case GIC_IRQ_TYPE_SGI: /* SGI, can't be set via DT */
+ *hwirq = fwspec->param[1];
+ break;
+ default:
+ return -EINVAL;
+ }
*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
@@ -1097,8 +1130,10 @@ static void gic_init_chip(struct gic_chip_data *gic, struct device *dev,
gic->chip.irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity;
}
- if (gic == &gic_data[0])
+ if (gic == &gic_data[0]) {
gic->chip.irq_set_affinity = gic_set_affinity;
+ gic->chip.ipi_send_mask = gic_ipi_send_mask;
+ }
}
static int gic_init_bases(struct gic_chip_data *gic,
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
WARNING: multiple messages have this Message-ID (diff)
From: Marc Zyngier <maz@kernel.org>
To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org
Cc: Will Deacon <will@kernel.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Russell King <linux@arm.linux.org.uk>,
Thomas Gleixner <tglx@linutronix.de>,
Jason Cooper <jason@lakedaemon.net>,
Sumit Garg <sumit.garg@linaro.org>,
kernel-team@android.com
Subject: [PATCH 08/11] irqchip/gic: Configure SGIs as standard interrupts
Date: Tue, 19 May 2020 17:17:52 +0100 [thread overview]
Message-ID: <20200519161755.209565-9-maz@kernel.org> (raw)
In-Reply-To: <20200519161755.209565-1-maz@kernel.org>
Change the way we deal with GIC SGIs by turning them into proper
IRQs, and calling into the arch code to register the interrupt range
instead of a callback.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
drivers/irqchip/irq-gic.c | 113 +++++++++++++++++++++++++-------------
1 file changed, 74 insertions(+), 39 deletions(-)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index e289810e794c..8d146ac28c74 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -47,6 +47,8 @@
#include "irq-gic-common.h"
+#define GIC_IRQ_TYPE_SGI 0x561
+
#ifdef CONFIG_ARM64
#include <asm/cpufeature.h>
@@ -335,31 +337,22 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
irqnr = irqstat & GICC_IAR_INT_ID_MASK;
- if (likely(irqnr > 15 && irqnr < 1020)) {
- if (static_branch_likely(&supports_deactivate_key))
- writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
- isb();
- handle_domain_irq(gic->domain, irqnr, regs);
- continue;
- }
- if (irqnr < 16) {
+ if (unlikely(irqnr >= 1020))
+ break;
+
+ if (static_branch_likely(&supports_deactivate_key))
writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
- if (static_branch_likely(&supports_deactivate_key))
- writel_relaxed(irqstat, cpu_base + GIC_CPU_DEACTIVATE);
-#ifdef CONFIG_SMP
- /*
- * Ensure any shared data written by the CPU sending
- * the IPI is read after we've read the ACK register
- * on the GIC.
- *
- * Pairs with the write barrier in gic_raise_softirq
- */
+ isb();
+
+ /*
+ * Ensure any shared data written by the CPU sending the IPI
+ * is read after we've read the ACK register on the GIC.
+ *
+ * Pairs with the write barrier in gic_ipi_send_mask
+ */
+ if (irqnr <= 15)
smp_rmb();
- handle_IPI(irqnr, regs);
-#endif
- continue;
- }
- break;
+ handle_domain_irq(gic->domain, irqnr, regs);
} while (1);
}
@@ -801,14 +794,14 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
return IRQ_SET_MASK_OK_DONE;
}
-static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
+static void gic_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)
{
int cpu;
unsigned long flags, map = 0;
if (unlikely(nr_cpu_ids == 1)) {
/* Only one CPU? let's do a self-IPI... */
- writel_relaxed(2 << 24 | irq,
+ writel_relaxed(2 << 24 | d->hwirq,
gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
return;
}
@@ -826,7 +819,7 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
dmb(ishst);
/* this always happens on GIC0 */
- writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+ writel_relaxed(map << 16 | d->hwirq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
gic_unlock_irqrestore(flags);
}
@@ -839,14 +832,40 @@ static int gic_starting_cpu(unsigned int cpu)
static __init void gic_smp_init(void)
{
- set_smp_cross_call(gic_raise_softirq);
+ struct irq_fwspec sgi_fwspec = {
+ .fwnode = gic_data[0].domain->fwnode,
+ };
+ int base_sgi;
+
cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING,
"irqchip/arm/gic:starting",
gic_starting_cpu, NULL);
+
+ if (is_of_node(gic_data[0].domain->fwnode)) {
+ /* DT */
+ sgi_fwspec.param_count = 3;
+ sgi_fwspec.param[0] = GIC_IRQ_TYPE_SGI;
+ sgi_fwspec.param[1] = 0;
+ sgi_fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+ } else {
+ /* ACPI */
+ sgi_fwspec.param_count = 2;
+ sgi_fwspec.param[0] = 0;
+ sgi_fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
+ }
+
+ base_sgi = __irq_domain_alloc_irqs(gic_data[0].domain, -1, 8,
+ NUMA_NO_NODE, &sgi_fwspec,
+ false, NULL);
+ if (WARN_ON(base_sgi <= 0))
+ return;
+
+ set_smp_ipi_range(base_sgi, 8);
}
#else
#define gic_smp_init() do { } while(0)
#define gic_set_affinity NULL
+#define gic_ipi_send_mask NULL
#endif
#ifdef CONFIG_BL_SWITCHER
@@ -993,16 +1012,26 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
{
struct gic_chip_data *gic = d->host_data;
- if (hw < 32) {
+ switch (hw) {
+ case 0 ... 15:
+ irq_set_percpu_devid(irq);
+ irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
+ handle_percpu_devid_fasteoi_ipi,
+ NULL, NULL);
+ irq_set_status_flags(irq, IRQ_NOAUTOEN);
+ break;
+ case 16 ... 31:
irq_set_percpu_devid(irq);
irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
handle_percpu_devid_irq, NULL, NULL);
irq_set_status_flags(irq, IRQ_NOAUTOEN);
- } else {
+ break;
+ default:
irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
handle_fasteoi_irq, NULL, NULL);
irq_set_probe(irq);
irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq)));
+ break;
}
return 0;
}
@@ -1020,15 +1049,19 @@ static int gic_irq_domain_translate(struct irq_domain *d,
if (fwspec->param_count < 3)
return -EINVAL;
- /* Get the interrupt number and add 16 to skip over SGIs */
- *hwirq = fwspec->param[1] + 16;
-
- /*
- * For SPIs, we need to add 16 more to get the GIC irq
- * ID number
- */
- if (!fwspec->param[0])
- *hwirq += 16;
+ switch (fwspec->param[0]) {
+ case 0: /* SPI */
+ *hwirq = fwspec->param[1] + 32;
+ break;
+ case 1: /* PPI */
+ *hwirq = fwspec->param[1] + 16;
+ break;
+ case GIC_IRQ_TYPE_SGI: /* SGI, can't be set via DT */
+ *hwirq = fwspec->param[1];
+ break;
+ default:
+ return -EINVAL;
+ }
*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
@@ -1097,8 +1130,10 @@ static void gic_init_chip(struct gic_chip_data *gic, struct device *dev,
gic->chip.irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity;
}
- if (gic == &gic_data[0])
+ if (gic == &gic_data[0]) {
gic->chip.irq_set_affinity = gic_set_affinity;
+ gic->chip.ipi_send_mask = gic_ipi_send_mask;
+ }
}
static int gic_init_bases(struct gic_chip_data *gic,
--
2.26.2
next prev parent reply other threads:[~2020-05-19 16:20 UTC|newest]
Thread overview: 72+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-19 16:17 [PATCH 00/11] arm/arm64: Turning IPIs into normal interrupts Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier
2020-05-19 16:17 ` [PATCH 01/11] genirq: Add fasteoi IPI flow Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier
2020-05-19 19:47 ` Florian Fainelli
2020-05-19 19:47 ` Florian Fainelli
2020-06-12 9:54 ` Marc Zyngier
2020-06-12 9:54 ` Marc Zyngier
2020-05-19 22:25 ` Valentin Schneider
2020-05-19 22:25 ` Valentin Schneider
2020-05-19 22:29 ` Valentin Schneider
2020-05-19 22:29 ` Valentin Schneider
2020-06-12 9:58 ` Marc Zyngier
2020-06-12 9:58 ` Marc Zyngier
2020-05-19 16:17 ` [PATCH 02/11] genirq: Allow interrupts to be excluded from /proc/interrupts Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier
2020-05-19 16:17 ` [PATCH 03/11] arm64: Allow IPIs to be handled as normal interrupts Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier
2020-05-21 14:03 ` Valentin Schneider
2020-05-21 14:03 ` Valentin Schneider
2020-05-19 16:17 ` [PATCH 04/11] ARM: " Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier
2020-05-19 22:24 ` Russell King - ARM Linux admin
2020-05-19 22:24 ` Russell King - ARM Linux admin
2020-05-21 14:03 ` Valentin Schneider
2020-05-21 14:03 ` Valentin Schneider
2020-05-21 15:12 ` Russell King - ARM Linux admin
2020-05-21 15:12 ` Russell King - ARM Linux admin
2020-05-21 16:11 ` Valentin Schneider
2020-05-21 16:11 ` Valentin Schneider
2020-05-19 16:17 ` [PATCH 05/11] irqchip/gic-v3: Describe the SGI range Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier
2020-05-19 16:17 ` [PATCH 06/11] irqchip/gic-v3: Configure SGIs as standard interrupts Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier
2020-05-20 9:52 ` Sumit Garg
2020-05-20 9:52 ` Sumit Garg
2020-05-20 10:24 ` Marc Zyngier
2020-05-20 10:24 ` Marc Zyngier
2020-05-21 14:04 ` Valentin Schneider
2020-05-21 14:04 ` Valentin Schneider
2020-06-12 10:39 ` Marc Zyngier
2020-06-12 10:39 ` Marc Zyngier
2020-05-19 16:17 ` [PATCH 07/11] irqchip/gic: Refactor SMP configuration Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier [this message]
2020-05-19 16:17 ` [PATCH 08/11] irqchip/gic: Configure SGIs as standard interrupts Marc Zyngier
2021-04-20 20:37 ` dann frazier
2021-04-20 20:37 ` dann frazier
2021-04-20 21:25 ` dann frazier
2021-04-20 21:25 ` dann frazier
2021-04-21 10:58 ` Marc Zyngier
2021-04-21 10:58 ` Marc Zyngier
2021-04-21 14:52 ` dann frazier
2021-04-21 14:52 ` dann frazier
2021-04-21 15:49 ` Marc Zyngier
2021-04-21 15:49 ` Marc Zyngier
2020-05-19 16:17 ` [PATCH 09/11] irqchip/gic-common: Don't enable SGIs by default Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier
2020-05-19 16:17 ` [PATCH 10/11] irqchip/bcm2836: Configure mailbox interrupts as standard interrupts Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier
2020-05-19 16:17 ` [PATCH 11/11] arm64: Kill __smp_cross_call and co Marc Zyngier
2020-05-19 16:17 ` Marc Zyngier
2020-05-19 17:50 ` [PATCH 00/11] arm/arm64: Turning IPIs into normal interrupts Florian Fainelli
2020-05-19 17:50 ` Florian Fainelli
2020-05-19 19:47 ` Florian Fainelli
2020-05-19 19:47 ` Florian Fainelli
2020-06-12 9:49 ` Marc Zyngier
2020-06-12 9:49 ` Marc Zyngier
2020-06-12 16:57 ` Florian Fainelli
2020-06-12 16:57 ` Florian Fainelli
2020-05-19 22:25 ` Valentin Schneider
2020-05-19 22:25 ` Valentin Schneider
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200519161755.209565-9-maz@kernel.org \
--to=maz@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=jason@lakedaemon.net \
--cc=kernel-team@android.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@arm.linux.org.uk \
--cc=sumit.garg@linaro.org \
--cc=tglx@linutronix.de \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.