2019-07-23 20:27:36

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 0/9] irqchip/gic-v3: Add support for GICv3.1 extended PPI/SPI ranges

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


2019-07-23 20:27:41

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 1/9] irqchip/gic: Rework gic_configure_irq to take the full ICFGR base

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 <[email protected]>
---
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

2019-07-23 20:28:03

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 3/9] dt-bindings: interrupt-controller: arm,gic-v3: Describe ESPI range support

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 <[email protected]>
---
.../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

2019-07-23 20:28:06

by Marc Zyngier

[permalink] [raw]
Subject: [PATCH 5/9] irqchip/gic: Prepare for more than 16 PPIs

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 <[email protected]>
---
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

2019-07-23 23:19:32

by Lokesh Vutla

[permalink] [raw]
Subject: Re: [PATCH 3/9] dt-bindings: interrupt-controller: arm, gic-v3: Describe ESPI range support



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 <[email protected]>
> ---
> .../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.
>

2019-07-23 23:26:52

by Marc Zyngier

[permalink] [raw]
Subject: Re: [PATCH 3/9] dt-bindings: interrupt-controller: arm, gic-v3: Describe ESPI range support

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 <[email protected]>
>> ---
>> .../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...

2019-07-23 23:41:33

by Lokesh Vutla

[permalink] [raw]
Subject: Re: [PATCH 3/9] dt-bindings: interrupt-controller: arm, gic-v3: Describe ESPI range support



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 <[email protected]>
>>> ---
>>> .../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 <[email protected]>

Thanks and regards,
Lokesh

>
> Thanks,
>
> M.
>