linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges
@ 2019-07-23 10:44 Marc Zyngier
  2019-07-23 10:44 ` [PATCH 1/9] irqchip/gic: Rework gic_configure_irq to take the full ICFGR base Marc Zyngier
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 10:44 UTC (permalink / raw)
  To: Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

Apparently, having ~1000 wired interrupts is not enough, and some
people need more. Fear not! The GIC Achitecture Department hereby
grants you another 1024 SPIs, together with 64 PPIs, provided that you
implement GICv3.1 (see [1] for the details)

This series implements the required support, which requires a bit of
infrastructure rework in order to make the thing less horrible...

This has been tested on a FastModel.

[1] https://developer.arm.com/docs/ihi0069/latest (version E)

Marc Zyngier (9):
  irqchip/gic: Rework gic_configure_irq to take the full ICFGR base
  irqchip/gic-v3: Add INTID range and convertion primitives
  dt-bindings: interrupt-controller: arm,gic-v3: Describe ESPI range
    support
  irqchip/gic-v3: Add ESPI range support
  irqchip/gic: Prepare for more than 16 PPIs
  irqchip/gic-v3: Dynamically allocate PPI NMI refcounts
  irqchip/gic-v3: Dynamically allocate PPI partition descriptors
  dt-bindings: interrupt-controller: arm,gic-v3: Describe EPPI range
    support
  irqchip/gic-v3: Add EPPI range support

 .../interrupt-controller/arm,gic-v3.yaml      |   6 +-
 drivers/irqchip/irq-gic-common.c              |  33 +-
 drivers/irqchip/irq-gic-common.h              |   2 +-
 drivers/irqchip/irq-gic-v3.c                  | 323 ++++++++++++++----
 drivers/irqchip/irq-gic.c                     |  12 +-
 drivers/irqchip/irq-hip04.c                   |   9 +-
 include/linux/irqchip/arm-gic-v3.h            |  29 +-
 7 files changed, 319 insertions(+), 95 deletions(-)

-- 
2.20.1


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

* [PATCH 1/9] irqchip/gic: Rework gic_configure_irq to take the full ICFGR base
  2019-07-23 10:44 [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges Marc Zyngier
@ 2019-07-23 10:44 ` Marc Zyngier
  2019-07-23 10:44 ` [PATCH 2/9] irqchip/gic-v3: Add INTID range and convertion primitives Marc Zyngier
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 10:44 UTC (permalink / raw)
  To: Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

gic_configure_irq is currently passed the (re)distributor address,
to which it applies an a fixed offset to get to the configuration
registers. This offset is constant across all GICs, or rather it was
until to v3.1...

An easy way out is for the individual drivers to pass the base
address of the configuration register for the considered interrupt.
At the same time, move part of the error handling back to the
individual drivers, as things are about to change on that front.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-common.c | 14 +++++---------
 drivers/irqchip/irq-gic-v3.c     | 11 ++++++++++-
 drivers/irqchip/irq-gic.c        | 10 +++++++++-
 drivers/irqchip/irq-hip04.c      |  7 ++++++-
 4 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index b0a8215a13fc..6900b6f0921c 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -63,7 +63,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
 	 * for "irq", depending on "type".
 	 */
 	raw_spin_lock_irqsave(&irq_controller_lock, flags);
-	val = oldval = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
+	val = oldval = readl_relaxed(base + confoff);
 	if (type & IRQ_TYPE_LEVEL_MASK)
 		val &= ~confmask;
 	else if (type & IRQ_TYPE_EDGE_BOTH)
@@ -83,14 +83,10 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
 	 * does not allow us to set the configuration or we are in a
 	 * non-secure mode, and hence it may not be catastrophic.
 	 */
-	writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
-	if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val) {
-		if (WARN_ON(irq >= 32))
-			ret = -EINVAL;
-		else
-			pr_warn("GIC: PPI%d is secure or misconfigured\n",
-				irq - 16);
-	}
+	writel_relaxed(val, base + confoff);
+	if (readl_relaxed(base + confoff) != val)
+		ret = -EINVAL;
+
 	raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
 
 	if (sync_access)
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 9bca4896fa6f..915b4ae8667f 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -407,6 +407,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 	unsigned int irq = gic_irq(d);
 	void (*rwp_wait)(void);
 	void __iomem *base;
+	int ret;
 
 	/* Interrupt configuration for SGIs can't be changed */
 	if (irq < 16)
@@ -425,7 +426,15 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 		rwp_wait = gic_dist_wait_for_rwp;
 	}
 
-	return gic_configure_irq(irq, type, base, rwp_wait);
+
+	ret = gic_configure_irq(irq, type, base + GICD_ICFGR, rwp_wait);
+	if (ret && irq < 32) {
+		/* Misconfigured PPIs are usually not fatal */
+		pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16);
+		ret = 0;
+	}
+
+	return ret;
 }
 
 static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index e45f45e68720..ab48760acabb 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -291,6 +291,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 {
 	void __iomem *base = gic_dist_base(d);
 	unsigned int gicirq = gic_irq(d);
+	int ret;
 
 	/* Interrupt configuration for SGIs can't be changed */
 	if (gicirq < 16)
@@ -301,7 +302,14 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 			    type != IRQ_TYPE_EDGE_RISING)
 		return -EINVAL;
 
-	return gic_configure_irq(gicirq, type, base, NULL);
+	ret = gic_configure_irq(gicirq, type, base + GIC_DIST_CONFIG, NULL);
+	if (ret && gicirq < 32) {
+		/* Misconfigured PPIs are usually not fatal */
+		pr_warn("GIC: PPI%d is secure or misconfigured\n", gicirq - 16);
+		ret = 0;
+	}
+
+	return ret;
 }
 
 static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
index cf705827599c..1626131834a6 100644
--- a/drivers/irqchip/irq-hip04.c
+++ b/drivers/irqchip/irq-hip04.c
@@ -130,7 +130,12 @@ static int hip04_irq_set_type(struct irq_data *d, unsigned int type)
 
 	raw_spin_lock(&irq_controller_lock);
 
-	ret = gic_configure_irq(irq, type, base, NULL);
+	ret = gic_configure_irq(irq, type, base + GIC_DIST_CONFIG, NULL);
+	if (ret && irq < 32) {
+		/* Misconfigured PPIs are usually not fatal */
+		pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16);
+		ret = 0;
+	}
 
 	raw_spin_unlock(&irq_controller_lock);
 
-- 
2.20.1


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

* [PATCH 2/9] irqchip/gic-v3: Add INTID range and convertion primitives
  2019-07-23 10:44 [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges Marc Zyngier
  2019-07-23 10:44 ` [PATCH 1/9] irqchip/gic: Rework gic_configure_irq to take the full ICFGR base Marc Zyngier
@ 2019-07-23 10:44 ` Marc Zyngier
  2019-07-23 10:44 ` [PATCH 3/9] dt-bindings: interrupt-controller: arm,gic-v3: Describe ESPI range support Marc Zyngier
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 10:44 UTC (permalink / raw)
  To: Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

In the beginning, life was simple. The GIC driver mostly cared about
PPIs, SPIs and LPIs, all with nicely layed out ranges.

We're about to change all that, with new ranges such as EPPI and ESPI
interleaved in the middle of the no-irq-land between the "special IDs"
and the LPI range. Boo.

In order to make our life less hellish, let's introduce a set of primitives
that will allow ranges to be identified easily and offsets to be remapped.

So far, there is no functionnal change.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3.c | 112 ++++++++++++++++++++++++++---------
 1 file changed, 83 insertions(+), 29 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 915b4ae8667f..2371e0a70215 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -97,6 +97,32 @@ static DEFINE_PER_CPU(bool, has_rss);
 /* Our default, arbitrary priority value. Linux only uses one anyway. */
 #define DEFAULT_PMR_VALUE	0xf0
 
