[tip: irq/urgent] genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is set

2021-01-30 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: 4c457e8cb75eda91906a4f89fc39bde3f9a43922
Gitweb:
https://git.kernel.org/tip/4c457e8cb75eda91906a4f89fc39bde3f9a43922
Author:Marc Zyngier 
AuthorDate:Sat, 23 Jan 2021 12:27:59 
Committer: Thomas Gleixner 
CommitterDate: Sat, 30 Jan 2021 01:22:31 +01:00

genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is set

When MSI_FLAG_ACTIVATE_EARLY is set (which is the case for PCI),
__msi_domain_alloc_irqs() performs the activation of the interrupt (which
in the case of PCI results in the endpoint being programmed) as soon as the
interrupt is allocated.

But it appears that this is only done for the first vector, introducing an
inconsistent behaviour for PCI Multi-MSI.

Fix it by iterating over the number of vectors allocated to each MSI
descriptor. This is easily achieved by introducing a new
"for_each_msi_vector" iterator, together with a tiny bit of refactoring.

Fixes: f3b0946d629c ("genirq/msi: Make sure PCI MSIs are activated early")
Reported-by: Shameer Kolothum 
Signed-off-by: Marc Zyngier 
Signed-off-by: Thomas Gleixner 
Tested-by: Shameer Kolothum 
Cc: sta...@vger.kernel.org
Link: https://lore.kernel.org/r/20210123122759.1781359-1-...@kernel.org

---
 include/linux/msi.h |  6 ++-
 kernel/irq/msi.c| 44 
 2 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/include/linux/msi.h b/include/linux/msi.h
index 360a0a7..aef35fd 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -178,6 +178,12 @@ struct msi_desc {
list_for_each_entry((desc), dev_to_msi_list((dev)), list)
 #define for_each_msi_entry_safe(desc, tmp, dev)\
list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list)
+#define for_each_msi_vector(desc, __irq, dev)  \
+   for_each_msi_entry((desc), (dev))   \
+   if ((desc)->irq)\
+   for (__irq = (desc)->irq;   \
+__irq < ((desc)->irq + (desc)->nvec_used); \
+__irq++)
 
 #ifdef CONFIG_IRQ_MSI_IOMMU
 static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index dc0e2d7..b338d62 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -436,22 +436,22 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, 
struct device *dev,
 
can_reserve = msi_check_reservation_mode(domain, info, dev);
 
-   for_each_msi_entry(desc, dev) {
-   virq = desc->irq;
-   if (desc->nvec_used == 1)
-   dev_dbg(dev, "irq %d for MSI\n", virq);
-   else
+   /*
+* This flag is set by the PCI layer as we need to activate
+* the MSI entries before the PCI layer enables MSI in the
+* card. Otherwise the card latches a random msi message.
+*/
+   if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY))
+   goto skip_activate;
+
+   for_each_msi_vector(desc, i, dev) {
+   if (desc->irq == i) {
+   virq = desc->irq;
dev_dbg(dev, "irq [%d-%d] for MSI\n",
virq, virq + desc->nvec_used - 1);
-   /*
-* This flag is set by the PCI layer as we need to activate
-* the MSI entries before the PCI layer enables MSI in the
-* card. Otherwise the card latches a random msi message.
-*/
-   if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY))
-   continue;
+   }
 
-   irq_data = irq_domain_get_irq_data(domain, desc->irq);
+   irq_data = irq_domain_get_irq_data(domain, i);
if (!can_reserve) {
irqd_clr_can_reserve(irq_data);
if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK)
@@ -462,28 +462,24 @@ int __msi_domain_alloc_irqs(struct irq_domain *domain, 
struct device *dev,
goto cleanup;
}
 
+skip_activate:
/*
 * If these interrupts use reservation mode, clear the activated bit
 * so request_irq() will assign the final vector.
 */