+enum gic_intid_range {
+	PPI_RANGE,
+	SPI_RANGE,
+	LPI_RANGE,
+	__INVALID_RANGE__
+};
+
+static enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq)
+{
+	switch (hwirq) {
+	case 16 ... 31:
+		return PPI_RANGE;
+	case 32 ... 1019:
+		return SPI_RANGE;
+	case 8192 ... GENMASK(23, 0):
+		return LPI_RANGE;
+	default:
+		return __INVALID_RANGE__;
+	}
+}
+
+static enum gic_intid_range get_intid_range(struct irq_data *d)
+{
+	return __get_intid_range(d->hwirq);
+}
+
 static inline unsigned int gic_irq(struct irq_data *d)
 {
 	return d->hwirq;
@@ -104,18 +130,23 @@ static inline unsigned int gic_irq(struct irq_data *d)
 
 static inline int gic_irq_in_rdist(struct irq_data *d)
 {
-	return gic_irq(d) < 32;
+	return get_intid_range(d) == PPI_RANGE;
 }
 
 static inline void __iomem *gic_dist_base(struct irq_data *d)
 {
-	if (gic_irq_in_rdist(d))	/* SGI+PPI -> SGI_base for this CPU */
+	switch (get_intid_range(d)) {
+	case PPI_RANGE:
+		/* SGI+PPI -> SGI_base for this CPU */
 		return gic_data_rdist_sgi_base();
 
-	if (d->hwirq <= 1023)		/* SPI -> dist_base */
+	case SPI_RANGE:
+		/* SPI -> dist_base */
 		return gic_data.dist_base;
 
-	return NULL;
+	default:
+		return NULL;
+	}
 }
 
 static void gic_do_wait_for_rwp(void __iomem *base)
@@ -196,24 +227,46 @@ static void gic_enable_redist(bool enable)
 /*
  * Routines to disable, enable, EOI and route interrupts
  */
+static u32 convert_offset_index(struct irq_data *d, u32 offset, u32 *index)
+{
+	switch (get_intid_range(d)) {
+	case PPI_RANGE:
+	case SPI_RANGE:
+		*index = d->hwirq;
+		return offset;
+	default:
+		break;
+	}
+
+	WARN_ON(1);
+	*index = d->hwirq;
+	return offset;
+}
+
 static int gic_peek_irq(struct irq_data *d, u32 offset)
 {
-	u32 mask = 1 << (gic_irq(d) % 32);
 	void __iomem *base;
+	u32 index, mask;
+
+	offset = convert_offset_index(d, offset, &index);
+	mask = 1 << (index % 32);
 
 	if (gic_irq_in_rdist(d))
 		base = gic_data_rdist_sgi_base();
 	else
 		base = gic_data.dist_base;
 
-	return !!(readl_relaxed(base + offset + (gic_irq(d) / 32) * 4) & mask);
+	return !!(readl_relaxed(base + offset + (index / 32) * 4) & mask);
 }
 
 static void gic_poke_irq(struct irq_data *d, u32 offset)
 {
-	u32 mask = 1 << (gic_irq(d) % 32);
 	void (*rwp_wait)(void);
 	void __iomem *base;
+	u32 index, mask;
+
+	offset = convert_offset_index(d, offset, &index);
+	mask = 1 << (index % 32);
 
 	if (gic_irq_in_rdist(d)) {
 		base = gic_data_rdist_sgi_base();
@@ -223,7 +276,7 @@ static void gic_poke_irq(struct irq_data *d, u32 offset)
 		rwp_wait = gic_dist_wait_for_rwp;
 	}
 
-	writel_relaxed(mask, base + offset + (gic_irq(d) / 32) * 4);
+	writel_relaxed(mask, base + offset + (index / 32) * 4);
 	rwp_wait();
 }
 
@@ -316,8 +369,11 @@ static int gic_irq_get_irqchip_state(struct irq_data *d,
 static void gic_irq_set_prio(struct irq_data *d, u8 prio)
 {
 	void __iomem *base = gic_dist_base(d);
+	u32 offset, index;
 
-	writeb_relaxed(prio, base + GICD_IPRIORITYR + gic_irq(d));
+	offset = convert_offset_index(d, GICD_IPRIORITYR, &index);
+
+	writeb_relaxed(prio, base + offset + index);
 }
 
 static int gic_irq_nmi_setup(struct irq_data *d)
@@ -407,6 +463,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 	unsigned int irq = gic_irq(d);
 	void (*rwp_wait)(void);
 	void __iomem *base;
+	u32 offset, index;
 	int ret;
 
 	/* Interrupt configuration for SGIs can't be changed */
@@ -426,8 +483,9 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 		rwp_wait = gic_dist_wait_for_rwp;
 	}
 
+	offset = convert_offset_index(d, GICD_ICFGR, &index);
 
-	ret = gic_configure_irq(irq, type, base + GICD_ICFGR, rwp_wait);
+	ret = gic_configure_irq(index, type, base + offset, rwp_wait);
 	if (ret && irq < 32) {
 		/* Misconfigured PPIs are usually not fatal */
 		pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16);
@@ -966,6 +1024,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 			    bool force)
 {
 	unsigned int cpu;
+	u32 offset, index;
 	void __iomem *reg;
 	int enabled;
 	u64 val;
@@ -986,7 +1045,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 	if (enabled)
 		gic_mask_irq(d);
 
-	reg = gic_dist_base(d) + GICD_IROUTER + (gic_irq(d) * 8);
+	offset = convert_offset_index(d, GICD_IROUTER, &index);
+	reg = gic_dist_base(d) + offset + (index * 8);
 	val = gic_mpidr_to_affinity(cpu_logical_map(cpu));
 
 	gic_write_irouter(val, reg);
@@ -1080,36 +1140,30 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
 	if (static_branch_likely(&supports_deactivate_key))
 		chip = &gic_eoimode1_chip;
 
-	/* SGIs are private to the core kernel */
-	if (hw < 16)
-		return -EPERM;
-	/* Nothing here */
-	if (hw >= gic_data.irq_nr && hw < 8192)
-		return -EPERM;
-	/* Off limits */
-	if (hw >= GIC_ID_NR)
-		return -EPERM;
-
-	/* PPIs */
-	if (hw < 32) {
+	switch (__get_intid_range(hw)) {
+	case PPI_RANGE:
 		irq_set_percpu_devid(irq);
 		irq_domain_set_info(d, irq, hw, chip, d->host_data,
 				    handle_percpu_devid_irq, NULL, NULL);
 		irq_set_status_flags(irq, IRQ_NOAUTOEN);
-	}
-	/* SPIs */
-	if (hw >= 32 && hw < gic_data.irq_nr) {
+		break;
+
+	case SPI_RANGE:
 		irq_domain_set_info(d, irq, hw, 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)));
-	}
-	/* LPIs */
-	if (hw >= 8192 && hw < GIC_ID_NR) {
+		break;
+
+	case LPI_RANGE:
 		if (!gic_dist_supports_lpis())
 			return -EPERM;
 		irq_domain_set_info(d, irq, hw, chip, d->host_data,
 				    handle_fasteoi_irq, NULL, NULL);
+		break;
+
+	default:
+		return -EPERM;
 	}
 
 	return 0;
-- 
2.20.1


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

* [PATCH 3/9] dt-bindings: interrupt-controller: arm,gic-v3: Describe ESPI range support
  2019-07-23 10:44 [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges Marc Zyngier
  2019-07-23 10:44 ` [PATCH 1/9] irqchip/gic: Rework gic_configure_irq to take the full ICFGR base Marc Zyngier
  2019-07-23 10:44 ` [PATCH 2/9] irqchip/gic-v3: Add INTID range and convertion primitives Marc Zyngier
@ 2019-07-23 10:44 ` Marc Zyngier
  2019-07-23 12:59   ` [PATCH 3/9] dt-bindings: interrupt-controller: arm, gic-v3: " Lokesh Vutla
  2019-07-23 10:44 ` [PATCH 4/9] irqchip/gic-v3: Add " Marc Zyngier
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 10:44 UTC (permalink / raw)
  To: Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

GICv3.1 introduces support for new interrupt ranges, one of them being
the Extended SPI range (ESPI). The DT binding is extended to deal with
it as a new interrupt class.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 .../devicetree/bindings/interrupt-controller/arm,gic-v3.yaml | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
index c34df35a25fc..98a3ecda8e07 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
@@ -44,11 +44,12 @@ properties:
       be at least 4.
 
       The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
-      interrupts. Other values are reserved for future use.
+      interrupts, 2 for interrupts in the Extended SPI range. Other values
+      are reserved for future use.
 
       The 2nd cell contains the interrupt number for the interrupt type.
       SPI interrupts are in the range [0-987]. PPI interrupts are in the
-      range [0-15].
+      range [0-15]. Extented SPI interrupts are in the range [0-1023].
 
       The 3rd cell is the flags, encoded as follows:
       bits[3:0] trigger type and level flags.
-- 
2.20.1


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

* [PATCH 4/9] irqchip/gic-v3: Add ESPI range support
  2019-07-23 10:44 [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges Marc Zyngier
                   ` (2 preceding siblings ...)
  2019-07-23 10:44 ` [PATCH 3/9] dt-bindings: interrupt-controller: arm,gic-v3: Describe ESPI range support Marc Zyngier
@ 2019-07-23 10:44 ` Marc Zyngier
  2019-07-23 12:50   ` Lokesh Vutla
  2019-07-23 10:44 ` [PATCH 5/9] irqchip/gic: Prepare for more than 16 PPIs Marc Zyngier
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 10:44 UTC (permalink / raw)
  To: Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

Add the required support for the ESPI range, which behave exactly like
the SPIs of old, only with new funky INTIDs.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3.c       | 85 ++++++++++++++++++++++++------
 include/linux/irqchip/arm-gic-v3.h | 17 +++++-
 2 files changed, 85 insertions(+), 17 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 2371e0a70215..d328a8de533f 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -51,13 +51,16 @@ struct gic_chip_data {
 	u32			nr_redist_regions;
 	u64			flags;
 	bool			has_rss;
-	unsigned int		irq_nr;
 	struct partition_desc	*ppi_descs[16];
 };
 
 static struct gic_chip_data gic_data __read_mostly;
 static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
 
+#define GIC_ID_NR	(1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer))
+#define GIC_LINE_NR	GICD_TYPER_SPIS(gic_data.rdists.gicd_typer)
+#define GIC_ESPI_NR	GICD_TYPER_ESPIS(gic_data.rdists.gicd_typer)
+
 /*
  * The behaviours of RPR and PMR registers differ depending on the value of
  * SCR_EL3.FIQ, and the behaviour of non-secure priority registers of the
@@ -100,6 +103,7 @@ static DEFINE_PER_CPU(bool, has_rss);
 enum gic_intid_range {
 	PPI_RANGE,
 	SPI_RANGE,
+	ESPI_RANGE,
 	LPI_RANGE,
 	__INVALID_RANGE__
 };
@@ -111,6 +115,8 @@ static enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq)
 		return PPI_RANGE;
 	case 32 ... 1019:
 		return SPI_RANGE;
+	case ESPI_BASE_INTID ... 8191:
+		return ESPI_RANGE;
 	case 8192 ... GENMASK(23, 0):
 		return LPI_RANGE;
 	default:
@@ -141,6 +147,7 @@ static inline void __iomem *gic_dist_base(struct irq_data *d)
 		return gic_data_rdist_sgi_base();
 
 	case SPI_RANGE:
+	case ESPI_RANGE:
 		/* SPI -> dist_base */
 		return gic_data.dist_base;
 
@@ -234,6 +241,31 @@ static u32 convert_offset_index(struct irq_data *d, u32 offset, u32 *index)
 	case SPI_RANGE:
 		*index = d->hwirq;
 		return offset;
+	case ESPI_RANGE:
+		*index = d->hwirq - ESPI_BASE_INTID;
+		switch (offset) {
+		case GICD_ISENABLER:
+			return GICD_ISENABLERnE;
+		case GICD_ICENABLER:
+			return GICD_ICENABLERnE;
+		case GICD_ISPENDR:
+			return GICD_ISPENDRnE;
+		case GICD_ICPENDR:
+			return GICD_ICPENDRnE;
+		case GICD_ISACTIVER:
+			return GICD_ISACTIVERnE;
+		case GICD_ICACTIVER:
+			return GICD_ICACTIVERnE;
+		case GICD_IPRIORITYR:
+			return GICD_IPRIORITYRnE;
+		case GICD_ICFGR:
+			return GICD_ICFGRnE;
+		case GICD_IROUTER:
+			return GICD_IROUTERnE;
+		default:
+			break;
+		}
+		break;
 	default:
 		break;
 	}