if (can_reserve) {
-   for_each_msi_entry(desc, dev) {
-   irq_data = irq_domain_get_irq_data(domain, desc->irq);
+   for_each_msi_vector(desc, i, dev) {
+   irq_data = irq_domain_get_irq_data(domain, i);
irqd_clr_activated(irq_data);
}
}
return 0;
 
 cleanup:
-   for_each_msi_entry(desc, dev) {
-   struct irq_data *irqd;
-
-   if (desc->irq == virq)
-   break;
-
-   irqd = 

[tip: irq/core] genirq/irqdomain: Don't try to free an interrupt that has no mapping

2020-11-30 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 4615fbc3788ddc8e7c6d697714ad35a53729aa2c
Gitweb:
https://git.kernel.org/tip/4615fbc3788ddc8e7c6d697714ad35a53729aa2c
Author:Marc Zyngier 
AuthorDate:Sun, 29 Nov 2020 13:55:51 
Committer: Thomas Gleixner 
CommitterDate: Mon, 30 Nov 2020 14:50:21 +01:00

genirq/irqdomain: Don't try to free an interrupt that has no mapping

When an interrupt allocation fails for N interrupts, it is pretty
common for the error handling code to free the same number of interrupts,
no matter how many interrupts have actually been allocated.

This may result in the domain freeing code to be unexpectedly called
for interrupts that have no mapping in that domain. Things end pretty
badly.

Instead, add some checks to irq_domain_free_irqs_hierarchy() to make sure
that thiss does not follow the hierarchy if no mapping exists for a given
interrupt.

Fixes: 6a6544e520abe ("genirq/irqdomain: Remove auto-recursive hierarchy 
support")
Signed-off-by: Marc Zyngier 
Signed-off-by: Thomas Gleixner 
Link: https://lore.kernel.org/r/20201129135551.396777-1-...@kernel.org

---
 kernel/irq/irqdomain.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 3d7463f..30a7887 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1381,8 +1381,15 @@ static void irq_domain_free_irqs_hierarchy(struct 
irq_domain *domain,
   unsigned int irq_base,
   unsigned int nr_irqs)
 {
-   if (domain->ops->free)
-   domain->ops->free(domain, irq_base, nr_irqs);
+   unsigned int i;
+
+   if (!domain->ops->free)
+   return;
+
+   for (i = 0; i < nr_irqs; i++) {
+   if (irq_domain_get_irq_data(domain, irq_base + i))
+   domain->ops->free(domain, irq_base + i, 1);
+   }
 }
 
 int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain,


[tip: irq/urgent] MAINTAINERS: Move Jason Cooper to CREDITS

2020-11-30 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: 509920aee72ae23235615a009c5148cdb38794c3
Gitweb:
https://git.kernel.org/tip/509920aee72ae23235615a009c5148cdb38794c3
Author:Marc Zyngier 
AuthorDate:Sat, 28 Nov 2020 10:37:07 
Committer: Thomas Gleixner 
CommitterDate: Mon, 30 Nov 2020 10:20:34 +01:00

MAINTAINERS: Move Jason Cooper to CREDITS

Jason's email address has now been bouncing for weeks, and no
reply was received when trying to reach out on other addresses.

We really hope he is OK. But until we hear of his whereabouts,
let's move him to the CREDITS file so that people stop Cc-ing
him.

Signed-off-by: Marc Zyngier 
Signed-off-by: Thomas Gleixner 
Acked-by: Gregory CLEMENT 
Acked-by: Andrew Lunn 
Link: https://lore.kernel.org/r/20201128103707.332874-1-...@kernel.org

---
 CREDITS | 5 +
 MAINTAINERS | 4 
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/CREDITS b/CREDITS
index 7483019..e88d1a7 100644
--- a/CREDITS
+++ b/CREDITS
@@ -740,6 +740,11 @@ S: (ask for current address)
 S: Portland, Oregon
 S: USA
 
+N: Jason Cooper
+D: ARM/Marvell SOC co-maintainer
+D: irqchip co-maintainer
+D: MVEBU PCI DRIVER co-maintainer
+
 N: Robin Cornelius
 E: robincornel...@users.sourceforge.net
 D: Ralink rt2x00 WLAN driver
diff --git a/MAINTAINERS b/MAINTAINERS
index 2daa6ee..4f27f43 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2014,7 +2014,6 @@ M:Philipp Zabel 
 S: Maintained
 
 ARM/Marvell Dove/MV78xx0/Orion SOC support
-M: Jason Cooper 
 M: Andrew Lunn 
 M: Sebastian Hesselbarth 
 M: Gregory Clement 
@@ -2031,7 +2030,6 @@ F:arch/arm/plat-orion/
 F: drivers/soc/dove/
 
 ARM/Marvell Kirkwood and Armada 370, 375, 38x, 39x, XP, 3700, 7K/8K, CN9130 
SOC support
-M: Jason Cooper 
 M: Andrew Lunn 
 M: Gregory Clement 
 M: Sebastian Hesselbarth 
@@ -9248,7 +9246,6 @@ F:kernel/irq/
 
 IRQCHIP DRIVERS
 M: Thomas Gleixner 
-M: Jason Cooper 
 M: Marc Zyngier 
 L: linux-kernel@vger.kernel.org
 S: Maintained
@@ -13394,7 +13391,6 @@ F:  drivers/pci/controller/mobiveil/pcie-mobiveil*
 
 PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
 M: Thomas Petazzoni 
-M: Jason Cooper 
 L: linux-...@vger.kernel.org
 L: linux-arm-ker...@lists.infradead.org (moderated for non-subscribers)
 S: Maintained


[tip: irq/urgent] irqchip/mips: Drop selection of IRQ_DOMAIN_HIERARCHY

2020-11-01 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: d26dd4131d0d6ad7aa294a7f8d18782b47c27c93
Gitweb:
https://git.kernel.org/tip/d26dd4131d0d6ad7aa294a7f8d18782b47c27c93
Author:Marc Zyngier 
AuthorDate:Fri, 16 Oct 2020 09:28:23 +01:00
Committer: Marc Zyngier 
CommitterDate: Fri, 16 Oct 2020 10:51:12 +01:00

irqchip/mips: Drop selection of IRQ_DOMAIN_HIERARCHY

Now that GENERIC_IRQ_IPI selects IRQ_DOMAIN_HIERARCHY, there is no
need to have this conditional select for IRQ_MIPS_CPU. Similarily,
MIPS_GIC only needs selecting GENERIC_IRQ_IPI.

Suggested-by: Thomas Gleixner 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/Kconfig | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index cd734df..38785a0 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -180,7 +180,6 @@ config IRQ_MIPS_CPU
select GENERIC_IRQ_CHIP
select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING
select IRQ_DOMAIN
-   select IRQ_DOMAIN_HIERARCHY if GENERIC_IRQ_IPI
select GENERIC_IRQ_EFFECTIVE_AFF_MASK
 
 config CLPS711X_IRQCHIP
@@ -307,7 +306,6 @@ config KEYSTONE_IRQ
 config MIPS_GIC
bool
select GENERIC_IRQ_IPI
-   select IRQ_DOMAIN_HIERARCHY
select MIPS_CM
 
 config INGENIC_IRQ


[tip: irq/urgent] irqchip/mst: Make mst_intc_of_init static

2020-11-01 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: 893a7cfb6b0bea650fafa43838d7f7f8f0f076bc
Gitweb:
https://git.kernel.org/tip/893a7cfb6b0bea650fafa43838d7f7f8f0f076bc
Author:Marc Zyngier 
AuthorDate:Thu, 15 Oct 2020 22:26:26 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 15 Oct 2020 22:32:31 +01:00

irqchip/mst: Make mst_intc_of_init static

mst_intc_of_init has no external caller, so let's make it static.

Reported-by: kernel test robot 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-mst-intc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-mst-intc.c b/drivers/irqchip/irq-mst-intc.c
index 4be0775..143657b 100644
--- a/drivers/irqchip/irq-mst-intc.c
+++ b/drivers/irqchip/irq-mst-intc.c
@@ -154,8 +154,8 @@ static const struct irq_domain_ops mst_intc_domain_ops = {
.free   = irq_domain_free_irqs_common,
 };
 
-int __init
-mst_intc_of_init(struct device_node *dn, struct device_node *parent)
+static int __init mst_intc_of_init(struct device_node *dn,
+  struct device_node *parent)
 {
struct irq_domain *domain, *domain_parent;
struct mst_intc_chip_data *cd;


[tip: irq/urgent] irqchip/bcm2836: Fix missing __init annotation

2020-11-01 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: 57733e009f0c7e0526e10a18be12f56996c5460e
Gitweb:
https://git.kernel.org/tip/57733e009f0c7e0526e10a18be12f56996c5460e
Author:Marc Zyngier 
AuthorDate:Sun, 25 Oct 2020 11:10:29 
Committer: Marc Zyngier 
CommitterDate: Sun, 25 Oct 2020 11:10:29 

irqchip/bcm2836: Fix missing __init annotation

bcm2836_arm_irqchip_smp_init() calls set_smp_ipi_range(), which has
an __init annotation. Make sure the caller has the same annotation.

Reported-by: kernel test robot 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-bcm2836.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c
index 97838eb..cbc7c74 100644
--- a/drivers/irqchip/irq-bcm2836.c
+++ b/drivers/irqchip/irq-bcm2836.c
@@ -244,7 +244,7 @@ static int bcm2836_cpu_dying(unsigned int cpu)
 
 #define BITS_PER_MBOX  32
 
-static void bcm2836_arm_irqchip_smp_init(void)
+static void __init bcm2836_arm_irqchip_smp_init(void)
 {
struct irq_fwspec ipi_fwspec = {
.fwnode = intc.domain->fwnode,


[tip: irq/urgent] genirq: Let GENERIC_IRQ_IPI select IRQ_DOMAIN_HIERARCHY

2020-11-01 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: 151a535171be6ff824a0a3875553ea38570f4c05
Gitweb:
https://git.kernel.org/tip/151a535171be6ff824a0a3875553ea38570f4c05
Author:Marc Zyngier 
AuthorDate:Thu, 15 Oct 2020 21:41:44 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 15 Oct 2020 21:41:44 +01:00

genirq: Let GENERIC_IRQ_IPI select IRQ_DOMAIN_HIERARCHY

kernel/irq/ipi.c otherwise fails to compile if nothing else
selects it.

Fixes: 379b656446a3 ("genirq: Add GENERIC_IRQ_IPI Kconfig symbol")
Reported-by: Pavel Machek 
Tested-by: Pavel Machek 
Signed-off-by: Marc Zyngier 
Link: https://lore.kernel.org/r/20201015101222.GA32747@amd
---
 kernel/irq/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 10a5aff..164a031 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -82,6 +82,7 @@ config IRQ_FASTEOI_HIERARCHY_HANDLERS
 # Generic IRQ IPI support
 config GENERIC_IRQ_IPI
bool
+   select IRQ_DOMAIN_HIERARCHY
 
 # Generic MSI interrupt support
 config GENERIC_MSI_IRQ


[tip: irq/core] arm: Move ipi_teardown() to a CONFIG_HOTPLUG_CPU section

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: ac15a54e03d13686d2fc016a88311801b0734046
Gitweb:
https://git.kernel.org/tip/ac15a54e03d13686d2fc016a88311801b0734046
Author:Marc Zyngier 
AuthorDate:Fri, 18 Sep 2020 17:19:46 +01:00
Committer: Marc Zyngier 
CommitterDate: Fri, 18 Sep 2020 17:40:48 +01:00

arm: Move ipi_teardown() to a CONFIG_HOTPLUG_CPU section

ipi_teardown() is only used when CONFIG_HOTPLUG_CPU is enabled.
Move the function to a location guarded by this config option.

Signed-off-by: Marc Zyngier 
---
 arch/arm/kernel/smp.c | 23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 00327fa..8425da5 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -85,7 +85,6 @@ static int nr_ipi __read_mostly = NR_IPI;
 static struct irq_desc *ipi_desc[MAX_IPI] __read_mostly;
 
 static void ipi_setup(int cpu);
-static void ipi_teardown(int cpu);
 
 static DECLARE_COMPLETION(cpu_running);
 
@@ -236,6 +235,17 @@ int platform_can_hotplug_cpu(unsigned int cpu)
return cpu != 0;
 }
 
+static void ipi_teardown(int cpu)
+{
+   int i;
+
+   if (WARN_ON_ONCE(!ipi_irq_base))
+   return;
+
+   for (i = 0; i < nr_ipi; i++)
+   disable_percpu_irq(ipi_irq_base + i);
+}
+
 /*
  * __cpu_disable runs on the processor to be shutdown.
  */
@@ -707,17 +717,6 @@ static void ipi_setup(int cpu)
enable_percpu_irq(ipi_irq_base + i, 0);
 }
 
-static void ipi_teardown(int cpu)
-{
-   int i;
-
-   if (WARN_ON_ONCE(!ipi_irq_base))
-   return;
-
-   for (i = 0; i < nr_ipi; i++)
-   disable_percpu_irq(ipi_irq_base + i);
-}
-
 void __init set_smp_ipi_range(int ipi_base, int n)
 {
int i;


[tip: irq/core] gpio: tegra186: Allow optional irq parent callbacks

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 986ec63d4482292570b579ac98b151acf8bdd1de
Gitweb:
https://git.kernel.org/tip/986ec63d4482292570b579ac98b151acf8bdd1de
Author:Marc Zyngier 
AuthorDate:Mon, 05 Oct 2020 10:27:27 +01:00
Committer: Marc Zyngier 
CommitterDate: Sat, 10 Oct 2020 12:12:10 +01:00

gpio: tegra186: Allow optional irq parent callbacks

Make the tegra186 GPIO driver resistent to variable depth
interrupt hierarchy, which we are about to introduce.

No functionnal change yet.

Signed-off-by: Marc Zyngier 
---
 drivers/gpio/gpio-tegra186.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index 178e912..9500074 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -430,7 +430,18 @@ static int tegra186_irq_set_type(struct irq_data *data, 
unsigned int type)
else
irq_set_handler_locked(data, handle_edge_irq);
 
-   return irq_chip_set_type_parent(data, type);
+   if (data->parent_data)
+   return irq_chip_set_type_parent(data, type);
+
+   return 0;
+}
+
+static int tegra186_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+   if (data->parent_data)
+   return irq_chip_set_wake_parent(data, on);
+
+   return 0;
 }
 
 static void tegra186_gpio_irq(struct irq_desc *desc)
@@ -678,7 +689,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
gpio->intc.irq_mask = tegra186_irq_mask;
gpio->intc.irq_unmask = tegra186_irq_unmask;
gpio->intc.irq_set_type = tegra186_irq_set_type;
-   gpio->intc.irq_set_wake = irq_chip_set_wake_parent;
+   gpio->intc.irq_set_wake = tegra186_irq_set_wake;
 
irq = >gpio.irq;
irq->chip = >intc;


[tip: irq/core] genirq/irqdomain: Allow partial trimming of irq_data hierarchy

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 55567976629e58fde28fb70612ca73228271eef2
Gitweb:
https://git.kernel.org/tip/55567976629e58fde28fb70612ca73228271eef2
Author:Marc Zyngier 
AuthorDate:Tue, 06 Oct 2020 10:10:20 +01:00
Committer: Marc Zyngier 
CommitterDate: Sat, 10 Oct 2020 12:12:10 +01:00

genirq/irqdomain: Allow partial trimming of irq_data hierarchy

It appears that some HW is ugly enough that not all the interrupts
connected to a particular interrupt controller end up with the same
hierarchy depth (some of them are terminated early). This leaves
the irqchip hacker with only two choices, both equally bad:

- create discrete domain chains, one for each "hierarchy depth",
  which is very hard to maintain

- create fake hierarchy levels for the shallow paths, leading
  to all kind of problems (what are the safe hwirq values for these
  fake levels?)

Implement the ability to cut short a single interrupt hierarchy
from a level marked as being disconnected by using the new
irq_domain_disconnect_hierarchy() helper.

The irqdomain allocation code will then perform the trimming

Signed-off-by: Marc Zyngier 
---
 include/linux/irqdomain.h |   3 +-
 kernel/irq/irqdomain.c|  99 +++--
 2 files changed, 98 insertions(+), 4 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index b37350c..a52b095 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -509,6 +509,9 @@ extern void irq_domain_free_irqs_parent(struct irq_domain 
*domain,
unsigned int irq_base,
unsigned int nr_irqs);
 
+extern int irq_domain_disconnect_hierarchy(struct irq_domain *domain,
+  unsigned int virq);
+
 static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
 {
return domain->flags & IRQ_DOMAIN_FLAG_HIERARCHY;
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 76cd7eb..cf8b374 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1136,6 +1136,17 @@ static struct irq_data 
*irq_domain_insert_irq_data(struct irq_domain *domain,
return irq_data;
 }
 
+static void __irq_domain_free_hierarchy(struct irq_data *irq_data)
+{
+   struct irq_data *tmp;
+
+   while (irq_data) {
+   tmp = irq_data;
+   irq_data = irq_data->parent_data;
+   kfree(tmp);
+   }
+}
+
 static void irq_domain_free_irq_data(unsigned int virq, unsigned int nr_irqs)
 {
struct irq_data *irq_data, *tmp;
@@ -1147,12 +1158,83 @@ static void irq_domain_free_irq_data(unsigned int virq, 
unsigned int nr_irqs)
irq_data->parent_data = NULL;
irq_data->domain = NULL;
 
-   while (tmp) {
-   irq_data = tmp;
-   tmp = tmp->parent_data;
-   kfree(irq_data);
+   __irq_domain_free_hierarchy(tmp);
+   }
+}
+
+/**
+ * irq_domain_disconnect_hierarchy - Mark the first unused level of a hierarchy
+ * @domain:IRQ domain from which the hierarchy is to be disconnected
+ * @virq:  IRQ number where the hierarchy is to be trimmed
+ *
+ * Marks the @virq level belonging to @domain as disconnected.
+ * Returns -EINVAL if @virq doesn't have a valid irq_data pointing
+ * to @domain.
+ *
+ * Its only use is to be able to trim levels of hierarchy that do not
+ * have any real meaning for this interrupt, and that the driver marks
+ * as such from its .alloc() callback.
+ */
+int irq_domain_disconnect_hierarchy(struct irq_domain *domain,
+   unsigned int virq)
+{
+   struct irq_data *irqd;
+
+   irqd = irq_domain_get_irq_data(domain, virq);
+   if (!irqd)
+   return -EINVAL;
+
+   irqd->chip = ERR_PTR(-ENOTCONN);
+   return 0;
+}
+
+static int irq_domain_trim_hierarchy(unsigned int virq)
+{
+   struct irq_data *tail, *irqd, *irq_data;
+
+   irq_data = irq_get_irq_data(virq);
+   tail = NULL;
+
+   /* The first entry must have a valid irqchip */
+   if (!irq_data->chip || IS_ERR(irq_data->chip))
+   return -EINVAL;
+
+   /*
+* Validate that the irq_data chain is sane in the presence of
+* a hierarchy trimming marker.
+*/
+   for (irqd = irq_data->parent_data; irqd; irq_data = irqd, irqd = 
irqd->parent_data) {
+   /* Can't have a valid irqchip after a trim marker */
+   if (irqd->chip && tail)
+   return -EINVAL;
+
+   /* Can't have an empty irqchip before a trim marker */
+   if (!irqd->chip && !tail)
+   return -EINVAL;
+
+   if (IS_ERR(irqd->chip)) {
+   /* Only -ENOTCONN is a valid trim marker */
+   if (PTR_ERR(irqd->chip) != 

[tip: irq/core] irqchip/bcm2836: Configure mailbox interrupts as standard interrupts

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 0809ae724904c3c5dbdddf4169d48aac9c6fcdc8
Gitweb:
https://git.kernel.org/tip/0809ae724904c3c5dbdddf4169d48aac9c6fcdc8
Author:Marc Zyngier 
AuthorDate:Tue, 05 May 2020 12:59:04 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:27 +01:00

irqchip/bcm2836: Configure mailbox interrupts as standard interrupts

In order to switch the bcm2836 driver to privide standard interrupts
for IPIs, it first needs to stop lying about the way things work.

The mailbox interrupt is actually a multiplexer, with enough
bits to store 32 pending interrupts per CPU. So let's turn it
into a chained irqchip.

Once this is done, we can instanciate the corresponding IPIs,
and pass them to the architecture code.

Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-bcm2836.c | 151 +++--
 1 file changed, 125 insertions(+), 26 deletions(-)

diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c
index 2038693..85df6dd 100644
--- a/drivers/irqchip/irq-bcm2836.c
+++ b/drivers/irqchip/irq-bcm2836.c
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -89,12 +90,24 @@ static struct irq_chip bcm2836_arm_irqchip_gpu = {
.irq_unmask = bcm2836_arm_irqchip_unmask_gpu_irq,
 };
 
+static void bcm2836_arm_irqchip_dummy_op(struct irq_data *d)
+{
+}
+
+static struct irq_chip bcm2836_arm_irqchip_dummy = {
+   .name   = "bcm2836-dummy",
+   .irq_eoi= bcm2836_arm_irqchip_dummy_op,
+};
+
 static int bcm2836_map(struct irq_domain *d, unsigned int irq,
   irq_hw_number_t hw)
 {
struct irq_chip *chip;
 
switch (hw) {
+   case LOCAL_IRQ_MAILBOX0:
+   chip = _arm_irqchip_dummy;
+   break;
case LOCAL_IRQ_CNTPSIRQ:
case LOCAL_IRQ_CNTPNSIRQ:
case LOCAL_IRQ_CNTHPIRQ:
@@ -127,17 +140,7 @@ __exception_irq_entry 
bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
u32 stat;
 
stat = readl_relaxed(intc.base + LOCAL_IRQ_PENDING0 + 4 * cpu);
-   if (stat & BIT(LOCAL_IRQ_MAILBOX0)) {
-#ifdef CONFIG_SMP
-   void __iomem *mailbox0 = (intc.base +
- LOCAL_MAILBOX0_CLR0 + 16 * cpu);
-   u32 mbox_val = readl(mailbox0);
-   u32 ipi = ffs(mbox_val) - 1;
-
-   writel(1 << ipi, mailbox0);
-   handle_IPI(ipi, regs);
-#endif
-   } else if (stat) {
+   if (stat) {
u32 hwirq = ffs(stat) - 1;
 
handle_domain_irq(intc.domain, hwirq, regs);
@@ -145,8 +148,35 @@ __exception_irq_entry 
bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
 }
 
 #ifdef CONFIG_SMP
-static void bcm2836_arm_irqchip_send_ipi(const struct cpumask *mask,
-unsigned int ipi)
+static struct irq_domain *ipi_domain;
+
+static void bcm2836_arm_irqchip_handle_ipi(struct irq_desc *desc)
+{
+   struct irq_chip *chip = irq_desc_get_chip(desc);
+   int cpu = smp_processor_id();
+   u32 mbox_val;
+
+   chained_irq_enter(chip, desc);
+
+   mbox_val = readl_relaxed(intc.base + LOCAL_MAILBOX0_CLR0 + 16 * cpu);
+   if (mbox_val) {
+   int hwirq = ffs(mbox_val) - 1;
+   generic_handle_irq(irq_find_mapping(ipi_domain, hwirq));
+   }
+
+   chained_irq_exit(chip, desc);
+}
+
+static void bcm2836_arm_irqchip_ipi_eoi(struct irq_data *d)
+{
+   int cpu = smp_processor_id();
+
+   writel_relaxed(BIT(d->hwirq),
+  intc.base + LOCAL_MAILBOX0_CLR0 + 16 * cpu);
+}
+
+static void bcm2836_arm_irqchip_ipi_send_mask(struct irq_data *d,
+ const struct cpumask *mask)
 {
int cpu;
void __iomem *mailbox0_base = intc.base + LOCAL_MAILBOX0_SET0;
@@ -157,11 +187,45 @@ static void bcm2836_arm_irqchip_send_ipi(const struct 
cpumask *mask,
 */
smp_wmb();
 
-   for_each_cpu(cpu, mask) {
-   writel(1 << ipi, mailbox0_base + 16 * cpu);
+   for_each_cpu(cpu, mask)
+   writel_relaxed(BIT(d->hwirq), mailbox0_base + 16 * cpu);
+}
+
+static struct irq_chip bcm2836_arm_irqchip_ipi = {
+   .name   = "IPI",
+   .irq_eoi= bcm2836_arm_irqchip_ipi_eoi,
+   .ipi_send_mask  = bcm2836_arm_irqchip_ipi_send_mask,
+};
+
+static int bcm2836_arm_irqchip_ipi_alloc(struct irq_domain *d,
+unsigned int virq,
+unsigned int nr_irqs, void *args)
+{
+   int i;
+
+   for (i = 0; i < nr_irqs; i++) {
+   irq_set_percpu_devid(virq + i);
+   irq_domain_set_info(d, virq + i, i, _arm_irqchip_ipi,
+   d->host_data,
+   handle_percpu_devid_fasteoi_ipi,
+

[tip: irq/core] irqchip/gic-v3: Configure SGIs as standard interrupts

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 64b499d8df40dadb1818ad9f74c4546951b37a8f
Gitweb:
https://git.kernel.org/tip/64b499d8df40dadb1818ad9f74c4546951b37a8f
Author:Marc Zyngier 
AuthorDate:Sat, 25 Apr 2020 15:24:01 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:26 +01:00

irqchip/gic-v3: Configure SGIs as standard interrupts

Change the way we deal with GICv3 SGIs by turning them into proper
IRQs, and calling into the arch code to register the interrupt range
instead of a callback.

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic-v3.c | 94 ++-
 1 file changed, 51 insertions(+), 43 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index f7c99a3..84ceb63 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -36,6 +36,8 @@
 #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996(1ULL << 0)
 #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539  (1ULL << 1)
 
+#define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1)
+
 struct redist_region {
void __iomem*redist_base;
phys_addr_t phys_base;
@@ -383,7 +385,7 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
 {
u32 reg;
 
-   if (d->hwirq >= 8192) /* PPI/SPI only */
+   if (d->hwirq >= 8192) /* SGI/PPI/SPI only */
return -EINVAL;
 
switch (which) {
@@ -550,12 +552,12 @@ static int gic_set_type(struct irq_data *d, unsigned int 
type)
u32 offset, index;
int ret;
 
-   /* Interrupt configuration for SGIs can't be changed */
-   if (irq < 16)
-   return -EINVAL;
-
range = get_intid_range(d);
 
+   /* Interrupt configuration for SGIs can't be changed */
+   if (range == SGI_RANGE)
+   return type != IRQ_TYPE_EDGE_RISING ? -EINVAL : 0;
+
/* SPIs have restrictions on the supported types */
if ((range == SPI_RANGE || range == ESPI_RANGE) &&
type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
@@ -583,6 +585,9 @@ static int gic_set_type(struct irq_data *d, unsigned int 
type)
 
 static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
 {
+   if (get_intid_range(d) == SGI_RANGE)
+   return -EINVAL;
+
if (vcpu)
irqd_set_forwarded_to_vcpu(d);
else
@@ -657,38 +662,14 @@ static asmlinkage void __exception_irq_entry 
gic_handle_irq(struct pt_regs *regs
if ((irqnr >= 1020 && irqnr <= 1023))
return;
 
-   /* Treat anything but SGIs in a uniform way */
-   if (likely(irqnr > 15)) {
-   int err;
-
-   if (static_branch_likely(_deactivate_key))
-   gic_write_eoir(irqnr);
-   else
-   isb();
-
-   err = handle_domain_irq(gic_data.domain, irqnr, regs);
-   if (err) {
-   WARN_ONCE(true, "Unexpected interrupt received!\n");
-   gic_deactivate_unhandled(irqnr);
-   }
-   return;
-   }
-   if (irqnr < 16) {
+   if (static_branch_likely(_deactivate_key))
gic_write_eoir(irqnr);
-   if (static_branch_likely(_deactivate_key))
-   gic_write_dir(irqnr);
-#ifdef CONFIG_SMP
-   /*
-* Unlike GICv2, we don't need an smp_rmb() here.
-* The control dependency from gic_read_iar to
-* the ISB in gic_write_eoir is enough to ensure
-* that any shared data read by handle_IPI will
-* be read after the ACK.
-*/
-   handle_IPI(irqnr, regs);
-#else
-   WARN_ONCE(true, "Unexpected SGI received!\n");
-#endif
+   else
+   isb();
+
+   if (handle_domain_irq(gic_data.domain, irqnr, regs)) {
+   WARN_ONCE(true, "Unexpected interrupt received!\n");
+   gic_deactivate_unhandled(irqnr);
}
 }
 
@@ -1136,11 +1117,11 @@ static void gic_send_sgi(u64 cluster_id, u16 tlist, 
unsigned int irq)
gic_write_sgi1r(val);
 }
 
-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;
 
-   if (WARN_ON(irq >= 16))
+   if (WARN_ON(d->hwirq >= 16))
return;
 
/*
@@ -1154,7 +1135,7 @@ static void gic_raise_softirq(const struct cpumask *mask, 
unsigned int irq)
u16 tlist;
 
tlist = gic_compute_target_list(, mask, cluster_id);
-   gic_send_sgi(cluster_id, tlist, irq);
+   gic_send_sgi(cluster_id, tlist, d->hwirq);
}
 
/* Force the above writes to ICC_SGI1R_EL1 to be executed */
@@ -1163,10 +1144,24 @@ static void 

[tip: irq/core] irqchip/gic: Cleanup Franken-GIC handling

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 8594c3b85171b6f68e34e07b533ec2f1bf7fb065
Gitweb:
https://git.kernel.org/tip/8594c3b85171b6f68e34e07b533ec2f1bf7fb065
Author:Marc Zyngier 
AuthorDate:Tue, 15 Sep 2020 14:03:51 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:29 +01:00

irqchip/gic: Cleanup Franken-GIC handling

Introduce a static key identifying Samsung's unique creation, allowing
to replace the indirect call to compute the base addresses with
a simple test on the static key.

Faster, cheaper, negative diffstat.

Tested-by: Marek Szyprowski 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic.c | 41 +++---
 1 file changed, 12 insertions(+), 29 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 66671e1..30edcca 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -83,9 +83,6 @@ struct gic_chip_data {
 #endif
struct irq_domain *domain;
unsigned int gic_irqs;
-#ifdef CONFIG_GIC_NON_BANKED
-   void __iomem *(*get_base)(union gic_base *);
-#endif
 };
 
 #ifdef CONFIG_BL_SWITCHER
@@ -127,35 +124,27 @@ static struct gic_kvm_info gic_v2_kvm_info;
 static DEFINE_PER_CPU(u32, sgi_intid);
 
 #ifdef CONFIG_GIC_NON_BANKED
-static void __iomem *gic_get_percpu_base(union gic_base *base)
-{
-   return raw_cpu_read(*base->percpu_base);
-}
+static DEFINE_STATIC_KEY_FALSE(frankengic_key);
 
-static void __iomem *gic_get_common_base(union gic_base *base)
+static void enable_frankengic(void)
 {
-   return base->common_base;
+   static_branch_enable(_key);
 }
 
-static inline void __iomem *gic_data_dist_base(struct gic_chip_data *data)
+static inline void __iomem *__get_base(union gic_base *base)
 {
-   return data->get_base(>dist_base);
-}
+   if (static_branch_unlikely(_key))
+   return raw_cpu_read(*base->percpu_base);
 
-static inline void __iomem *gic_data_cpu_base(struct gic_chip_data *data)
-{
-   return data->get_base(>cpu_base);
+   return base->common_base;
 }
 
-static inline void gic_set_base_accessor(struct gic_chip_data *data,
-void __iomem *(*f)(union gic_base *))
-{
-   data->get_base = f;
-}
+#define gic_data_dist_base(d)  __get_base(&(d)->dist_base)
+#define gic_data_cpu_base(d)   __get_base(&(d)->cpu_base)
 #else
 #define gic_data_dist_base(d)  ((d)->dist_base.common_base)
 #define gic_data_cpu_base(d)   ((d)->cpu_base.common_base)
-#define gic_set_base_accessor(d, f)
+#define enable_frankengic()do { } while(0)
 #endif
 
 static inline void __iomem *gic_dist_base(struct irq_data *d)
@@ -307,7 +296,7 @@ static int gic_set_type(struct irq_data *d, unsigned int 
type)
 
/* Interrupt configuration for SGIs can't be changed */
if (gicirq < 16)
-   return type == IRQ_TYPE_EDGE_RISING ? 0 : -EINVAL;
+   return type != IRQ_TYPE_EDGE_RISING ? -EINVAL : 0;
 
/* SPIs have restrictions on the supported types */
if (gicirq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
@@ -720,11 +709,6 @@ static int gic_notifier(struct notifier_block *self, 
unsigned long cmd,void *v)
int i;
 
for (i = 0; i < CONFIG_ARM_GIC_MAX_NR; i++) {
-#ifdef CONFIG_GIC_NON_BANKED
-   /* Skip over unused GICs */
-   if (!gic_data[i].get_base)
-   continue;
-#endif
switch (cmd) {
case CPU_PM_ENTER:
gic_cpu_save(_data[i]);
@@ -1165,7 +1149,7 @@ static int gic_init_bases(struct gic_chip_data *gic,
gic->raw_cpu_base + offset;
}
 
-   gic_set_base_accessor(gic, gic_get_percpu_base);
+   enable_frankengic();
} else {
/* Normal, sane GIC... */
WARN(gic->percpu_offset,
@@ -1173,7 +1157,6 @@ static int gic_init_bases(struct gic_chip_data *gic,
 gic->percpu_offset);
gic->dist_base.common_base = gic->raw_dist_base;
gic->cpu_base.common_base = gic->raw_cpu_base;
-   gic_set_base_accessor(gic, gic_get_common_base);
}
 
/*


[tip: irq/core] arm64: Kill __smp_cross_call and co

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 5cebfd2d47c214f69d918e3d34ad183c061eddb2
Gitweb:
https://git.kernel.org/tip/5cebfd2d47c214f69d918e3d34ad183c061eddb2
Author:Marc Zyngier 
AuthorDate:Sat, 09 May 2020 14:00:23 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:28 +01:00

arm64: Kill __smp_cross_call and co

The old IPI registration interface is now unused on arm64, so let's
get rid of it.

Reviewed-by: Valentin Schneider 
Acked-by: Catalin Marinas 
Signed-off-by: Marc Zyngier 
---
 arch/arm64/include/asm/irq_work.h |  4 +---
 arch/arm64/include/asm/smp.h  | 12 +-
 arch/arm64/kernel/smp.c   | 38 +-
 3 files changed, 8 insertions(+), 46 deletions(-)

diff --git a/arch/arm64/include/asm/irq_work.h 
b/arch/arm64/include/asm/irq_work.h
index 8a1ef19..a102028 100644
--- a/arch/arm64/include/asm/irq_work.h
+++ b/arch/arm64/include/asm/irq_work.h
@@ -2,11 +2,9 @@
 #ifndef __ASM_IRQ_WORK_H
 #define __ASM_IRQ_WORK_H
 
-#include 
-
 static inline bool arch_irq_work_has_interrupt(void)
 {
-   return !!__smp_cross_call;
+   return true;
 }
 
 #endif /* __ASM_IRQ_WORK_H */
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 57c5db1..c298ad0 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -61,24 +61,12 @@ struct seq_file;
 extern void show_ipi_list(struct seq_file *p, int prec);
 
 /*
- * Called from C code, this handles an IPI.
- */
-extern void handle_IPI(int ipinr, struct pt_regs *regs);
-
-/*
  * Discover the set of possible CPUs and determine their
  * SMP operations.
  */
 extern void smp_init_cpus(void);
 
 /*
- * Provide a function to raise an IPI cross call on CPUs in callmap.
- */
-extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));
-
-extern void (*__smp_cross_call)(const struct cpumask *, unsigned int);
-
-/*
  * Register IPI interrupts with the arch SMP code
  */
 extern void set_smp_ipi_range(int ipi_base, int nr_ipi);
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 00c9db1..58fb155 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -782,13 +782,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
 }
 
-void (*__smp_cross_call)(const struct cpumask *, unsigned int);
-
-void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned 
int))
-{
-   __smp_cross_call = fn;
-}
-
 static const char *ipi_types[NR_IPI] __tracepoint_string = {
 #define S(x,s) [x] = s
S(IPI_RESCHEDULE, "Rescheduling interrupts"),
@@ -800,11 +793,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = 
{
S(IPI_WAKEUP, "CPU wake-up interrupts"),
 };
 
-static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
-{
-   trace_ipi_raise(target, ipi_types[ipinr]);
-   __smp_cross_call(target, ipinr);
-}
+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr);
 
 void show_ipi_list(struct seq_file *p, int prec)
 {
@@ -851,8 +840,7 @@ void arch_send_wakeup_ipi_mask(const struct cpumask *mask)
 #ifdef CONFIG_IRQ_WORK
 void arch_irq_work_raise(void)
 {
-   if (__smp_cross_call)
-   smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
+   smp_cross_call(cpumask_of(smp_processor_id()), IPI_IRQ_WORK);
 }
 #endif
 
@@ -959,34 +947,23 @@ static void do_handle_IPI(int ipinr)
trace_ipi_exit_rcuidle(ipi_types[ipinr]);
 }
 
-/* Legacy version, should go away once all irqchips have been converted */
-void handle_IPI(int ipinr, struct pt_regs *regs)
-{
-   struct pt_regs *old_regs = set_irq_regs(regs);
-
-   irq_enter();
-   do_handle_IPI(ipinr);
-   irq_exit();
-
-   set_irq_regs(old_regs);
-}
-
 static irqreturn_t ipi_handler(int irq, void *data)
 {
do_handle_IPI(irq - ipi_irq_base);
return IRQ_HANDLED;
 }
 
-static void ipi_send(const struct cpumask *target, unsigned int ipi)
+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
 {
-   __ipi_send_mask(ipi_desc[ipi], target);
+   trace_ipi_raise(target, ipi_types[ipinr]);
+   __ipi_send_mask(ipi_desc[ipinr], target);
 }
 
 static void ipi_setup(int cpu)
 {
int i;
 
-   if (!ipi_irq_base)
+   if (WARN_ON_ONCE(!ipi_irq_base))
return;
 
for (i = 0; i < nr_ipi; i++)
@@ -997,7 +974,7 @@ static void ipi_teardown(int cpu)
 {
int i;
 
-   if (!ipi_irq_base)
+   if (WARN_ON_ONCE(!ipi_irq_base))
return;
 
for (i = 0; i < nr_ipi; i++)
@@ -1023,7 +1000,6 @@ void __init set_smp_ipi_range(int ipi_base, int n)
}
 
ipi_irq_base = ipi_base;
-   __smp_cross_call = ipi_send;
 
/* Setup the boot CPU immediately */
ipi_setup(smp_processor_id());


[tip: irq/core] ARM: Kill __smp_cross_call and co

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 8aa837cb7a032884c787b15de81f7d9de8af0869
Gitweb:
https://git.kernel.org/tip/8aa837cb7a032884c787b15de81f7d9de8af0869
Author:Marc Zyngier 
AuthorDate:Mon, 22 Jun 2020 22:15:54 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:28 +01:00

ARM: Kill __smp_cross_call and co

The old IPI registration interface is now unused on arm, so let's
get rid of it.

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 arch/arm/include/asm/smp.h |  6 --
 arch/arm/kernel/smp.c  | 26 +++---
 2 files changed, 7 insertions(+), 25 deletions(-)

diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 0e29730..0ca55a6 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -39,12 +39,6 @@ void handle_IPI(int ipinr, struct pt_regs *regs);
  */
 extern void smp_init_cpus(void);
 
-
-/*
- * Provide a function to raise an IPI cross call on CPUs in callmap.
- */
-extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));
-
 /*
  * Register IPI interrupts with the arch SMP code
  */
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index f21f784..d51e649 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -511,14 +511,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
}
 }
 
-static void (*__smp_cross_call)(const struct cpumask *, unsigned int);
-
-void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned 
int))
-{
-   if (!__smp_cross_call)
-   __smp_cross_call = fn;
-}
-
 static const char *ipi_types[NR_IPI] __tracepoint_string = {
 #define S(x,s) [x] = s
S(IPI_WAKEUP, "CPU wakeup interrupts"),
@@ -530,11 +522,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = 
{
S(IPI_COMPLETION, "completion interrupts"),
 };
 
-static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
-{
-   trace_ipi_raise_rcuidle(target, ipi_types[ipinr]);
-   __smp_cross_call(target, ipinr);
-}
+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr);
 
 void show_ipi_list(struct seq_file *p, int prec)
 {
@@ -713,16 +701,17 @@ static irqreturn_t ipi_handler(int irq, void *data)
return IRQ_HANDLED;
 }
 
-static void ipi_send(const struct cpumask *target, unsigned int ipi)
+static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
 {
-   __ipi_send_mask(ipi_desc[ipi], target);
+   trace_ipi_raise_rcuidle(target, ipi_types[ipinr]);
+   __ipi_send_mask(ipi_desc[ipinr], target);
 }
 
 static void ipi_setup(int cpu)
 {
int i;
 
-   if (!ipi_irq_base)
+   if (WARN_ON_ONCE(!ipi_irq_base))
return;
 
for (i = 0; i < nr_ipi; i++)
@@ -733,7 +722,7 @@ static void ipi_teardown(int cpu)
 {
int i;
 
-   if (!ipi_irq_base)
+   if (WARN_ON_ONCE(!ipi_irq_base))
return;
 
for (i = 0; i < nr_ipi; i++)
@@ -759,7 +748,6 @@ void __init set_smp_ipi_range(int ipi_base, int n)
}
 
ipi_irq_base = ipi_base;
-   set_smp_cross_call(ipi_send);
 
/* Setup the boot CPU immediately */
ipi_setup(smp_processor_id());
@@ -872,7 +860,7 @@ core_initcall(register_cpufreq_notifier);
 
 static void raise_nmi(cpumask_t *mask)
 {
-   __smp_cross_call(mask, IPI_CPU_BACKTRACE);
+   __ipi_send_mask(ipi_desc[IPI_CPU_BACKTRACE], mask);
 }
 
 void arch_trigger_cpumask_backtrace(const cpumask_t *mask, bool exclude_self)


[tip: irq/core] ARM: Remove custom IRQ stat accounting

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 5ebf353af22c89d18964bb3b877a95200dfe07b9
Gitweb:
https://git.kernel.org/tip/5ebf353af22c89d18964bb3b877a95200dfe07b9
Author:Marc Zyngier 
AuthorDate:Tue, 23 Jun 2020 21:15:00 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:28 +01:00

ARM: Remove custom IRQ stat accounting

Let's switch the arm code to the core accounting, which already
does everything we need.

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 arch/arm/include/asm/hardirq.h | 17 -
 arch/arm/kernel/irq.c  |  1 -
 arch/arm/kernel/smp.c  | 21 +
 3 files changed, 5 insertions(+), 34 deletions(-)

diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h
index 7a88f16..b95848e 100644
--- a/arch/arm/include/asm/hardirq.h
+++ b/arch/arm/include/asm/hardirq.h
@@ -6,29 +6,12 @@
 #include 
 #include 
 
-/* number of IPIS _not_ including IPI_CPU_BACKTRACE */
-#define NR_IPI 7
-
 typedef struct {
unsigned int __softirq_pending;
-#ifdef CONFIG_SMP
-   unsigned int ipi_irqs[NR_IPI];
-#endif
 } cacheline_aligned irq_cpustat_t;
 
 #include  /* Standard mappings for irq_cpustat_t above */
 
-#define __inc_irq_stat(cpu, member)__IRQ_STAT(cpu, member)++
-#define __get_irq_stat(cpu, member)__IRQ_STAT(cpu, member)
-
-#ifdef CONFIG_SMP
-u64 smp_irq_stat_cpu(unsigned int cpu);
-#else
-#define smp_irq_stat_cpu(cpu)  0
-#endif
-
-#define arch_irq_stat_cpu  smp_irq_stat_cpu
-
 #define __ARCH_IRQ_EXIT_IRQS_DISABLED  1
 
 #endif /* __ASM_HARDIRQ_H */
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index ee51403..698b6f6 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -18,7 +18,6 @@
  *  IRQ's are in fact implemented a bit like signal handlers for the kernel.
  *  Naturally it's not a 1:1 relation, but there are similarities.
  */
-#include 
 #include 
 #include 
 #include 
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index d51e649..00327fa 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -65,6 +66,7 @@ enum ipi_msg_type {
IPI_CPU_STOP,
IPI_IRQ_WORK,
IPI_COMPLETION,
+   NR_IPI,
/*
 * CPU_BACKTRACE is special and not included in NR_IPI
 * or tracable with trace_ipi_*
@@ -529,27 +531,16 @@ void show_ipi_list(struct seq_file *p, int prec)
unsigned int cpu, i;
 
for (i = 0; i < NR_IPI; i++) {
+   unsigned int irq = irq_desc_get_irq(ipi_desc[i]);
seq_printf(p, "%*s%u: ", prec - 1, "IPI", i);
 
for_each_online_cpu(cpu)
-   seq_printf(p, "%10u ",
-  __get_irq_stat(cpu, ipi_irqs[i]));
+   seq_printf(p, "%10u ", kstat_irqs_cpu(irq, cpu));
 
seq_printf(p, " %s\n", ipi_types[i]);
}
 }
 
-u64 smp_irq_stat_cpu(unsigned int cpu)
-{
-   u64 sum = 0;
-   int i;
-
-   for (i = 0; i < NR_IPI; i++)
-   sum += __get_irq_stat(cpu, ipi_irqs[i]);
-
-   return sum;
-}
-
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 {
smp_cross_call(mask, IPI_CALL_FUNC);
@@ -630,10 +621,8 @@ static void do_handle_IPI(int ipinr)
 {
unsigned int cpu = smp_processor_id();
 
-   if ((unsigned)ipinr < NR_IPI) {
+   if ((unsigned)ipinr < NR_IPI)
trace_ipi_entry_rcuidle(ipi_types[ipinr]);
-   __inc_irq_stat(cpu, ipi_irqs[ipinr]);
-   }
 
switch (ipinr) {
case IPI_WAKEUP:


[tip: irq/core] irqchip/bcm2836: Provide mask/unmask dummy methods for IPIs

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: c3330399931be38ce459e82bf7dea140338ae43f
Gitweb:
https://git.kernel.org/tip/c3330399931be38ce459e82bf7dea140338ae43f
Author:Marc Zyngier 
AuthorDate:Mon, 14 Sep 2020 17:21:16 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:28 +01:00

irqchip/bcm2836: Provide mask/unmask dummy methods for IPIs

Although it doesn't seem possible to disable individual mailbox
interrupts, we still need to provide some callbacks.

Fixes: 09eb672ce4fb ("irqchip/bcm2836: Configure mailbox interrupts as standard 
interrupts")
Reported-by: Marek Szyprowski 
Tested-by: Marek Szyprowski 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-bcm2836.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c
index 85df6dd..97838eb 100644
--- a/drivers/irqchip/irq-bcm2836.c
+++ b/drivers/irqchip/irq-bcm2836.c
@@ -193,6 +193,8 @@ static void bcm2836_arm_irqchip_ipi_send_mask(struct 
irq_data *d,
 
 static struct irq_chip bcm2836_arm_irqchip_ipi = {
.name   = "IPI",
+   .irq_mask   = bcm2836_arm_irqchip_dummy_op,
+   .irq_unmask = bcm2836_arm_irqchip_dummy_op,
.irq_eoi= bcm2836_arm_irqchip_ipi_eoi,
.ipi_send_mask  = bcm2836_arm_irqchip_ipi_send_mask,
 };


[tip: irq/core] ARM: Allow IPIs to be handled as normal interrupts

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 56afcd3dbd1995c526bfbd920cebde6158b22c4a
Gitweb:
https://git.kernel.org/tip/56afcd3dbd1995c526bfbd920cebde6158b22c4a
Author:Marc Zyngier 
AuthorDate:Tue, 23 Jun 2020 20:38:41 +01:00
Committer: Marc Zyngier 
CommitterDate: Sun, 13 Sep 2020 17:05:39 +01:00

ARM: Allow IPIs to be handled as normal interrupts

In order to deal with IPIs as normal interrupts, let's add
a new way to register them with the architecture code.

set_smp_ipi_range() takes a range of interrupts, and allows
the arch code to request them as if the were normal interrupts.
A standard handler is then called by the core IRQ code to deal
with the IPI.

This means that we don't need to call irq_enter/irq_exit, and
that we don't need to deal with set_irq_regs either. So let's
move the dispatcher into its own function, and leave handle_IPI()
as a compatibility function.

On the sending side, let's make use of ipi_send_mask, which
already exists for this purpose.

One of the major difference is that we end up, in some cases
(such as when performing IRQ time accounting on the scheduler
IPI), end up with nested irq_enter()/irq_exit() pairs.
Other than the (relatively small) overhead, there should be
no consequences to it (these pairs are designed to nest
correctly, and the accounting shouldn't be off).

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 arch/arm/Kconfig   |   1 +-
 arch/arm/include/asm/smp.h |   5 ++-
 arch/arm/kernel/smp.c  |  99 ++--
 3 files changed, 89 insertions(+), 16 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e00d94b..e67ef15 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -49,6 +49,7 @@ config ARM
select GENERIC_ARCH_TOPOLOGY if ARM_CPU_TOPOLOGY
select GENERIC_ATOMIC64 if CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+   select GENERIC_IRQ_IPI if SMP
select GENERIC_CPU_AUTOPROBE
select GENERIC_EARLY_IOREMAP
select GENERIC_IDLE_POLL_SETUP
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index a91f21e..0e29730 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -46,6 +46,11 @@ extern void smp_init_cpus(void);
 extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));
 
 /*
+ * Register IPI interrupts with the arch SMP code
+ */
+extern void set_smp_ipi_range(int ipi_base, int nr_ipi);
+
+/*
  * Called from platform specific assembly code, this is the
  * secondary CPU entry point.
  */
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 5d9da61..f21f784 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -69,14 +69,22 @@ enum ipi_msg_type {
 * CPU_BACKTRACE is special and not included in NR_IPI
 * or tracable with trace_ipi_*
 */
-   IPI_CPU_BACKTRACE,
+   IPI_CPU_BACKTRACE = NR_IPI,
/*
 * SGI8-15 can be reserved by secure firmware, and thus may
 * not be usable by the kernel. Please keep the above limited
 * to at most 8 entries.
 */
+   MAX_IPI
 };
 
+static int ipi_irq_base __read_mostly;
+static int nr_ipi __read_mostly = NR_IPI;
+static struct irq_desc *ipi_desc[MAX_IPI] __read_mostly;
+
+static void ipi_setup(int cpu);
+static void ipi_teardown(int cpu);
+
 static DECLARE_COMPLETION(cpu_running);
 
 static struct smp_operations smp_ops __ro_after_init;
@@ -247,6 +255,7 @@ int __cpu_disable(void)
 * and we must not schedule until we're ready to give up the cpu.
 */
set_cpu_online(cpu, false);
+   ipi_teardown(cpu);
 
/*
 * OK - migrate IRQs away from this CPU
@@ -422,6 +431,8 @@ asmlinkage void secondary_start_kernel(void)
 
notify_cpu_starting(cpu);
 
+   ipi_setup(cpu);
+
calibrate_delay();
 
smp_store_cpu_info(cpu);
@@ -627,10 +638,9 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, 
struct pt_regs *regs)
handle_IPI(ipinr, regs);
 }
 
-void handle_IPI(int ipinr, struct pt_regs *regs)
+static void do_handle_IPI(int ipinr)
 {
unsigned int cpu = smp_processor_id();
-   struct pt_regs *old_regs = set_irq_regs(regs);
 
if ((unsigned)ipinr < NR_IPI) {
trace_ipi_entry_rcuidle(ipi_types[ipinr]);
@@ -643,9 +653,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
case IPI_TIMER:
-   irq_enter();
tick_receive_broadcast();
-   irq_exit();
break;
 #endif
 
@@ -654,36 +662,26 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
break;
 
case IPI_CALL_FUNC:
-   irq_enter();
generic_smp_call_function_interrupt();
-   irq_exit();
break;
 
case IPI_CPU_STOP:

[tip: irq/core] irqchip/gic-v3: Describe the SGI range

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 70a29c32cf7909e96a469ae71d88b2c0fbcbd767
Gitweb:
https://git.kernel.org/tip/70a29c32cf7909e96a469ae71d88b2c0fbcbd767
Author:Marc Zyngier 
AuthorDate:Sat, 25 Apr 2020 15:11:20 +01:00
Committer: Marc Zyngier 
CommitterDate: Sun, 13 Sep 2020 17:05:39 +01:00

irqchip/gic-v3: Describe the SGI range

As we are about to start making use of SGIs in a more conventional
way, let's describe it is the GICv3 list of interrupt types.

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic-v3.c | 18 +++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 850842f..f7c99a3 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -112,6 +112,7 @@ static DEFINE_PER_CPU(bool, has_rss);
 #define DEFAULT_PMR_VALUE  0xf0
 
 enum gic_intid_range {
+   SGI_RANGE,
PPI_RANGE,
SPI_RANGE,
EPPI_RANGE,
@@ -123,6 +124,8 @@ enum gic_intid_range {
 static enum gic_intid_range __get_intid_range(irq_hw_number_t hwirq)
 {
switch (hwirq) {
+   case 0 ... 15:
+   return SGI_RANGE;
case 16 ... 31:
return PPI_RANGE;
case 32 ... 1019:
@@ -148,15 +151,22 @@ static inline unsigned int gic_irq(struct irq_data *d)
return d->hwirq;
 }
 
-static inline int gic_irq_in_rdist(struct irq_data *d)
+static inline bool gic_irq_in_rdist(struct irq_data *d)
 {
-   enum gic_intid_range range = get_intid_range(d);
-   return range == PPI_RANGE || range == EPPI_RANGE;
+   switch (get_intid_range(d)) {
+   case SGI_RANGE:
+   case PPI_RANGE:
+   case EPPI_RANGE:
+   return true;
+   default:
+   return false;
+   }
 }
 
 static inline void __iomem *gic_dist_base(struct irq_data *d)
 {
switch (get_intid_range(d)) {
+   case SGI_RANGE:
case PPI_RANGE:
case EPPI_RANGE:
/* SGI+PPI -> SGI_base for this CPU */
@@ -253,6 +263,7 @@ static void gic_enable_redist(bool enable)
 static u32 convert_offset_index(struct irq_data *d, u32 offset, u32 *index)
 {
switch (get_intid_range(d)) {
+   case SGI_RANGE:
case PPI_RANGE:
case SPI_RANGE:
*index = d->hwirq;
@@ -1277,6 +1288,7 @@ static int gic_irq_domain_map(struct irq_domain *d, 
unsigned int irq,
chip = _eoimode1_chip;
 
switch (__get_intid_range(hw)) {
+   case SGI_RANGE:
case PPI_RANGE:
case EPPI_RANGE:
irq_set_percpu_devid(irq);


[tip: irq/core] genirq: Add fasteoi IPI flow

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: c5e5ec033c4ab25c53f1fd217849e75deb0bf7bf
Gitweb:
https://git.kernel.org/tip/c5e5ec033c4ab25c53f1fd217849e75deb0bf7bf
Author:Marc Zyngier 
AuthorDate:Tue, 19 May 2020 10:41:00 +01:00
Committer: Marc Zyngier 
CommitterDate: Sun, 13 Sep 2020 17:04:38 +01:00

genirq: Add fasteoi IPI flow

For irqchips using the fasteoi flow, IPIs are a bit special.
They need to be EOI'd early (before calling the handler), as
funny things may happen in the handler (they do not necessarily
behave like a normal interrupt).

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 include/linux/irq.h |  1 +
 kernel/irq/chip.c   | 27 +++
 2 files changed, 28 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 1b7f4df..57205bb 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -634,6 +634,7 @@ static inline int irq_set_parent(int irq, int parent_irq)
  */
 extern void handle_level_irq(struct irq_desc *desc);
 extern void handle_fasteoi_irq(struct irq_desc *desc);
+extern void handle_percpu_devid_fasteoi_ipi(struct irq_desc *desc);
 extern void handle_edge_irq(struct irq_desc *desc);
 extern void handle_edge_eoi_irq(struct irq_desc *desc);
 extern void handle_simple_irq(struct irq_desc *desc);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 857f5f4..bed517d 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -945,6 +945,33 @@ void handle_percpu_devid_irq(struct irq_desc *desc)
 }
 
 /**
+ * handle_percpu_devid_fasteoi_ipi - Per CPU local IPI handler with per cpu
+ *  dev ids
+ * @desc:  the interrupt description structure for this irq
+ *
+ * The biggest difference with the IRQ version is that the interrupt is
+ * EOIed early, as the IPI could result in a context switch, and we need to
+ * make sure the IPI can fire again. We also assume that the arch code has
+ * registered an action. If not, we are positively doomed.
+ */
+void handle_percpu_devid_fasteoi_ipi(struct irq_desc *desc)
+{
+   struct irq_chip *chip = irq_desc_get_chip(desc);
+   struct irqaction *action = desc->action;
+   unsigned int irq = irq_desc_get_irq(desc);
+   irqreturn_t res;
+
+   __kstat_incr_irqs_this_cpu(desc);
+
+   if (chip->irq_eoi)
+   chip->irq_eoi(>irq_data);
+
+   trace_irq_handler_entry(irq, action);
+   res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id));
+   trace_irq_handler_exit(irq, action, res);
+}
+
+/**
  * handle_percpu_devid_fasteoi_nmi - Per CPU local NMI handler with per cpu
  *  dev ids
  * @desc:  the interrupt description structure for this irq


[tip: irq/core] genirq: Allow interrupts to be excluded from /proc/interrupts

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 83cfac95c01817819c2a51f0931d798d851f8a08
Gitweb:
https://git.kernel.org/tip/83cfac95c01817819c2a51f0931d798d851f8a08
Author:Marc Zyngier 
AuthorDate:Tue, 19 May 2020 14:58:13 +01:00
Committer: Marc Zyngier 
CommitterDate: Sun, 13 Sep 2020 17:04:38 +01:00

genirq: Allow interrupts to be excluded from /proc/interrupts

A number of architectures implement IPI statistics directly,
duplicating the core kstat_irqs accounting. As we move IPIs to
being actual IRQs, we would end-up with a confusing display
in /proc/interrupts (where the IPIs would appear twice).

In order to solve this, allow interrupts to be flagged as
"hidden", which excludes them from /proc/interrupts.

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 include/linux/irq.h   | 4 +++-
 kernel/irq/debugfs.c  | 1 +
 kernel/irq/proc.c | 2 +-
 kernel/irq/settings.h | 7 +++
 4 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 57205bb..63b9d96 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -71,6 +71,7 @@ enum irqchip_irq_state;
  *   it from the spurious interrupt detection
  *   mechanism and from core side polling.
  * IRQ_DISABLE_UNLAZY  - Disable lazy irq disable
+ * IRQ_HIDDEN  - Don't show up in /proc/interrupts
  */
 enum {
IRQ_TYPE_NONE   = 0x,
@@ -97,13 +98,14 @@ enum {
IRQ_PER_CPU_DEVID   = (1 << 17),
IRQ_IS_POLLED   = (1 << 18),
IRQ_DISABLE_UNLAZY  = (1 << 19),
+   IRQ_HIDDEN  = (1 << 20),
 };
 
 #define IRQF_MODIFY_MASK   \
(IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
 IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \
 IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID | \
-IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY)
+IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY | IRQ_HIDDEN)
 
 #define IRQ_NO_BALANCING_MASK  (IRQ_PER_CPU | IRQ_NO_BALANCING)
 
diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c
index b95ff5d..acabc0c 100644
--- a/kernel/irq/debugfs.c
+++ b/kernel/irq/debugfs.c
@@ -136,6 +136,7 @@ static const struct irq_bit_descr irqdesc_states[] = {
BIT_MASK_DESCR(_IRQ_PER_CPU_DEVID),
BIT_MASK_DESCR(_IRQ_IS_POLLED),
BIT_MASK_DESCR(_IRQ_DISABLE_UNLAZY),
+   BIT_MASK_DESCR(_IRQ_HIDDEN),
 };
 
 static const struct irq_bit_descr irqdesc_istates[] = {
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 32c071d..72513ed 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -485,7 +485,7 @@ int show_interrupts(struct seq_file *p, void *v)
 
rcu_read_lock();
desc = irq_to_desc(i);
-   if (!desc)
+   if (!desc || irq_settings_is_hidden(desc))
goto outsparse;
 
if (desc->kstat_irqs)
diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h
index e43795c..403378b 100644
--- a/kernel/irq/settings.h
+++ b/kernel/irq/settings.h
@@ -17,6 +17,7 @@ enum {
_IRQ_PER_CPU_DEVID  = IRQ_PER_CPU_DEVID,
_IRQ_IS_POLLED  = IRQ_IS_POLLED,
_IRQ_DISABLE_UNLAZY = IRQ_DISABLE_UNLAZY,
+   _IRQ_HIDDEN = IRQ_HIDDEN,
_IRQF_MODIFY_MASK   = IRQF_MODIFY_MASK,
 };
 
@@ -31,6 +32,7 @@ enum {
 #define IRQ_PER_CPU_DEVID  GOT_YOU_MORON
 #define IRQ_IS_POLLED  GOT_YOU_MORON
 #define IRQ_DISABLE_UNLAZY GOT_YOU_MORON
+#define IRQ_HIDDEN GOT_YOU_MORON
 #undef IRQF_MODIFY_MASK
 #define IRQF_MODIFY_MASK   GOT_YOU_MORON
 
@@ -167,3 +169,8 @@ static inline void irq_settings_clr_disable_unlazy(struct 
irq_desc *desc)
 {
desc->status_use_accessors &= ~_IRQ_DISABLE_UNLAZY;
 }
+
+static inline bool irq_settings_is_hidden(struct irq_desc *desc)
+{
+   return desc->status_use_accessors & _IRQ_HIDDEN;
+}


[tip: irq/core] arm64: Allow IPIs to be handled as normal interrupts

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: d3afc7f12987581eb0d1215b518d719fb9d762da
Gitweb:
https://git.kernel.org/tip/d3afc7f12987581eb0d1215b518d719fb9d762da
Author:Marc Zyngier 
AuthorDate:Sat, 25 Apr 2020 15:03:47 +01:00
Committer: Marc Zyngier 
CommitterDate: Sun, 13 Sep 2020 17:05:24 +01:00

arm64: Allow IPIs to be handled as normal interrupts

In order to deal with IPIs as normal interrupts, let's add
a new way to register them with the architecture code.

set_smp_ipi_range() takes a range of interrupts, and allows
the arch code to request them as if the were normal interrupts.
A standard handler is then called by the core IRQ code to deal
with the IPI.

This means that we don't need to call irq_enter/irq_exit, and
that we don't need to deal with set_irq_regs either. So let's
move the dispatcher into its own function, and leave handle_IPI()
as a compatibility function.

On the sending side, let's make use of ipi_send_mask, which
already exists for this purpose.

One of the major difference is that we end up, in some cases
(such as when performing IRQ time accounting on the scheduler
IPI), end up with nested irq_enter()/irq_exit() pairs.
Other than the (relatively small) overhead, there should be
no consequences to it (these pairs are designed to nest
correctly, and the accounting shouldn't be off).

Reviewed-by: Valentin Schneider 
Acked-by: Catalin Marinas 
Signed-off-by: Marc Zyngier 
---
 arch/arm64/Kconfig   |  1 +-
 arch/arm64/include/asm/smp.h |  5 ++-
 arch/arm64/kernel/smp.c  | 93 ++-
 3 files changed, 87 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6d23283..d0fdbe5 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -106,6 +106,7 @@ config ARM64
select GENERIC_CPU_VULNERABILITIES
select GENERIC_EARLY_IOREMAP
select GENERIC_IDLE_POLL_SETUP
+   select GENERIC_IRQ_IPI
select GENERIC_IRQ_MULTI_HANDLER
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 0eadbf9..57c5db1 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -79,6 +79,11 @@ extern void set_smp_cross_call(void (*)(const struct cpumask 
*, unsigned int));
 extern void (*__smp_cross_call)(const struct cpumask *, unsigned int);
 
 /*
+ * Register IPI interrupts with the arch SMP code
+ */
+extern void set_smp_ipi_range(int ipi_base, int nr_ipi);
+
+/*
  * Called from the secondary holding pen, this is the secondary CPU entry 
point.
  */
 asmlinkage void secondary_start_kernel(void);
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 355ee9e..00c9db1 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -75,6 +75,13 @@ enum ipi_msg_type {
IPI_WAKEUP
 };
 
+static int ipi_irq_base __read_mostly;
+static int nr_ipi __read_mostly = NR_IPI;
+static struct irq_desc *ipi_desc[NR_IPI] __read_mostly;
+
+static void ipi_setup(int cpu);
+static void ipi_teardown(int cpu);
+
 #ifdef CONFIG_HOTPLUG_CPU
 static int op_cpu_kill(unsigned int cpu);
 #else
@@ -237,6 +244,8 @@ asmlinkage notrace void secondary_start_kernel(void)
 */
notify_cpu_starting(cpu);
 
+   ipi_setup(cpu);
+
store_cpu_topology(cpu);
numa_add_cpu(cpu);
 
@@ -302,6 +311,7 @@ int __cpu_disable(void)
 * and we must not schedule until we're ready to give up the cpu.
 */
set_cpu_online(cpu, false);
+   ipi_teardown(cpu);
 
/*
 * OK - migrate IRQs away from this CPU
@@ -890,10 +900,9 @@ static void ipi_cpu_crash_stop(unsigned int cpu, struct 
pt_regs *regs)
 /*
  * Main handler for inter-processor interrupts
  */
-void handle_IPI(int ipinr, struct pt_regs *regs)
+static void do_handle_IPI(int ipinr)
 {
unsigned int cpu = smp_processor_id();
-   struct pt_regs *old_regs = set_irq_regs(regs);
 
if ((unsigned)ipinr < NR_IPI) {
trace_ipi_entry_rcuidle(ipi_types[ipinr]);
@@ -906,21 +915,16 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
break;
 
case IPI_CALL_FUNC:
-   irq_enter();
generic_smp_call_function_interrupt();
-   irq_exit();
break;
 
case IPI_CPU_STOP:
-   irq_enter();
local_cpu_stop();
-   irq_exit();
break;
 
case IPI_CPU_CRASH_STOP:
if (IS_ENABLED(CONFIG_KEXEC_CORE)) {
-   irq_enter();
-   ipi_cpu_crash_stop(cpu, regs);
+   ipi_cpu_crash_stop(cpu, get_irq_regs());
 
unreachable();
}
@@ -928,17 +932,13 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
case IPI_TIMER:
-   

[tip: irq/core] irqchip/armada-370-xp: Configure IPIs as standard interrupts

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: f02147dd02eb5fab31b55b73e7524f94b5f20324
Gitweb:
https://git.kernel.org/tip/f02147dd02eb5fab31b55b73e7524f94b5f20324
Author:Marc Zyngier 
AuthorDate:Mon, 22 Jun 2020 21:23:36 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:27 +01:00

irqchip/armada-370-xp: Configure IPIs as standard interrupts

To introduce IPIs as standard interrupts to the Armada 370-XP
driver, let's allocate a completely separate irqdomain and
irqchip combo that lives parallel to the "standard" one.

This effectively should be modelled as a chained interrupt
controller, but the code is in such a state that it is
pretty hard to shoehorn, as it would require the rewrite
of the MSI layer as well.

Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-armada-370-xp.c | 262 ++-
 1 file changed, 178 insertions(+), 84 deletions(-)

diff --git a/drivers/irqchip/irq-armada-370-xp.c 
b/drivers/irqchip/irq-armada-370-xp.c
index c9bdc52..d7eb2e9 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -310,7 +310,134 @@ static inline int armada_370_xp_msi_init(struct 
device_node *node,
 }
 #endif
 
+static void armada_xp_mpic_perf_init(void)
+{
+   unsigned long cpuid = cpu_logical_map(smp_processor_id());
+
+   /* Enable Performance Counter Overflow interrupts */
+   writel(ARMADA_370_XP_INT_CAUSE_PERF(cpuid),
+  per_cpu_int_base + ARMADA_370_XP_INT_FABRIC_MASK_OFFS);
+}
+
 #ifdef CONFIG_SMP
+static struct irq_domain *ipi_domain;
+
+static void armada_370_xp_ipi_mask(struct irq_data *d)
+{
+   u32 reg;
+   reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
+   reg &= ~BIT(d->hwirq);
+   writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
+}
+
+static void armada_370_xp_ipi_unmask(struct irq_data *d)
+{
+   u32 reg;
+   reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
+   reg |= BIT(d->hwirq);
+   writel(reg, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
+}
+
+static void armada_370_xp_ipi_send_mask(struct irq_data *d,
+   const struct cpumask *mask)
+{
+   unsigned long map = 0;
+   int cpu;
+
+   /* Convert our logical CPU mask into a physical one. */
+   for_each_cpu(cpu, mask)
+   map |= 1 << cpu_logical_map(cpu);
+
+   /*
+* Ensure that stores to Normal memory are visible to the
+* other CPUs before issuing the IPI.
+*/
+   dsb();
+
+   /* submit softirq */
+   writel((map << 8) | d->hwirq, main_int_base +
+   ARMADA_370_XP_SW_TRIG_INT_OFFS);
+}
+
+static void armada_370_xp_ipi_eoi(struct irq_data *d)
+{
+   writel(~BIT(d->hwirq), per_cpu_int_base + 
ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
+}
+
+static struct irq_chip ipi_irqchip = {
+   .name   = "IPI",
+   .irq_mask   = armada_370_xp_ipi_mask,
+   .irq_unmask = armada_370_xp_ipi_unmask,
+   .irq_eoi= armada_370_xp_ipi_eoi,
+   .ipi_send_mask  = armada_370_xp_ipi_send_mask,
+};
+
+static int armada_370_xp_ipi_alloc(struct irq_domain *d,
+unsigned int virq,
+unsigned int nr_irqs, void *args)
+{
+   int i;
+
+   for (i = 0; i < nr_irqs; i++) {
+   irq_set_percpu_devid(virq + i);
+   irq_domain_set_info(d, virq + i, i, _irqchip,
+   d->host_data,
+   handle_percpu_devid_fasteoi_ipi,
+   NULL, NULL);
+   }
+
+   return 0;
+}
+
+static void armada_370_xp_ipi_free(struct irq_domain *d,
+unsigned int virq,
+unsigned int nr_irqs)
+{
+   /* Not freeing IPIs */
+}
+
+static const struct irq_domain_ops ipi_domain_ops = {
+   .alloc  = armada_370_xp_ipi_alloc,
+   .free   = armada_370_xp_ipi_free,
+};
+
+static void ipi_resume(void)
+{
+   int i;
+
+   for (i = 0; i < IPI_DOORBELL_END; i++) {
+   int irq;
+
+   irq = irq_find_mapping(ipi_domain, i);
+   if (irq <= 0)
+   continue;
+   if (irq_percpu_is_enabled(irq)) {
+   struct irq_data *d;
+   d = irq_domain_get_irq_data(ipi_domain, irq);
+   armada_370_xp_ipi_unmask(d);
+   }
+   }
+}
+
+static __init void armada_xp_ipi_init(struct device_node *node)
+{
+   int base_ipi;
+
+   ipi_domain = irq_domain_create_linear(of_node_to_fwnode(node),
+ IPI_DOORBELL_END,
+ _domain_ops, NULL);
+   if (WARN_ON(!ipi_domain))
+   return;
+
+   

[tip: irq/core] genirq: Walk the irq_data hierarchy when resending an interrupt

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: cd1752d34ef33d68d82ef9dcc699b4eaa17c07fc
Gitweb:
https://git.kernel.org/tip/cd1752d34ef33d68d82ef9dcc699b4eaa17c07fc
Author:Marc Zyngier 
AuthorDate:Wed, 26 Aug 2020 18:37:50 +01:00
Committer: Marc Zyngier 
CommitterDate: Sun, 06 Sep 2020 18:25:23 +01:00

genirq: Walk the irq_data hierarchy when resending an interrupt

On resending an interrupt, we only check the outermost irqchip for
a irq_retrigger callback. However, this callback could be implemented
at an inner level. Use irq_chip_retrigger_hierarchy() in this case.

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 kernel/irq/resend.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index c48ce19..8ccd32a 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -86,6 +86,18 @@ static int irq_sw_resend(struct irq_desc *desc)
 }
 #endif
 
+static int try_retrigger(struct irq_desc *desc)
+{
+   if (desc->irq_data.chip->irq_retrigger)
+   return desc->irq_data.chip->irq_retrigger(>irq_data);
+
+#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
+   return irq_chip_retrigger_hierarchy(>irq_data);
+#else
+   return 0;
+#endif
+}
+
 /*
  * IRQ resend
  *
@@ -113,8 +125,7 @@ int check_irq_resend(struct irq_desc *desc, bool inject)
 
desc->istate &= ~IRQS_PENDING;
 
-   if (!desc->irq_data.chip->irq_retrigger ||
-   !desc->irq_data.chip->irq_retrigger(>irq_data))
+   if (!try_retrigger(desc))
err = irq_sw_resend(desc);
 
/* If the retrigger was successfull, mark it with the REPLAY bit */


[tip: irq/core] ARM: Handle no IPI being registered in show_ipi_list()

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 220387048d859896ccc362c0ebf9bc1e0fa62eb9
Gitweb:
https://git.kernel.org/tip/220387048d859896ccc362c0ebf9bc1e0fa62eb9
Author:Marc Zyngier 
AuthorDate:Fri, 25 Sep 2020 16:22:00 +01:00
Committer: Marc Zyngier 
CommitterDate: Mon, 28 Sep 2020 11:32:04 +01:00

ARM: Handle no IPI being registered in show_ipi_list()

As SMP-on-UP is a valid configuration on 32bit ARM, do not assume that
IPIs are populated in show_ipi_list().

Reported-by: Guillaume Tucker 
Reported-by: kernelci.org bot 
Tested-by: Guillaume Tucker 
Signed-off-by: Marc Zyngier 
---
 arch/arm/kernel/smp.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 8425da5..48099c6 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -541,7 +541,12 @@ void show_ipi_list(struct seq_file *p, int prec)
unsigned int cpu, i;
 
for (i = 0; i < NR_IPI; i++) {
-   unsigned int irq = irq_desc_get_irq(ipi_desc[i]);
+   unsigned int irq;
+
+   if (!ipi_desc[i])
+   continue;
+
+   irq = irq_desc_get_irq(ipi_desc[i]);
seq_printf(p, "%*s%u: ", prec - 1, "IPI", i);
 
for_each_online_cpu(cpu)


[tip: irq/core] irqchip/gic: Configure SGIs as standard interrupts

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 64a267e9a41c5a91efdfa5bf55bd2509cb4f7170
Gitweb:
https://git.kernel.org/tip/64a267e9a41c5a91efdfa5bf55bd2509cb4f7170
Author:Marc Zyngier 
AuthorDate:Sat, 25 Apr 2020 15:24:01 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:27 +01:00

irqchip/gic: Configure SGIs as standard interrupts

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.

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic.c | 128 +
 1 file changed, 87 insertions(+), 41 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 4ffd62a..66671e1 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -124,6 +124,8 @@ static struct gic_chip_data gic_data[CONFIG_ARM_GIC_MAX_NR] 
__read_mostly;
 
 static struct gic_kvm_info gic_v2_kvm_info;
 
+static DEFINE_PER_CPU(u32, sgi_intid);
+
 #ifdef CONFIG_GIC_NON_BANKED
 static void __iomem *gic_get_percpu_base(union gic_base *base)
 {
@@ -226,16 +228,26 @@ static void gic_unmask_irq(struct irq_data *d)
 
 static void gic_eoi_irq(struct irq_data *d)
 {
-   writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
+   u32 hwirq = gic_irq(d);
+
+   if (hwirq < 16)
+   hwirq = this_cpu_read(sgi_intid);
+
+   writel_relaxed(hwirq, gic_cpu_base(d) + GIC_CPU_EOI);
 }
 
 static void gic_eoimode1_eoi_irq(struct irq_data *d)
 {
+   u32 hwirq = gic_irq(d);
+
/* Do not deactivate an IRQ forwarded to a vcpu. */
if (irqd_is_forwarded_to_vcpu(d))
return;
 
-   writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_DEACTIVATE);
+   if (hwirq < 16)
+   hwirq = this_cpu_read(sgi_intid);
+
+   writel_relaxed(hwirq, gic_cpu_base(d) + GIC_CPU_DEACTIVATE);
 }
 
 static int gic_irq_set_irqchip_state(struct irq_data *d,
@@ -295,7 +307,7 @@ static int gic_set_type(struct irq_data *d, unsigned int 
type)
 
/* Interrupt configuration for SGIs can't be changed */
if (gicirq < 16)
-   return -EINVAL;
+   return type == IRQ_TYPE_EDGE_RISING ? 0 : -EINVAL;
 
/* SPIs have restrictions on the supported types */
if (gicirq >= 32 && type != IRQ_TYPE_LEVEL_HIGH &&
@@ -315,7 +327,7 @@ static int gic_set_type(struct irq_data *d, unsigned int 
type)
 static int gic_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
 {
/* Only interrupts on the primary GIC can be forwarded to a vcpu. */
-   if (cascading_gic_irq(d))
+   if (cascading_gic_irq(d) || gic_irq(d) < 16)
return -EINVAL;
 
if (vcpu)
@@ -335,31 +347,33 @@ 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(_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(_deactivate_key))
writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
-   if (static_branch_likely(_deactivate_key))
-   writel_relaxed(irqstat, cpu_base + 
GIC_CPU_DEACTIVATE);
-#ifdef CONFIG_SMP
+   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();
+
/*
-* 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
+* The GIC encodes the source CPU in GICC_IAR,
+* leading to the deactivation to fail if not
+* written back as is to GICC_EOI.  Stash the INTID
+* away for gic_eoi_irq() to write back.  This only
+* works because we don't nest SGIs...
 */
-   smp_rmb();
-   handle_IPI(irqnr, 

[tip: irq/core] irqchip/gic: Refactor SMP configuration

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 7ec46b519467852fc8eb83b6214ad568f8007846
Gitweb:
https://git.kernel.org/tip/7ec46b519467852fc8eb83b6214ad568f8007846
Author:Marc Zyngier 
AuthorDate:Sat, 25 Apr 2020 15:24:01 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:26 +01:00

irqchip/gic: Refactor SMP configuration

As we are about to change quite a lot of the SMP support code,
let's start by moving it around so that it minimizes the amount
of #ifdefery.

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic.c | 76 --
 1 file changed, 40 insertions(+), 36 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index a27ba2c..4ffd62a 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -325,28 +325,6 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, 
void *vcpu)
return 0;
 }
 
-#ifdef CONFIG_SMP
-static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
-   bool force)
-{
-   void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d);
-   unsigned int cpu;
-
-   if (!force)
-   cpu = cpumask_any_and(mask_val, cpu_online_mask);
-   else
-   cpu = cpumask_first(mask_val);
-
-   if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
-   return -EINVAL;
-
-   writeb_relaxed(gic_cpu_map[cpu], reg);
-   irq_data_update_effective_affinity(d, cpumask_of(cpu));
-
-   return IRQ_SET_MASK_OK_DONE;
-}
-#endif
-
 static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
 {
u32 irqstat, irqnr;
@@ -795,6 +773,26 @@ static int gic_pm_init(struct gic_chip_data *gic)
 #endif
 
 #ifdef CONFIG_SMP
+static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
+   bool force)
+{
+   void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d);
+   unsigned int cpu;
+
+   if (!force)
+   cpu = cpumask_any_and(mask_val, cpu_online_mask);
+   else
+   cpu = cpumask_first(mask_val);
+
+   if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
+   return -EINVAL;
+
+   writeb_relaxed(gic_cpu_map[cpu], reg);
+   irq_data_update_effective_affinity(d, cpumask_of(cpu));
+
+   return IRQ_SET_MASK_OK_DONE;
+}
+
 static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
int cpu;
@@ -824,6 +822,23 @@ static void gic_raise_softirq(const struct cpumask *mask, 
unsigned int irq)
 
gic_unlock_irqrestore(flags);
 }
+
+static int gic_starting_cpu(unsigned int cpu)
+{
+   gic_cpu_init(_data[0]);
+   return 0;
+}
+
+static __init void gic_smp_init(void)
+{
+   set_smp_cross_call(gic_raise_softirq);
+   cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING,
+ "irqchip/arm/gic:starting",
+ gic_starting_cpu, NULL);
+}
+#else
+#define gic_smp_init() do { } while(0)
+#define gic_set_affinity   NULL
 #endif
 
 #ifdef CONFIG_BL_SWITCHER
@@ -1027,12 +1042,6 @@ static int gic_irq_domain_translate(struct irq_domain *d,
return -EINVAL;
 }
 
-static int gic_starting_cpu(unsigned int cpu)
-{
-   gic_cpu_init(_data[0]);
-   return 0;
-}
-
 static int gic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs, void *arg)
 {
@@ -1079,10 +1088,8 @@ static void gic_init_chip(struct gic_chip_data *gic, 
struct device *dev,
gic->chip.irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity;
}
 
-#ifdef CONFIG_SMP
if (gic == _data[0])
gic->chip.irq_set_affinity = gic_set_affinity;
-#endif
 }
 
 static int gic_init_bases(struct gic_chip_data *gic,
@@ -1199,12 +1206,7 @@ static int __init __gic_init_bases(struct gic_chip_data 
*gic,
 */
for (i = 0; i < NR_GIC_CPU_IF; i++)
gic_cpu_map[i] = 0xff;
-#ifdef CONFIG_SMP
-   set_smp_cross_call(gic_raise_softirq);
-#endif
-   cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING,
- "irqchip/arm/gic:starting",
- gic_starting_cpu, NULL);
+
set_handle_irq(gic_handle_irq);
if (static_branch_likely(_deactivate_key))
pr_info("GIC: Using split EOI/Deactivate mode\n");
@@ -1221,6 +1223,8 @@ static int __init __gic_init_bases(struct gic_chip_data 
*gic,
ret = gic_init_bases(gic, handle);
if (ret)
kfree(name);
+   else if (gic == _data[0])
+   gic_smp_init();
 
return ret;
 }


[tip: irq/core] irqchip/git-v3-its: Implement irq_retrigger callback for device-triggered LPIs

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 5f774f5e12512b850a611aa99b4601d7eac50edb
Gitweb:
https://git.kernel.org/tip/5f774f5e12512b850a611aa99b4601d7eac50edb
Author:Marc Zyngier 
AuthorDate:Fri, 31 Jul 2020 11:33:13 +01:00
Committer: Marc Zyngier 
CommitterDate: Sun, 06 Sep 2020 18:26:13 +01:00

irqchip/git-v3-its: Implement irq_retrigger callback for device-triggered LPIs

It is pretty easy to provide a retrigger callback for the ITS,
as it we already have the required support in terms of
irq_set_irqchip_state().

Note that this only works for device-generated LPIs, and not
the GICv4 doorbells, which should never have to be retriggered
anyway.

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic-v3-its.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 95f0974..2808545 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1720,6 +1720,11 @@ static int its_irq_set_irqchip_state(struct irq_data *d,
return 0;
 }
 
+static int its_irq_retrigger(struct irq_data *d)
+{
+   return !its_irq_set_irqchip_state(d, IRQCHIP_STATE_PENDING, true);
+}
+
 /*
  * Two favourable cases:
  *
@@ -1971,6 +1976,7 @@ static struct irq_chip its_irq_chip = {
.irq_set_affinity   = its_set_affinity,
.irq_compose_msi_msg= its_irq_compose_msi_msg,
.irq_set_irqchip_state  = its_irq_set_irqchip_state,
+   .irq_retrigger  = its_irq_retrigger,
.irq_set_vcpu_affinity  = its_irq_set_vcpu_affinity,
 };
 


[tip: irq/core] irqchip/gic-common: Don't enable SGIs by default

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 3567c6ca47546106d36d995790e4eb80e3f14632
Gitweb:
https://git.kernel.org/tip/3567c6ca47546106d36d995790e4eb80e3f14632
Author:Marc Zyngier 
AuthorDate:Tue, 19 May 2020 09:42:46 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:27 +01:00

irqchip/gic-common: Don't enable SGIs by default

The architecture code now enables the IPIs as required, so no
need to enable SGIs by default in the GIC code.

Reviewed-by: Valentin Schneider 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic-common.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index 8252000..f47b41d 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -152,9 +152,6 @@ void gic_cpu_config(void __iomem *base, int nr, void 
(*sync_access)(void))
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();
 }


[tip: irq/core] arm64: Remove custom IRQ stat accounting

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: a263881525310e10ecd46ae8e8531ac9e968b1b4
Gitweb:
https://git.kernel.org/tip/a263881525310e10ecd46ae8e8531ac9e968b1b4
Author:Marc Zyngier 
AuthorDate:Sat, 20 Jun 2020 17:19:00 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:28 +01:00

arm64: Remove custom IRQ stat accounting

Let's switch the arm64 code to the core accounting, which already
does everything we need.

Reviewed-by: Valentin Schneider 
Acked-by: Catalin Marinas 
Signed-off-by: Marc Zyngier 
---
 arch/arm64/include/asm/hardirq.h |  9 -
 arch/arm64/include/asm/smp.h |  5 -
 arch/arm64/kernel/irq.c  | 11 +--
 arch/arm64/kernel/smp.c  | 30 --
 4 files changed, 13 insertions(+), 42 deletions(-)

diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h
index 985493a..5ffa4ba 100644
--- a/arch/arm64/include/asm/hardirq.h
+++ b/arch/arm64/include/asm/hardirq.h
@@ -13,21 +13,12 @@
 #include 
 #include 
 
-#define NR_IPI 7
-
 typedef struct {
unsigned int __softirq_pending;
-   unsigned int ipi_irqs[NR_IPI];
 } cacheline_aligned irq_cpustat_t;
 
 #include  /* Standard mappings for irq_cpustat_t above */
 
-#define __inc_irq_stat(cpu, member)__IRQ_STAT(cpu, member)++
-#define __get_irq_stat(cpu, member)__IRQ_STAT(cpu, member)
-
-u64 smp_irq_stat_cpu(unsigned int cpu);
-#define arch_irq_stat_cpu  smp_irq_stat_cpu
-
 #define __ARCH_IRQ_EXIT_IRQS_DISABLED  1
 
 struct nmi_ctx {
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index c298ad0..2e7f529 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -56,11 +56,6 @@ static inline void set_cpu_logical_map(int cpu, u64 hwid)
 struct seq_file;
 
 /*
- * generate IPI list text
- */
-extern void show_ipi_list(struct seq_file *p, int prec);
-
-/*
  * Discover the set of possible CPUs and determine their
  * SMP operations.
  */
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
index 04a327c..9cf2fb8 100644
--- a/arch/arm64/kernel/irq.c
+++ b/arch/arm64/kernel/irq.c
@@ -10,10 +10,10 @@
  * Copyright (C) 2012 ARM Ltd.
  */
 
-#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -22,20 +22,11 @@
 #include 
 #include 
 
-unsigned long irq_err_count;
-
 /* Only access this in an NMI enter/exit */
 DEFINE_PER_CPU(struct nmi_ctx, nmi_contexts);
 
 DEFINE_PER_CPU(unsigned long *, irq_stack_ptr);
 
-int arch_show_interrupts(struct seq_file *p, int prec)
-{
-   show_ipi_list(p, prec);
-   seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
-   return 0;
-}
-
 #ifdef CONFIG_VMAP_STACK
 static void init_irq_stacks(void)
 {
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 58fb155..b6bde26 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -30,6 +30,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -72,7 +73,8 @@ enum ipi_msg_type {
IPI_CPU_CRASH_STOP,
IPI_TIMER,
IPI_IRQ_WORK,
-   IPI_WAKEUP
+   IPI_WAKEUP,
+   NR_IPI
 };
 
 static int ipi_irq_base __read_mostly;
@@ -795,29 +797,23 @@ static const char *ipi_types[NR_IPI] __tracepoint_string 
= {
 
 static void smp_cross_call(const struct cpumask *target, unsigned int ipinr);
 
-void show_ipi_list(struct seq_file *p, int prec)
+unsigned long irq_err_count;
+
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
unsigned int cpu, i;
 
for (i = 0; i < NR_IPI; i++) {
+   unsigned int irq = irq_desc_get_irq(ipi_desc[i]);
seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,
   prec >= 4 ? " " : "");
for_each_online_cpu(cpu)
-   seq_printf(p, "%10u ",
-  __get_irq_stat(cpu, ipi_irqs[i]));
+   seq_printf(p, "%10u ", kstat_irqs_cpu(irq, cpu));
seq_printf(p, "  %s\n", ipi_types[i]);
}
-}
-
-u64 smp_irq_stat_cpu(unsigned int cpu)
-{
-   u64 sum = 0;
-   int i;
 
-   for (i = 0; i < NR_IPI; i++)
-   sum += __get_irq_stat(cpu, ipi_irqs[i]);
-
-   return sum;
+   seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
+   return 0;
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
@@ -892,10 +888,8 @@ static void do_handle_IPI(int ipinr)
 {
unsigned int cpu = smp_processor_id();
 
-   if ((unsigned)ipinr < NR_IPI) {
+   if ((unsigned)ipinr < NR_IPI)
trace_ipi_entry_rcuidle(ipi_types[ipinr]);
-   __inc_irq_stat(cpu, ipi_irqs[ipinr]);
-   }
 
switch (ipinr) {
case IPI_RESCHEDULE:
@@ -992,7 +986,7 @@ void __init set_smp_ipi_range(int ipi_base, int n)
int err;
 
err = request_percpu_irq(ipi_base + 

[tip: irq/core] irqchip/hip04: Configure IPIs as standard interrupts

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: a2df12c5899e9bb181cb64385b04f2bc755780b6
Gitweb:
https://git.kernel.org/tip/a2df12c5899e9bb181cb64385b04f2bc755780b6
Author:Marc Zyngier 
AuthorDate:Sat, 20 Jun 2020 20:02:18 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 17 Sep 2020 16:37:27 +01:00

irqchip/hip04: Configure IPIs as standard interrupts

In order to switch the hip04 driver to provide standard interrupts
for IPIs, rework the way interrupts are allocated, making sure
the irqdomain covers the SGIs as well as the rest of the interrupt
range.

The driver is otherwise so old-school that it creates all interrupts
upfront (duh!), so there is hardly anything else to change, apart
from communicating the IPIs to the arch code.

Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-hip04.c | 89 
 1 file changed, 40 insertions(+), 49 deletions(-)

diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c
index 130caa1..9b73dcf 100644
--- a/drivers/irqchip/irq-hip04.c
+++ b/drivers/irqchip/irq-hip04.c
@@ -171,6 +171,29 @@ static int hip04_irq_set_affinity(struct irq_data *d,
 
return IRQ_SET_MASK_OK;
 }
+
+static void hip04_ipi_send_mask(struct irq_data *d, const struct cpumask *mask)
+{
+   int cpu;
+   unsigned long flags, map = 0;
+
+   raw_spin_lock_irqsave(_controller_lock, flags);
+
+   /* Convert our logical CPU mask into a physical one. */
+   for_each_cpu(cpu, mask)
+   map |= hip04_cpu_map[cpu];
+
+   /*
+* Ensure that stores to Normal memory are visible to the
+* other CPUs before they observe us issuing the IPI.
+*/
+   dmb(ishst);
+
+   /* this always happens on GIC0 */
+   writel_relaxed(map << 8 | d->hwirq, hip04_data.dist_base + 
GIC_DIST_SOFTINT);
+
+   raw_spin_unlock_irqrestore(_controller_lock, flags);
+}
 #endif
 
 static void __exception_irq_entry hip04_handle_irq(struct pt_regs *regs)
@@ -182,19 +205,9 @@ static void __exception_irq_entry hip04_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 <= HIP04_MAX_IRQS)) {
+   if (irqnr <= HIP04_MAX_IRQS)
handle_domain_irq(hip04_data.domain, irqnr, regs);
-   continue;
-   }
-   if (irqnr < 16) {
-   writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
-#ifdef CONFIG_SMP
-   handle_IPI(irqnr, regs);
-#endif
-   continue;
-   }
-   break;
-   } while (1);
+   } while (irqnr > HIP04_MAX_IRQS);
 }
 
 static struct irq_chip hip04_irq_chip = {
@@ -205,6 +218,7 @@ static struct irq_chip hip04_irq_chip = {
.irq_set_type   = hip04_irq_set_type,
 #ifdef CONFIG_SMP
.irq_set_affinity   = hip04_irq_set_affinity,
+   .ipi_send_mask  = hip04_ipi_send_mask,
 #endif
.flags  = IRQCHIP_SET_TYPE_MASKED |
  IRQCHIP_SKIP_SET_WAKE |
@@ -279,39 +293,17 @@ static void hip04_irq_cpu_init(struct hip04_irq_data 
*intc)
writel_relaxed(1, base + GIC_CPU_CTRL);
 }
 
-#ifdef CONFIG_SMP
-static void hip04_raise_softirq(const struct cpumask *mask, unsigned int irq)
-{
-   int cpu;
-   unsigned long flags, map = 0;
-
-   raw_spin_lock_irqsave(_controller_lock, flags);
-
-   /* Convert our logical CPU mask into a physical one. */
-   for_each_cpu(cpu, mask)
-   map |= hip04_cpu_map[cpu];
-
-   /*
-* Ensure that stores to Normal memory are visible to the
-* other CPUs before they observe us issuing the IPI.
-*/
-   dmb(ishst);
-
-   /* this always happens on GIC0 */
-   writel_relaxed(map << 8 | irq, hip04_data.dist_base + GIC_DIST_SOFTINT);
-
-   raw_spin_unlock_irqrestore(_controller_lock, flags);
-}
-#endif
-
 static int hip04_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
 {
-   if (hw < 32) {
+   if (hw < 16) {
+   irq_set_percpu_devid(irq);
+   irq_set_chip_and_handler(irq, _irq_chip,
+handle_percpu_devid_fasteoi_ipi);
+   } else if (hw < 32) {
irq_set_percpu_devid(irq);
irq_set_chip_and_handler(irq, _irq_chip,
 handle_percpu_devid_irq);
-   irq_set_status_flags(irq, IRQ_NOAUTOEN);
} else {
irq_set_chip_and_handler(irq, _irq_chip,
 handle_fasteoi_irq);
@@ -328,10 +320,13 @@ static int hip04_irq_domain_xlate(struct irq_domain *d,
  unsigned long *out_hwirq,
  

[tip: irq/core] soc/tegra: pmc: Allow optional irq parent callbacks

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 8681cc33f817842df7ebe3c36558d97f5497a177
Gitweb:
https://git.kernel.org/tip/8681cc33f817842df7ebe3c36558d97f5497a177
Author:Marc Zyngier 
AuthorDate:Sun, 04 Oct 2020 21:16:24 +01:00
Committer: Marc Zyngier 
CommitterDate: Sat, 10 Oct 2020 12:12:11 +01:00

soc/tegra: pmc: Allow optional irq parent callbacks

Make the PMC driver resistent to variable depth interrupt hierarchy,
which we are about to introduce.

Signed-off-by: Marc Zyngier 
---
 drivers/soc/tegra/pmc.c | 36 
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index d332e5d..b39536c 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -2184,6 +2184,34 @@ static int tegra186_pmc_irq_set_type(struct irq_data 
*data, unsigned int type)
return 0;
 }
 
+static void tegra_irq_mask_parent(struct irq_data *data)
+{
+   if (data->parent_data)
+   irq_chip_mask_parent(data);
+}
+
+static void tegra_irq_unmask_parent(struct irq_data *data)
+{
+   if (data->parent_data)
+   irq_chip_unmask_parent(data);
+}
+
+static void tegra_irq_eoi_parent(struct irq_data *data)
+{
+   if (data->parent_data)
+   irq_chip_eoi_parent(data);
+}
+
+static int tegra_irq_set_affinity_parent(struct irq_data *data,
+const struct cpumask *dest,
+bool force)
+{
+   if (data->parent_data)
+   return irq_chip_set_affinity_parent(data, dest, force);
+
+   return -EINVAL;
+}
+
 static int tegra_pmc_irq_init(struct tegra_pmc *pmc)
 {
struct irq_domain *parent = NULL;
@@ -2199,10 +2227,10 @@ static int tegra_pmc_irq_init(struct tegra_pmc *pmc)
return 0;
 
pmc->irq.name = dev_name(pmc->dev);
-   pmc->irq.irq_mask = irq_chip_mask_parent;
-   pmc->irq.irq_unmask = irq_chip_unmask_parent;
-   pmc->irq.irq_eoi = irq_chip_eoi_parent;
-   pmc->irq.irq_set_affinity = irq_chip_set_affinity_parent;
+   pmc->irq.irq_mask = tegra_irq_mask_parent;
+   pmc->irq.irq_unmask = tegra_irq_unmask_parent;
+   pmc->irq.irq_eoi = tegra_irq_eoi_parent;
+   pmc->irq.irq_set_affinity = tegra_irq_set_affinity_parent;
pmc->irq.irq_set_type = pmc->soc->irq_set_type;
pmc->irq.irq_set_wake = pmc->soc->irq_set_wake;
 


[tip: irq/core] soc/tegra: pmc: Don't create fake interrupt hierarchy levels

2020-10-11 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: c351ab7bf2a565951172cadbdebe686137c3fd43
Gitweb:
https://git.kernel.org/tip/c351ab7bf2a565951172cadbdebe686137c3fd43
Author:Marc Zyngier 
AuthorDate:Sun, 04 Oct 2020 18:27:04 +01:00
Committer: Marc Zyngier 
CommitterDate: Sat, 10 Oct 2020 12:12:11 +01:00

soc/tegra: pmc: Don't create fake interrupt hierarchy levels

The Tegra PMC driver does ungodly things with the interrupt hierarchy,
repeatedly corrupting it by pulling hwirq numbers out of thin air,
overriding existing IRQ mappings and changing the handling flow
of unsuspecting users.

All of this is done in the name of preserving the interrupt hierarchy
even when these levels do not exist in the HW. Together with the use
of proper IRQs for IPIs, this leads to an unbootable system as the
rescheduling IPI gets repeatedly repurposed for random drivers...

Instead, let's simply mark the level from which the hierarchy does
not make sense for the HW, and let the core code trim the usused
levels from the hierarchy.

Signed-off-by: Marc Zyngier 
---
 drivers/soc/tegra/pmc.c | 55 +---
 1 file changed, 7 insertions(+), 48 deletions(-)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index b39536c..b0bba8a 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1990,44 +1990,17 @@ static int tegra_pmc_irq_alloc(struct irq_domain 
*domain, unsigned int virq,
event->id,
>irq, pmc);
 
-   /*
-* GPIOs don't have an equivalent interrupt in the
-* parent controller (GIC). However some code, such
-* as the one in irq_get_irqchip_state(), require a
-* valid IRQ chip to be set. Make sure that's the
-* case by passing NULL here, which will install a
-* dummy IRQ chip for the interrupt in the parent
-* domain.
-*/
-   if (domain->parent)
-   irq_domain_set_hwirq_and_chip(domain->parent,
- virq, 0, NULL,
- NULL);
-
+   /* GPIO hierarchies stop at the PMC level */
+   if (!err && domain->parent)
+   err = 
irq_domain_disconnect_hierarchy(domain->parent,
+ virq);
break;
}
}
 
-   /*
-* For interrupts that don't have associated wake events, assign a
-* dummy hardware IRQ number. This is used in the ->irq_set_type()
-* and ->irq_set_wake() callbacks to return early for these IRQs.
-*/
-   if (i == soc->num_wake_events) {
-   err = irq_domain_set_hwirq_and_chip(domain, virq, ULONG_MAX,
-   >irq, pmc);
-
-   /*
-* Interrupts without a wake event don't have a corresponding
-* interrupt in the parent controller (GIC). Pass NULL for the
-* chip here, which causes a dummy IRQ chip to be installed
-* for the interrupt in the parent domain, to make this
-* explicit.
-*/
-   if (domain->parent)
-   irq_domain_set_hwirq_and_chip(domain->parent, virq, 0,
- NULL, NULL);
-   }
+   /* If there is no wake-up event, there is no PMC mapping */
+   if (i == soc->num_wake_events)
+   err = irq_domain_disconnect_hierarchy(domain, virq);
 
return err;
 }
@@ -2043,9 +2016,6 @@ static int tegra210_pmc_irq_set_wake(struct irq_data 
*data, unsigned int on)
unsigned int offset, bit;
u32 value;
 
-   if (data->hwirq == ULONG_MAX)
-   return 0;
-
offset = data->hwirq / 32;
bit = data->hwirq % 32;
 
@@ -2080,9 +2050,6 @@ static int tegra210_pmc_irq_set_type(struct irq_data 
*data, unsigned int type)
unsigned int offset, bit;
u32 value;
 
-   if (data->hwirq == ULONG_MAX)
-   return 0;
-
offset = data->hwirq / 32;
bit = data->hwirq % 32;
 
@@ -2123,10 +2090,6 @@ static int tegra186_pmc_irq_set_wake(struct irq_data 
*data, unsigned int on)
unsigned int offset, bit;
u32 value;
 
-   /* nothing to do if there's no associated wake event */
-   if (WARN_ON(data->hwirq == ULONG_MAX))
-   return 0;
-
offset = data->hwirq / 32;
bit = data->hwirq % 32;
 
@@ -2154,10 +2117,6 @@ static int 

[tip: irq/urgent] irqchip: Fix probing deferal when using IRQCHIP_PLATFORM_DRIVER helpers

2020-08-25 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: 7828a3ef8646fb2e69ed45616c8453a037ca7867
Gitweb:
https://git.kernel.org/tip/7828a3ef8646fb2e69ed45616c8453a037ca7867
Author:Marc Zyngier 
AuthorDate:Thu, 06 Aug 2020 10:57:45 +01:00
Committer: Marc Zyngier 
CommitterDate: Mon, 17 Aug 2020 08:06:11 +01:00

irqchip: Fix probing deferal when using IRQCHIP_PLATFORM_DRIVER helpers

When probing an interrupt controller that is behind a parent,
we try to check whether the parent domain is available as
an indication that we can actually try to probe.

Unfortunately, we are checking this with the firmware node of
the about to be probed device, not the parent. This is obviously
bound to fail.

Instead, use the parent node.

Fixes: f8410e626569 ("irqchip: Add IRQCHIP_PLATFORM_DRIVER_BEGIN/END and 
IRQCHIP_MATCH helper macros")
Reported-by: John Stultz 
Tested-by: John Stultz 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irqchip.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c
index 1bb0e36..d234115 100644
--- a/drivers/irqchip/irqchip.c
+++ b/drivers/irqchip/irqchip.c
@@ -52,7 +52,7 @@ int platform_irqchip_probe(struct platform_device *pdev)
 * interrupt controller. The actual initialization callback of this
 * interrupt controller can check for specific domains as necessary.
 */
-   if (par_np && !irq_find_matching_host(np, DOMAIN_BUS_ANY))
+   if (par_np && !irq_find_matching_host(par_np, DOMAIN_BUS_ANY))
return -EPROBE_DEFER;
 
return irq_init_cb(np, par_np);


[tip: irq/urgent] irqchip: Revert modular support for drivers using IRQCHIP_PLATFORM_DRIVER helperse

2020-08-25 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: a150dac5a8fb711fdc378c23f44bee4546f04246
Gitweb:
https://git.kernel.org/tip/a150dac5a8fb711fdc378c23f44bee4546f04246
Author:Marc Zyngier 
AuthorDate:Tue, 25 Aug 2020 10:38:39 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 25 Aug 2020 10:48:54 +01:00

irqchip: Revert modular support for drivers using IRQCHIP_PLATFORM_DRIVER 
helperse

It has become obvious that switching a number of irqchip drivers
to being platform drivers without considering the platform was a
mistake. We have multiple reports of end-point drivers not
probing because the irqchip driver isn't there yet, breaking
the expectations of the users.

This patch reverts:

920ecb8c35cb ("irqchip/mtk-cirq: Convert to a platform driver")
f97dbf48ca43 ("irqchip/mtk-sysirq: Convert to a platform driver")
5be57099d445 ("irqchip/qcom-pdc: Switch to using IRQCHIP_PLATFORM_DRIVER helper 
macros")
95bf9305d2e3 ("irqchip/qcom-pdc: Allow QCOM_PDC to be loadable as a permanent 
module")

and leave QCOM PDC, MTK sysrq and cirq drivers as built-in, special purpose
drivers for the time being until we have worked out a better solution.

Reported-by: Enric Balletbo i Serra 
Reported-by: Frank Wunderlich 
Signed-off-by: Marc Zyngier 
Link: https://lore.kernel.org/r/93debe6a0308b66d3f307af67ba7e...@kernel.org
---
 drivers/irqchip/Kconfig  | 2 +-
 drivers/irqchip/irq-mtk-cirq.c   | 4 +---
 drivers/irqchip/irq-mtk-sysirq.c | 4 +---
 drivers/irqchip/qcom-pdc.c   | 8 +---
 4 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index bb70b71..bfc9719 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -425,7 +425,7 @@ config GOLDFISH_PIC
  for Goldfish based virtual platforms.
 
 config QCOM_PDC
-   tristate "QCOM PDC"
+   bool "QCOM PDC"
depends on ARCH_QCOM
select IRQ_DOMAIN_HIERARCHY
help
diff --git a/drivers/irqchip/irq-mtk-cirq.c b/drivers/irqchip/irq-mtk-cirq.c
index 62a6127..69ba8ce 100644
--- a/drivers/irqchip/irq-mtk-cirq.c
+++ b/drivers/irqchip/irq-mtk-cirq.c
@@ -295,6 +295,4 @@ out_free:
return ret;
 }
 
-IRQCHIP_PLATFORM_DRIVER_BEGIN(mtk_cirq)
-IRQCHIP_MATCH("mediatek,mtk-cirq", mtk_cirq_of_init)
-IRQCHIP_PLATFORM_DRIVER_END(mtk_cirq)
+IRQCHIP_DECLARE(mtk_cirq, "mediatek,mtk-cirq", mtk_cirq_of_init);
diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c
index 7299c5a..6ff98b8 100644
--- a/drivers/irqchip/irq-mtk-sysirq.c
+++ b/drivers/irqchip/irq-mtk-sysirq.c
@@ -231,6 +231,4 @@ out_free_chip:
kfree(chip_data);
return ret;
 }
-IRQCHIP_PLATFORM_DRIVER_BEGIN(mtk_sysirq)
-IRQCHIP_MATCH("mediatek,mt6577-sysirq", mtk_sysirq_of_init)
-IRQCHIP_PLATFORM_DRIVER_END(mtk_sysirq)
+IRQCHIP_DECLARE(mtk_sysirq, "mediatek,mt6577-sysirq", mtk_sysirq_of_init);
diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c
index c1c5dfa..6ae9e1f 100644
--- a/drivers/irqchip/qcom-pdc.c
+++ b/drivers/irqchip/qcom-pdc.c
@@ -11,11 +11,9 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -432,8 +430,4 @@ fail:
return ret;
 }
 
-IRQCHIP_PLATFORM_DRIVER_BEGIN(qcom_pdc)
-IRQCHIP_MATCH("qcom,pdc", qcom_pdc_init)
-IRQCHIP_PLATFORM_DRIVER_END(qcom_pdc)
-MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Power Domain Controller");
-MODULE_LICENSE("GPL v2");
+IRQCHIP_DECLARE(qcom_pdc, "qcom,pdc", qcom_pdc_init);


[tip: irq/urgent] genirq/debugfs: Add missing irqchip flags

2020-07-27 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: aa251fc5b936d3ddb4b4c4b36427eb9aa3347c82
Gitweb:
https://git.kernel.org/tip/aa251fc5b936d3ddb4b4c4b36427eb9aa3347c82
Author:Marc Zyngier 
AuthorDate:Sat, 25 Jul 2020 13:30:55 +01:00
Committer: Thomas Gleixner 
CommitterDate: Mon, 27 Jul 2020 16:20:40 +02:00

genirq/debugfs: Add missing irqchip flags

Recently introduced irqchip flags lack the corresponding printouts in
debugfs. Add them.

Signed-off-by: Marc Zyngier 
Signed-off-by: Thomas Gleixner 
Link: https://lkml.kernel.org/r/874kpvydxc.wl-...@kernel.org


---
 kernel/irq/debugfs.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c
index 4f9f844..b95ff5d 100644
--- a/kernel/irq/debugfs.c
+++ b/kernel/irq/debugfs.c
@@ -112,6 +112,7 @@ static const struct irq_bit_descr irqdata_states[] = {
BIT_MASK_DESCR(IRQD_AFFINITY_SET),
BIT_MASK_DESCR(IRQD_SETAFFINITY_PENDING),
BIT_MASK_DESCR(IRQD_AFFINITY_MANAGED),
+   BIT_MASK_DESCR(IRQD_AFFINITY_ON_ACTIVATE),
BIT_MASK_DESCR(IRQD_MANAGED_SHUTDOWN),
BIT_MASK_DESCR(IRQD_CAN_RESERVE),
BIT_MASK_DESCR(IRQD_MSI_NOMASK_QUIRK),
@@ -120,6 +121,10 @@ static const struct irq_bit_descr irqdata_states[] = {
 
BIT_MASK_DESCR(IRQD_WAKEUP_STATE),
BIT_MASK_DESCR(IRQD_WAKEUP_ARMED),
+
+   BIT_MASK_DESCR(IRQD_DEFAULT_TRIGGER_SET),
+
+   BIT_MASK_DESCR(IRQD_HANDLE_ENFORCE_IRQCTX),
 };
 
 static const struct irq_bit_descr irqdesc_states[] = {


[tip: irq/urgent] irqchip/gic: Atomically update affinity

2020-06-30 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: 005c34ae4b44f085120d7f371121ec7ded677761
Gitweb:
https://git.kernel.org/tip/005c34ae4b44f085120d7f371121ec7ded677761
Author:Marc Zyngier 
AuthorDate:Sun, 21 Jun 2020 14:43:15 +01:00
Committer: Marc Zyngier 
CommitterDate: Sun, 21 Jun 2020 15:24:46 +01:00

irqchip/gic: Atomically update affinity

The GIC driver uses a RMW sequence to update the affinity, and
relies on the gic_lock_irqsave/gic_unlock_irqrestore sequences
to update it atomically.

But these sequences only expand into anything meaningful if
the BL_SWITCHER option is selected, which almost never happens.

It also turns out that using a RMW and locks is just as silly,
as the GIC distributor supports byte accesses for the GICD_TARGETRn
registers, which when used make the update atomic by definition.

Drop the terminally broken code and replace it by a byte write.

Fixes: 04c8b0f82c7d ("irqchip/gic: Make locking a BL_SWITCHER only feature")
Cc: sta...@vger.kernel.org
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 00de05a..c17fabd 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -329,10 +329,8 @@ static int gic_irq_set_vcpu_affinity(struct irq_data *d, 
void *vcpu)
 static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
bool force)
 {
-   void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & 
~3);
-   unsigned int cpu, shift = (gic_irq(d) % 4) * 8;
-   u32 val, mask, bit;
-   unsigned long flags;
+   void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d);
+   unsigned int cpu;
 
if (!force)
cpu = cpumask_any_and(mask_val, cpu_online_mask);
@@ -342,13 +340,7 @@ static int gic_set_affinity(struct irq_data *d, const 
struct cpumask *mask_val,
if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
return -EINVAL;
 
-   gic_lock_irqsave(flags);
-   mask = 0xff << shift;
-   bit = gic_cpu_map[cpu] << shift;
-   val = readl_relaxed(reg) & ~mask;
-   writel_relaxed(val | bit, reg);
-   gic_unlock_irqrestore(flags);
-
+   writeb_relaxed(gic_cpu_map[cpu], reg);
irq_data_update_effective_affinity(d, cpumask_of(cpu));
 
return IRQ_SET_MASK_OK_DONE;


[tip: irq/core] irqchip/gic-v3-its: Track LPI distribution on a per CPU basis

2020-05-30 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 2f13ff1d1d5c0257c97ea76b86a2d9c99c44a4b9
Gitweb:
https://git.kernel.org/tip/2f13ff1d1d5c0257c97ea76b86a2d9c99c44a4b9
Author:Marc Zyngier 
AuthorDate:Fri, 15 May 2020 17:57:51 +01:00
Committer: Marc Zyngier 
CommitterDate: Mon, 18 May 2020 10:30:42 +01:00

irqchip/gic-v3-its: Track LPI distribution on a per CPU basis

In order to improve the distribution of LPIs among CPUs, let start by
tracking the number of LPIs assigned to CPUs, both for managed and
non-managed interrupts (as separate counters).

Signed-off-by: Marc Zyngier 
Tested-by: John Garry 
Link: https://lore.kernel.org/r/20200515165752.121296-2-...@kernel.org
---
 drivers/irqchip/irq-gic-v3-its.c | 49 +--
 1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 124251b..4eb8441 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -174,6 +174,13 @@ static struct {
int next_victim;
 } vpe_proxy;
 
+struct cpu_lpi_count {
+   atomic_tmanaged;
+   atomic_tunmanaged;
+};
+
+static DEFINE_PER_CPU(struct cpu_lpi_count, cpu_lpi_count);
+
 static LIST_HEAD(its_nodes);
 static DEFINE_RAW_SPINLOCK(its_lock);
 static struct rdists *gic_rdists;
@@ -1510,6 +1517,30 @@ static void its_unmask_irq(struct irq_data *d)
lpi_update_config(d, 0, LPI_PROP_ENABLED);
 }
 
+static __maybe_unused u32 its_read_lpi_count(struct irq_data *d, int cpu)
+{
+   if (irqd_affinity_is_managed(d))
+   return atomic_read(_cpu_ptr(_lpi_count, cpu)->managed);
+
+   return atomic_read(_cpu_ptr(_lpi_count, cpu)->unmanaged);
+}
+
+static void its_inc_lpi_count(struct irq_data *d, int cpu)
+{
+   if (irqd_affinity_is_managed(d))
+   atomic_inc(_cpu_ptr(_lpi_count, cpu)->managed);
+   else
+   atomic_inc(_cpu_ptr(_lpi_count, cpu)->unmanaged);
+}
+
+static void its_dec_lpi_count(struct irq_data *d, int cpu)
+{
+   if (irqd_affinity_is_managed(d))
+   atomic_dec(_cpu_ptr(_lpi_count, cpu)->managed);
+   else
+   atomic_dec(_cpu_ptr(_lpi_count, cpu)->unmanaged);
+}
+
 static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
bool force)
 {
@@ -1518,34 +1549,44 @@ static int its_set_affinity(struct irq_data *d, const 
struct cpumask *mask_val,
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
struct its_collection *target_col;
u32 id = its_get_event_id(d);
+   int prev_cpu;
 
/* A forwarded interrupt should use irq_set_vcpu_affinity */
if (irqd_is_forwarded_to_vcpu(d))
return -EINVAL;
 
+   prev_cpu = its_dev->event_map.col_map[id];
+   its_dec_lpi_count(d, prev_cpu);
+
/* lpi cannot be routed to a redistributor that is on a foreign node */
if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) {
if (its_dev->its->numa_node >= 0) {
cpu_mask = cpumask_of_node(its_dev->its->numa_node);
if (!cpumask_intersects(mask_val, cpu_mask))
-   return -EINVAL;
+   goto err;
}
}
 
cpu = cpumask_any_and(mask_val, cpu_mask);
 
if (cpu >= nr_cpu_ids)
-   return -EINVAL;
+   goto err;
 
/* don't set the affinity when the target cpu is same as current one */
-   if (cpu != its_dev->event_map.col_map[id]) {
+   if (cpu != prev_cpu) {
target_col = _dev->its->collections[cpu];
its_send_movi(its_dev, target_col, id);
its_dev->event_map.col_map[id] = cpu;
irq_data_update_effective_affinity(d, cpumask_of(cpu));
}
 
+   its_inc_lpi_count(d, cpu);
+
return IRQ_SET_MASK_OK_DONE;
+
+err:
+   its_inc_lpi_count(d, prev_cpu);
+   return -EINVAL;
 }
 
 static u64 its_irq_get_msi_base(struct its_device *its_dev)
@@ -3448,6 +3489,7 @@ static int its_irq_domain_activate(struct irq_domain 
*domain,
cpu = cpumask_first(cpu_online_mask);
}
 
+   its_inc_lpi_count(d, cpu);
its_dev->event_map.col_map[event] = cpu;
irq_data_update_effective_affinity(d, cpumask_of(cpu));
 
@@ -3462,6 +3504,7 @@ static void its_irq_domain_deactivate(struct irq_domain 
*domain,
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
u32 event = its_get_event_id(d);
 
+   its_dec_lpi_count(d, its_dev->event_map.col_map[event]);
/* Stop the delivery of interrupts */
its_send_discard(its_dev, event);
 }


[tip: irq/core] irqchip/gic-v3-its: Balance initial LPI affinity across CPUs

2020-05-30 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: c5d6082d35e0bcc20a26a067ffcfddcb5257e580
Gitweb:
https://git.kernel.org/tip/c5d6082d35e0bcc20a26a067ffcfddcb5257e580
Author:Marc Zyngier 
AuthorDate:Fri, 15 May 2020 17:57:52 +01:00
Committer: Marc Zyngier 
CommitterDate: Wed, 20 May 2020 11:00:00 +01:00

irqchip/gic-v3-its: Balance initial LPI affinity across CPUs

When mapping a LPI, the ITS driver picks the first possible
affinity, which is in most cases CPU0, assuming that if
that's not suitable, someone will come and set the affinity
to something more interesting.

It apparently isn't the case, and people complain of poor
performance when many interrupts are glued to the same CPU.
So let's place the interrupts by finding the "least loaded"
CPU (that is, the one that has the fewer LPIs mapped to it).
So called 'managed' interrupts are an interesting case where
the affinity is actually dictated by the kernel itself, and
we should honor this.

Reported-by: John Garry 
Signed-off-by: Marc Zyngier 
Tested-by: John Garry 
Link: 
https://lore.kernel.org/r/1575642904-58295-1-git-send-email-john.ga...@huawei.com
Link: https://lore.kernel.org/r/20200515165752.121296-3-...@kernel.org
---
 drivers/irqchip/irq-gic-v3-its.c | 127 +++---
 1 file changed, 100 insertions(+), 27 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 4eb8441..cd685f5 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1541,15 +1541,104 @@ static void its_dec_lpi_count(struct irq_data *d, int 
cpu)
atomic_dec(_cpu_ptr(_lpi_count, cpu)->unmanaged);
 }
 
+static unsigned int cpumask_pick_least_loaded(struct irq_data *d,
+ const struct cpumask *cpu_mask)
+{
+   unsigned int cpu = nr_cpu_ids, tmp;
+   int count = S32_MAX;
+
+   for_each_cpu(tmp, cpu_mask) {
+   int this_count = its_read_lpi_count(d, tmp);
+   if (this_count < count) {
+   cpu = tmp;
+   count = this_count;
+   }
+   }
+
+   return cpu;
+}
+
+/*
+ * As suggested by Thomas Gleixner in:
+ * https://lore.kernel.org/r/87h80q2aoc@nanos.tec.linutronix.de
+ */
+static int its_select_cpu(struct irq_data *d,
+ const struct cpumask *aff_mask)
+{
+   struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+   cpumask_var_t tmpmask;
+   int cpu, node;
+
+   if (!alloc_cpumask_var(, GFP_ATOMIC))
+   return -ENOMEM;
+
+   node = its_dev->its->numa_node;
+
+   if (!irqd_affinity_is_managed(d)) {
+   /* First try the NUMA node */
+   if (node != NUMA_NO_NODE) {
+   /*
+* Try the intersection of the affinity mask and the
+* node mask (and the online mask, just to be safe).
+*/
+   cpumask_and(tmpmask, cpumask_of_node(node), aff_mask);
+   cpumask_and(tmpmask, tmpmask, cpu_online_mask);
+
+   /*
+* Ideally, we would check if the mask is empty, and
+* try again on the full node here.
+*
+* But it turns out that the way ACPI describes the
+* affinity for ITSs only deals about memory, and
+* not target CPUs, so it cannot describe a single
+* ITS placed next to two NUMA nodes.
+*
+* Instead, just fallback on the online mask. This
+* diverges from Thomas' suggestion above.
+*/
+   cpu = cpumask_pick_least_loaded(d, tmpmask);
+   if (cpu < nr_cpu_ids)
+   goto out;
+
+   /* If we can't cross sockets, give up */
+   if ((its_dev->its->flags & 
ITS_FLAGS_WORKAROUND_CAVIUM_23144))
+   goto out;
+
+   /* If the above failed, expand the search */
+   }
+
+   /* Try the intersection of the affinity and online masks */
+   cpumask_and(tmpmask, aff_mask, cpu_online_mask);
+
+   /* If that doesn't fly, the online mask is the last resort */
+   if (cpumask_empty(tmpmask))
+   cpumask_copy(tmpmask, cpu_online_mask);
+
+   cpu = cpumask_pick_least_loaded(d, tmpmask);
+   } else {
+   cpumask_and(tmpmask, irq_data_get_affinity_mask(d), 
cpu_online_mask);
+
+   /* If we cannot cross sockets, limit the search to that node */
+   if ((its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144) &&
+   node 

[tip: irq/urgent] irqchip/sifive-plic: Switch to fasteoi flow

2019-10-14 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

Commit-ID: bb0fed1c60cccbe4063b455a7228818395dac86e
Gitweb:
https://git.kernel.org/tip/bb0fed1c60cccbe4063b455a7228818395dac86e
Author:Marc Zyngier 
AuthorDate:Sun, 15 Sep 2019 15:17:45 +01:00
Committer: Marc Zyngier 
CommitterDate: Wed, 18 Sep 2019 12:29:52 +01:00

irqchip/sifive-plic: Switch to fasteoi flow

The SiFive PLIC interrupt controller seems to have all the HW
features to support the fasteoi flow, but the driver seems to be
stuck in a distant past. Bring it into the 21st century.

Signed-off-by: Marc Zyngier 
Tested-by: Palmer Dabbelt  (QEMU Boot)
Tested-by: Darius Rad  (on 2 HW PLIC implementations)
Tested-by: Paul Walmsley  (HiFive Unleashed)
Reviewed-by: Palmer Dabbelt 
Cc: sta...@vger.kernel.org
Link: https://lore.kernel.org/r/8636gxskmj.wl-...@kernel.org
---
 drivers/irqchip/irq-sifive-plic.c | 29 +++--
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/irqchip/irq-sifive-plic.c 
b/drivers/irqchip/irq-sifive-plic.c
index cf75596..3e51dee 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -97,7 +97,7 @@ static inline void plic_irq_toggle(const struct cpumask *mask,
}
 }
 
-static void plic_irq_enable(struct irq_data *d)
+static void plic_irq_unmask(struct irq_data *d)
 {
unsigned int cpu = cpumask_any_and(irq_data_get_affinity_mask(d),
   cpu_online_mask);
@@ -106,7 +106,7 @@ static void plic_irq_enable(struct irq_data *d)
plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1);
 }
 
-static void plic_irq_disable(struct irq_data *d)
+static void plic_irq_mask(struct irq_data *d)
 {
plic_irq_toggle(cpu_possible_mask, d->hwirq, 0);
 }
@@ -125,10 +125,8 @@ static int plic_set_affinity(struct irq_data *d,
if (cpu >= nr_cpu_ids)
return -EINVAL;
 
-   if (!irqd_irq_disabled(d)) {
-   plic_irq_toggle(cpu_possible_mask, d->hwirq, 0);
-   plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1);
-   }
+   plic_irq_toggle(cpu_possible_mask, d->hwirq, 0);
+   plic_irq_toggle(cpumask_of(cpu), d->hwirq, 1);
 
irq_data_update_effective_affinity(d, cpumask_of(cpu));
 
@@ -136,14 +134,18 @@ static int plic_set_affinity(struct irq_data *d,
 }
 #endif
 
+static void plic_irq_eoi(struct irq_data *d)
+{
+   struct plic_handler *handler = this_cpu_ptr(_handlers);
+
+   writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
+}
+
 static struct irq_chip plic_chip = {
.name   = "SiFive PLIC",
-   /*
-* There is no need to mask/unmask PLIC interrupts.  They are "masked"
-* by reading claim and "unmasked" when writing it back.
-*/
-   .irq_enable = plic_irq_enable,
-   .irq_disable= plic_irq_disable,
+   .irq_mask   = plic_irq_mask,
+   .irq_unmask = plic_irq_unmask,
+   .irq_eoi= plic_irq_eoi,
 #ifdef CONFIG_SMP
.irq_set_affinity = plic_set_affinity,
 #endif
@@ -152,7 +154,7 @@ static struct irq_chip plic_chip = {
 static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq,
  irq_hw_number_t hwirq)
 {
-   irq_set_chip_and_handler(irq, _chip, handle_simple_irq);
+   irq_set_chip_and_handler(irq, _chip, handle_fasteoi_irq);
irq_set_chip_data(irq, NULL);
irq_set_noprobe(irq);
return 0;
@@ -188,7 +190,6 @@ static void plic_handle_irq(struct pt_regs *regs)
hwirq);
else
generic_handle_irq(irq);
-   writel(hwirq, claim);
}
csr_set(sie, SIE_SEIE);
 }


[tip: irq/core] irqchip/gic-v3-its: Fix LPI release for Multi-MSI devices

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: c9c96e30ecaa0aafa225aa1a5392cb7db17c7a82
Gitweb:
https://git.kernel.org/tip/c9c96e30ecaa0aafa225aa1a5392cb7db17c7a82
Author:Marc Zyngier 
AuthorDate:Thu, 05 Sep 2019 14:56:47 +01:00
Committer: Marc Zyngier 
CommitterDate: Thu, 05 Sep 2019 16:03:48 +01:00

irqchip/gic-v3-its: Fix LPI release for Multi-MSI devices

When allocating a range of LPIs for a Multi-MSI capable device,
this allocation extended to the closest power of 2.

But on the release path, the interrupts are released one by
one. This results in not releasing the "extra" range, leaking
the its_device. Trying to reprobe the device will then fail.

Fix it by releasing the LPIs the same way we allocate them.

Fixes: 8208d1708b88 ("irqchip/gic-v3-its: Align PCI Multi-MSI allocation on 
their size")
Reported-by: Jiaxing Luo 
Tested-by: John Garry 
Signed-off-by: Marc Zyngier 
Link: https://lore.kernel.org/r/f5e948aa-e32f-3f74-ae30-31fee06c2...@huawei.com
---
 drivers/irqchip/irq-gic-v3-its.c |  9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 9380aa4..62e54f1 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -2641,14 +2641,13 @@ static void its_irq_domain_free(struct irq_domain 
*domain, unsigned int virq,
struct its_node *its = its_dev->its;
int i;
 
+   bitmap_release_region(its_dev->event_map.lpi_map,
+ its_get_event_id(irq_domain_get_irq_data(domain, 
virq)),
+ get_count_order(nr_irqs));
+
for (i = 0; i < nr_irqs; i++) {
struct irq_data *data = irq_domain_get_irq_data(domain,
virq + i);
-   u32 event = its_get_event_id(data);
-
-   /* Mark interrupt index as unused */
-   clear_bit(event, its_dev->event_map.lpi_map);
-
/* Nuke the entry in the domain */
irq_domain_reset_irq_data(data);
}


[tip: irq/core] irqchip/gic-v3: Dynamically allocate PPI NMI refcounts

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 81a43273045b116901e569ca27ddf0f92caf
Gitweb:
https://git.kernel.org/tip/81a43273045b116901e569ca27ddf0f92caf
Author:Marc Zyngier 
AuthorDate:Thu, 18 Jul 2019 12:53:05 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:23:34 +01:00

irqchip/gic-v3: Dynamically allocate PPI NMI refcounts

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 
---
 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 f884dd9..869a805 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(_nmi_refs[gic_irq(d) - 16])) {
-   refcount_set(_nmi_refs[gic_irq(d) - 16], 1);
+   if (!refcount_inc_not_zero(_nmi_refs[idx])) {
+   refcount_set(_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(_nmi_refs[gic_irq(d) - 16]))
+   if (refcount_dec_and_test(_nmi_refs[idx]))
desc->handle_irq = handle_percpu_devid_irq;
} else {
desc->handle_irq = handle_fasteoi_irq;
@@ -1394,7 +1408,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(_nmi_refs[i], 0);
 
static_branch_enable(_pseudo_nmis);
@@ -1472,12 +1498,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;
 


[tip: irq/core] irqchip/gic-v3: Warn about inconsistent implementations of extended ranges

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: ad5a78d3da81836c88d1f2d53310484462660997
Gitweb:
https://git.kernel.org/tip/ad5a78d3da81836c88d1f2d53310484462660997
Author:Marc Zyngier 
AuthorDate:Thu, 25 Jul 2019 15:30:51 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:23:35 +01:00

irqchip/gic-v3: Warn about inconsistent implementations of extended ranges

As is it usual for the GIC, it isn't disallowed to put together a system
that is majorly inconsistent, with a distributor supporting the
extended ranges while some of the CPUs don't.

Kindly tell the user that things are sailing isn't going to be smooth.

Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic-v3.c   | 5 +
 include/linux/irqchip/arm-gic-v3.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index d3727e8..8af08dd 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1014,6 +1014,11 @@ static void gic_cpu_init(void)
 
gic_enable_redist(true);
 
+   WARN((gic_data.ppi_nr > 16 || GIC_ESPI_NR != 0) &&
+!(gic_read_ctlr() & ICC_CTLR_EL1_ExtRange),
+"Distributor has extended ranges, but CPU%d doesn't\n",
+smp_processor_id());
+
rbase = gic_data_rdist_sgi_base();
 
/* Configure SGIs/PPIs as non-secure Group-1 */
diff --git a/include/linux/irqchip/arm-gic-v3.h 
b/include/linux/irqchip/arm-gic-v3.h
index 9ec3349..5cc10cf 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -496,6 +496,7 @@
 #define ICC_CTLR_EL1_A3V_SHIFT 15
 #define ICC_CTLR_EL1_A3V_MASK  (0x1 << ICC_CTLR_EL1_A3V_SHIFT)
 #define ICC_CTLR_EL1_RSS   (0x1 << 18)
+#define ICC_CTLR_EL1_ExtRange  (0x1 << 19)
 #define ICC_PMR_EL1_SHIFT  0
 #define ICC_PMR_EL1_MASK   (0xff << ICC_PMR_EL1_SHIFT)
 #define ICC_BPR0_EL1_SHIFT 0


[tip: irq/core] irqchip/gic: Skip DT quirks when evaluating IIDR-based quirks

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 25edaed6c7feca8fded25348732c628283304364
Gitweb:
https://git.kernel.org/tip/25edaed6c7feca8fded25348732c628283304364
Author:Marc Zyngier 
AuthorDate:Wed, 31 Jul 2019 17:28:49 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:23:35 +01:00

irqchip/gic: Skip DT quirks when evaluating IIDR-based quirks

When evaluating potential quirks matched by reads of the IIDR
register, skip the quirk entries that use a "compatible"
property attached to them, as these are DT based.

Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic-common.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c
index 14110db..8252000 100644
--- a/drivers/irqchip/irq-gic-common.c
+++ b/drivers/irqchip/irq-gic-common.c
@@ -41,6 +41,8 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk 
*quirks,
void *data)
 {
for (; quirks->desc; quirks++) {
+   if (quirks->compatible)
+   continue;
if (quirks->iidr != (quirks->mask & iidr))
continue;
if (quirks->init(data))


[tip: irq/core] dt-bindings: interrupt-controller: arm,gic-v3: Describe ESPI range support

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 866246534836c60f706076cdefcd45072ad9eab2
Gitweb:
https://git.kernel.org/tip/866246534836c60f706076cdefcd45072ad9eab2
Author:Marc Zyngier 
AuthorDate:Tue, 16 Jul 2019 15:18:40 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:04:09 +01:00

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.

Reviewed-by: Lokesh Vutla 
Signed-off-by: Marc Zyngier 
---
 Documentation/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 c34df35..98a3ecd 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.


[tip: irq/core] irqdomain/debugfs: Use PAs to generate fwnode names

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: b977fcf477c176e5f41775f0ea139f935b0f25b7
Gitweb:
https://git.kernel.org/tip/b977fcf477c176e5f41775f0ea139f935b0f25b7
Author:Marc Zyngier 
AuthorDate:Wed, 31 Jul 2019 15:13:19 +01:00
Committer: Marc Zyngier 
CommitterDate: Wed, 07 Aug 2019 14:24:54 +01:00

irqdomain/debugfs: Use PAs to generate fwnode names

Booting a large arm64 server (HiSi D05) leads to the following
shouting at boot time:

[   20.722132] debugfs: File 'irqchip@(ptrval)-3' in directory 
'domains' already present!
[   20.730851] debugfs: File 'irqchip@(ptrval)-3' in directory 
'domains' already present!
[   20.739560] debugfs: File 'irqchip@(ptrval)-3' in directory 
'domains' already present!
[   20.748267] debugfs: File 'irqchip@(ptrval)-3' in directory 
'domains' already present!
[   20.756975] debugfs: File 'irqchip@(ptrval)-3' in directory 
'domains' already present!
[   20.765683] debugfs: File 'irqchip@(ptrval)-3' in directory 
'domains' already present!
[   20.774391] debugfs: File 'irqchip@(ptrval)-3' in directory 
'domains' already present!

and many more... Evidently, we expect something a bit more informative
than ptrval, and certainly we want all of our domains, not just
the first one.

For that, turn the %p used to generate the fwnode name into something
that won't be repainted (%pa). Given that we've now fixed all users to
pass a pointer to a PA, it will actually do the right thing.

Acked-by: Thomas Gleixner 
Signed-off-by: Marc Zyngier 
---
 include/linux/irqdomain.h |  6 +++---
 kernel/irq/irqdomain.c|  9 +
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 07ec8b3..583e7ab 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -220,7 +220,7 @@ static inline struct device_node 
*irq_domain_get_of_node(struct irq_domain *d)
 
 #ifdef CONFIG_IRQ_DOMAIN
 struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
-   const char *name, void *data);
+   const char *name, phys_addr_t 
*pa);
 
 enum {
IRQCHIP_FWNODE_REAL,
@@ -241,9 +241,9 @@ struct fwnode_handle 
*irq_domain_alloc_named_id_fwnode(const char *name, int id)
 NULL);
 }
 
-static inline struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
+static inline struct fwnode_handle *irq_domain_alloc_fwnode(phys_addr_t *pa)
 {
-   return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, data);
+   return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, pa);
 }
 
 void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 3078d0e..e7bbab1 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -31,7 +31,7 @@ struct irqchip_fwid {
struct fwnode_handlefwnode;
unsigned inttype;
char*name;
-   void *data;
+   phys_addr_t *pa;
 };
 
 #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
@@ -62,7 +62,8 @@ EXPORT_SYMBOL_GPL(irqchip_fwnode_ops);
  * domain struct.
  */
 struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
-   const char *name, void *data)
+   const char *name,
+   phys_addr_t *pa)
 {
struct irqchip_fwid *fwid;
char *n;
@@ -77,7 +78,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int 
type, int id,
n = kasprintf(GFP_KERNEL, "%s-%d", name, id);
break;
default:
-   n = kasprintf(GFP_KERNEL, "irqchip@%p", data);
+   n = kasprintf(GFP_KERNEL, "irqchip@%pa", pa);
break;
}
 
@@ -89,7 +90,7 @@ struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int 
type, int id,
 
fwid->type = type;
fwid->name = n;
-   fwid->data = data;
+   fwid->pa = pa;
fwid->fwnode.ops = _fwnode_ops;
return >fwnode;
 }


[tip: irq/core] irqchip/gic: Rework gic_configure_irq to take the full ICFGR base

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 13d22e2e1f35f2d3cc7ddc002c23e733c2782dd4
Gitweb:
https://git.kernel.org/tip/13d22e2e1f35f2d3cc7ddc002c23e733c2782dd4
Author:Marc Zyngier 
AuthorDate:Tue, 16 Jul 2019 14:35:17 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:04:09 +01:00

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 
---
 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 b0a8215..6900b6f 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(_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(_controller_lock, flags);
 
if (sync_access)
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index be961c2..efc5319 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 b6b8573..5ca7d55 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 cf70582..1626131 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 

[tip: irq/core] irqchip/gic-v3: Add quirks for HIP06/07 invalid GICD_TYPER erratum 161010803

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 7f2481b39b4c776fb9c03081ffcfe81f4961601c
Gitweb:
https://git.kernel.org/tip/7f2481b39b4c776fb9c03081ffcfe81f4961601c
Author:Marc Zyngier 
AuthorDate:Wed, 31 Jul 2019 17:29:33 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:23:35 +01:00

irqchip/gic-v3: Add quirks for HIP06/07 invalid GICD_TYPER erratum 161010803

It looks like the HIP06/07 SoCs have extra bits in their GICD_TYPER
registers, which confuse the GICv3.1 code (these systems appear to
expose ESPIs while they actually don't).

Detect these systems as early as possible and wipe the fields that
should be RES0 in the register.

Tested-by: John Garry 
Signed-off-by: Marc Zyngier 
---
 Documentation/arm64/silicon-errata.rst |  2 +-
 drivers/irqchip/irq-gic-v3.c   | 56 -
 2 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/Documentation/arm64/silicon-errata.rst 
b/Documentation/arm64/silicon-errata.rst
index 3e57d09..17ea3fe 100644
--- a/Documentation/arm64/silicon-errata.rst
+++ b/Documentation/arm64/silicon-errata.rst
@@ -115,6 +115,8 @@ stable kernels.
 
++-+-+-+
 | Hisilicon  | Hip0{6,7}   | #161010701  | N/A 
|
 
++-+-+-+
+| Hisilicon  | Hip0{6,7}   | #161010803  | N/A 
|
+++-+-+-+
 | Hisilicon  | Hip07   | #161600802  | 
HISILICON_ERRATUM_161600802 |
 
++-+-+-+
 | Hisilicon  | Hip08 SMMU PMCG | #162001800  | N/A 
|
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 8af08dd..422664a 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1441,6 +1441,48 @@ static bool gic_enable_quirk_msm8996(void *data)
return true;
 }
 
+static bool gic_enable_quirk_hip06_07(void *data)
+{
+   struct gic_chip_data *d = data;
+
+   /*
+* HIP06 GICD_IIDR clashes with GIC-600 product number (despite
+* not being an actual ARM implementation). The saving grace is
+* that GIC-600 doesn't have ESPI, so nothing to do in that case.
+* HIP07 doesn't even have a proper IIDR, and still pretends to
+* have ESPI. In both cases, put them right.
+*/
+   if (d->rdists.gicd_typer & GICD_TYPER_ESPI) {
+   /* Zero both ESPI and the RES0 field next to it... */
+   d->rdists.gicd_typer &= ~GENMASK(9, 8);
+   return true;
+   }
+
+   return false;
+}
+
+static const struct gic_quirk gic_quirks[] = {
+   {
+   .desc   = "GICv3: Qualcomm MSM8996 broken firmware",
+   .compatible = "qcom,msm8996-gic-v3",
+   .init   = gic_enable_quirk_msm8996,
+   },
+   {
+   .desc   = "GICv3: HIP06 erratum 161010803",
+   .iidr   = 0x0204043b,
+   .mask   = 0x,
+   .init   = gic_enable_quirk_hip06_07,
+   },
+   {
+   .desc   = "GICv3: HIP07 erratum 161010803",
+   .iidr   = 0x,
+   .mask   = 0x,
+   .init   = gic_enable_quirk_hip06_07,
+   },
+   {
+   }
+};
+
 static void gic_enable_nmi_support(void)
 {
int i;
@@ -1494,6 +1536,10 @@ static int __init gic_init_bases(void __iomem *dist_base,
 */
typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
gic_data.rdists.gicd_typer = typer;
+
+   gic_enable_quirks(readl_relaxed(gic_data.dist_base + GICD_IIDR),
+ gic_quirks, _data);
+
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, _irq_domain_ops,
@@ -1676,16 +1722,6 @@ static void __init gic_of_setup_kvm_info(struct 
device_node *node)
gic_set_kvm_info(_v3_kvm_info);
 }
 
-static const struct gic_quirk gic_quirks[] = {
-   {
-   .desc   = "GICv3: Qualcomm MSM8996 broken firmware",
-   .compatible = "qcom,msm8996-gic-v3",
-   .init   = gic_enable_quirk_msm8996,
-   },
-   {
-   }
-};
-
 static int __init gic_of_init(struct device_node *node, struct device_node 
*parent)
 {
void __iomem *dist_base;


[tip: irq/core] dt-bindings: interrupt-controller: arm,gic-v3: Describe EPPI range support

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 4b049063e0bcbfd302f6bf867de9d55a965d622e
Gitweb:
https://git.kernel.org/tip/4b049063e0bcbfd302f6bf867de9d55a965d622e
Author:Marc Zyngier 
AuthorDate:Thu, 18 Jul 2019 13:18:51 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:23:35 +01:00

dt-bindings: interrupt-controller: arm,gic-v3: Describe EPPI range support

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

Signed-off-by: Marc Zyngier 
---
 Documentation/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 98a3ecd..1fe147d 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.


[tip: irq/core] irqchip/gic-v3: Register the distributor's PA instead of its VA in fwnode

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 0d093afc2e352e15b23bca38f69aad3d689b
Gitweb:
https://git.kernel.org/tip/0d093afc2e352e15b23bca38f69aad3d689b
Author:Marc Zyngier 
AuthorDate:Wed, 31 Jul 2019 16:13:42 +01:00
Committer: Marc Zyngier 
CommitterDate: Wed, 07 Aug 2019 14:24:19 +01:00

irqchip/gic-v3: Register the distributor's PA instead of its VA in fwnode

Do not expose the distributor's VA (it appears in debugfs). Instead,
record the PA, which at least can be used to precisely identify
the associated irqchip and domain.

Acked-by: Thomas Gleixner 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic-v3.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 96d927f..be961c2 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1845,7 +1845,7 @@ gic_acpi_init(struct acpi_subtable_header *header, const 
unsigned long end)
if (err)
goto out_redist_unmap;
 
-   domain_handle = irq_domain_alloc_fwnode(acpi_data.dist_base);
+   domain_handle = irq_domain_alloc_fwnode(>base_address);
if (!domain_handle) {
err = -ENOMEM;
goto out_redist_unmap;


[tip: irq/core] irqchip/gic-v3: Add EPPI range support

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 5f51f803826e4f4aedff415ddaf14efa707be5a7
Gitweb:
https://git.kernel.org/tip/5f51f803826e4f4aedff415ddaf14efa707be5a7
Author:Marc Zyngier 
AuthorDate:Thu, 18 Jul 2019 13:19:25 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:23:35 +01:00

irqchip/gic-v3: Add EPPI range support

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 
---
 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 f5dbdbf..d3727e8 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 ... (EPPI_BASE_INTID + 63):
+   return EPPI_RANGE;
case ESPI_BASE_INTID ... (ESPI_BASE_INTID + 1023):
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, );
 
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);
 
   

[tip: irq/core] irqchip/gic-v3: Add ESPI range support

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 211bddd210a6746e4fdfa9b6cdfbdb15026530a7
Gitweb:
https://git.kernel.org/tip/211bddd210a6746e4fdfa9b6cdfbdb15026530a7
Author:Marc Zyngier 
AuthorDate:Tue, 16 Jul 2019 15:17:31 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:23:34 +01:00

irqchip/gic-v3: Add ESPI range support

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 
---
 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 660ec43..0afc942 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;
boolhas_rss;
-   unsigned intirq_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_NRmax(GICD_TYPER_SPIS(gic_data.rdists.gicd_typer), 1020U)
+#define GIC_ESPI_NRGICD_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 ... (ESPI_BASE_INTID + 1023):
+   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(_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,
 * 

[tip: irq/core] irqchip/gic-v3-its: Register the ITS' PA instead of its VA in fwnode

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 5778cc77111f09fd2033c66cdf1654f542771ed0
Gitweb:
https://git.kernel.org/tip/5778cc77111f09fd2033c66cdf1654f542771ed0
Author:Marc Zyngier 
AuthorDate:Wed, 31 Jul 2019 16:13:42 +01:00
Committer: Marc Zyngier 
CommitterDate: Wed, 07 Aug 2019 14:24:28 +01:00

irqchip/gic-v3-its: Register the ITS' PA instead of its VA in fwnode

Do not expose the ITS' VA (it appears in debugfs). Instead, record
the PA, which at least can be used to precisely identify the associated
irqchip and domain.

Acked-by: Thomas Gleixner 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic-v3-its.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 1b5c367..8eeb0e2 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3921,7 +3921,7 @@ static int __init gic_acpi_parse_madt_its(union 
acpi_subtable_headers *header,
res.end = its_entry->base_address + ACPI_GICV3_ITS_MEM_SIZE - 1;
res.flags = IORESOURCE_MEM;
 
-   dom_handle = irq_domain_alloc_fwnode((void *)its_entry->base_address);
+   dom_handle = irq_domain_alloc_fwnode();
if (!dom_handle) {
pr_err("ITS@%pa: Unable to allocate GICv3 ITS domain token\n",
   );


[tip: irq/core] irqchip/gic-v2m: Register the frame's PA instead of its VA in fwnode

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 7d5b7695c22f6e22d9a16df17f477832eef8e2b7
Gitweb:
https://git.kernel.org/tip/7d5b7695c22f6e22d9a16df17f477832eef8e2b7
Author:Marc Zyngier 
AuthorDate:Wed, 31 Jul 2019 16:13:42 +01:00
Committer: Marc Zyngier 
CommitterDate: Wed, 07 Aug 2019 14:24:37 +01:00

irqchip/gic-v2m: Register the frame's PA instead of its VA in fwnode

Do not expose the frame's VA (it appears in debugfs). Instead,
record the PA, which at least can be used to precisely identify
the associated irqchip and domain.

Acked-by: Thomas Gleixner 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic-v2m.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 7338f90..e88e75c 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -525,7 +525,7 @@ acpi_parse_madt_msi(union acpi_subtable_headers *header,
spi_start, nr_spis);
}
 
-   fwnode = irq_domain_alloc_fwnode((void *)m->base_address);
+   fwnode = irq_domain_alloc_fwnode();
if (!fwnode) {
pr_err("Unable to allocate GICv2m domain token\n");
return -EINVAL;


[tip: irq/core] irqchip/ixp4xx: Register the base PA instead of its VA in fwnode

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 9adc54d4e8c56ed5851bb51314ffcbaebdfbf17e
Gitweb:
https://git.kernel.org/tip/9adc54d4e8c56ed5851bb51314ffcbaebdfbf17e
Author:Marc Zyngier 
AuthorDate:Wed, 31 Jul 2019 16:13:42 +01:00
Committer: Marc Zyngier 
CommitterDate: Wed, 07 Aug 2019 14:24:41 +01:00

irqchip/ixp4xx: Register the base PA instead of its VA in fwnode

Do not expose the base VA (it appears in debugfs). Instead,
record the PA, which at least can be used to precisely identify
the associated irqchip and domain.

Acked-by: Thomas Gleixner 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-ixp4xx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-ixp4xx.c b/drivers/irqchip/irq-ixp4xx.c
index 6751c35..37e0749 100644
--- a/drivers/irqchip/irq-ixp4xx.c
+++ b/drivers/irqchip/irq-ixp4xx.c
@@ -319,7 +319,7 @@ void __init ixp4xx_irq_init(resource_size_t irqbase,
pr_crit("IXP4XX: could not ioremap interrupt controller\n");
return;
}
-   fwnode = irq_domain_alloc_fwnode(base);
+   fwnode = irq_domain_alloc_fwnode();
if (!fwnode) {
pr_crit("IXP4XX: no domain handle\n");
return;


[tip: irq/core] PCI: hv: Allocate a named fwnode instead of an address-based one

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 467a3bb974320a23c0c000559cc54b64e06e9787
Gitweb:
https://git.kernel.org/tip/467a3bb974320a23c0c000559cc54b64e06e9787
Author:Marc Zyngier 
AuthorDate:Tue, 06 Aug 2019 15:23:33 +01:00
Committer: Marc Zyngier 
CommitterDate: Wed, 07 Aug 2019 14:24:49 +01:00

PCI: hv: Allocate a named fwnode instead of an address-based one

To allocate its fwnode that is then used to allocate an irqdomain,
the driver uses irq_domain_alloc_fwnode(), passing it a VA as an
identifier. This is a rather bad idea, as this address ends up
published in debugfs (and we want to move away from VAs there
anyway).

Instead, let's allocate a named fwnode by using the device GUID as
an identifier. It is allegedly unique, and can be traced back to
the original device.

Acked-by: Thomas Gleixner 
Signed-off-by: Marc Zyngier 
---
 drivers/pci/controller/pci-hyperv.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pci-hyperv.c 
b/drivers/pci/controller/pci-hyperv.c
index 40b6254..97056f3 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -2521,6 +2521,7 @@ static int hv_pci_probe(struct hv_device *hdev,
const struct hv_vmbus_device_id *dev_id)
 {
struct hv_pcibus_device *hbus;
+   char *name;
int ret;
 
/*
@@ -2589,7 +2590,14 @@ static int hv_pci_probe(struct hv_device *hdev,
goto free_config;
}
 
-   hbus->sysdata.fwnode = irq_domain_alloc_fwnode(hbus);
+   name = kasprintf(GFP_KERNEL, "%pUL", >dev_instance);
+   if (!name) {
+   ret = -ENOMEM;
+   goto unmap;
+   }
+
+   hbus->sysdata.fwnode = irq_domain_alloc_named_fwnode(name);
+   kfree(name);
if (!hbus->sysdata.fwnode) {
ret = -ENOMEM;
goto unmap;


[tip: irq/core] irqchip/gic-v3: Add INTID range and convertion primitives

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: e91b036e1c20d80419164ddfc32125052df3fb39
Gitweb:
https://git.kernel.org/tip/e91b036e1c20d80419164ddfc32125052df3fb39
Author:Marc Zyngier 
AuthorDate:Tue, 16 Jul 2019 14:41:40 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:04:09 +01:00

irqchip/gic-v3: Add INTID range and convertion primitives

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 
---
 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 efc5319..660ec43 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, );
+   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, );
+   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, );
+
+   

[tip: irq/core] gpio/ixp4xx: Register the base PA instead of its VA in fwnode

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: daa19fe5b082779962988a5ba9e38509004db3de
Gitweb:
https://git.kernel.org/tip/daa19fe5b082779962988a5ba9e38509004db3de
Author:Marc Zyngier 
AuthorDate:Wed, 31 Jul 2019 16:13:42 +01:00
Committer: Marc Zyngier 
CommitterDate: Wed, 07 Aug 2019 14:24:45 +01:00

gpio/ixp4xx: Register the base PA instead of its VA in fwnode

Do not expose the base VA (it appears in debugfs). Instead,
record the PA, which at least can be used to precisely identify
the associated irqchip and domain.

Reviewed-by: Linus Walleij 
Acked-by: Thomas Gleixner 
Signed-off-by: Marc Zyngier 
---
 drivers/gpio/gpio-ixp4xx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c
index 670c2a8..cc72c9a 100644
--- a/drivers/gpio/gpio-ixp4xx.c
+++ b/drivers/gpio/gpio-ixp4xx.c
@@ -400,7 +400,7 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
g->fwnode = of_node_to_fwnode(np);
} else {
parent = ixp4xx_get_irq_domain();
-   g->fwnode = irq_domain_alloc_fwnode(g->base);
+   g->fwnode = irq_domain_alloc_fwnode(>start);
if (!g->fwnode) {
dev_err(dev, "no domain base\n");
return -ENODEV;


[tip: irq/core] irqchip/gic: Prepare for more than 16 PPIs

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 1a60e1e6439164c06636dce5d32660de505d23c3
Gitweb:
https://git.kernel.org/tip/1a60e1e6439164c06636dce5d32660de505d23c3
Author:Marc Zyngier 
AuthorDate:Thu, 18 Jul 2019 11:15:14 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:23:34 +01:00

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 discover 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 
---
 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 6900b6f..14110db 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 5a46b6b..ccba8b0 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 0afc942..f884dd9 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;
boolhas_rss;
+   unsigned intppi_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, 

[tip: irq/core] irqchip/gic: Register the distributor's PA instead of its VA in fwnode

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 188a8471ef03718709bd785d3976f6cd72bb551d
Gitweb:
https://git.kernel.org/tip/188a8471ef03718709bd785d3976f6cd72bb551d
Author:Marc Zyngier 
AuthorDate:Wed, 31 Jul 2019 16:13:42 +01:00
Committer: Marc Zyngier 
CommitterDate: Wed, 07 Aug 2019 14:24:33 +01:00

irqchip/gic: Register the distributor's PA instead of its VA in fwnode

Do not expose the distributor's VA (it appears in debugfs). Instead,
record the PA, which at least can be used to precisely identify
the associated irqchip and domain.

Acked-by: Thomas Gleixner 
Signed-off-by: Marc Zyngier 
---
 drivers/irqchip/irq-gic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index e45f45e..b6b8573 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -1627,7 +1627,7 @@ static int __init gic_v2_acpi_init(struct 
acpi_subtable_header *header,
/*
 * Initialize GIC instance zero (no multi-GIC support).
 */
-   domain_handle = irq_domain_alloc_fwnode(gic->raw_dist_base);
+   domain_handle = irq_domain_alloc_fwnode(>base_address);
if (!domain_handle) {
pr_err("Unable to allocate domain handle\n");
gic_teardown(gic);


[tip: irq/core] irqchip/gic-v3: Dynamically allocate PPI partition descriptors

2019-09-06 Thread tip-bot2 for Marc Zyngier
The following commit has been merged into the irq/core branch of tip:

Commit-ID: 52085d3f2028d853f8d6ce7ead2f8a504f6077fa
Gitweb:
https://git.kernel.org/tip/52085d3f2028d853f8d6ce7ead2f8a504f6077fa
Author:Marc Zyngier 
AuthorDate:Thu, 18 Jul 2019 13:05:17 +01:00
Committer: Marc Zyngier 
CommitterDate: Tue, 20 Aug 2019 10:23:34 +01:00

irqchip/gic-v3: Dynamically allocate PPI partition descriptors

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 
---
 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 869a805..f5dbdbf 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;
boolhas_rss;
unsigned intppi_nr;
-   struct partition_desc   *ppi_descs[16];
+   struct partition_desc   **ppi_descs;
 };
 
 static struct gic_chip_data gic_data __read_mostly;
@@ -1354,7 +1354,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;
@@ -1375,6 +1376,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;
@@ -1531,6 +1535,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)
@@ -1582,7 +1590,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 = {