@@ -316,7 +348,7 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
 {
 	u32 reg;
 
-	if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
+	if (d->hwirq >= 8192) /* PPI/SPI only */
 		return -EINVAL;
 
 	switch (which) {
@@ -343,7 +375,7 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
 static int gic_irq_get_irqchip_state(struct irq_data *d,
 				     enum irqchip_irq_state which, bool *val)
 {
-	if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
+	if (d->hwirq >= 8192) /* PPI/SPI only */
 		return -EINVAL;
 
 	switch (which) {
@@ -567,7 +599,12 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
 		gic_arch_enable_irqs();
 	}
 
-	if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) {
+	/* Check for special IDs first */
+	if ((irqnr >= 1020 && irqnr <= 1023))
+		return;
+
+	/* Treat anything but SGIs in a uniform way */
+	if (likely(irqnr > 15)) {
 		int err;
 
 		if (static_branch_likely(&supports_deactivate_key))
@@ -655,10 +692,26 @@ static void __init gic_dist_init(void)
 	 * do the right thing if the kernel is running in secure mode,
 	 * but that's not the intended use case anyway.
 	 */
-	for (i = 32; i < gic_data.irq_nr; i += 32)
+	for (i = 32; i < GIC_LINE_NR; i += 32)
 		writel_relaxed(~0, base + GICD_IGROUPR + i / 8);
 
-	gic_dist_config(base, gic_data.irq_nr, gic_dist_wait_for_rwp);
+	/* Extended SPI range, not handled by the GICv2/GICv3 common code */
+	for (i = 0; i < GIC_ESPI_NR; i += 32) {
+		writel_relaxed(~0U, base + GICD_ICENABLERnE + i / 8);
+		writel_relaxed(~0U, base + GICD_ICACTIVERnE + i / 8);
+	}
+
+	for (i = 0; i < GIC_ESPI_NR; i += 32)
+		writel_relaxed(~0U, base + GICD_IGROUPRnE + i / 8);
+
+	for (i = 0; i < GIC_ESPI_NR; i += 16)
+		writel_relaxed(0, base + GICD_ICFGRnE + i / 4);
+
+	for (i = 0; i < GIC_ESPI_NR; i += 4)
+		writel_relaxed(GICD_INT_DEF_PRI_X4, base + GICD_IPRIORITYRnE + i);
+
+	/* Now do the common stuff, and wait for the distributor to drain */
+	gic_dist_config(base, GIC_LINE_NR, gic_dist_wait_for_rwp);
 
 	/* Enable distributor with ARE, Group1 */
 	writel_relaxed(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
@@ -669,8 +722,11 @@ static void __init gic_dist_init(void)
 	 * enabled.
 	 */
 	affinity = gic_mpidr_to_affinity(cpu_logical_map(smp_processor_id()));
-	for (i = 32; i < gic_data.irq_nr; i++)
+	for (i = 32; i < GIC_LINE_NR; i++)
 		gic_write_irouter(affinity, base + GICD_IROUTER + i * 8);
+
+	for (i = 0; i < GIC_ESPI_NR; i++)
+		gic_write_irouter(affinity, base + GICD_IROUTERnE + i * 8);
 }
 
 static int gic_iterate_rdists(int (*fn)(struct redist_region *, void __iomem *))
@@ -1130,8 +1186,6 @@ static struct irq_chip gic_eoimode1_chip = {
 				  IRQCHIP_MASK_ON_SUSPEND,
 };
 
-#define GIC_ID_NR	(1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer))
-
 static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
 			      irq_hw_number_t hw)
 {
@@ -1149,6 +1203,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
 		break;
 
 	case SPI_RANGE:
+	case ESPI_RANGE:
 		irq_domain_set_info(d, irq, hw, chip, d->host_data,
 				    handle_fasteoi_irq, NULL, NULL);
 		irq_set_probe(irq);
@@ -1188,6 +1243,9 @@ static int gic_irq_domain_translate(struct irq_domain *d,
 		case GIC_IRQ_TYPE_PARTITION:
 			*hwirq = fwspec->param[1] + 16;
 			break;
+		case 2:			/* ESPI */
+			*hwirq = fwspec->param[1] + ESPI_BASE_INTID;
+			break;
 		case GIC_IRQ_TYPE_LPI:	/* LPI */
 			*hwirq = fwspec->param[1];
 			break;
@@ -1342,7 +1400,6 @@ static int __init gic_init_bases(void __iomem *dist_base,
 				 struct fwnode_handle *handle)
 {
 	u32 typer;
-	int gic_irqs;
 	int err;
 
 	if (!is_hyp_mode_available())
@@ -1359,15 +1416,11 @@ static int __init gic_init_bases(void __iomem *dist_base,
 
 	/*
 	 * Find out how many interrupts are supported.
-	 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
 	 */
 	typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
 	gic_data.rdists.gicd_typer = typer;
-	gic_irqs = GICD_TYPER_IRQS(typer);
-	if (gic_irqs > 1020)
-		gic_irqs = 1020;
-	gic_data.irq_nr = gic_irqs;
-
+	pr_info("%d SPIs implemented\n", GIC_LINE_NR - 32);
+	pr_info("%d Extended SPIs implemented\n", GIC_ESPI_NR);
 	gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,
 						 &gic_data);
 	irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED);
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 67c4b9806d43..c523bf1faa55 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -30,10 +30,22 @@
 #define GICD_ICFGR			0x0C00
 #define GICD_IGRPMODR			0x0D00
 #define GICD_NSACR			0x0E00
+#define GICD_IGROUPRnE			0x1000
+#define GICD_ISENABLERnE		0x1200
+#define GICD_ICENABLERnE		0x1400
+#define GICD_ISPENDRnE			0x1600
+#define GICD_ICPENDRnE			0x1800
+#define GICD_ISACTIVERnE		0x1A00
+#define GICD_ICACTIVERnE		0x1C00
+#define GICD_IPRIORITYRnE		0x2000
+#define GICD_ICFGRnE			0x3000
 #define GICD_IROUTER			0x6000
+#define GICD_IROUTERnE			0x8000
 #define GICD_IDREGS			0xFFD0
 #define GICD_PIDR2			0xFFE8
 
+#define ESPI_BASE_INTID			4096
+
 /*
  * Those registers are actually from GICv2, but the spec demands that they
  * are implemented as RES0 if ARE is 1 (which we do in KVM's emulated GICv3).
@@ -69,10 +81,13 @@
 #define GICD_TYPER_RSS			(1U << 26)
 #define GICD_TYPER_LPIS			(1U << 17)
 #define GICD_TYPER_MBIS			(1U << 16)
+#define GICD_TYPER_ESPI			(1U << 8)
 
 #define GICD_TYPER_ID_BITS(typer)	((((typer) >> 19) & 0x1f) + 1)
 #define GICD_TYPER_NUM_LPIS(typer)	((((typer) >> 11) & 0x1f) + 1)
-#define GICD_TYPER_IRQS(typer)		((((typer) & 0x1f) + 1) * 32)
+#define GICD_TYPER_SPIS(typer)		((((typer) & 0x1f) + 1) * 32)
+#define GICD_TYPER_ESPIS(typer)						\
+	(((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
 
 #define GICD_IROUTER_SPI_MODE_ONE	(0U << 31)
 #define GICD_IROUTER_SPI_MODE_ANY	(1U << 31)
-- 
2.20.1


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

* [PATCH 5/9] irqchip/gic: Prepare for more than 16 PPIs
  2019-07-23 10:44 [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges Marc Zyngier
                   ` (3 preceding siblings ...)
  2019-07-23 10:44 ` [PATCH 4/9] irqchip/gic-v3: Add " Marc Zyngier
@ 2019-07-23 10:44 ` Marc Zyngier
  2019-07-23 10:44 ` [PATCH 6/9] irqchip/gic-v3: Dynamically allocate PPI NMI refcounts Marc Zyngier
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 10:44 UTC (permalink / raw)
  To: Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

GICv3.1 allows up to 80 PPIs (16 legaci PPIs and 64 Extended PPIs),
meaning we can't just leave the old 16 hardcoded everywhere.

We also need to add the infrastructure to discuver the number of PPIs
on a per redistributor basis, although we still pretend there is only
16 of them for now.

No functional change.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-common.c | 19 ++++++++++++-------
 drivers/irqchip/irq-gic-common.h |  2 +-
 drivers/irqchip/irq-gic-v3.c     | 22 +++++++++++++++-------
 drivers/irqchip/irq-gic.c        |  2 +-
 drivers/irqchip/irq-hip04.c      |  2 +-
 5 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index 6900b6f0921c..14110db01c05 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -128,26 +128,31 @@ void gic_dist_config(void __iomem *base, int gic_irqs,
 		sync_access();
 }
 
-void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
+void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void))
 {
 	int i;
 
 	/*
 	 * Deal with the banked PPI and SGI interrupts - disable all
-	 * PPI interrupts, ensure all SGI interrupts are enabled.
-	 * Make sure everything is deactivated.
+	 * private interrupts. Make sure everything is deactivated.
 	 */
-	writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR);
-	writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR);
-	writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
+	for (i = 0; i < nr; i += 32) {
+		writel_relaxed(GICD_INT_EN_CLR_X32,
+			       base + GIC_DIST_ACTIVE_CLEAR + i / 8);
+		writel_relaxed(GICD_INT_EN_CLR_X32,
+			       base + GIC_DIST_ENABLE_CLEAR + i / 8);
+	}
 
 	/*
 	 * Set priority on PPI and SGI interrupts
 	 */
-	for (i = 0; i < 32; i += 4)
+	for (i = 0; i < nr; i += 4)
 		writel_relaxed(GICD_INT_DEF_PRI_X4,
 					base + GIC_DIST_PRI + i * 4 / 4);
 
+	/* Ensure all SGI interrupts are now enabled */
+	writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
+
 	if (sync_access)
 		sync_access();
 }
diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h
index 5a46b6b57750..ccba8b0fe0f5 100644
--- a/drivers/irqchip/irq-gic-common.h
+++ b/drivers/irqchip/irq-gic-common.h
@@ -22,7 +22,7 @@ int gic_configure_irq(unsigned int irq, unsigned int type,
                        void __iomem *base, void (*sync_access)(void));
 void gic_dist_config(void __iomem *base, int gic_irqs,
 		     void (*sync_access)(void));
-void gic_cpu_config(void __iomem *base, void (*sync_access)(void));
+void gic_cpu_config(void __iomem *base, int nr, void (*sync_access)(void));
 void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
 		void *data);
 void gic_enable_of_quirks(const struct device_node *np,
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index d328a8de533f..2d4ecf36d0fd 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -51,6 +51,7 @@ struct gic_chip_data {
 	u32			nr_redist_regions;
 	u64			flags;
 	bool			has_rss;
+	unsigned int		ppi_nr;
 	struct partition_desc	*ppi_descs[16];
 };
 
@@ -812,19 +813,24 @@ static int gic_populate_rdist(void)
 	return -ENODEV;
 }
 
-static int __gic_update_vlpi_properties(struct redist_region *region,
-					void __iomem *ptr)
+static int __gic_update_rdist_properties(struct redist_region *region,
+					 void __iomem *ptr)
 {
 	u64 typer = gic_read_typer(ptr + GICR_TYPER);
 	gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
 	gic_data.rdists.has_direct_lpi &= !!(typer & GICR_TYPER_DirectLPIS);
+	gic_data.ppi_nr = 16;
 
 	return 1;
 }
 
-static void gic_update_vlpi_properties(void)
+static void gic_update_rdist_properties(void)
 {
-	gic_iterate_rdists(__gic_update_vlpi_properties);
+	gic_data.ppi_nr = UINT_MAX;
+	gic_iterate_rdists(__gic_update_rdist_properties);
+	if (WARN_ON(gic_data.ppi_nr == UINT_MAX))
+		gic_data.ppi_nr = 0;
+	pr_info("%d PPIs implemented\n", gic_data.ppi_nr);
 	pr_info("%sVLPI support, %sdirect LPI support\n",
 		!gic_data.rdists.has_vlpis ? "no " : "",
 		!gic_data.rdists.has_direct_lpi ? "no " : "");
@@ -964,6 +970,7 @@ static int gic_dist_supports_lpis(void)
 static void gic_cpu_init(void)
 {
 	void __iomem *rbase;
+	int i;
 
 	/* Register ourselves with the rest of the world */
 	if (gic_populate_rdist())
@@ -974,9 +981,10 @@ static void gic_cpu_init(void)
 	rbase = gic_data_rdist_sgi_base();
 
 	/* Configure SGIs/PPIs as non-secure Group-1 */
-	writel_relaxed(~0, rbase + GICR_IGROUPR0);
+	for (i = 0; i < gic_data.ppi_nr + 16; i += 32)
+		writel_relaxed(~0, rbase + GICR_IGROUPR0 + i / 8);
 
-	gic_cpu_config(rbase, gic_redist_wait_for_rwp);
+	gic_cpu_config(rbase, gic_data.ppi_nr + 16, gic_redist_wait_for_rwp);
 
 	/* initialise system registers */
 	gic_cpu_sys_reg_init();
@@ -1445,7 +1453,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
 
 	set_handle_irq(gic_handle_irq);
 
-	gic_update_vlpi_properties();
+	gic_update_rdist_properties();
 
 	gic_smp_init();
 	gic_dist_init();
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index ab48760acabb..25c1ae69db30 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -543,7 +543,7 @@ static int gic_cpu_init(struct gic_chip_data *gic)
 				gic_cpu_map[i] &= ~cpu_mask;
 	}
 
-	gic_cpu_config(dist_base, NULL);
+	gic_cpu_config(dist_base, 32, NULL);
 
 	writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK);
 	gic_cpu_if_up(gic);
diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
index 1626131834a6..130caa1c9d93 100644
--- a/drivers/irqchip/irq-hip04.c
+++ b/drivers/irqchip/irq-hip04.c
@@ -273,7 +273,7 @@ static void hip04_irq_cpu_init(struct hip04_irq_data *intc)
 		if (i != cpu)
 			hip04_cpu_map[i] &= ~cpu_mask;
 
-	gic_cpu_config(dist_base, NULL);
+	gic_cpu_config(dist_base, 32, NULL);
 
 	writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
 	writel_relaxed(1, base + GIC_CPU_CTRL);
-- 
2.20.1


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

* [PATCH 6/9] irqchip/gic-v3: Dynamically allocate PPI NMI refcounts
  2019-07-23 10:44 [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges Marc Zyngier
                   ` (4 preceding siblings ...)
  2019-07-23 10:44 ` [PATCH 5/9] irqchip/gic: Prepare for more than 16 PPIs Marc Zyngier
@ 2019-07-23 10:44 ` Marc Zyngier
  2019-07-23 10:44 ` [PATCH 7/9] irqchip/gic-v3: Dynamically allocate PPI partition descriptors Marc Zyngier
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 10:44 UTC (permalink / raw)
  To: Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

As we're about to have a variable number of PPIs, let's make the
allocation of the NMI refcounts dynamic. Also apply some minor
cleanups (moving things around).

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3.c | 47 ++++++++++++++++++++++++++----------
 1 file changed, 34 insertions(+), 13 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 2d4ecf36d0fd..ec0f885fa373 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -88,7 +88,7 @@ static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
 static DEFINE_STATIC_KEY_FALSE(supports_pseudo_nmis);
 
 /* ppi_nmi_refs[n] == number of cpus having ppi[n + 16] set as NMI */
-static refcount_t ppi_nmi_refs[16];
+static refcount_t *ppi_nmi_refs;
 
 static struct gic_kvm_info gic_v3_kvm_info;
 static DEFINE_PER_CPU(bool, has_rss);
@@ -409,6 +409,16 @@ static void gic_irq_set_prio(struct irq_data *d, u8 prio)
 	writeb_relaxed(prio, base + offset + index);
 }
 
+static u32 gic_get_ppi_index(struct irq_data *d)
+{
+	switch (get_intid_range(d)) {
+	case PPI_RANGE:
+		return d->hwirq - 16;
+	default:
+		unreachable();
+	}
+}
+
 static int gic_irq_nmi_setup(struct irq_data *d)
 {
 	struct irq_desc *desc = irq_to_desc(d->irq);
@@ -429,10 +439,12 @@ static int gic_irq_nmi_setup(struct irq_data *d)
 		return -EINVAL;
 
 	/* desc lock should already be held */
-	if (gic_irq(d) < 32) {
+	if (gic_irq_in_rdist(d)) {
+		u32 idx = gic_get_ppi_index(d);
+
 		/* Setting up PPI as NMI, only switch handler for first NMI */
-		if (!refcount_inc_not_zero(&ppi_nmi_refs[gic_irq(d) - 16])) {
-			refcount_set(&ppi_nmi_refs[gic_irq(d) - 16], 1);
+		if (!refcount_inc_not_zero(&ppi_nmi_refs[idx])) {
+			refcount_set(&ppi_nmi_refs[idx], 1);
 			desc->handle_irq = handle_percpu_devid_fasteoi_nmi;
 		}
 	} else {
@@ -464,9 +476,11 @@ static void gic_irq_nmi_teardown(struct irq_data *d)
 		return;
 
 	/* desc lock should already be held */
-	if (gic_irq(d) < 32) {
+	if (gic_irq_in_rdist(d)) {
+		u32 idx = gic_get_ppi_index(d);
+
 		/* Tearing down NMI, only switch handler for last NMI */
-		if (refcount_dec_and_test(&ppi_nmi_refs[gic_irq(d) - 16]))
+		if (refcount_dec_and_test(&ppi_nmi_refs[idx]))
 			desc->handle_irq = handle_percpu_devid_irq;
 	} else {
 		desc->handle_irq = handle_fasteoi_irq;
@@ -1390,7 +1404,19 @@ static void gic_enable_nmi_support(void)
 {
 	int i;
 
-	for (i = 0; i < 16; i++)
+	if (!gic_prio_masking_enabled())
+		return;
+
+	if (gic_has_group0() && !gic_dist_security_disabled()) {
+		pr_warn("SCR_EL3.FIQ is cleared, cannot enable use of pseudo-NMIs\n");
+		return;
+	}
+
+	ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL);
+	if (!ppi_nmi_refs)
+		return;
+
+	for (i = 0; i < gic_data.ppi_nr; i++)
 		refcount_set(&ppi_nmi_refs[i], 0);
 
 	static_branch_enable(&supports_pseudo_nmis);
@@ -1468,12 +1494,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
 			gicv2m_init(handle, gic_data.domain);
 	}
 
-	if (gic_prio_masking_enabled()) {
-		if (!gic_has_group0() || gic_dist_security_disabled())
-			gic_enable_nmi_support();
-		else
-			pr_warn("SCR_EL3.FIQ is cleared, cannot enable use of pseudo-NMIs\n");
-	}
+	gic_enable_nmi_support();
 
 	return 0;
 
-- 
2.20.1


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

* [PATCH 7/9] irqchip/gic-v3: Dynamically allocate PPI partition descriptors
  2019-07-23 10:44 [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges Marc Zyngier
                   ` (5 preceding siblings ...)
  2019-07-23 10:44 ` [PATCH 6/9] irqchip/gic-v3: Dynamically allocate PPI NMI refcounts Marc Zyngier
@ 2019-07-23 10:44 ` Marc Zyngier
  2019-07-23 10:44 ` [PATCH 8/9] dt-bindings: interrupt-controller: arm,gic-v3: Describe EPPI range support Marc Zyngier
  2019-07-23 10:44 ` [PATCH 9/9] irqchip/gic-v3: Add " Marc Zyngier
  8 siblings, 0 replies; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 10:44 UTC (permalink / raw)
  To: Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

Again, PPIs are becoming a variable set. Let's hack the PPI partition
code to make the top-level array dynamically allocated.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index ec0f885fa373..b85acab4a6a1 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -52,7 +52,7 @@ struct gic_chip_data {
 	u64			flags;
 	bool			has_rss;
 	unsigned int		ppi_nr;
-	struct partition_desc	*ppi_descs[16];
+	struct partition_desc	**ppi_descs;
 };
 
 static struct gic_chip_data gic_data __read_mostly;
@@ -1350,7 +1350,8 @@ static int gic_irq_domain_select(struct irq_domain *d,
 	 * then we need to match the partition domain.
 	 */
 	if (fwspec->param_count >= 4 &&
-	    fwspec->param[0] == 1 && fwspec->param[3] != 0)
+	    fwspec->param[0] == 1 && fwspec->param[3] != 0 &&
+	    gic_data.ppi_descs)
 		return d == partition_get_domain(gic_data.ppi_descs[fwspec->param[1]]);
 
 	return d == gic_data.domain;
@@ -1371,6 +1372,9 @@ static int partition_domain_translate(struct irq_domain *d,
 	struct device_node *np;
 	int ret;
 
+	if (!gic_data.ppi_descs)
+		return -ENOMEM;
+
 	np = of_find_node_by_phandle(fwspec->param[3]);
 	if (WARN_ON(!np))
 		return -EINVAL;
@@ -1527,6 +1531,10 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
 	if (!parts_node)
 		return;
 
+	gic_data.ppi_descs = kcalloc(gic_data.ppi_nr, sizeof(*gic_data.ppi_descs), GFP_KERNEL);
+	if (!gic_data.ppi_descs)
+		return;
+
 	nr_parts = of_get_child_count(parts_node);
 
 	if (!nr_parts)
@@ -1578,7 +1586,7 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
 		part_idx++;
 	}
 
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < gic_data.ppi_nr; i++) {
 		unsigned int irq;
 		struct partition_desc *desc;
 		struct irq_fwspec ppi_fwspec = {
-- 
2.20.1


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

* [PATCH 8/9] dt-bindings: interrupt-controller: arm,gic-v3: Describe EPPI range support
  2019-07-23 10:44 [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges Marc Zyngier
                   ` (6 preceding siblings ...)
  2019-07-23 10:44 ` [PATCH 7/9] irqchip/gic-v3: Dynamically allocate PPI partition descriptors Marc Zyngier
@ 2019-07-23 10:44 ` Marc Zyngier
  2019-07-23 10:44 ` [PATCH 9/9] irqchip/gic-v3: Add " Marc Zyngier
  8 siblings, 0 replies; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 10:44 UTC (permalink / raw)
  To: Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

Update the GICv3 binding to allow interrupts in the EPPI range.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 .../devicetree/bindings/interrupt-controller/arm,gic-v3.yaml | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
index 98a3ecda8e07..1fe147daca4c 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
@@ -44,12 +44,13 @@ properties:
       be at least 4.
 
       The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
-      interrupts, 2 for interrupts in the Extended SPI range. Other values
-      are reserved for future use.
+      interrupts, 2 for interrupts in the Extended SPI range, 3 for the
+      Extended PPI range. Other values are reserved for future use.
 
       The 2nd cell contains the interrupt number for the interrupt type.
       SPI interrupts are in the range [0-987]. PPI interrupts are in the
       range [0-15]. Extented SPI interrupts are in the range [0-1023].
+      Extended PPI interrupts are in the range [0-127].
 
       The 3rd cell is the flags, encoded as follows:
       bits[3:0] trigger type and level flags.
-- 
2.20.1


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

* [PATCH 9/9] irqchip/gic-v3: Add EPPI range support
  2019-07-23 10:44 [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges Marc Zyngier
                   ` (7 preceding siblings ...)
  2019-07-23 10:44 ` [PATCH 8/9] dt-bindings: interrupt-controller: arm,gic-v3: Describe EPPI range support Marc Zyngier
@ 2019-07-23 10:44 ` Marc Zyngier
  8 siblings, 0 replies; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 10:44 UTC (permalink / raw)
  To: Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

Expand the pre-existing PPI support to be able to deal with the
Extended PPI range (EPPI). This includes obtaining the number of PPIs
from each individual redistributor, and compute the minimum set
(just in case someone builds something really clever...).

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3.c       | 42 +++++++++++++++++++++++++-----
 include/linux/irqchip/arm-gic-v3.h | 12 +++++++++
 2 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index b85acab4a6a1..c91e4c759c95 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -104,6 +104,7 @@ static DEFINE_PER_CPU(bool, has_rss);
 enum gic_intid_range {
 	PPI_RANGE,
 	SPI_RANGE,
+	EPPI_RANGE,
 	ESPI_RANGE,
 	LPI_RANGE,
 	__INVALID_RANGE__
@@ -116,6 +117,8 @@ static enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq)
 		return PPI_RANGE;
 	case 32 ... 1019:
 		return SPI_RANGE;
+	case EPPI_BASE_INTID ... 1119:
+		return EPPI_RANGE;
 	case ESPI_BASE_INTID ... 8191:
 		return ESPI_RANGE;
 	case 8192 ... GENMASK(23, 0):
@@ -137,13 +140,15 @@ static inline unsigned int gic_irq(struct irq_data *d)
 
 static inline int gic_irq_in_rdist(struct irq_data *d)
 {
-	return get_intid_range(d) == PPI_RANGE;
+	enum gic_intid_range range = get_intid_range(d);
+	return range == PPI_RANGE || range == EPPI_RANGE;
 }
 
 static inline void __iomem *gic_dist_base(struct irq_data *d)
 {
 	switch (get_intid_range(d)) {
 	case PPI_RANGE:
+	case EPPI_RANGE:
 		/* SGI+PPI -> SGI_base for this CPU */
 		return gic_data_rdist_sgi_base();
 
@@ -242,6 +247,14 @@ static u32 convert_offset_index(struct irq_data *d, u32 offset, u32 *index)
 	case SPI_RANGE:
 		*index = d->hwirq;
 		return offset;
+	case EPPI_RANGE:
+		/*
+		 * Contrary to the ESPI range, the EPPI range is contiguous
+		 * to the PPI range in the registers, so let's adjust the
+		 * displacement accordingly. Consistency is overrated.
+		 */
+		*index = d->hwirq - EPPI_BASE_INTID + 32;
+		return offset;
 	case ESPI_RANGE:
 		*index = d->hwirq - ESPI_BASE_INTID;
 		switch (offset) {
@@ -414,6 +427,8 @@ static u32 gic_get_ppi_index(struct irq_data *d)
 	switch (get_intid_range(d)) {
 	case PPI_RANGE:
 		return d->hwirq - 16;
+	case EPPI_RANGE:
+		return d->hwirq - EPPI_BASE_INTID + 16;
 	default:
 		unreachable();
 	}
@@ -507,6 +522,7 @@ static void gic_eoimode1_eoi_irq(struct irq_data *d)
 
 static int gic_set_type(struct irq_data *d, unsigned int type)
 {
+	enum gic_intid_range range;
 	unsigned int irq = gic_irq(d);
 	void (*rwp_wait)(void);
 	void __iomem *base;
@@ -517,9 +533,11 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 	if (irq < 16)
 		return -EINVAL;
 
+	range = get_intid_range(d);
+
 	/* SPIs have restrictions on the supported types */
-	if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
-			 type != IRQ_TYPE_EDGE_RISING)
+	if ((range == SPI_RANGE || range == ESPI_RANGE) &&
+	    type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
 		return -EINVAL;
 
 	if (gic_irq_in_rdist(d)) {
@@ -533,9 +551,9 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 	offset = convert_offset_index(d, GICD_ICFGR, &index);
 
 	ret = gic_configure_irq(index, type, base + offset, rwp_wait);
-	if (ret && irq < 32) {
+	if (ret && (range == PPI_RANGE || range == EPPI_RANGE)) {
 		/* Misconfigured PPIs are usually not fatal */
-		pr_warn("GIC: PPI%d is secure or misconfigured\n", irq - 16);
+		pr_warn("GIC: PPI INTID%d is secure or misconfigured\n", irq);
 		ret = 0;
 	}
 
@@ -833,7 +851,7 @@ static int __gic_update_rdist_properties(struct redist_region *region,
 	u64 typer = gic_read_typer(ptr + GICR_TYPER);
 	gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
 	gic_data.rdists.has_direct_lpi &= !!(typer & GICR_TYPER_DirectLPIS);
-	gic_data.ppi_nr = 16;
+	gic_data.ppi_nr = min(GICR_TYPER_NR_PPIS(typer), gic_data.ppi_nr);
 
 	return 1;
 }
@@ -1218,6 +1236,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
 
 	switch (__get_intid_range(hw)) {
 	case PPI_RANGE:
+	case EPPI_RANGE:
 		irq_set_percpu_devid(irq);
 		irq_domain_set_info(d, irq, hw, chip, d->host_data,
 				    handle_percpu_devid_irq, NULL, NULL);
@@ -1262,15 +1281,24 @@ static int gic_irq_domain_translate(struct irq_domain *d,
 			*hwirq = fwspec->param[1] + 32;
 			break;
 		case 1:			/* PPI */
-		case GIC_IRQ_TYPE_PARTITION:
 			*hwirq = fwspec->param[1] + 16;
 			break;
 		case 2:			/* ESPI */
 			*hwirq = fwspec->param[1] + ESPI_BASE_INTID;
 			break;
+		case 3:			/* EPPI */
+			*hwirq = fwspec->param[1] + EPPI_BASE_INTID;
+			break;
 		case GIC_IRQ_TYPE_LPI:	/* LPI */
 			*hwirq = fwspec->param[1];
 			break;
+		case GIC_IRQ_TYPE_PARTITION:
+			*hwirq = fwspec->param[1];
+			if (fwspec->param[1] >= 16)
+				*hwirq += EPPI_BASE_INTID - 16;
+			else
+				*hwirq += 16;
+			break;
 		default:
 			return -EINVAL;
 		}
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index c523bf1faa55..9ec3349dee04 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -124,6 +124,18 @@
 
 #define GICR_TYPER_CPU_NUMBER(r)	(((r) >> 8) & 0xffff)
 
+#define EPPI_BASE_INTID			1056
+
+#define GICR_TYPER_NR_PPIS(r)						\
+	({								\
+		unsigned int __ppinum = ((r) >> 27) & 0x1f;		\
+		unsigned int __nr_ppis = 16;				\
+		if (__ppinum == 1 || __ppinum == 2)			\
+			__nr_ppis +=  __ppinum * 32;			\
+									\
+		__nr_ppis;						\
+	 })
+
 #define GICR_WAKER_ProcessorSleep	(1U << 1)
 #define GICR_WAKER_ChildrenAsleep	(1U << 2)
 
-- 
2.20.1


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

* Re: [PATCH 4/9] irqchip/gic-v3: Add ESPI range support
  2019-07-23 10:44 ` [PATCH 4/9] irqchip/gic-v3: Add " Marc Zyngier
@ 2019-07-23 12:50   ` Lokesh Vutla
  2019-07-23 13:04     ` Marc Zyngier
  0 siblings, 1 reply; 15+ messages in thread
From: Lokesh Vutla @ 2019-07-23 12:50 UTC (permalink / raw)
  To: Marc Zyngier, Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel



On 23/07/19 4:14 PM, Marc Zyngier wrote:
> Add the required support for the ESPI range, which behave exactly like
> the SPIs of old, only with new funky INTIDs.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
>  drivers/irqchip/irq-gic-v3.c       | 85 ++++++++++++++++++++++++------
>  include/linux/irqchip/arm-gic-v3.h | 17 +++++-
>  2 files changed, 85 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index 2371e0a70215..d328a8de533f 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -51,13 +51,16 @@ struct gic_chip_data {
>  	u32			nr_redist_regions;
>  	u64			flags;
>  	bool			has_rss;
> -	unsigned int		irq_nr;
>  	struct partition_desc	*ppi_descs[16];
>  };
>  
>  static struct gic_chip_data gic_data __read_mostly;
>  static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
>  
> +#define GIC_ID_NR	(1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer))
> +#define GIC_LINE_NR	GICD_TYPER_SPIS(gic_data.rdists.gicd_typer)
> +#define GIC_ESPI_NR	GICD_TYPER_ESPIS(gic_data.rdists.gicd_typer)
> +
>  /*
>   * The behaviours of RPR and PMR registers differ depending on the value of
>   * SCR_EL3.FIQ, and the behaviour of non-secure priority registers of the
> @@ -100,6 +103,7 @@ static DEFINE_PER_CPU(bool, has_rss);
>  enum gic_intid_range {
>  	PPI_RANGE,
>  	SPI_RANGE,
> +	ESPI_RANGE,
>  	LPI_RANGE,
>  	__INVALID_RANGE__
>  };
> @@ -111,6 +115,8 @@ static enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq)
>  		return PPI_RANGE;
>  	case 32 ... 1019:
>  		return SPI_RANGE;
> +	case ESPI_BASE_INTID ... 8191:

as per dt documentation, shouldn't the range be
	case ESPI_BASE_INTID ... 5119:

> +		return ESPI_RANGE;
>  	case 8192 ... GENMASK(23, 0):
>  		return LPI_RANGE;
>  	default:
> @@ -141,6 +147,7 @@ static inline void __iomem *gic_dist_base(struct irq_data *d)
>  		return gic_data_rdist_sgi_base();
>  
>  	case SPI_RANGE:
> +	case ESPI_RANGE:
>  		/* SPI -> dist_base */
>  		return gic_data.dist_base;
>  
> @@ -234,6 +241,31 @@ static u32 convert_offset_index(struct irq_data *d, u32 offset, u32 *index)
>  	case SPI_RANGE:
>  		*index = d->hwirq;
>  		return offset;
> +	case ESPI_RANGE:
> +		*index = d->hwirq - ESPI_BASE_INTID;
> +		switch (offset) {
> +		case GICD_ISENABLER:
> +			return GICD_ISENABLERnE;
> +		case GICD_ICENABLER:
> +			return GICD_ICENABLERnE;
> +		case GICD_ISPENDR:
> +			return GICD_ISPENDRnE;
> +		case GICD_ICPENDR:
> +			return GICD_ICPENDRnE;
> +		case GICD_ISACTIVER:
> +			return GICD_ISACTIVERnE;
> +		case GICD_ICACTIVER:
> +			return GICD_ICACTIVERnE;
> +		case GICD_IPRIORITYR:
> +			return GICD_IPRIORITYRnE;
> +		case GICD_ICFGR:
> +			return GICD_ICFGRnE;
> +		case GICD_IROUTER:
> +			return GICD_IROUTERnE;
> +		default:
> +			break;
> +		}
> +		break;
>  	default:
>  		break;
>  	}
> @@ -316,7 +348,7 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
>  {
>  	u32 reg;
>  
> -	if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
> +	if (d->hwirq >= 8192) /* PPI/SPI only */
>  		return -EINVAL;
>  
>  	switch (which) {
> @@ -343,7 +375,7 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
>  static int gic_irq_get_irqchip_state(struct irq_data *d,
>  				     enum irqchip_irq_state which, bool *val)
>  {
> -	if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
> +	if (d->hwirq >= 8192) /* PPI/SPI only */
>  		return -EINVAL;
>  
>  	switch (which) {
> @@ -567,7 +599,12 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
>  		gic_arch_enable_irqs();
>  	}
>  
> -	if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) {
> +	/* Check for special IDs first */
> +	if ((irqnr >= 1020 && irqnr <= 1023))
> +		return;

May be I am missing something here, what is special about these 4 interrupts? or
you meant to check for reserved range here?

Thanks and regards,
Lokesh



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

* Re: [PATCH 3/9] dt-bindings: interrupt-controller: arm, gic-v3: Describe ESPI range support
  2019-07-23 10:44 ` [PATCH 3/9] dt-bindings: interrupt-controller: arm,gic-v3: Describe ESPI range support Marc Zyngier
@ 2019-07-23 12:59   ` Lokesh Vutla
  2019-07-23 13:15     ` Marc Zyngier
  0 siblings, 1 reply; 15+ messages in thread
From: Lokesh Vutla @ 2019-07-23 12:59 UTC (permalink / raw)
  To: Marc Zyngier, Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel



On 23/07/19 4:14 PM, Marc Zyngier wrote:
> GICv3.1 introduces support for new interrupt ranges, one of them being
> the Extended SPI range (ESPI). The DT binding is extended to deal with
> it as a new interrupt class.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
>  .../devicetree/bindings/interrupt-controller/arm,gic-v3.yaml | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
> index c34df35a25fc..98a3ecda8e07 100644
> --- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
> +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
> @@ -44,11 +44,12 @@ properties:
>        be at least 4.
>  
>        The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
> -      interrupts. Other values are reserved for future use.
> +      interrupts, 2 for interrupts in the Extended SPI range. Other values
> +      are reserved for future use.

Any reason why hardware did not consider extending SPIs from 1020:2043? This way
only EPPI would have been introduced. Just a thought.

Either ways, just to be consistent with hardware numbering can ESPI range be 3
and EPPI range be 2?

Thanks and regards,
Lokesh

>  
>        The 2nd cell contains the interrupt number for the interrupt type.
>        SPI interrupts are in the range [0-987]. PPI interrupts are in the
> -      range [0-15].
> +      range [0-15]. Extented SPI interrupts are in the range [0-1023].
>  
>        The 3rd cell is the flags, encoded as follows:
>        bits[3:0] trigger type and level flags.
> 

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

* Re: [PATCH 4/9] irqchip/gic-v3: Add ESPI range support
  2019-07-23 12:50   ` Lokesh Vutla
@ 2019-07-23 13:04     ` Marc Zyngier
  0 siblings, 0 replies; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 13:04 UTC (permalink / raw)
  To: Lokesh Vutla, Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

On 23/07/2019 13:50, Lokesh Vutla wrote:
> 
> 
> On 23/07/19 4:14 PM, Marc Zyngier wrote:
>> Add the required support for the ESPI range, which behave exactly like
>> the SPIs of old, only with new funky INTIDs.
>>
>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>> ---
>>  drivers/irqchip/irq-gic-v3.c       | 85 ++++++++++++++++++++++++------
>>  include/linux/irqchip/arm-gic-v3.h | 17 +++++-
>>  2 files changed, 85 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
>> index 2371e0a70215..d328a8de533f 100644
>> --- a/drivers/irqchip/irq-gic-v3.c
>> +++ b/drivers/irqchip/irq-gic-v3.c
>> @@ -51,13 +51,16 @@ struct gic_chip_data {
>>  	u32			nr_redist_regions;
>>  	u64			flags;
>>  	bool			has_rss;
>> -	unsigned int		irq_nr;
>>  	struct partition_desc	*ppi_descs[16];
>>  };
>>  
>>  static struct gic_chip_data gic_data __read_mostly;
>>  static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
>>  
>> +#define GIC_ID_NR	(1U << GICD_TYPER_ID_BITS(gic_data.rdists.gicd_typer))
>> +#define GIC_LINE_NR	GICD_TYPER_SPIS(gic_data.rdists.gicd_typer)
>> +#define GIC_ESPI_NR	GICD_TYPER_ESPIS(gic_data.rdists.gicd_typer)
>> +
>>  /*
>>   * The behaviours of RPR and PMR registers differ depending on the value of
>>   * SCR_EL3.FIQ, and the behaviour of non-secure priority registers of the
>> @@ -100,6 +103,7 @@ static DEFINE_PER_CPU(bool, has_rss);
>>  enum gic_intid_range {
>>  	PPI_RANGE,
>>  	SPI_RANGE,
>> +	ESPI_RANGE,
>>  	LPI_RANGE,
>>  	__INVALID_RANGE__
>>  };
>> @@ -111,6 +115,8 @@ static enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq)
>>  		return PPI_RANGE;
>>  	case 32 ... 1019:
>>  		return SPI_RANGE;
>> +	case ESPI_BASE_INTID ... 8191:
> 
> as per dt documentation, shouldn't the range be
> 	case ESPI_BASE_INTID ... 5119:

Yes, you're right. Although I strongly suspect that someone will bump
this limit up again at some point (there is enough space in the new
register space for 4k interrupts -- madness).

> 
>> +		return ESPI_RANGE;
>>  	case 8192 ... GENMASK(23, 0):
>>  		return LPI_RANGE;
>>  	default:
>> @@ -141,6 +147,7 @@ static inline void __iomem *gic_dist_base(struct irq_data *d)
>>  		return gic_data_rdist_sgi_base();
>>  
>>  	case SPI_RANGE:
>> +	case ESPI_RANGE:
>>  		/* SPI -> dist_base */
>>  		return gic_data.dist_base;
>>  
>> @@ -234,6 +241,31 @@ static u32 convert_offset_index(struct irq_data *d, u32 offset, u32 *index)
>>  	case SPI_RANGE:
>>  		*index = d->hwirq;
>>  		return offset;
>> +	case ESPI_RANGE:
>> +		*index = d->hwirq - ESPI_BASE_INTID;
>> +		switch (offset) {
>> +		case GICD_ISENABLER:
>> +			return GICD_ISENABLERnE;
>> +		case GICD_ICENABLER:
>> +			return GICD_ICENABLERnE;
>> +		case GICD_ISPENDR:
>> +			return GICD_ISPENDRnE;
>> +		case GICD_ICPENDR:
>> +			return GICD_ICPENDRnE;
>> +		case GICD_ISACTIVER:
>> +			return GICD_ISACTIVERnE;
>> +		case GICD_ICACTIVER:
>> +			return GICD_ICACTIVERnE;
>> +		case GICD_IPRIORITYR:
>> +			return GICD_IPRIORITYRnE;
>> +		case GICD_ICFGR:
>> +			return GICD_ICFGRnE;
>> +		case GICD_IROUTER:
>> +			return GICD_IROUTERnE;
>> +		default:
>> +			break;
>> +		}
>> +		break;
>>  	default:
>>  		break;
>>  	}
>> @@ -316,7 +348,7 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
>>  {
>>  	u32 reg;
>>  
>> -	if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
>> +	if (d->hwirq >= 8192) /* PPI/SPI only */
>>  		return -EINVAL;
>>  
>>  	switch (which) {
>> @@ -343,7 +375,7 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
>>  static int gic_irq_get_irqchip_state(struct irq_data *d,
>>  				     enum irqchip_irq_state which, bool *val)
>>  {
>> -	if (d->hwirq >= gic_data.irq_nr) /* PPI/SPI only */
>> +	if (d->hwirq >= 8192) /* PPI/SPI only */
>>  		return -EINVAL;
>>  
>>  	switch (which) {
>> @@ -567,7 +599,12 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
>>  		gic_arch_enable_irqs();
>>  	}
>>  
>> -	if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) {
>> +	/* Check for special IDs first */
>> +	if ((irqnr >= 1020 && irqnr <= 1023))
>> +		return;
> 
> May be I am missing something here, what is special about these 4 interrupts? or
> you meant to check for reserved range here?

What's so special about the special INTID range is that these are not
interrupts at all. That's how the GIC signals that *something else* is
happening (see 2.2.1 "Special INTIDs" in the architecture spec). In
practice, and as long as you run Linux in non-secure mode, only 1023 can
happen.

Thanks,

	M.
-- 
Jazz is not dead, it just smells funny...

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

* Re: [PATCH 3/9] dt-bindings: interrupt-controller: arm, gic-v3: Describe ESPI range support
  2019-07-23 12:59   ` [PATCH 3/9] dt-bindings: interrupt-controller: arm, gic-v3: " Lokesh Vutla
@ 2019-07-23 13:15     ` Marc Zyngier
  2019-07-23 13:35       ` Lokesh Vutla
  0 siblings, 1 reply; 15+ messages in thread
From: Marc Zyngier @ 2019-07-23 13:15 UTC (permalink / raw)
  To: Lokesh Vutla, Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel

On 23/07/2019 13:59, Lokesh Vutla wrote:
> 
> 
> On 23/07/19 4:14 PM, Marc Zyngier wrote:
>> GICv3.1 introduces support for new interrupt ranges, one of them being
>> the Extended SPI range (ESPI). The DT binding is extended to deal with
>> it as a new interrupt class.
>>
>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>> ---
>>  .../devicetree/bindings/interrupt-controller/arm,gic-v3.yaml | 5 +++--
>>  1 file changed, 3 insertions(+), 2 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
>> index c34df35a25fc..98a3ecda8e07 100644
>> --- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
>> +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
>> @@ -44,11 +44,12 @@ properties:
>>        be at least 4.
>>  
>>        The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
>> -      interrupts. Other values are reserved for future use.
>> +      interrupts, 2 for interrupts in the Extended SPI range. Other values
>> +      are reserved for future use.
> 
> Any reason why hardware did not consider extending SPIs from 1020:2043? This way
> only EPPI would have been introduced. Just a thought.

First, 1020-1023 is the special INTID range. You can't have anything
else there.

Then, making the range contiguous could imply that the range is also
contiguous in the register space, which isn't possible (note that the
EPPI range does it the other way around -- it is discontinuous in the
INTID space, and yet continuous in the register space).

Finally, the decision to push the numbering out towards the LPI range
allows the ESPI space to be grown easily up to 4k.

But frankly, none of that really matters. They are just numbers.

> Either ways, just to be consistent with hardware numbering can ESPI range be 3
> and EPPI range be 2?

Well, the way I see it is that it is more logical for the binding
itself. We already have 0 for SPIs and 1 for PPIs, despite PPIs being
before SPIs in the INTID space.

Thanks,

	M.
-- 
Jazz is not dead, it just smells funny...

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

* Re: [PATCH 3/9] dt-bindings: interrupt-controller: arm, gic-v3: Describe ESPI range support
  2019-07-23 13:15     ` Marc Zyngier
@ 2019-07-23 13:35       ` Lokesh Vutla
  0 siblings, 0 replies; 15+ messages in thread
From: Lokesh Vutla @ 2019-07-23 13:35 UTC (permalink / raw)
  To: Marc Zyngier, Thomas Gleixner, Jason Cooper, Julien Thierry, Rob Herring
  Cc: linux-kernel, linux-arm-kernel



On 23/07/19 6:45 PM, Marc Zyngier wrote:
> On 23/07/2019 13:59, Lokesh Vutla wrote:
>>
>>
>> On 23/07/19 4:14 PM, Marc Zyngier wrote:
>>> GICv3.1 introduces support for new interrupt ranges, one of them being
>>> the Extended SPI range (ESPI). The DT binding is extended to deal with
>>> it as a new interrupt class.
>>>
>>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>>> ---
>>>  .../devicetree/bindings/interrupt-controller/arm,gic-v3.yaml | 5 +++--
>>>  1 file changed, 3 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
>>> index c34df35a25fc..98a3ecda8e07 100644
>>> --- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
>>> +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
>>> @@ -44,11 +44,12 @@ properties:
>>>        be at least 4.
>>>  
>>>        The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
>>> -      interrupts. Other values are reserved for future use.
>>> +      interrupts, 2 for interrupts in the Extended SPI range. Other values
>>> +      are reserved for future use.
>>
>> Any reason why hardware did not consider extending SPIs from 1020:2043? This way
>> only EPPI would have been introduced. Just a thought.
> 
> First, 1020-1023 is the special INTID range. You can't have anything
> else there.
> 
> Then, making the range contiguous could imply that the range is also
> contiguous in the register space, which isn't possible (note that the
> EPPI range does it the other way around -- it is discontinuous in the
> INTID space, and yet continuous in the register space).
> 
> Finally, the decision to push the numbering out towards the LPI range
> allows the ESPI space to be grown easily up to 4k.

okay, got it.

> 
> But frankly, none of that really matters. They are just numbers.
> 
>> Either ways, just to be consistent with hardware numbering can ESPI range be 3
>> and EPPI range be 2?
> 
> Well, the way I see it is that it is more logical for the binding
> itself. We already have 0 for SPIs and 1 for PPIs, despite PPIs being
> before SPIs in the INTID space.

Agreed. Patch looks good to me. FWIW:

Reviewed-by: Lokesh Vutla <lokeshvutla@ti.com>

Thanks and regards,
Lokesh

> 
> Thanks,
> 
> 	M.
> 

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

end of thread, other threads:[~2019-07-23 13:36 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-23 10:44 [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges Marc Zyngier
2019-07-23 10:44 ` [PATCH 1/9] irqchip/gic: Rework gic_configure_irq to take the full ICFGR base Marc Zyngier
2019-07-23 10:44 ` [PATCH 2/9] irqchip/gic-v3: Add INTID range and convertion primitives Marc Zyngier
2019-07-23 10:44 ` [PATCH 3/9] dt-bindings: interrupt-controller: arm,gic-v3: Describe ESPI range support Marc Zyngier
2019-07-23 12:59   ` [PATCH 3/9] dt-bindings: interrupt-controller: arm, gic-v3: " Lokesh Vutla
2019-07-23 13:15     ` Marc Zyngier
2019-07-23 13:35       ` Lokesh Vutla
2019-07-23 10:44 ` [PATCH 4/9] irqchip/gic-v3: Add " Marc Zyngier
2019-07-23 12:50   ` Lokesh Vutla
2019-07-23 13:04     ` Marc Zyngier
2019-07-23 10:44 ` [PATCH 5/9] irqchip/gic: Prepare for more than 16 PPIs Marc Zyngier
2019-07-23 10:44 ` [PATCH 6/9] irqchip/gic-v3: Dynamically allocate PPI NMI refcounts Marc Zyngier
2019-07-23 10:44 ` [PATCH 7/9] irqchip/gic-v3: Dynamically allocate PPI partition descriptors Marc Zyngier
2019-07-23 10:44 ` [PATCH 8/9] dt-bindings: interrupt-controller: arm,gic-v3: Describe EPPI range support Marc Zyngier
2019-07-23 10:44 ` [PATCH 9/9] irqchip/gic-v3: Add " Marc Zyngier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).