All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] Implement generic IPI support mechanism
@ 2015-11-03 11:12 ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips,
	Qais Yousef, Jonathan Corbet, linux-doc

This series adds support for a generic IPI mechanism that can be used by both
arch and drivers to send IPIs to other CPUs.

The first 9 patches add the new functionality in the generic code.

Patches 10-13 make MIPS GIC irqchip driver support the new API and move MIPS
arch code to use the new generic IPI mechanism if the irqchip driver supports it.

Patch 14 adds IRQ-ipi.txt to Documentation explaining the new API and how to
make use of it.

This series is built on last RFC discussion[1]. I should have taken all
comments into account and hopefully haven't missed any.

This series is based on 4.3 irq/core.

Thanks,
Qais

[1] https://lkml.org/lkml/2015/10/13/227

Qais Yousef (14):
  genirq: Add new IRQ_DOMAIN_FLAGS_IPI
  genirq: Add DOMAIN_BUS_IPI
  genirq: Add GENERIC_IRQ_IPI Kconfig symbol
  genirq: Add new struct ipi_mask and helper functions
  genirq: Add struct ipi_mask to irq_data
  genirq: Add struct ipi_mapping and its helper functions
  genirq: Add a new generic IPI reservation code to irq core
  genirq: Add a new irq_send_ipi() to irq_chip
  genirq: Implement irq_send_ipi() to be used by drivers
  irqchip/mips-gic: Add a IPI hierarchy domain
  MIPS: Add generic SMP IPI support
  MIPS: Make smp CMP, CPS and MT use the new generic IPI functions
  MIPS: Delete smp-gic.c
  Docs: IRQ: Add new IRQ-ipi.txt

 Documentation/IRQ-ipi.txt        |  81 +++++++++++++
 arch/mips/Kconfig                |   6 -
 arch/mips/include/asm/smp-ops.h  |   5 +-
 arch/mips/kernel/Makefile        |   1 -
 arch/mips/kernel/smp-cmp.c       |   4 +-
 arch/mips/kernel/smp-cps.c       |   4 +-
 arch/mips/kernel/smp-gic.c       |  64 ----------
 arch/mips/kernel/smp-mt.c        |   2 +-
 arch/mips/kernel/smp.c           | 136 ++++++++++++++++++++++
 drivers/irqchip/Kconfig          |   2 +
 drivers/irqchip/irq-mips-gic.c   | 244 +++++++++++++++++++++++++--------------
 include/linux/irq.h              | 101 ++++++++++++++++
 include/linux/irqchip/mips-gic.h |   3 -
 include/linux/irqdomain.h        |  20 ++++
 kernel/irq/Kconfig               |   4 +
 kernel/irq/irqdomain.c           |  98 ++++++++++++++++
 kernel/irq/manage.c              | 151 ++++++++++++++++++++++++
 17 files changed, 757 insertions(+), 169 deletions(-)
 create mode 100644 Documentation/IRQ-ipi.txt
 delete mode 100644 arch/mips/kernel/smp-gic.c

Cc: Jonathan Corbet <corbet@lwn.net>
Cc: linux-doc@vger.kernel.org

-- 
2.1.0


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

* [PATCH 00/14] Implement generic IPI support mechanism
@ 2015-11-03 11:12 ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips,
	Qais Yousef, Jonathan Corbet, linux-doc

This series adds support for a generic IPI mechanism that can be used by both
arch and drivers to send IPIs to other CPUs.

The first 9 patches add the new functionality in the generic code.

Patches 10-13 make MIPS GIC irqchip driver support the new API and move MIPS
arch code to use the new generic IPI mechanism if the irqchip driver supports it.

Patch 14 adds IRQ-ipi.txt to Documentation explaining the new API and how to
make use of it.

This series is built on last RFC discussion[1]. I should have taken all
comments into account and hopefully haven't missed any.

This series is based on 4.3 irq/core.

Thanks,
Qais

[1] https://lkml.org/lkml/2015/10/13/227

Qais Yousef (14):
  genirq: Add new IRQ_DOMAIN_FLAGS_IPI
  genirq: Add DOMAIN_BUS_IPI
  genirq: Add GENERIC_IRQ_IPI Kconfig symbol
  genirq: Add new struct ipi_mask and helper functions
  genirq: Add struct ipi_mask to irq_data
  genirq: Add struct ipi_mapping and its helper functions
  genirq: Add a new generic IPI reservation code to irq core
  genirq: Add a new irq_send_ipi() to irq_chip
  genirq: Implement irq_send_ipi() to be used by drivers
  irqchip/mips-gic: Add a IPI hierarchy domain
  MIPS: Add generic SMP IPI support
  MIPS: Make smp CMP, CPS and MT use the new generic IPI functions
  MIPS: Delete smp-gic.c
  Docs: IRQ: Add new IRQ-ipi.txt

 Documentation/IRQ-ipi.txt        |  81 +++++++++++++
 arch/mips/Kconfig                |   6 -
 arch/mips/include/asm/smp-ops.h  |   5 +-
 arch/mips/kernel/Makefile        |   1 -
 arch/mips/kernel/smp-cmp.c       |   4 +-
 arch/mips/kernel/smp-cps.c       |   4 +-
 arch/mips/kernel/smp-gic.c       |  64 ----------
 arch/mips/kernel/smp-mt.c        |   2 +-
 arch/mips/kernel/smp.c           | 136 ++++++++++++++++++++++
 drivers/irqchip/Kconfig          |   2 +
 drivers/irqchip/irq-mips-gic.c   | 244 +++++++++++++++++++++++++--------------
 include/linux/irq.h              | 101 ++++++++++++++++
 include/linux/irqchip/mips-gic.h |   3 -
 include/linux/irqdomain.h        |  20 ++++
 kernel/irq/Kconfig               |   4 +
 kernel/irq/irqdomain.c           |  98 ++++++++++++++++
 kernel/irq/manage.c              | 151 ++++++++++++++++++++++++
 17 files changed, 757 insertions(+), 169 deletions(-)
 create mode 100644 Documentation/IRQ-ipi.txt
 delete mode 100644 arch/mips/kernel/smp-gic.c

Cc: Jonathan Corbet <corbet@lwn.net>
Cc: linux-doc@vger.kernel.org

-- 
2.1.0

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

* [PATCH 01/14] genirq: Add new IRQ_DOMAIN_FLAGS_IPI
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

This flag will be used to identify an IPI domain.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irqdomain.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index d5e5c5bef28c..adb61366ce8b 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -171,6 +171,9 @@ enum {
 	/* Core calls alloc/free recursive through the domain hierarchy. */
 	IRQ_DOMAIN_FLAG_AUTO_RECURSIVE	= (1 << 1),
 
+	/* Irq domain is an IPI domain */
+	IRQ_DOMAIN_FLAG_IPI		= (1 << 2),
+
 	/*
 	 * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
 	 * for implementation specific purposes and ignored by the
@@ -391,6 +394,11 @@ static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
 {
 	return domain->flags & IRQ_DOMAIN_FLAG_HIERARCHY;
 }
+
+static inline bool irq_domain_is_ipi(struct irq_domain *domain)
+{
+	return domain->flags & IRQ_DOMAIN_FLAG_IPI;
+}
 #else	/* CONFIG_IRQ_DOMAIN_HIERARCHY */
 static inline void irq_domain_activate_irq(struct irq_data *data) { }
 static inline void irq_domain_deactivate_irq(struct irq_data *data) { }
@@ -404,6 +412,11 @@ static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
 {
 	return false;
 }
+
+static inline bool irq_domain_is_ipi(struct irq_domain *domain)
+{
+	return false;
+}
 #endif	/* CONFIG_IRQ_DOMAIN_HIERARCHY */
 
 #else /* CONFIG_IRQ_DOMAIN */
-- 
2.1.0


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

* [PATCH 01/14] genirq: Add new IRQ_DOMAIN_FLAGS_IPI
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

This flag will be used to identify an IPI domain.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irqdomain.h | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index d5e5c5bef28c..adb61366ce8b 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -171,6 +171,9 @@ enum {
 	/* Core calls alloc/free recursive through the domain hierarchy. */
 	IRQ_DOMAIN_FLAG_AUTO_RECURSIVE	= (1 << 1),
 
+	/* Irq domain is an IPI domain */
+	IRQ_DOMAIN_FLAG_IPI		= (1 << 2),
+
 	/*
 	 * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
 	 * for implementation specific purposes and ignored by the
@@ -391,6 +394,11 @@ static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
 {
 	return domain->flags & IRQ_DOMAIN_FLAG_HIERARCHY;
 }
+
+static inline bool irq_domain_is_ipi(struct irq_domain *domain)
+{
+	return domain->flags & IRQ_DOMAIN_FLAG_IPI;
+}
 #else	/* CONFIG_IRQ_DOMAIN_HIERARCHY */
 static inline void irq_domain_activate_irq(struct irq_data *data) { }
 static inline void irq_domain_deactivate_irq(struct irq_data *data) { }
@@ -404,6 +412,11 @@ static inline bool irq_domain_is_hierarchy(struct irq_domain *domain)
 {
 	return false;
 }
+
+static inline bool irq_domain_is_ipi(struct irq_domain *domain)
+{
+	return false;
+}
 #endif	/* CONFIG_IRQ_DOMAIN_HIERARCHY */
 
 #else /* CONFIG_IRQ_DOMAIN */
-- 
2.1.0

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

* [PATCH 02/14] genirq: Add DOMAIN_BUS_IPI
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

We need a way to search and match IPI domains.

Using the new enum we can use irq_find_matching_host() to do that.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irqdomain.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index adb61366ce8b..422b6a1617b8 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -73,6 +73,7 @@ enum irq_domain_bus_token {
 	DOMAIN_BUS_PCI_MSI,
 	DOMAIN_BUS_PLATFORM_MSI,
 	DOMAIN_BUS_NEXUS,
+	DOMAIN_BUS_IPI,
 };
 
 /**
-- 
2.1.0


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

* [PATCH 02/14] genirq: Add DOMAIN_BUS_IPI
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

We need a way to search and match IPI domains.

Using the new enum we can use irq_find_matching_host() to do that.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irqdomain.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index adb61366ce8b..422b6a1617b8 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -73,6 +73,7 @@ enum irq_domain_bus_token {
 	DOMAIN_BUS_PCI_MSI,
 	DOMAIN_BUS_PLATFORM_MSI,
 	DOMAIN_BUS_NEXUS,
+	DOMAIN_BUS_IPI,
 };
 
 /**
-- 
2.1.0

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

* [PATCH 03/14] genirq: Add GENERIC_IRQ_IPI Kconfig symbol
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

irqchip should select this config to denote it supports generic IPI.

This will aid generic arch code to know when it can use generic IPI layer.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 kernel/irq/Kconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 3b48dab80164..3bbfd6a9c475 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -64,6 +64,10 @@ config IRQ_DOMAIN_HIERARCHY
 	bool
 	select IRQ_DOMAIN
 
+# Generic IRQ IPI support
+config GENERIC_IRQ_IPI
+	bool
+
 # Generic MSI interrupt support
 config GENERIC_MSI_IRQ
 	bool
-- 
2.1.0


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

* [PATCH 03/14] genirq: Add GENERIC_IRQ_IPI Kconfig symbol
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

irqchip should select this config to denote it supports generic IPI.

This will aid generic arch code to know when it can use generic IPI layer.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 kernel/irq/Kconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 3b48dab80164..3bbfd6a9c475 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -64,6 +64,10 @@ config IRQ_DOMAIN_HIERARCHY
 	bool
 	select IRQ_DOMAIN
 
+# Generic IRQ IPI support
+config GENERIC_IRQ_IPI
+	bool
+
 # Generic MSI interrupt support
 config GENERIC_MSI_IRQ
 	bool
-- 
2.1.0

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

* [PATCH 04/14] genirq: Add new struct ipi_mask and helper functions
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

cpumask is limited to NR_CPUS. Introduce ipi_mask which allows us to address
cpu range that is higher than NR_CPUS which is required for drivers to send
IPIs for coprocessor that are outside Linux CPU range.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irq.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 3c1c96786248..77ed4c53ef64 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -19,6 +19,7 @@
 #include <linux/irqreturn.h>
 #include <linux/irqnr.h>
 #include <linux/errno.h>
+#include <linux/slab.h>
 #include <linux/topology.h>
 #include <linux/wait.h>
 #include <linux/io.h>
@@ -128,6 +129,25 @@ struct msi_desc;
 struct irq_domain;
 
 /**
+ * struct ipi_mask - IPI mask information
+ * @nbits: number of bits in cpumask
+ * @global: whether the mask is SMP IPI ie: subset of cpu_possible_mask or not
+ * @cpumask: cpumask to be used when the ipi_mask is global
+ * @cpu_bitmap: the cpu bitmap to use when the ipi_mask is not global
+ *
+ * ipi_mask is similar to cpumask, but it provides nbits that's configurable
+ * rather than fixed to NR_CPUS.
+ */
+struct ipi_mask {
+	unsigned int	nbits;
+	bool		global;
+	union {
+		struct cpumask	cpumask;
+		unsigned long	cpu_bitmap[0];
+	};
+};
+
+/**
  * struct irq_common_data - per irq data shared by all irqchips
  * @state_use_accessors: status information for irq chip functions.
  *			Use accessor functions to deal with it
@@ -934,4 +954,52 @@ static inline u32 irq_reg_readl(struct irq_chip_generic *gc,
 		return readl(gc->reg_base + reg_offset);
 }
 
+static inline const unsigned long *ipi_mask_bits(const struct ipi_mask *ipimask)
+{
+	if (ipimask->global)
+		return cpumask_bits(&ipimask->cpumask);
+	else
+		return ipimask->cpu_bitmap;
+}
+
+static inline unsigned int ipi_mask_weight(const struct ipi_mask *ipimask)
+{
+	if (ipimask->global)
+		return cpumask_weight(&ipimask->cpumask);
+	else
+		return bitmap_weight(ipimask->cpu_bitmap, ipimask->nbits);
+}
+
+static inline void ipi_mask_copy(struct ipi_mask *dst,
+				 const struct ipi_mask *src)
+{
+	dst->nbits = src->nbits;
+	dst->global = src->global;
+
+	if (src->global)
+		return cpumask_copy(&dst->cpumask, &src->cpumask);
+	else
+		return bitmap_copy(dst->cpu_bitmap,
+					src->cpu_bitmap, src->nbits);
+}
+
+static inline struct ipi_mask *ipi_mask_alloc(unsigned int nbits)
+{
+	size_t size = sizeof(struct ipi_mask) + BITS_TO_LONGS(nbits);
+	return kzalloc(size, GFP_KERNEL);
+}
+
+static inline void ipi_mask_free(struct ipi_mask *ipimask)
+{
+	kfree(ipimask);
+}
+
+static inline void ipi_mask_set_cpumask(struct ipi_mask *ipimask,
+					const struct cpumask *cpumask)
+{
+	ipimask->nbits = NR_CPUS;
+	ipimask->global = true;
+	cpumask_copy(&ipimask->cpumask, cpumask);
+}
+
 #endif /* _LINUX_IRQ_H */
-- 
2.1.0


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

* [PATCH 04/14] genirq: Add new struct ipi_mask and helper functions
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

cpumask is limited to NR_CPUS. Introduce ipi_mask which allows us to address
cpu range that is higher than NR_CPUS which is required for drivers to send
IPIs for coprocessor that are outside Linux CPU range.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irq.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 3c1c96786248..77ed4c53ef64 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -19,6 +19,7 @@
 #include <linux/irqreturn.h>
 #include <linux/irqnr.h>
 #include <linux/errno.h>
+#include <linux/slab.h>
 #include <linux/topology.h>
 #include <linux/wait.h>
 #include <linux/io.h>
@@ -128,6 +129,25 @@ struct msi_desc;
 struct irq_domain;
 
 /**
+ * struct ipi_mask - IPI mask information
+ * @nbits: number of bits in cpumask
+ * @global: whether the mask is SMP IPI ie: subset of cpu_possible_mask or not
+ * @cpumask: cpumask to be used when the ipi_mask is global
+ * @cpu_bitmap: the cpu bitmap to use when the ipi_mask is not global
+ *
+ * ipi_mask is similar to cpumask, but it provides nbits that's configurable
+ * rather than fixed to NR_CPUS.
+ */
+struct ipi_mask {
+	unsigned int	nbits;
+	bool		global;
+	union {
+		struct cpumask	cpumask;
+		unsigned long	cpu_bitmap[0];
+	};
+};
+
+/**
  * struct irq_common_data - per irq data shared by all irqchips
  * @state_use_accessors: status information for irq chip functions.
  *			Use accessor functions to deal with it
@@ -934,4 +954,52 @@ static inline u32 irq_reg_readl(struct irq_chip_generic *gc,
 		return readl(gc->reg_base + reg_offset);
 }
 
+static inline const unsigned long *ipi_mask_bits(const struct ipi_mask *ipimask)
+{
+	if (ipimask->global)
+		return cpumask_bits(&ipimask->cpumask);
+	else
+		return ipimask->cpu_bitmap;
+}
+
+static inline unsigned int ipi_mask_weight(const struct ipi_mask *ipimask)
+{
+	if (ipimask->global)
+		return cpumask_weight(&ipimask->cpumask);
+	else
+		return bitmap_weight(ipimask->cpu_bitmap, ipimask->nbits);
+}
+
+static inline void ipi_mask_copy(struct ipi_mask *dst,
+				 const struct ipi_mask *src)
+{
+	dst->nbits = src->nbits;
+	dst->global = src->global;
+
+	if (src->global)
+		return cpumask_copy(&dst->cpumask, &src->cpumask);
+	else
+		return bitmap_copy(dst->cpu_bitmap,
+					src->cpu_bitmap, src->nbits);
+}
+
+static inline struct ipi_mask *ipi_mask_alloc(unsigned int nbits)
+{
+	size_t size = sizeof(struct ipi_mask) + BITS_TO_LONGS(nbits);
+	return kzalloc(size, GFP_KERNEL);
+}
+
+static inline void ipi_mask_free(struct ipi_mask *ipimask)
+{
+	kfree(ipimask);
+}
+
+static inline void ipi_mask_set_cpumask(struct ipi_mask *ipimask,
+					const struct cpumask *cpumask)
+{
+	ipimask->nbits = NR_CPUS;
+	ipimask->global = true;
+	cpumask_copy(&ipimask->cpumask, cpumask);
+}
+
 #endif /* _LINUX_IRQ_H */
-- 
2.1.0

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

* [PATCH 05/14] genirq: Add struct ipi_mask to irq_data
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

It has a similar role to affinity mask, but tracks the IPI affinity instead.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irq.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 77ed4c53ef64..2d3ff30c0cee 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -164,6 +164,7 @@ struct irq_common_data {
 	void			*handler_data;
 	struct msi_desc		*msi_desc;
 	cpumask_var_t		affinity;
+	struct ipi_mask		*ipi_mask;
 };
 
 /**
@@ -689,6 +690,11 @@ static inline int irq_data_get_node(struct irq_data *d)
 	return irq_common_data_get_node(d->common);
 }
 
+static inline struct cpumask *irq_data_get_ipi_mask(struct irq_data *d)
+{
+	return &d->common->ipi_mask->cpumask;
+}
+
 static inline struct cpumask *irq_get_affinity_mask(int irq)
 {
 	struct irq_data *d = irq_get_irq_data(irq);
-- 
2.1.0


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

* [PATCH 05/14] genirq: Add struct ipi_mask to irq_data
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

It has a similar role to affinity mask, but tracks the IPI affinity instead.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irq.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 77ed4c53ef64..2d3ff30c0cee 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -164,6 +164,7 @@ struct irq_common_data {
 	void			*handler_data;
 	struct msi_desc		*msi_desc;
 	cpumask_var_t		affinity;
+	struct ipi_mask		*ipi_mask;
 };
 
 /**
@@ -689,6 +690,11 @@ static inline int irq_data_get_node(struct irq_data *d)
 	return irq_common_data_get_node(d->common);
 }
 
+static inline struct cpumask *irq_data_get_ipi_mask(struct irq_data *d)
+{
+	return &d->common->ipi_mask->cpumask;
+}
+
 static inline struct cpumask *irq_get_affinity_mask(int irq)
 {
 	struct irq_data *d = irq_get_irq_data(irq);
-- 
2.1.0

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

* [PATCH 06/14] genirq: Add struct ipi_mapping and its helper functions
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

struct ipi_mapping will provide a mechanism for irqchip code to fill out the
mapping at reservation and to look it up when sending.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irq.h | 21 +++++++++++++
 kernel/irq/manage.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 107 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 2d3ff30c0cee..ccd53143cc1e 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -1008,4 +1008,25 @@ static inline void ipi_mask_set_cpumask(struct ipi_mask *ipimask,
 	cpumask_copy(&ipimask->cpumask, cpumask);
 }
 
+#define INVALID_HWIRQ	-1
+
+/**
+ * struct ipi_mapping - IPI mapping information object
+ * @nr_hwirqs: number of hwirqs mapped
+ * @nr_cpus: number of cpus the controller can talk to
+ * @cpumap: per cpu hwirq mapping table
+ */
+struct ipi_mapping {
+	unsigned int nr_hwirqs;
+	unsigned int nr_cpus;
+	unsigned int cpumap[];
+};
+
+struct ipi_mapping *irq_alloc_ipi_mapping(unsigned int nr_cpus);
+void irq_free_ipi_mapping(struct ipi_mapping *map);
+int irq_map_ipi(struct ipi_mapping *map,
+		unsigned int cpu, irq_hw_number_t hwirq);
+int irq_unmap_ipi(struct ipi_mapping *map,
+		  unsigned int cpu, irq_hw_number_t *hwirq);
+
 #endif /* _LINUX_IRQ_H */
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index a71175ff98d5..67a71667a359 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2001,3 +2001,89 @@ int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
 	return err;
 }
 EXPORT_SYMBOL_GPL(irq_set_irqchip_state);
+
+/**
+ *	irq_alloc_ipi_mapping - allocate memory for struct ipi_mapping
+ *	@nr_cpus: number of CPUs the mapping will have
+ *
+ *	Will allocate and setup ipi_mapping structure.
+ *
+ *	Returns a valid ipi_mapping pointer on success and NULL on error.
+ */
+struct ipi_mapping *irq_alloc_ipi_mapping(unsigned int nr_cpus)
+{
+	struct ipi_mapping *map;
+	int i;
+
+	map = kzalloc(sizeof(struct ipi_mapping) +
+			BITS_TO_LONGS(nr_cpus), GFP_KERNEL);
+	if (!map)
+		return NULL;
+
+	map->nr_cpus = nr_cpus;
+
+	memset(map->cpumap, INVALID_HWIRQ, nr_cpus);
+
+	return map;
+}
+
+/**
+ *	irq_free_ipi_mapping - release mempry associated with ipi_mapping struct
+ *	@map: pointer to struct ipi_mapping to be freed
+ *
+ *	Release the memory allocated for sturct ipi_mapping to the system.
+ */
+void irq_free_ipi_mapping(struct ipi_mapping *map)
+{
+	kfree(map);
+}
+
+/**
+ *	irq_map_ipi - create a CPU to HWIRQ mapping for an IPI
+ *	@map: pointer to the mapping structure
+ *	@cpu: the CPU to map
+ *	@hwirq: the HWIRQ to associate with @cpu
+ *
+ *	Returns zero on success and negative error number on failure.
+ */
+int irq_map_ipi(struct ipi_mapping *map,
+		unsigned int cpu, irq_hw_number_t hwirq)
+{
+	if (cpu >= map->nr_cpus)
+		return -EINVAL;
+
+	map->cpumap[cpu] = hwirq;
+	map->nr_hwirqs++;
+
+	return 0;
+}
+
+/**
+ *	irq_unmap_ipi - remove the CPU mapping of an IPI
+ *	@map: pointer to the mapping structure
+ *	@cpu: the CPU to be unmapped
+ *	@hwirq: pointer to HWIRQ to be filled with old value before unampping
+ *
+ *	Mark the IPI mapping of a CPU to INVALID_HWIRQ setting @hwirq to the
+ *	old value before unamapping. This old value might be required by the
+ *	caller to return it to the pool of IPIs in a dynamic system.
+ *
+ *	Returns zero on success and negative error number on failure.
+ */
+int irq_unmap_ipi(struct ipi_mapping *map,
+		  unsigned int cpu, irq_hw_number_t *hwirq)
+{
+	if (cpu >= map->nr_cpus)
+		return -EINVAL;
+
+	if (map->cpumap[cpu] == INVALID_HWIRQ)
+		return -EINVAL;
+
+	if (hwirq)
+		*hwirq = map->cpumap[cpu];
+
+	map->cpumap[cpu] = INVALID_HWIRQ;
+	map->nr_hwirqs--;
+
+	return 0;
+}
-- 
2.1.0


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

* [PATCH 06/14] genirq: Add struct ipi_mapping and its helper functions
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

struct ipi_mapping will provide a mechanism for irqchip code to fill out the
mapping at reservation and to look it up when sending.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irq.h | 21 +++++++++++++
 kernel/irq/manage.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 107 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 2d3ff30c0cee..ccd53143cc1e 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -1008,4 +1008,25 @@ static inline void ipi_mask_set_cpumask(struct ipi_mask *ipimask,
 	cpumask_copy(&ipimask->cpumask, cpumask);
 }
 
+#define INVALID_HWIRQ	-1
+
+/**
+ * struct ipi_mapping - IPI mapping information object
+ * @nr_hwirqs: number of hwirqs mapped
+ * @nr_cpus: number of cpus the controller can talk to
+ * @cpumap: per cpu hwirq mapping table
+ */
+struct ipi_mapping {
+	unsigned int nr_hwirqs;
+	unsigned int nr_cpus;
+	unsigned int cpumap[];
+};
+
+struct ipi_mapping *irq_alloc_ipi_mapping(unsigned int nr_cpus);
+void irq_free_ipi_mapping(struct ipi_mapping *map);
+int irq_map_ipi(struct ipi_mapping *map,
+		unsigned int cpu, irq_hw_number_t hwirq);
+int irq_unmap_ipi(struct ipi_mapping *map,
+		  unsigned int cpu, irq_hw_number_t *hwirq);
+
 #endif /* _LINUX_IRQ_H */
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index a71175ff98d5..67a71667a359 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2001,3 +2001,89 @@ int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
 	return err;
 }
 EXPORT_SYMBOL_GPL(irq_set_irqchip_state);
+
+/**
+ *	irq_alloc_ipi_mapping - allocate memory for struct ipi_mapping
+ *	@nr_cpus: number of CPUs the mapping will have
+ *
+ *	Will allocate and setup ipi_mapping structure.
+ *
+ *	Returns a valid ipi_mapping pointer on success and NULL on error.
+ */
+struct ipi_mapping *irq_alloc_ipi_mapping(unsigned int nr_cpus)
+{
+	struct ipi_mapping *map;
+	int i;
+
+	map = kzalloc(sizeof(struct ipi_mapping) +
+			BITS_TO_LONGS(nr_cpus), GFP_KERNEL);
+	if (!map)
+		return NULL;
+
+	map->nr_cpus = nr_cpus;
+
+	memset(map->cpumap, INVALID_HWIRQ, nr_cpus);
+
+	return map;
+}
+
+/**
+ *	irq_free_ipi_mapping - release mempry associated with ipi_mapping struct
+ *	@map: pointer to struct ipi_mapping to be freed
+ *
+ *	Release the memory allocated for sturct ipi_mapping to the system.
+ */
+void irq_free_ipi_mapping(struct ipi_mapping *map)
+{
+	kfree(map);
+}
+
+/**
+ *	irq_map_ipi - create a CPU to HWIRQ mapping for an IPI
+ *	@map: pointer to the mapping structure
+ *	@cpu: the CPU to map
+ *	@hwirq: the HWIRQ to associate with @cpu
+ *
+ *	Returns zero on success and negative error number on failure.
+ */
+int irq_map_ipi(struct ipi_mapping *map,
+		unsigned int cpu, irq_hw_number_t hwirq)
+{
+	if (cpu >= map->nr_cpus)
+		return -EINVAL;
+
+	map->cpumap[cpu] = hwirq;
+	map->nr_hwirqs++;
+
+	return 0;
+}
+
+/**
+ *	irq_unmap_ipi - remove the CPU mapping of an IPI
+ *	@map: pointer to the mapping structure
+ *	@cpu: the CPU to be unmapped
+ *	@hwirq: pointer to HWIRQ to be filled with old value before unampping
+ *
+ *	Mark the IPI mapping of a CPU to INVALID_HWIRQ setting @hwirq to the
+ *	old value before unamapping. This old value might be required by the
+ *	caller to return it to the pool of IPIs in a dynamic system.
+ *
+ *	Returns zero on success and negative error number on failure.
+ */
+int irq_unmap_ipi(struct ipi_mapping *map,
+		  unsigned int cpu, irq_hw_number_t *hwirq)
+{
+	if (cpu >= map->nr_cpus)
+		return -EINVAL;
+
+	if (map->cpumap[cpu] == INVALID_HWIRQ)
+		return -EINVAL;
+
+	if (hwirq)
+		*hwirq = map->cpumap[cpu];
+
+	map->cpumap[cpu] = INVALID_HWIRQ;
+	map->nr_hwirqs--;
+
+	return 0;
+}
-- 
2.1.0

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

* [PATCH 07/14] genirq: Add a new generic IPI reservation code to irq core
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

Add a generic mechanism to dynamically allocate an IPI.

With this change the user can call irq_reserve_ipi() to dynamically allocate an
IPI and use the associated virq to send one to 1 or more cpus.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irqdomain.h |  6 +++
 kernel/irq/irqdomain.c    | 98 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 104 insertions(+)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 422b6a1617b8..9ba67bfe8ad2 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -39,6 +39,7 @@ struct irq_domain;
 struct of_device_id;
 struct irq_chip;
 struct irq_data;
+struct ipi_mask;
 
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS	16
@@ -333,6 +334,11 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
 			const u32 *intspec, unsigned int intsize,
 			irq_hw_number_t *out_hwirq, unsigned int *out_type);
 
+/* IPI functions */
+unsigned int irq_reserve_ipi(struct irq_domain *domain,
+			     const struct ipi_mask *dest);
+void irq_destroy_ipi(unsigned int irq);
+
 /* V2 interfaces to support hierarchy IRQ domains. */
 extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain,
 						unsigned int virq);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 22aa9612ef7c..dd240914301d 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -852,6 +852,104 @@ static int irq_domain_alloc_descs(int virq, unsigned int cnt,
 	return virq;
 }
 
+/**
+ * irq_reserve_ipi() - setup an IPI to destination cpumask
+ * @domain: IPI domain
+ * @dest: cpumask of cpus to receive the IPI
+ *
+ * Allocate a virq that can be used to send IPI to any CPU in dest mask.
+ *
+ * On success it'll return linux irq number and 0 on failure
+ */
+unsigned int irq_reserve_ipi(struct irq_domain *domain,
+			     const struct ipi_mask *dest)
+{
+	struct irq_data *data;
+	unsigned int nr_irqs;
+	int virq, i;
+
+	if (domain == NULL) {
+		pr_warn("Must provide a valid IPI domain!\n");
+		return 0;
+	}
+
+	if (!irq_domain_is_ipi(domain)) {
+		pr_warn("Not an IPI domain!\n");
+		return 0;
+	}
+
+	/* always allocate a virq per cpu */
+	nr_irqs = ipi_mask_weight(dest);
+
+	virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE);
+	if (virq <= 0) {
+		pr_warn("Can't reserve IPI, failed to alloc descs\n");
+		return 0;
+	}
+
+	virq = __irq_domain_alloc_irqs(domain, virq, nr_irqs, NUMA_NO_NODE,
+					(void *) dest, true);
+	if (virq <= 0) {
+		pr_warn("Can't reserve IPI, failed to alloc irqs\n");
+		goto free_descs;
+	}
+
+	for (i = virq; i < virq + nr_irqs; i++) {
+		data = irq_get_irq_data(i);
+		data->common->ipi_mask = ipi_mask_alloc(dest->nbits);
+		if (!data->common->ipi_mask)
+			goto free_ipi_mask;
+		ipi_mask_copy(data->common->ipi_mask, dest);
+	}
+
+	return virq;
+
+free_ipi_mask:
+	for (i = virq; i < virq + nr_irqs; i++) {
+		data = irq_get_irq_data(i);
+		ipi_mask_free(data->common->ipi_mask);
+	}
+free_descs:
+	irq_free_descs(virq, nr_irqs);
+	return 0;
+}
+
+/**
+ * irq_destroy_ipi() - unreserve an IPI that was previously allocated
+ * @irq: linux irq number to be destroyed
+ *
+ * Return the IPIs allocated with irq_reserve_ipi() to the system destroying all
+ * virqs associated with them.
+ */
+void irq_destroy_ipi(unsigned int irq)
+{
+	struct irq_data *data = irq_get_irq_data(irq);
+	struct irq_domain *domain;
+	unsigned int nr_irqs, i;
+
+	if (!irq || !data)
+		return;
+
+	domain = data->domain;
+	if (WARN_ON(domain == NULL))
+		return;
+
+	if (!irq_domain_is_ipi(domain)) {
+		pr_warn("Not an IPI domain!\n");
+		return;
+	}
+
+	nr_irqs = ipi_mask_weight(data->common->ipi_mask);
+	ipi_mask_free(data->common->ipi_mask);
+
+	for (i = irq + 1; i < irq + nr_irqs; i++) {
+		data = irq_get_irq_data(i);
+		ipi_mask_free(data->common->ipi_mask);
+	}
+
+	irq_domain_free_irqs(irq, nr_irqs);
+}
+
 #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
 /**
  * irq_domain_create_hierarchy - Add a irqdomain into the hierarchy
-- 
2.1.0


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

* [PATCH 07/14] genirq: Add a new generic IPI reservation code to irq core
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

Add a generic mechanism to dynamically allocate an IPI.

With this change the user can call irq_reserve_ipi() to dynamically allocate an
IPI and use the associated virq to send one to 1 or more cpus.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irqdomain.h |  6 +++
 kernel/irq/irqdomain.c    | 98 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 104 insertions(+)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 422b6a1617b8..9ba67bfe8ad2 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -39,6 +39,7 @@ struct irq_domain;
 struct of_device_id;
 struct irq_chip;
 struct irq_data;
+struct ipi_mask;
 
 /* Number of irqs reserved for a legacy isa controller */
 #define NUM_ISA_INTERRUPTS	16
@@ -333,6 +334,11 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
 			const u32 *intspec, unsigned int intsize,
 			irq_hw_number_t *out_hwirq, unsigned int *out_type);
 
+/* IPI functions */
+unsigned int irq_reserve_ipi(struct irq_domain *domain,
+			     const struct ipi_mask *dest);
+void irq_destroy_ipi(unsigned int irq);
+
 /* V2 interfaces to support hierarchy IRQ domains. */
 extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain,
 						unsigned int virq);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 22aa9612ef7c..dd240914301d 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -852,6 +852,104 @@ static int irq_domain_alloc_descs(int virq, unsigned int cnt,
 	return virq;
 }
 
+/**
+ * irq_reserve_ipi() - setup an IPI to destination cpumask
+ * @domain: IPI domain
+ * @dest: cpumask of cpus to receive the IPI
+ *
+ * Allocate a virq that can be used to send IPI to any CPU in dest mask.
+ *
+ * On success it'll return linux irq number and 0 on failure
+ */
+unsigned int irq_reserve_ipi(struct irq_domain *domain,
+			     const struct ipi_mask *dest)
+{
+	struct irq_data *data;
+	unsigned int nr_irqs;
+	int virq, i;
+
+	if (domain == NULL) {
+		pr_warn("Must provide a valid IPI domain!\n");
+		return 0;
+	}
+
+	if (!irq_domain_is_ipi(domain)) {
+		pr_warn("Not an IPI domain!\n");
+		return 0;
+	}
+
+	/* always allocate a virq per cpu */
+	nr_irqs = ipi_mask_weight(dest);
+
+	virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE);
+	if (virq <= 0) {
+		pr_warn("Can't reserve IPI, failed to alloc descs\n");
+		return 0;
+	}
+
+	virq = __irq_domain_alloc_irqs(domain, virq, nr_irqs, NUMA_NO_NODE,
+					(void *) dest, true);
+	if (virq <= 0) {
+		pr_warn("Can't reserve IPI, failed to alloc irqs\n");
+		goto free_descs;
+	}
+
+	for (i = virq; i < virq + nr_irqs; i++) {
+		data = irq_get_irq_data(i);
+		data->common->ipi_mask = ipi_mask_alloc(dest->nbits);
+		if (!data->common->ipi_mask)
+			goto free_ipi_mask;
+		ipi_mask_copy(data->common->ipi_mask, dest);
+	}
+
+	return virq;
+
+free_ipi_mask:
+	for (i = virq; i < virq + nr_irqs; i++) {
+		data = irq_get_irq_data(i);
+		ipi_mask_free(data->common->ipi_mask);
+	}
+free_descs:
+	irq_free_descs(virq, nr_irqs);
+	return 0;
+}
+
+/**
+ * irq_destroy_ipi() - unreserve an IPI that was previously allocated
+ * @irq: linux irq number to be destroyed
+ *
+ * Return the IPIs allocated with irq_reserve_ipi() to the system destroying all
+ * virqs associated with them.
+ */
+void irq_destroy_ipi(unsigned int irq)
+{
+	struct irq_data *data = irq_get_irq_data(irq);
+	struct irq_domain *domain;
+	unsigned int nr_irqs, i;
+
+	if (!irq || !data)
+		return;
+
+	domain = data->domain;
+	if (WARN_ON(domain == NULL))
+		return;
+
+	if (!irq_domain_is_ipi(domain)) {
+		pr_warn("Not an IPI domain!\n");
+		return;
+	}
+
+	nr_irqs = ipi_mask_weight(data->common->ipi_mask);
+	ipi_mask_free(data->common->ipi_mask);
+
+	for (i = irq + 1; i < irq + nr_irqs; i++) {
+		data = irq_get_irq_data(i);
+		ipi_mask_free(data->common->ipi_mask);
+	}
+
+	irq_domain_free_irqs(irq, nr_irqs);
+}
+
 #ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY
 /**
  * irq_domain_create_hierarchy - Add a irqdomain into the hierarchy
-- 
2.1.0

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

* [PATCH 08/14] genirq: Add a new irq_send_ipi() to irq_chip
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

Introduce the new function to allow generic IPI send mechanism to be
used from drivers code.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irq.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index ccd53143cc1e..3b2f448b7ac3 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -362,6 +362,7 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
  * @irq_get_irqchip_state:	return the internal state of an interrupt
  * @irq_set_irqchip_state:	set the internal state of a interrupt
  * @irq_set_vcpu_affinity:	optional to target a vCPU in a virtual machine
+ * @irq_send_ipi:	send an IPI to destination cpus
  * @flags:		chip specific flags
  */
 struct irq_chip {
@@ -406,6 +407,8 @@ struct irq_chip {
 
 	int		(*irq_set_vcpu_affinity)(struct irq_data *data, void *vcpu_info);
 
+	void		(*irq_send_ipi)(struct irq_data *data, const struct ipi_mask *dest);
+
 	unsigned long	flags;
 };
 
-- 
2.1.0


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

* [PATCH 08/14] genirq: Add a new irq_send_ipi() to irq_chip
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

Introduce the new function to allow generic IPI send mechanism to be
used from drivers code.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irq.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index ccd53143cc1e..3b2f448b7ac3 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -362,6 +362,7 @@ static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
  * @irq_get_irqchip_state:	return the internal state of an interrupt
  * @irq_set_irqchip_state:	set the internal state of a interrupt
  * @irq_set_vcpu_affinity:	optional to target a vCPU in a virtual machine
+ * @irq_send_ipi:	send an IPI to destination cpus
  * @flags:		chip specific flags
  */
 struct irq_chip {
@@ -406,6 +407,8 @@ struct irq_chip {
 
 	int		(*irq_set_vcpu_affinity)(struct irq_data *data, void *vcpu_info);
 
+	void		(*irq_send_ipi)(struct irq_data *data, const struct ipi_mask *dest);
+
 	unsigned long	flags;
 };
 
-- 
2.1.0

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

* [PATCH 09/14] genirq: Implement irq_send_ipi() to be used by drivers
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

There are 2 variants. __irq_desc_send_ipi() is meant to be used by arch code to
save the desc lookup when doing SMP IPIs.

irq_send_ipi() is meant for drivers that want to send IPIs to coprocessors they
interact with.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irq.h |  3 +++
 kernel/irq/manage.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 3b2f448b7ac3..680bee078879 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -1032,4 +1032,7 @@ int irq_map_ipi(struct ipi_mapping *map,
 int irq_unmap_ipi(struct ipi_mapping *map,
 		  unsigned int cpu, irq_hw_number_t *hwirq);
 
+int __irq_desc_send_ipi(struct irq_desc *desc, const struct ipi_mask *dest);
+int irq_send_ipi(unsigned int virq, const struct ipi_mask *dest);
+
 #endif /* _LINUX_IRQ_H */
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 67a71667a359..4bdf6df95b45 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2013,7 +2013,6 @@ EXPORT_SYMBOL_GPL(irq_set_irqchip_state);
 struct ipi_mapping *irq_alloc_ipi_mapping(unsigned int nr_cpus)
 {
 	struct ipi_mapping *map;
-	int i;
 
 	map = kzalloc(sizeof(struct ipi_mapping) +
 			BITS_TO_LONGS(nr_cpus), GFP_KERNEL);
@@ -2087,3 +2086,69 @@ int irq_unmap_ipi(struct ipi_mapping *map,
 
 	return 0;
 }
+
+/**
+ *	__irq_desc_send_ipi - send an IPI to target CPU(s)
+ *	@irq_desc: pointer to irq_desc of the IRQ
+ *	@dest: dest CPU(s), must be the same or a subset of the mask passed to
+ *	       irq_reserve_ipi()
+ *
+ *	Sends an IPI to all cpus in dest mask.
+ *	This function is meant to be used from arch code to save the need to do
+ *	desc lookup that happens in the generic irq_send_ipi().
+ *
+ *	Returns zero on success and negative error number on failure.
+ */
+int __irq_desc_send_ipi(struct irq_desc *desc, const struct ipi_mask *dest)
+{
+	struct irq_data *data = irq_desc_get_irq_data(desc);
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
+
+	if (!chip || !chip->irq_send_ipi)
+		return -EINVAL;
+
+	if (dest->nbits > data->common->ipi_mask->nbits)
+		return -EINVAL;
+
+	/*
+	 * Do not validate the mask for IPIs marked global. These are
+	 * regular IPIs so we can avoid the operation as their target
+	 * mask is the cpu_possible_mask.
+	 */
+	if (!data->common->ipi_mask->global) {
+		if (dest->global)
+			return -EINVAL;
+
+		if (!bitmap_subset(dest->cpu_bitmap,
+				   data->common->ipi_mask->cpu_bitmap,
+				   dest->nbits))
+			return -EINVAL;
+	} else {
+		if (!dest->global)
+			return -EINVAL;
+	}
+
+	chip->irq_send_ipi(data, dest);
+	return 0;
+}
+
+/**
+ *	irq_send_ipi - send an IPI to target CPU(s)
+ *	@irq: linux irq number from irq_reserve_ipi()
+ *	@dest: dest CPU(s), must be the same or a subset of the mask passed to
+ *	       irq_reserve_ipi()
+ *
+ *	Sends an IPI to all cpus in dest mask.
+ *
+ *	Returns zero on success and negative error number on failure.
+ */
+int irq_send_ipi(unsigned int virq, const struct ipi_mask *dest)
+{
+	struct irq_desc *desc = irq_to_desc(virq);
+
+	if (!desc)
+		return -EINVAL;
+
+	return __irq_desc_send_ipi(desc, dest);
+}
+EXPORT_SYMBOL_GPL(irq_send_ipi);
-- 
2.1.0


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

* [PATCH 09/14] genirq: Implement irq_send_ipi() to be used by drivers
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

There are 2 variants. __irq_desc_send_ipi() is meant to be used by arch code to
save the desc lookup when doing SMP IPIs.

irq_send_ipi() is meant for drivers that want to send IPIs to coprocessors they
interact with.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 include/linux/irq.h |  3 +++
 kernel/irq/manage.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 3b2f448b7ac3..680bee078879 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -1032,4 +1032,7 @@ int irq_map_ipi(struct ipi_mapping *map,
 int irq_unmap_ipi(struct ipi_mapping *map,
 		  unsigned int cpu, irq_hw_number_t *hwirq);
 
+int __irq_desc_send_ipi(struct irq_desc *desc, const struct ipi_mask *dest);
+int irq_send_ipi(unsigned int virq, const struct ipi_mask *dest);
+
 #endif /* _LINUX_IRQ_H */
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 67a71667a359..4bdf6df95b45 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2013,7 +2013,6 @@ EXPORT_SYMBOL_GPL(irq_set_irqchip_state);
 struct ipi_mapping *irq_alloc_ipi_mapping(unsigned int nr_cpus)
 {
 	struct ipi_mapping *map;
-	int i;
 
 	map = kzalloc(sizeof(struct ipi_mapping) +
 			BITS_TO_LONGS(nr_cpus), GFP_KERNEL);
@@ -2087,3 +2086,69 @@ int irq_unmap_ipi(struct ipi_mapping *map,
 
 	return 0;
 }
+
+/**
+ *	__irq_desc_send_ipi - send an IPI to target CPU(s)
+ *	@irq_desc: pointer to irq_desc of the IRQ
+ *	@dest: dest CPU(s), must be the same or a subset of the mask passed to
+ *	       irq_reserve_ipi()
+ *
+ *	Sends an IPI to all cpus in dest mask.
+ *	This function is meant to be used from arch code to save the need to do
+ *	desc lookup that happens in the generic irq_send_ipi().
+ *
+ *	Returns zero on success and negative error number on failure.
+ */
+int __irq_desc_send_ipi(struct irq_desc *desc, const struct ipi_mask *dest)
+{
+	struct irq_data *data = irq_desc_get_irq_data(desc);
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
+
+	if (!chip || !chip->irq_send_ipi)
+		return -EINVAL;
+
+	if (dest->nbits > data->common->ipi_mask->nbits)
+		return -EINVAL;
+
+	/*
+	 * Do not validate the mask for IPIs marked global. These are
+	 * regular IPIs so we can avoid the operation as their target
+	 * mask is the cpu_possible_mask.
+	 */
+	if (!data->common->ipi_mask->global) {
+		if (dest->global)
+			return -EINVAL;
+
+		if (!bitmap_subset(dest->cpu_bitmap,
+				   data->common->ipi_mask->cpu_bitmap,
+				   dest->nbits))
+			return -EINVAL;
+	} else {
+		if (!dest->global)
+			return -EINVAL;
+	}
+
+	chip->irq_send_ipi(data, dest);
+	return 0;
+}
+
+/**
+ *	irq_send_ipi - send an IPI to target CPU(s)
+ *	@irq: linux irq number from irq_reserve_ipi()
+ *	@dest: dest CPU(s), must be the same or a subset of the mask passed to
+ *	       irq_reserve_ipi()
+ *
+ *	Sends an IPI to all cpus in dest mask.
+ *
+ *	Returns zero on success and negative error number on failure.
+ */
+int irq_send_ipi(unsigned int virq, const struct ipi_mask *dest)
+{
+	struct irq_desc *desc = irq_to_desc(virq);
+
+	if (!desc)
+		return -EINVAL;
+
+	return __irq_desc_send_ipi(desc, dest);
+}
+EXPORT_SYMBOL_GPL(irq_send_ipi);
-- 
2.1.0

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

* [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

Add a new ipi domain on top of the normal domain.

MIPS GIC now supports dynamic allocation of an IPI.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 drivers/irqchip/Kconfig        |   1 +
 drivers/irqchip/irq-mips-gic.c | 142 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 136 insertions(+), 7 deletions(-)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4d7294e5d982..e1dcfdffd2c7 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -168,6 +168,7 @@ config KEYSTONE_IRQ
 
 config MIPS_GIC
 	bool
+	select IRQ_DOMAIN_HIERARCHY
 	select MIPS_CM
 
 config INGENIC_IRQ
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index aeaa061f0dbf..9bcaa4e6f40c 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -33,11 +33,14 @@ static void __iomem *gic_base;
 static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static DEFINE_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
+static struct irq_domain *gic_ipi_domain;
 static int gic_shared_intrs;
 static int gic_vpes;
 static unsigned int gic_cpu_pin;
 static unsigned int timer_cpu_pin;
 static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
+DECLARE_BITMAP(ipi_intrs, GIC_MAX_INTRS);
+DECLARE_BITMAP(ipi_resrv, GIC_MAX_INTRS);
 
 static void __gic_irq_dispatch(void);
 
@@ -335,8 +338,14 @@ static void gic_handle_shared_int(bool chained)
 
 	intr = find_first_bit(pending, gic_shared_intrs);
 	while (intr != gic_shared_intrs) {
-		virq = irq_linear_revmap(gic_irq_domain,
-					 GIC_SHARED_TO_HWIRQ(intr));
+		if (test_bit(intr, ipi_intrs)) {
+			virq = irq_linear_revmap(gic_ipi_domain,
+					GIC_SHARED_TO_HWIRQ(intr));
+		} else {
+			virq = irq_linear_revmap(gic_irq_domain,
+					GIC_SHARED_TO_HWIRQ(intr));
+		}
+
 		if (chained)
 			generic_handle_irq(virq);
 		else
@@ -741,7 +750,7 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
 }
 
 static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
-				     irq_hw_number_t hw)
+				     irq_hw_number_t hw, unsigned int vpe)
 {
 	int intr = GIC_HWIRQ_TO_SHARED(hw);
 	unsigned long flags;
@@ -751,9 +760,8 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
 
 	spin_lock_irqsave(&gic_lock, flags);
 	gic_map_to_pin(intr, gic_cpu_pin);
-	/* Map to VPE 0 by default */
-	gic_map_to_vpe(intr, 0);
-	set_bit(intr, pcpu_masks[0].pcpu_mask);
+	gic_map_to_vpe(intr, vpe);
+	set_bit(intr, pcpu_masks[vpe].pcpu_mask);
 	spin_unlock_irqrestore(&gic_lock, flags);
 
 	return 0;
@@ -764,7 +772,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
 {
 	if (GIC_HWIRQ_TO_LOCAL(hw) < GIC_NUM_LOCAL_INTRS)
 		return gic_local_irq_domain_map(d, virq, hw);
-	return gic_shared_irq_domain_map(d, virq, hw);
+	return gic_shared_irq_domain_map(d, virq, hw, 0);
 }
 
 static int gic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
@@ -791,6 +799,115 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
 	.xlate = gic_irq_domain_xlate,
 };
 
+static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
+				const u32 *intspec, unsigned int intsize,
+				irq_hw_number_t *out_hwirq,
+				unsigned int *out_type)
+{
+	/*
+	 * There's nothing to translate here. hwirq is dynamically allocated and
+	 * the irq type is always edge triggered.
+	 * */
+	*out_hwirq = 0;
+	*out_type = IRQ_TYPE_EDGE_RISING;
+
+	return 0;
+}
+
+static int gic_ipi_domain_alloc(struct irq_domain *d, unsigned int virq,
+				unsigned int nr_irqs, void *arg)
+{
+	struct ipi_mask *ipimask = arg;
+	const unsigned long *bits;
+	struct ipi_mapping *map;
+	irq_hw_number_t hwirq;
+	int cpu, ret;
+
+	map = irq_alloc_ipi_mapping(gic_vpes);
+	if (!map)
+		return -ENOMEM;
+
+	bits = ipi_mask_bits(ipimask);
+
+	cpu = find_first_bit(bits, ipimask->nbits);
+	while (cpu != ipimask->nbits) {
+		hwirq = find_first_bit(ipi_resrv, gic_shared_intrs);
+		if (hwirq == gic_shared_intrs) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		bitmap_clear(ipi_resrv, hwirq, 1);
+		bitmap_set(ipi_intrs, hwirq, 1);
+
+		ret = irq_map_ipi(map, cpu, hwirq);
+		if (ret)
+			goto out;
+
+		hwirq = GIC_SHARED_TO_HWIRQ(hwirq);
+		ret = irq_domain_set_hwirq_and_chip(d, virq + cpu, hwirq,
+						&gic_edge_irq_controller, map);
+		if (ret)
+			goto out;
+
+		ret = gic_shared_irq_domain_map(d, virq + cpu, hwirq, cpu);
+		if (ret)
+			goto out;
+
+		ret = irq_set_irq_type(virq + cpu, IRQ_TYPE_EDGE_RISING);
+		if (ret)
+			goto out;
+
+		cpu = find_next_bit(bits, ipimask->nbits, cpu + 1);
+	}
+
+	return 0;
+out:
+	irq_free_ipi_mapping(map);
+	return ret;
+}
+
+void gic_ipi_domain_free(struct irq_domain *d, unsigned int virq,
+			 unsigned int nr_irqs)
+{
+	struct ipi_mapping *map = irq_get_chip_data(virq);
+	irq_hw_number_t hwirq;
+	int ret, cpu;
+
+	for (cpu = 0; cpu < map->nr_cpus; cpu++) {
+		ret = irq_unmap_ipi(map, cpu, &hwirq);
+		if (!ret) {
+			bitmap_set(ipi_resrv, hwirq, 1);
+			bitmap_clear(ipi_intrs, hwirq, 1);
+		}
+	}
+
+	irq_free_ipi_mapping(map);
+}
+
+int gic_ipi_domain_match(struct irq_domain *d, struct device_node *node,
+			 enum irq_domain_bus_token bus_token)
+{
+	bool is_ipi = true;
+
+	switch (bus_token) {
+	case DOMAIN_BUS_IPI:
+		is_ipi = d->bus_token == bus_token;
+	case DOMAIN_BUS_ANY:
+		return to_of_node(d->fwnode) == node && is_ipi;
+		break;
+	default:
+		return 0;
+	}
+}
+
+static struct irq_domain_ops gic_ipi_domain_ops = {
+	.xlate = gic_ipi_domain_xlate,
+	.alloc = gic_ipi_domain_alloc,
+	.free = gic_ipi_domain_free,
+	.match = gic_ipi_domain_match,
+};
+
 static void __init __gic_init(unsigned long gic_base_addr,
 			      unsigned long gic_addrspace_size,
 			      unsigned int cpu_vec, unsigned int irqbase,
@@ -850,6 +967,17 @@ static void __init __gic_init(unsigned long gic_base_addr,
 	if (!gic_irq_domain)
 		panic("Failed to add GIC IRQ domain");
 
+	gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain, IRQ_DOMAIN_FLAG_IPI,
+						  GIC_NUM_LOCAL_INTRS + gic_shared_intrs,
+						  node, &gic_ipi_domain_ops, NULL);
+	if (!gic_ipi_domain)
+		panic("Failed to add GIC IPI domain");
+
+	gic_ipi_domain->bus_token = DOMAIN_BUS_IPI;
+
+	/* Make the last 2 * NR_CPUS available for IPIs */
+	bitmap_set(ipi_resrv, gic_shared_intrs - 2 * NR_CPUS, 2 * NR_CPUS);
+
 	gic_basic_init();
 
 	gic_ipi_init();
-- 
2.1.0


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

* [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

Add a new ipi domain on top of the normal domain.

MIPS GIC now supports dynamic allocation of an IPI.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 drivers/irqchip/Kconfig        |   1 +
 drivers/irqchip/irq-mips-gic.c | 142 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 136 insertions(+), 7 deletions(-)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4d7294e5d982..e1dcfdffd2c7 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -168,6 +168,7 @@ config KEYSTONE_IRQ
 
 config MIPS_GIC
 	bool
+	select IRQ_DOMAIN_HIERARCHY
 	select MIPS_CM
 
 config INGENIC_IRQ
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index aeaa061f0dbf..9bcaa4e6f40c 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -33,11 +33,14 @@ static void __iomem *gic_base;
 static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
 static DEFINE_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
+static struct irq_domain *gic_ipi_domain;
 static int gic_shared_intrs;
 static int gic_vpes;
 static unsigned int gic_cpu_pin;
 static unsigned int timer_cpu_pin;
 static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
+DECLARE_BITMAP(ipi_intrs, GIC_MAX_INTRS);
+DECLARE_BITMAP(ipi_resrv, GIC_MAX_INTRS);
 
 static void __gic_irq_dispatch(void);
 
@@ -335,8 +338,14 @@ static void gic_handle_shared_int(bool chained)
 
 	intr = find_first_bit(pending, gic_shared_intrs);
 	while (intr != gic_shared_intrs) {
-		virq = irq_linear_revmap(gic_irq_domain,
-					 GIC_SHARED_TO_HWIRQ(intr));
+		if (test_bit(intr, ipi_intrs)) {
+			virq = irq_linear_revmap(gic_ipi_domain,
+					GIC_SHARED_TO_HWIRQ(intr));
+		} else {
+			virq = irq_linear_revmap(gic_irq_domain,
+					GIC_SHARED_TO_HWIRQ(intr));
+		}
+
 		if (chained)
 			generic_handle_irq(virq);
 		else
@@ -741,7 +750,7 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
 }
 
 static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
-				     irq_hw_number_t hw)
+				     irq_hw_number_t hw, unsigned int vpe)
 {
 	int intr = GIC_HWIRQ_TO_SHARED(hw);
 	unsigned long flags;
@@ -751,9 +760,8 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq,
 
 	spin_lock_irqsave(&gic_lock, flags);
 	gic_map_to_pin(intr, gic_cpu_pin);
-	/* Map to VPE 0 by default */
-	gic_map_to_vpe(intr, 0);
-	set_bit(intr, pcpu_masks[0].pcpu_mask);
+	gic_map_to_vpe(intr, vpe);
+	set_bit(intr, pcpu_masks[vpe].pcpu_mask);
 	spin_unlock_irqrestore(&gic_lock, flags);
 
 	return 0;
@@ -764,7 +772,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
 {
 	if (GIC_HWIRQ_TO_LOCAL(hw) < GIC_NUM_LOCAL_INTRS)
 		return gic_local_irq_domain_map(d, virq, hw);
-	return gic_shared_irq_domain_map(d, virq, hw);
+	return gic_shared_irq_domain_map(d, virq, hw, 0);
 }
 
 static int gic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
@@ -791,6 +799,115 @@ static const struct irq_domain_ops gic_irq_domain_ops = {
 	.xlate = gic_irq_domain_xlate,
 };
 
+static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
+				const u32 *intspec, unsigned int intsize,
+				irq_hw_number_t *out_hwirq,
+				unsigned int *out_type)
+{
+	/*
+	 * There's nothing to translate here. hwirq is dynamically allocated and
+	 * the irq type is always edge triggered.
+	 * */
+	*out_hwirq = 0;
+	*out_type = IRQ_TYPE_EDGE_RISING;
+
+	return 0;
+}
+
+static int gic_ipi_domain_alloc(struct irq_domain *d, unsigned int virq,
+				unsigned int nr_irqs, void *arg)
+{
+	struct ipi_mask *ipimask = arg;
+	const unsigned long *bits;
+	struct ipi_mapping *map;
+	irq_hw_number_t hwirq;
+	int cpu, ret;
+
+	map = irq_alloc_ipi_mapping(gic_vpes);
+	if (!map)
+		return -ENOMEM;
+
+	bits = ipi_mask_bits(ipimask);
+
+	cpu = find_first_bit(bits, ipimask->nbits);
+	while (cpu != ipimask->nbits) {
+		hwirq = find_first_bit(ipi_resrv, gic_shared_intrs);
+		if (hwirq == gic_shared_intrs) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		bitmap_clear(ipi_resrv, hwirq, 1);
+		bitmap_set(ipi_intrs, hwirq, 1);
+
+		ret = irq_map_ipi(map, cpu, hwirq);
+		if (ret)
+			goto out;
+
+		hwirq = GIC_SHARED_TO_HWIRQ(hwirq);
+		ret = irq_domain_set_hwirq_and_chip(d, virq + cpu, hwirq,
+						&gic_edge_irq_controller, map);
+		if (ret)
+			goto out;
+
+		ret = gic_shared_irq_domain_map(d, virq + cpu, hwirq, cpu);
+		if (ret)
+			goto out;
+
+		ret = irq_set_irq_type(virq + cpu, IRQ_TYPE_EDGE_RISING);
+		if (ret)
+			goto out;
+
+		cpu = find_next_bit(bits, ipimask->nbits, cpu + 1);
+	}
+
+	return 0;
+out:
+	irq_free_ipi_mapping(map);
+	return ret;
+}
+
+void gic_ipi_domain_free(struct irq_domain *d, unsigned int virq,
+			 unsigned int nr_irqs)
+{
+	struct ipi_mapping *map = irq_get_chip_data(virq);
+	irq_hw_number_t hwirq;
+	int ret, cpu;
+
+	for (cpu = 0; cpu < map->nr_cpus; cpu++) {
+		ret = irq_unmap_ipi(map, cpu, &hwirq);
+		if (!ret) {
+			bitmap_set(ipi_resrv, hwirq, 1);
+			bitmap_clear(ipi_intrs, hwirq, 1);
+		}
+	}
+
+	irq_free_ipi_mapping(map);
+}
+
+int gic_ipi_domain_match(struct irq_domain *d, struct device_node *node,
+			 enum irq_domain_bus_token bus_token)
+{
+	bool is_ipi = true;
+
+	switch (bus_token) {
+	case DOMAIN_BUS_IPI:
+		is_ipi = d->bus_token == bus_token;
+	case DOMAIN_BUS_ANY:
+		return to_of_node(d->fwnode) == node && is_ipi;
+		break;
+	default:
+		return 0;
+	}
+}
+
+static struct irq_domain_ops gic_ipi_domain_ops = {
+	.xlate = gic_ipi_domain_xlate,
+	.alloc = gic_ipi_domain_alloc,
+	.free = gic_ipi_domain_free,
+	.match = gic_ipi_domain_match,
+};
+
 static void __init __gic_init(unsigned long gic_base_addr,
 			      unsigned long gic_addrspace_size,
 			      unsigned int cpu_vec, unsigned int irqbase,
@@ -850,6 +967,17 @@ static void __init __gic_init(unsigned long gic_base_addr,
 	if (!gic_irq_domain)
 		panic("Failed to add GIC IRQ domain");
 
+	gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain, IRQ_DOMAIN_FLAG_IPI,
+						  GIC_NUM_LOCAL_INTRS + gic_shared_intrs,
+						  node, &gic_ipi_domain_ops, NULL);
+	if (!gic_ipi_domain)
+		panic("Failed to add GIC IPI domain");
+
+	gic_ipi_domain->bus_token = DOMAIN_BUS_IPI;
+
+	/* Make the last 2 * NR_CPUS available for IPIs */
+	bitmap_set(ipi_resrv, gic_shared_intrs - 2 * NR_CPUS, 2 * NR_CPUS);
+
 	gic_basic_init();
 
 	gic_ipi_init();
-- 
2.1.0

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

* [PATCH 11/14] MIPS: Add generic SMP IPI support
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

Use the new generic IPI layer to provide generic SMP IPI support if the irqchip
supports it.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 arch/mips/kernel/smp.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index bd4385a8e6e8..197e1c8af4ef 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -33,12 +33,16 @@
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/ftrace.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 
 #include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/idle.h>
 #include <asm/r4k-timer.h>
+#include <asm/mips-cpc.h>
 #include <asm/mmu_context.h>
 #include <asm/time.h>
 #include <asm/setup.h>
@@ -79,6 +83,11 @@ static cpumask_t cpu_core_setup_map;
 
 cpumask_t cpu_coherent_mask;
 
+#ifdef CONFIG_GENERIC_IRQ_IPI
+static struct irq_desc *call_desc;
+static struct irq_desc *sched_desc;
+#endif
+
 static inline void set_cpu_sibling_map(int cpu)
 {
 	int i;
@@ -145,6 +154,133 @@ void register_smp_ops(struct plat_smp_ops *ops)
 	mp_ops = ops;
 }
 
+#ifdef CONFIG_GENERIC_IRQ_IPI
+void mips_smp_send_ipi_single(int cpu, unsigned int action)
+{
+	mips_smp_send_ipi_mask(cpumask_of(cpu), action);
+}
+
+void mips_smp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+{
+	unsigned long flags;
+	unsigned int core;
+	int cpu;
+	struct ipi_mask ipimask;
+
+	ipi_mask_set_cpumask(&ipimask, mask);
+
+	local_irq_save(flags);
+
+	switch (action) {
+	case SMP_CALL_FUNCTION:
+		__irq_desc_send_ipi(call_desc, &ipimask);
+		break;
+
+	case SMP_RESCHEDULE_YOURSELF:
+		__irq_desc_send_ipi(sched_desc, &ipimask);
+		break;
+
+	default:
+		BUG();
+	}
+
+	if (mips_cpc_present()) {
+		for_each_cpu(cpu, mask) {
+			core = cpu_data[cpu].core;
+
+			if (core == current_cpu_data.core)
+				continue;
+
+			while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
+				mips_cpc_lock_other(core);
+				write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
+				mips_cpc_unlock_other();
+			}
+		}
+	}
+
+	local_irq_restore(flags);
+}
+
+
+static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
+{
+	scheduler_ipi();
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
+{
+	generic_smp_call_function_interrupt();
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction irq_resched = {
+	.handler	= ipi_resched_interrupt,
+	.flags		= IRQF_PERCPU,
+	.name		= "IPI resched"
+};
+
+static struct irqaction irq_call = {
+	.handler	= ipi_call_interrupt,
+	.flags		= IRQF_PERCPU,
+	.name		= "IPI call"
+};
+
+static __init void smp_ipi_init_one(unsigned int virq,
+				    struct irqaction *action)
+{
+	int ret;
+
+	irq_set_handler(virq, handle_percpu_irq);
+	ret = setup_irq(virq, action);
+	BUG_ON(ret);
+}
+
+static int __init mips_smp_ipi_init(void)
+{
+	unsigned int call_virq, sched_virq;
+	struct irq_domain *ipidomain;
+	struct device_node *node;
+	struct ipi_mask ipimask;
+	int cpu;
+
+	node = of_irq_find_parent(of_root);
+	ipidomain = irq_find_matching_host(node, DOMAIN_BUS_IPI);
+
+	/*
+	 * Some platforms have half DT setup. So if we found irq node but
+	 * didn't find an ipidomain, try to search for one that is not in the
+	 * DT.
+	 */
+	if (node && !ipidomain)
+		ipidomain = irq_find_matching_host(NULL, DOMAIN_BUS_IPI);
+
+	BUG_ON(!ipidomain);
+
+	ipi_mask_set_cpumask(&ipimask, cpu_possible_mask);
+
+	call_virq = irq_reserve_ipi(ipidomain, &ipimask);
+	BUG_ON(!call_virq);
+
+	sched_virq = irq_reserve_ipi(ipidomain, &ipimask);
+	BUG_ON(!sched_virq);
+
+	for_each_cpu(cpu, cpu_possible_mask) {
+		smp_ipi_init_one(call_virq + cpu, &irq_call);
+		smp_ipi_init_one(sched_virq + cpu, &irq_resched);
+	}
+
+	call_desc = irq_to_desc(call_virq);
+	sched_desc = irq_to_desc(sched_virq);
+
+	return 0;
+}
+early_initcall(mips_smp_ipi_init);
+#endif
+
 /*
  * First C code run on the secondary CPUs after being started up by
  * the master.
-- 
2.1.0


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

* [PATCH 11/14] MIPS: Add generic SMP IPI support
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips, Qais Yousef

Use the new generic IPI layer to provide generic SMP IPI support if the irqchip
supports it.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
---
 arch/mips/kernel/smp.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index bd4385a8e6e8..197e1c8af4ef 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -33,12 +33,16 @@
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/ftrace.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 
 #include <linux/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/idle.h>
 #include <asm/r4k-timer.h>
+#include <asm/mips-cpc.h>
 #include <asm/mmu_context.h>
 #include <asm/time.h>
 #include <asm/setup.h>
@@ -79,6 +83,11 @@ static cpumask_t cpu_core_setup_map;
 
 cpumask_t cpu_coherent_mask;
 
+#ifdef CONFIG_GENERIC_IRQ_IPI
+static struct irq_desc *call_desc;
+static struct irq_desc *sched_desc;
+#endif
+
 static inline void set_cpu_sibling_map(int cpu)
 {
 	int i;
@@ -145,6 +154,133 @@ void register_smp_ops(struct plat_smp_ops *ops)
 	mp_ops = ops;
 }
 
+#ifdef CONFIG_GENERIC_IRQ_IPI
+void mips_smp_send_ipi_single(int cpu, unsigned int action)
+{
+	mips_smp_send_ipi_mask(cpumask_of(cpu), action);
+}
+
+void mips_smp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
+{
+	unsigned long flags;
+	unsigned int core;
+	int cpu;
+	struct ipi_mask ipimask;
+
+	ipi_mask_set_cpumask(&ipimask, mask);
+
+	local_irq_save(flags);
+
+	switch (action) {
+	case SMP_CALL_FUNCTION:
+		__irq_desc_send_ipi(call_desc, &ipimask);
+		break;
+
+	case SMP_RESCHEDULE_YOURSELF:
+		__irq_desc_send_ipi(sched_desc, &ipimask);
+		break;
+
+	default:
+		BUG();
+	}
+
+	if (mips_cpc_present()) {
+		for_each_cpu(cpu, mask) {
+			core = cpu_data[cpu].core;
+
+			if (core == current_cpu_data.core)
+				continue;
+
+			while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
+				mips_cpc_lock_other(core);
+				write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
+				mips_cpc_unlock_other();
+			}
+		}
+	}
+
+	local_irq_restore(flags);
+}
+
+
+static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
+{
+	scheduler_ipi();
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
+{
+	generic_smp_call_function_interrupt();
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction irq_resched = {
+	.handler	= ipi_resched_interrupt,
+	.flags		= IRQF_PERCPU,
+	.name		= "IPI resched"
+};
+
+static struct irqaction irq_call = {
+	.handler	= ipi_call_interrupt,
+	.flags		= IRQF_PERCPU,
+	.name		= "IPI call"
+};
+
+static __init void smp_ipi_init_one(unsigned int virq,
+				    struct irqaction *action)
+{
+	int ret;
+
+	irq_set_handler(virq, handle_percpu_irq);
+	ret = setup_irq(virq, action);
+	BUG_ON(ret);
+}
+
+static int __init mips_smp_ipi_init(void)
+{
+	unsigned int call_virq, sched_virq;
+	struct irq_domain *ipidomain;
+	struct device_node *node;
+	struct ipi_mask ipimask;
+	int cpu;
+
+	node = of_irq_find_parent(of_root);
+	ipidomain = irq_find_matching_host(node, DOMAIN_BUS_IPI);
+
+	/*
+	 * Some platforms have half DT setup. So if we found irq node but
+	 * didn't find an ipidomain, try to search for one that is not in the
+	 * DT.
+	 */
+	if (node && !ipidomain)
+		ipidomain = irq_find_matching_host(NULL, DOMAIN_BUS_IPI);
+
+	BUG_ON(!ipidomain);
+
+	ipi_mask_set_cpumask(&ipimask, cpu_possible_mask);
+
+	call_virq = irq_reserve_ipi(ipidomain, &ipimask);
+	BUG_ON(!call_virq);
+
+	sched_virq = irq_reserve_ipi(ipidomain, &ipimask);
+	BUG_ON(!sched_virq);
+
+	for_each_cpu(cpu, cpu_possible_mask) {
+		smp_ipi_init_one(call_virq + cpu, &irq_call);
+		smp_ipi_init_one(sched_virq + cpu, &irq_resched);
+	}
+
+	call_desc = irq_to_desc(call_virq);
+	sched_desc = irq_to_desc(sched_virq);
+
+	return 0;
+}
+early_initcall(mips_smp_ipi_init);
+#endif
+
 /*
  * First C code run on the secondary CPUs after being started up by
  * the master.
-- 
2.1.0

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

* [PATCH 12/14] MIPS: Make smp CMP, CPS and MT use the new generic IPI functions
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips,
	Qais Yousef, James Hogan, Paul Burton

This commit does several things to avoid breaking bisectability.

	1- Remove IPI init code from irqchip/mips-gic
	2- Implement the new irqchip->send_ipi() in irqchip/mips-gic
	3- Select GENERIC_IRQ_IPI Kconfig symbol for MIPS_GIC
	4- Change MIPS SMP to use the generic IPI implementation

Only the SMP variants that use GIC were converted as it's the only irqchip that
will have the support for generic IPI for now.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/smp-ops.h  |   5 +-
 arch/mips/kernel/smp-cmp.c       |   4 +-
 arch/mips/kernel/smp-cps.c       |   4 +-
 arch/mips/kernel/smp-mt.c        |   2 +-
 drivers/irqchip/Kconfig          |   1 +
 drivers/irqchip/irq-mips-gic.c   | 102 ++++++++-------------------------------
 include/linux/irqchip/mips-gic.h |   3 --
 7 files changed, 30 insertions(+), 91 deletions(-)

diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h
index 6ba1fb8b11e2..db7c322f057f 100644
--- a/arch/mips/include/asm/smp-ops.h
+++ b/arch/mips/include/asm/smp-ops.h
@@ -44,8 +44,9 @@ static inline void plat_smp_setup(void)
 	mp_ops->smp_setup();
 }
 
-extern void gic_send_ipi_single(int cpu, unsigned int action);
-extern void gic_send_ipi_mask(const struct cpumask *mask, unsigned int action);
+extern void mips_smp_send_ipi_single(int cpu, unsigned int action);
+extern void mips_smp_send_ipi_mask(const struct cpumask *mask,
+				      unsigned int action);
 
 #else /* !CONFIG_SMP */
 
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index d5e0f949dc48..76923349b4fe 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -149,8 +149,8 @@ void __init cmp_prepare_cpus(unsigned int max_cpus)
 }
 
 struct plat_smp_ops cmp_smp_ops = {
-	.send_ipi_single	= gic_send_ipi_single,
-	.send_ipi_mask		= gic_send_ipi_mask,
+	.send_ipi_single	= mips_smp_send_ipi_single,
+	.send_ipi_mask		= mips_smp_send_ipi_mask,
 	.init_secondary		= cmp_init_secondary,
 	.smp_finish		= cmp_smp_finish,
 	.boot_secondary		= cmp_boot_secondary,
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index c88937745b4e..69d811e72f2b 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -444,8 +444,8 @@ static struct plat_smp_ops cps_smp_ops = {
 	.boot_secondary		= cps_boot_secondary,
 	.init_secondary		= cps_init_secondary,
 	.smp_finish		= cps_smp_finish,
-	.send_ipi_single	= gic_send_ipi_single,
-	.send_ipi_mask		= gic_send_ipi_mask,
+	.send_ipi_single	= mips_smp_send_ipi_single,
+	.send_ipi_mask		= mips_smp_send_ipi_mask,
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_disable		= cps_cpu_disable,
 	.cpu_die		= cps_cpu_die,
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 86311a164ef1..4f9570a57e8d 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -121,7 +121,7 @@ static void vsmp_send_ipi_single(int cpu, unsigned int action)
 
 #ifdef CONFIG_MIPS_GIC
 	if (gic_present) {
-		gic_send_ipi_single(cpu, action);
+		mips_smp_send_ipi_single(cpu, action);
 		return;
 	}
 #endif
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index e1dcfdffd2c7..590bc55f28da 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -168,6 +168,7 @@ config KEYSTONE_IRQ
 
 config MIPS_GIC
 	bool
+	select GENERIC_IRQ_IPI
 	select IRQ_DOMAIN_HIERARCHY
 	select MIPS_CM
 
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 9bcaa4e6f40c..456938a83050 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -266,9 +266,27 @@ static void gic_bind_eic_interrupt(int irq, int set)
 		  GIC_VPE_EIC_SS(irq), set);
 }
 
-void gic_send_ipi(unsigned int intr)
+static void gic_send_ipi(struct irq_data *d, const struct ipi_mask *ipimask)
 {
-	gic_write(GIC_REG(SHARED, GIC_SH_WEDGE), GIC_SH_WEDGE_SET(intr));
+	struct ipi_mapping *map = irq_data_get_irq_chip_data(d);
+	const unsigned long *bits;
+	irq_hw_number_t intr;
+	int vpe;
+
+	if (!map)
+		return;
+
+	bits = ipi_mask_bits(ipimask);
+
+	vpe = find_first_bit(bits, ipimask->nbits);
+	while (vpe != ipimask->nbits) {
+		intr = map->cpumap[vpe];
+		if (intr == INVALID_HWIRQ)
+			continue;
+		gic_write(GIC_REG(SHARED, GIC_SH_WEDGE), GIC_SH_WEDGE_SET(intr));
+
+		vpe = find_next_bit(bits, ipimask->nbits, vpe + 1);
+	}
 }
 
 int gic_get_c0_compare_int(void)
@@ -476,6 +494,7 @@ static struct irq_chip gic_edge_irq_controller = {
 #ifdef CONFIG_SMP
 	.irq_set_affinity	=	gic_set_affinity,
 #endif
+	.irq_send_ipi		=	gic_send_ipi,
 };
 
 static void gic_handle_local_int(bool chained)
@@ -569,83 +588,6 @@ static void gic_irq_dispatch(struct irq_desc *desc)
 	gic_handle_shared_int(true);
 }
 
-#ifdef CONFIG_MIPS_GIC_IPI
-static int gic_resched_int_base;
-static int gic_call_int_base;
-
-unsigned int plat_ipi_resched_int_xlate(unsigned int cpu)
-{
-	return gic_resched_int_base + cpu;
-}
-
-unsigned int plat_ipi_call_int_xlate(unsigned int cpu)
-{
-	return gic_call_int_base + cpu;
-}
-
-static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
-{
-	scheduler_ipi();
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
-{
-	generic_smp_call_function_interrupt();
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction irq_resched = {
-	.handler	= ipi_resched_interrupt,
-	.flags		= IRQF_PERCPU,
-	.name		= "IPI resched"
-};
-
-static struct irqaction irq_call = {
-	.handler	= ipi_call_interrupt,
-	.flags		= IRQF_PERCPU,
-	.name		= "IPI call"
-};
-
-static __init void gic_ipi_init_one(unsigned int intr, int cpu,
-				    struct irqaction *action)
-{
-	int virq = irq_create_mapping(gic_irq_domain,
-				      GIC_SHARED_TO_HWIRQ(intr));
-	int i;
-
-	gic_map_to_vpe(intr, mips_cm_vp_id(cpu));
-	for (i = 0; i < NR_CPUS; i++)
-		clear_bit(intr, pcpu_masks[i].pcpu_mask);
-	set_bit(intr, pcpu_masks[cpu].pcpu_mask);
-
-	irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
-
-	irq_set_handler(virq, handle_percpu_irq);
-	setup_irq(virq, action);
-}
-
-static __init void gic_ipi_init(void)
-{
-	int i;
-
-	/* Use last 2 * NR_CPUS interrupts as IPIs */
-	gic_resched_int_base = gic_shared_intrs - nr_cpu_ids;
-	gic_call_int_base = gic_resched_int_base - nr_cpu_ids;
-
-	for (i = 0; i < nr_cpu_ids; i++) {
-		gic_ipi_init_one(gic_call_int_base + i, i, &irq_call);
-		gic_ipi_init_one(gic_resched_int_base + i, i, &irq_resched);
-	}
-}
-#else
-static inline void gic_ipi_init(void)
-{
-}
-#endif
-
 static void __init gic_basic_init(void)
 {
 	unsigned int i;
@@ -979,8 +921,6 @@ static void __init __gic_init(unsigned long gic_base_addr,
 	bitmap_set(ipi_resrv, gic_shared_intrs - 2 * NR_CPUS, 2 * NR_CPUS);
 
 	gic_basic_init();
-
-	gic_ipi_init();
 }
 
 void __init gic_init(unsigned long gic_base_addr,
diff --git a/include/linux/irqchip/mips-gic.h b/include/linux/irqchip/mips-gic.h
index 4e6861605050..321278767506 100644
--- a/include/linux/irqchip/mips-gic.h
+++ b/include/linux/irqchip/mips-gic.h
@@ -258,9 +258,6 @@ extern void gic_write_compare(cycle_t cnt);
 extern void gic_write_cpu_compare(cycle_t cnt, int cpu);
 extern void gic_start_count(void);
 extern void gic_stop_count(void);
-extern void gic_send_ipi(unsigned int intr);
-extern unsigned int plat_ipi_call_int_xlate(unsigned int);
-extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 extern int gic_get_c0_compare_int(void);
 extern int gic_get_c0_perfcount_int(void);
 extern int gic_get_c0_fdc_int(void);
-- 
2.1.0


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

* [PATCH 12/14] MIPS: Make smp CMP, CPS and MT use the new generic IPI functions
@ 2015-11-03 11:12   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:12 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips,
	Qais Yousef, James Hogan, Paul Burton

This commit does several things to avoid breaking bisectability.

	1- Remove IPI init code from irqchip/mips-gic
	2- Implement the new irqchip->send_ipi() in irqchip/mips-gic
	3- Select GENERIC_IRQ_IPI Kconfig symbol for MIPS_GIC
	4- Change MIPS SMP to use the generic IPI implementation

Only the SMP variants that use GIC were converted as it's the only irqchip that
will have the support for generic IPI for now.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/include/asm/smp-ops.h  |   5 +-
 arch/mips/kernel/smp-cmp.c       |   4 +-
 arch/mips/kernel/smp-cps.c       |   4 +-
 arch/mips/kernel/smp-mt.c        |   2 +-
 drivers/irqchip/Kconfig          |   1 +
 drivers/irqchip/irq-mips-gic.c   | 102 ++++++++-------------------------------
 include/linux/irqchip/mips-gic.h |   3 --
 7 files changed, 30 insertions(+), 91 deletions(-)

diff --git a/arch/mips/include/asm/smp-ops.h b/arch/mips/include/asm/smp-ops.h
index 6ba1fb8b11e2..db7c322f057f 100644
--- a/arch/mips/include/asm/smp-ops.h
+++ b/arch/mips/include/asm/smp-ops.h
@@ -44,8 +44,9 @@ static inline void plat_smp_setup(void)
 	mp_ops->smp_setup();
 }
 
-extern void gic_send_ipi_single(int cpu, unsigned int action);
-extern void gic_send_ipi_mask(const struct cpumask *mask, unsigned int action);
+extern void mips_smp_send_ipi_single(int cpu, unsigned int action);
+extern void mips_smp_send_ipi_mask(const struct cpumask *mask,
+				      unsigned int action);
 
 #else /* !CONFIG_SMP */
 
diff --git a/arch/mips/kernel/smp-cmp.c b/arch/mips/kernel/smp-cmp.c
index d5e0f949dc48..76923349b4fe 100644
--- a/arch/mips/kernel/smp-cmp.c
+++ b/arch/mips/kernel/smp-cmp.c
@@ -149,8 +149,8 @@ void __init cmp_prepare_cpus(unsigned int max_cpus)
 }
 
 struct plat_smp_ops cmp_smp_ops = {
-	.send_ipi_single	= gic_send_ipi_single,
-	.send_ipi_mask		= gic_send_ipi_mask,
+	.send_ipi_single	= mips_smp_send_ipi_single,
+	.send_ipi_mask		= mips_smp_send_ipi_mask,
 	.init_secondary		= cmp_init_secondary,
 	.smp_finish		= cmp_smp_finish,
 	.boot_secondary		= cmp_boot_secondary,
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index c88937745b4e..69d811e72f2b 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -444,8 +444,8 @@ static struct plat_smp_ops cps_smp_ops = {
 	.boot_secondary		= cps_boot_secondary,
 	.init_secondary		= cps_init_secondary,
 	.smp_finish		= cps_smp_finish,
-	.send_ipi_single	= gic_send_ipi_single,
-	.send_ipi_mask		= gic_send_ipi_mask,
+	.send_ipi_single	= mips_smp_send_ipi_single,
+	.send_ipi_mask		= mips_smp_send_ipi_mask,
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_disable		= cps_cpu_disable,
 	.cpu_die		= cps_cpu_die,
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c
index 86311a164ef1..4f9570a57e8d 100644
--- a/arch/mips/kernel/smp-mt.c
+++ b/arch/mips/kernel/smp-mt.c
@@ -121,7 +121,7 @@ static void vsmp_send_ipi_single(int cpu, unsigned int action)
 
 #ifdef CONFIG_MIPS_GIC
 	if (gic_present) {
-		gic_send_ipi_single(cpu, action);
+		mips_smp_send_ipi_single(cpu, action);
 		return;
 	}
 #endif
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index e1dcfdffd2c7..590bc55f28da 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -168,6 +168,7 @@ config KEYSTONE_IRQ
 
 config MIPS_GIC
 	bool
+	select GENERIC_IRQ_IPI
 	select IRQ_DOMAIN_HIERARCHY
 	select MIPS_CM
 
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 9bcaa4e6f40c..456938a83050 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -266,9 +266,27 @@ static void gic_bind_eic_interrupt(int irq, int set)
 		  GIC_VPE_EIC_SS(irq), set);
 }
 
-void gic_send_ipi(unsigned int intr)
+static void gic_send_ipi(struct irq_data *d, const struct ipi_mask *ipimask)
 {
-	gic_write(GIC_REG(SHARED, GIC_SH_WEDGE), GIC_SH_WEDGE_SET(intr));
+	struct ipi_mapping *map = irq_data_get_irq_chip_data(d);
+	const unsigned long *bits;
+	irq_hw_number_t intr;
+	int vpe;
+
+	if (!map)
+		return;
+
+	bits = ipi_mask_bits(ipimask);
+
+	vpe = find_first_bit(bits, ipimask->nbits);
+	while (vpe != ipimask->nbits) {
+		intr = map->cpumap[vpe];
+		if (intr == INVALID_HWIRQ)
+			continue;
+		gic_write(GIC_REG(SHARED, GIC_SH_WEDGE), GIC_SH_WEDGE_SET(intr));
+
+		vpe = find_next_bit(bits, ipimask->nbits, vpe + 1);
+	}
 }
 
 int gic_get_c0_compare_int(void)
@@ -476,6 +494,7 @@ static struct irq_chip gic_edge_irq_controller = {
 #ifdef CONFIG_SMP
 	.irq_set_affinity	=	gic_set_affinity,
 #endif
+	.irq_send_ipi		=	gic_send_ipi,
 };
 
 static void gic_handle_local_int(bool chained)
@@ -569,83 +588,6 @@ static void gic_irq_dispatch(struct irq_desc *desc)
 	gic_handle_shared_int(true);
 }
 
-#ifdef CONFIG_MIPS_GIC_IPI
-static int gic_resched_int_base;
-static int gic_call_int_base;
-
-unsigned int plat_ipi_resched_int_xlate(unsigned int cpu)
-{
-	return gic_resched_int_base + cpu;
-}
-
-unsigned int plat_ipi_call_int_xlate(unsigned int cpu)
-{
-	return gic_call_int_base + cpu;
-}
-
-static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
-{
-	scheduler_ipi();
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
-{
-	generic_smp_call_function_interrupt();
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction irq_resched = {
-	.handler	= ipi_resched_interrupt,
-	.flags		= IRQF_PERCPU,
-	.name		= "IPI resched"
-};
-
-static struct irqaction irq_call = {
-	.handler	= ipi_call_interrupt,
-	.flags		= IRQF_PERCPU,
-	.name		= "IPI call"
-};
-
-static __init void gic_ipi_init_one(unsigned int intr, int cpu,
-				    struct irqaction *action)
-{
-	int virq = irq_create_mapping(gic_irq_domain,
-				      GIC_SHARED_TO_HWIRQ(intr));
-	int i;
-
-	gic_map_to_vpe(intr, mips_cm_vp_id(cpu));
-	for (i = 0; i < NR_CPUS; i++)
-		clear_bit(intr, pcpu_masks[i].pcpu_mask);
-	set_bit(intr, pcpu_masks[cpu].pcpu_mask);
-
-	irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
-
-	irq_set_handler(virq, handle_percpu_irq);
-	setup_irq(virq, action);
-}
-
-static __init void gic_ipi_init(void)
-{
-	int i;
-
-	/* Use last 2 * NR_CPUS interrupts as IPIs */
-	gic_resched_int_base = gic_shared_intrs - nr_cpu_ids;
-	gic_call_int_base = gic_resched_int_base - nr_cpu_ids;
-
-	for (i = 0; i < nr_cpu_ids; i++) {
-		gic_ipi_init_one(gic_call_int_base + i, i, &irq_call);
-		gic_ipi_init_one(gic_resched_int_base + i, i, &irq_resched);
-	}
-}
-#else
-static inline void gic_ipi_init(void)
-{
-}
-#endif
-
 static void __init gic_basic_init(void)
 {
 	unsigned int i;
@@ -979,8 +921,6 @@ static void __init __gic_init(unsigned long gic_base_addr,
 	bitmap_set(ipi_resrv, gic_shared_intrs - 2 * NR_CPUS, 2 * NR_CPUS);
 
 	gic_basic_init();
-
-	gic_ipi_init();
 }
 
 void __init gic_init(unsigned long gic_base_addr,
diff --git a/include/linux/irqchip/mips-gic.h b/include/linux/irqchip/mips-gic.h
index 4e6861605050..321278767506 100644
--- a/include/linux/irqchip/mips-gic.h
+++ b/include/linux/irqchip/mips-gic.h
@@ -258,9 +258,6 @@ extern void gic_write_compare(cycle_t cnt);
 extern void gic_write_cpu_compare(cycle_t cnt, int cpu);
 extern void gic_start_count(void);
 extern void gic_stop_count(void);
-extern void gic_send_ipi(unsigned int intr);
-extern unsigned int plat_ipi_call_int_xlate(unsigned int);
-extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
 extern int gic_get_c0_compare_int(void);
 extern int gic_get_c0_perfcount_int(void);
 extern int gic_get_c0_fdc_int(void);
-- 
2.1.0

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

* [PATCH 13/14] MIPS: Delete smp-gic.c
@ 2015-11-03 11:13   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips,
	Qais Yousef, Paul Burton

We now have a generic IPI layer that will use GIC automatically
if it's compiled in.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/Kconfig          |  6 -----
 arch/mips/kernel/Makefile  |  1 -
 arch/mips/kernel/smp-gic.c | 64 ----------------------------------------------
 3 files changed, 71 deletions(-)
 delete mode 100644 arch/mips/kernel/smp-gic.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e3aa5b0b4ef1..5a73c1217af7 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2123,7 +2123,6 @@ config MIPS_MT_SMP
 	select CPU_MIPSR2_IRQ_VI
 	select CPU_MIPSR2_IRQ_EI
 	select SYNC_R4K
-	select MIPS_GIC_IPI
 	select MIPS_MT
 	select SMP
 	select SMP_UP
@@ -2221,7 +2220,6 @@ config MIPS_VPE_APSP_API_MT
 config MIPS_CMP
 	bool "MIPS CMP framework support (DEPRECATED)"
 	depends on SYS_SUPPORTS_MIPS_CMP && !CPU_MIPSR6
-	select MIPS_GIC_IPI
 	select SMP
 	select SYNC_R4K
 	select SYS_SUPPORTS_SMP
@@ -2241,7 +2239,6 @@ config MIPS_CPS
 	select MIPS_CM
 	select MIPS_CPC
 	select MIPS_CPS_PM if HOTPLUG_CPU
-	select MIPS_GIC_IPI
 	select SMP
 	select SYNC_R4K if (CEVT_R4K || CSRC_R4K)
 	select SYS_SUPPORTS_HOTPLUG_CPU
@@ -2259,9 +2256,6 @@ config MIPS_CPS_PM
 	select MIPS_CPC
 	bool
 
-config MIPS_GIC_IPI
-	bool
-
 config MIPS_CM
 	bool
 
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index d982be1ea1c3..a4bfc41d46b5 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -51,7 +51,6 @@ obj-$(CONFIG_MIPS_MT_FPAFF)	+= mips-mt-fpaff.o
 obj-$(CONFIG_MIPS_MT_SMP)	+= smp-mt.o
 obj-$(CONFIG_MIPS_CMP)		+= smp-cmp.o
 obj-$(CONFIG_MIPS_CPS)		+= smp-cps.o cps-vec.o
-obj-$(CONFIG_MIPS_GIC_IPI)	+= smp-gic.o
 obj-$(CONFIG_MIPS_SPRAM)	+= spram.o
 
 obj-$(CONFIG_MIPS_VPE_LOADER)	+= vpe.o
diff --git a/arch/mips/kernel/smp-gic.c b/arch/mips/kernel/smp-gic.c
deleted file mode 100644
index 5f0ab5bcd01e..000000000000
--- a/arch/mips/kernel/smp-gic.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2013 Imagination Technologies
- * Author: Paul Burton <paul.burton@imgtec.com>
- *
- * Based on smp-cmp.c:
- *  Copyright (C) 2007 MIPS Technologies, Inc.
- *  Author: Chris Dearman (chris@mips.com)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/irqchip/mips-gic.h>
-#include <linux/printk.h>
-
-#include <asm/mips-cpc.h>
-#include <asm/smp-ops.h>
-
-void gic_send_ipi_single(int cpu, unsigned int action)
-{
-	unsigned long flags;
-	unsigned int intr;
-	unsigned int core = cpu_data[cpu].core;
-
-	pr_debug("CPU%d: %s cpu %d action %u status %08x\n",
-		 smp_processor_id(), __func__, cpu, action, read_c0_status());
-
-	local_irq_save(flags);
-
-	switch (action) {
-	case SMP_CALL_FUNCTION:
-		intr = plat_ipi_call_int_xlate(cpu);
-		break;
-
-	case SMP_RESCHEDULE_YOURSELF:
-		intr = plat_ipi_resched_int_xlate(cpu);
-		break;
-
-	default:
-		BUG();
-	}
-
-	gic_send_ipi(intr);
-
-	if (mips_cpc_present() && (core != current_cpu_data.core)) {
-		while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
-			mips_cpc_lock_other(core);
-			write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
-			mips_cpc_unlock_other();
-		}
-	}
-
-	local_irq_restore(flags);
-}
-
-void gic_send_ipi_mask(const struct cpumask *mask, unsigned int action)
-{
-	unsigned int i;
-
-	for_each_cpu(i, mask)
-		gic_send_ipi_single(i, action);
-}
-- 
2.1.0


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

* [PATCH 13/14] MIPS: Delete smp-gic.c
@ 2015-11-03 11:13   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips,
	Qais Yousef, Paul Burton

We now have a generic IPI layer that will use GIC automatically
if it's compiled in.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
---
 arch/mips/Kconfig          |  6 -----
 arch/mips/kernel/Makefile  |  1 -
 arch/mips/kernel/smp-gic.c | 64 ----------------------------------------------
 3 files changed, 71 deletions(-)
 delete mode 100644 arch/mips/kernel/smp-gic.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e3aa5b0b4ef1..5a73c1217af7 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -2123,7 +2123,6 @@ config MIPS_MT_SMP
 	select CPU_MIPSR2_IRQ_VI
 	select CPU_MIPSR2_IRQ_EI
 	select SYNC_R4K
-	select MIPS_GIC_IPI
 	select MIPS_MT
 	select SMP
 	select SMP_UP
@@ -2221,7 +2220,6 @@ config MIPS_VPE_APSP_API_MT
 config MIPS_CMP
 	bool "MIPS CMP framework support (DEPRECATED)"
 	depends on SYS_SUPPORTS_MIPS_CMP && !CPU_MIPSR6
-	select MIPS_GIC_IPI
 	select SMP
 	select SYNC_R4K
 	select SYS_SUPPORTS_SMP
@@ -2241,7 +2239,6 @@ config MIPS_CPS
 	select MIPS_CM
 	select MIPS_CPC
 	select MIPS_CPS_PM if HOTPLUG_CPU
-	select MIPS_GIC_IPI
 	select SMP
 	select SYNC_R4K if (CEVT_R4K || CSRC_R4K)
 	select SYS_SUPPORTS_HOTPLUG_CPU
@@ -2259,9 +2256,6 @@ config MIPS_CPS_PM
 	select MIPS_CPC
 	bool
 
-config MIPS_GIC_IPI
-	bool
-
 config MIPS_CM
 	bool
 
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index d982be1ea1c3..a4bfc41d46b5 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -51,7 +51,6 @@ obj-$(CONFIG_MIPS_MT_FPAFF)	+= mips-mt-fpaff.o
 obj-$(CONFIG_MIPS_MT_SMP)	+= smp-mt.o
 obj-$(CONFIG_MIPS_CMP)		+= smp-cmp.o
 obj-$(CONFIG_MIPS_CPS)		+= smp-cps.o cps-vec.o
-obj-$(CONFIG_MIPS_GIC_IPI)	+= smp-gic.o
 obj-$(CONFIG_MIPS_SPRAM)	+= spram.o
 
 obj-$(CONFIG_MIPS_VPE_LOADER)	+= vpe.o
diff --git a/arch/mips/kernel/smp-gic.c b/arch/mips/kernel/smp-gic.c
deleted file mode 100644
index 5f0ab5bcd01e..000000000000
--- a/arch/mips/kernel/smp-gic.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2013 Imagination Technologies
- * Author: Paul Burton <paul.burton@imgtec.com>
- *
- * Based on smp-cmp.c:
- *  Copyright (C) 2007 MIPS Technologies, Inc.
- *  Author: Chris Dearman (chris@mips.com)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/irqchip/mips-gic.h>
-#include <linux/printk.h>
-
-#include <asm/mips-cpc.h>
-#include <asm/smp-ops.h>
-
-void gic_send_ipi_single(int cpu, unsigned int action)
-{
-	unsigned long flags;
-	unsigned int intr;
-	unsigned int core = cpu_data[cpu].core;
-
-	pr_debug("CPU%d: %s cpu %d action %u status %08x\n",
-		 smp_processor_id(), __func__, cpu, action, read_c0_status());
-
-	local_irq_save(flags);
-
-	switch (action) {
-	case SMP_CALL_FUNCTION:
-		intr = plat_ipi_call_int_xlate(cpu);
-		break;
-
-	case SMP_RESCHEDULE_YOURSELF:
-		intr = plat_ipi_resched_int_xlate(cpu);
-		break;
-
-	default:
-		BUG();
-	}
-
-	gic_send_ipi(intr);
-
-	if (mips_cpc_present() && (core != current_cpu_data.core)) {
-		while (!cpumask_test_cpu(cpu, &cpu_coherent_mask)) {
-			mips_cpc_lock_other(core);
-			write_cpc_co_cmd(CPC_Cx_CMD_PWRUP);
-			mips_cpc_unlock_other();
-		}
-	}
-
-	local_irq_restore(flags);
-}
-
-void gic_send_ipi_mask(const struct cpumask *mask, unsigned int action)
-{
-	unsigned int i;
-
-	for_each_cpu(i, mask)
-		gic_send_ipi_single(i, action);
-}
-- 
2.1.0

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

* [PATCH 14/14] Docs: IRQ: Add new IRQ-ipi.txt
@ 2015-11-03 11:13   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips,
	Qais Yousef, Jonathan Corbet, linux-doc

The new file describes how to use the new generic IPI support API and implement
the support in the irqchip driver.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: linux-doc@vger.kernel.org
---
 Documentation/IRQ-ipi.txt | 81 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)
 create mode 100644 Documentation/IRQ-ipi.txt

diff --git a/Documentation/IRQ-ipi.txt b/Documentation/IRQ-ipi.txt
new file mode 100644
index 000000000000..07e5d9abdf38
--- /dev/null
+++ b/Documentation/IRQ-ipi.txt
@@ -0,0 +1,81 @@
+Generic IPI allocation and sending
+
+
+We now have a generic IPI mechanism to allocate and send IPIs which can be used
+to implement ARCH's SMP IPIs or by the driver to exchange IPIs with a coprocessor
+it's talking to.
+
+
+=====
+ API
+=====
+
+Structs:
+
+	-- struct ipi_mask --
+
+	Similar to cpumask but can handle CPUs outside NR_CPU range.
+
+Functions:
+
+	-- irq_reserve_ipi() --
+
+	Dynamically allocate an IPI from an IPI irq_domain registered by the
+	system. An IPI mask must be passed specifying the destination CPUs this
+	IPI will target.
+
+	On success it will return a virq that can be used to send an IPI to one
+	subset of CPUs in the passed IPI mask.
+
+	This function is not exported. Ideally the IPI should be requested from
+	device tree which will use this function indirectly.
+
+	-- irq_send_ipi() --
+
+	To be used by drivers to send an IPI. It takesthe  virq that was
+	returned by irq_reserve_ipi() and an IPI mask containing a subset of the
+	IPI mask used to allocate the IPI.
+
+	This function is exported to allow drivers to use it.
+
+	-- __irq_desc_send_ipi() --
+
+	To be used by ARCH code to send SMP IPIs. It takes a desc instead of virq
+	to save having to do desc lookup on this common case.
+
+	This function is not exported as it's meant for ARCH code use only.
+
+
+=========================================
+ Adding support into your irqchip driver
+=========================================
+
+For this new feature to be used, you need to have an irqchip driver that provides
+an IPI domain.
+
+The IPI domain must be a Hierarchy Domain with IRQ_DOMAIN_FLAG_IPI set and
+domain bust set to DOMAIN_BUS_IPI to allow the system to identify it.
+
+structs:
+
+	-- struct ipi_mapping --
+
+	This struct is provided to aid in creating a CPU to HWIRQ mapping when
+	allocating an IPI and perform the lookup when sending one.
+
+functions:
+
+	-- irq_domain_ops->alloc() --
+
+	This function should be used to implement the hardware specific mechanism
+	to reserve an IPI.
+
+	The generic layer will allocate a virq for each CPU in the IPI mask
+	passed in the call to irq_reserve_ipi() which the driver can freely
+	choose to use or ignore depends if it needs to have a one to one mapping
+	between virq and hwirq or one virq is enough to identify multiple hwirqs.
+
+	-- irqchip->irq_send_ipi() --
+
+	The generic layer will call this irqchip function after doing some sanity
+	checking for the driver to perform the actual IPI kick.
-- 
2.1.0


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

* [PATCH 14/14] Docs: IRQ: Add new IRQ-ipi.txt
@ 2015-11-03 11:13   ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-03 11:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: tglx, jason, marc.zyngier, jiang.liu, ralf, linux-mips,
	Qais Yousef, Jonathan Corbet, linux-doc

The new file describes how to use the new generic IPI support API and implement
the support in the irqchip driver.

Signed-off-by: Qais Yousef <qais.yousef@imgtec.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: linux-doc@vger.kernel.org
---
 Documentation/IRQ-ipi.txt | 81 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)
 create mode 100644 Documentation/IRQ-ipi.txt

diff --git a/Documentation/IRQ-ipi.txt b/Documentation/IRQ-ipi.txt
new file mode 100644
index 000000000000..07e5d9abdf38
--- /dev/null
+++ b/Documentation/IRQ-ipi.txt
@@ -0,0 +1,81 @@
+Generic IPI allocation and sending
+
+
+We now have a generic IPI mechanism to allocate and send IPIs which can be used
+to implement ARCH's SMP IPIs or by the driver to exchange IPIs with a coprocessor
+it's talking to.
+
+
+=====
+ API
+=====
+
+Structs:
+
+	-- struct ipi_mask --
+
+	Similar to cpumask but can handle CPUs outside NR_CPU range.
+
+Functions:
+
+	-- irq_reserve_ipi() --
+
+	Dynamically allocate an IPI from an IPI irq_domain registered by the
+	system. An IPI mask must be passed specifying the destination CPUs this
+	IPI will target.
+
+	On success it will return a virq that can be used to send an IPI to one
+	subset of CPUs in the passed IPI mask.
+
+	This function is not exported. Ideally the IPI should be requested from
+	device tree which will use this function indirectly.
+
+	-- irq_send_ipi() --
+
+	To be used by drivers to send an IPI. It takesthe  virq that was
+	returned by irq_reserve_ipi() and an IPI mask containing a subset of the
+	IPI mask used to allocate the IPI.
+
+	This function is exported to allow drivers to use it.
+
+	-- __irq_desc_send_ipi() --
+
+	To be used by ARCH code to send SMP IPIs. It takes a desc instead of virq
+	to save having to do desc lookup on this common case.
+
+	This function is not exported as it's meant for ARCH code use only.
+
+
+=========================================
+ Adding support into your irqchip driver
+=========================================
+
+For this new feature to be used, you need to have an irqchip driver that provides
+an IPI domain.
+
+The IPI domain must be a Hierarchy Domain with IRQ_DOMAIN_FLAG_IPI set and
+domain bust set to DOMAIN_BUS_IPI to allow the system to identify it.
+
+structs:
+
+	-- struct ipi_mapping --
+
+	This struct is provided to aid in creating a CPU to HWIRQ mapping when
+	allocating an IPI and perform the lookup when sending one.
+
+functions:
+
+	-- irq_domain_ops->alloc() --
+
+	This function should be used to implement the hardware specific mechanism
+	to reserve an IPI.
+
+	The generic layer will allocate a virq for each CPU in the IPI mask
+	passed in the call to irq_reserve_ipi() which the driver can freely
+	choose to use or ignore depends if it needs to have a one to one mapping
+	between virq and hwirq or one virq is enough to identify multiple hwirqs.
+
+	-- irqchip->irq_send_ipi() --
+
+	The generic layer will call this irqchip function after doing some sanity
+	checking for the driver to perform the actual IPI kick.
-- 
2.1.0

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

* Re: [PATCH 07/14] genirq: Add a new generic IPI reservation code to irq core
@ 2015-11-03 12:06     ` kbuild test robot
  0 siblings, 0 replies; 64+ messages in thread
From: kbuild test robot @ 2015-11-03 12:06 UTC (permalink / raw)
  To: Qais Yousef
  Cc: kbuild-all, linux-kernel, tglx, jason, marc.zyngier, jiang.liu,
	ralf, linux-mips, Qais Yousef

[-- Attachment #1: Type: text/plain, Size: 3503 bytes --]

Hi Qais,

[auto build test ERROR on tip/irq/core -- if it's inappropriate base, please suggest rules for selecting the more suitable base]

url:    https://github.com/0day-ci/linux/commits/Qais-Yousef/Implement-generic-IPI-support-mechanism/20151103-192028
config: mips-jz4740 (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=mips 

All errors (new ones prefixed by >>):

   kernel/irq/irqdomain.c: In function 'irq_reserve_ipi':
>> kernel/irq/irqdomain.c:890:9: error: implicit declaration of function '__irq_domain_alloc_irqs' [-Werror=implicit-function-declaration]
     virq = __irq_domain_alloc_irqs(domain, virq, nr_irqs, NUMA_NO_NODE,
            ^
   kernel/irq/irqdomain.c: In function 'irq_destroy_ipi':
>> kernel/irq/irqdomain.c:950:2: error: implicit declaration of function 'irq_domain_free_irqs' [-Werror=implicit-function-declaration]
     irq_domain_free_irqs(irq, nr_irqs);
     ^
   cc1: some warnings being treated as errors

vim +/__irq_domain_alloc_irqs +890 kernel/irq/irqdomain.c

   884		virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE);
   885		if (virq <= 0) {
   886			pr_warn("Can't reserve IPI, failed to alloc descs\n");
   887			return 0;
   888		}
   889	
 > 890		virq = __irq_domain_alloc_irqs(domain, virq, nr_irqs, NUMA_NO_NODE,
   891						(void *) dest, true);
   892		if (virq <= 0) {
   893			pr_warn("Can't reserve IPI, failed to alloc irqs\n");
   894			goto free_descs;
   895		}
   896	
   897		for (i = virq; i < virq + nr_irqs; i++) {
   898			data = irq_get_irq_data(i);
   899			data->common->ipi_mask = ipi_mask_alloc(dest->nbits);
   900			if (!data->common->ipi_mask)
   901				goto free_ipi_mask;
   902			ipi_mask_copy(data->common->ipi_mask, dest);
   903		}
   904	
   905		return virq;
   906	
   907	free_ipi_mask:
   908		for (i = virq; i < virq + nr_irqs; i++) {
   909			data = irq_get_irq_data(i);
   910			ipi_mask_free(data->common->ipi_mask);
   911		}
   912	free_descs:
   913		irq_free_descs(virq, nr_irqs);
   914		return 0;
   915	}
   916	
   917	/**
   918	 * irq_destroy_ipi() - unreserve an IPI that was previously allocated
   919	 * @irq: linux irq number to be destroyed
   920	 *
   921	 * Return the IPIs allocated with irq_reserve_ipi() to the system destroying all
   922	 * virqs associated with them.
   923	 */
   924	void irq_destroy_ipi(unsigned int irq)
   925	{
   926		struct irq_data *data = irq_get_irq_data(irq);
   927		struct irq_domain *domain;
   928		unsigned int nr_irqs, i;
   929	
   930		if (!irq || !data)
   931			return;
   932	
   933		domain = data->domain;
   934		if (WARN_ON(domain == NULL))
   935			return;
   936	
   937		if (!irq_domain_is_ipi(domain)) {
   938			pr_warn("Not an IPI domain!\n");
   939			return;
   940		}
   941	
   942		nr_irqs = ipi_mask_weight(data->common->ipi_mask);
   943		ipi_mask_free(data->common->ipi_mask);
   944	
   945		for (i = irq + 1; i < irq + nr_irqs; i++) {
   946			data = irq_get_irq_data(i);
   947			ipi_mask_free(data->common->ipi_mask);
   948		}
   949	
 > 950		irq_domain_free_irqs(irq, nr_irqs);
   951	}
   952	
   953	#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 17582 bytes --]

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

* Re: [PATCH 07/14] genirq: Add a new generic IPI reservation code to irq core
@ 2015-11-03 12:06     ` kbuild test robot
  0 siblings, 0 replies; 64+ messages in thread
From: kbuild test robot @ 2015-11-03 12:06 UTC (permalink / raw)
  To: Qais Yousef
  Cc: kbuild-all, linux-kernel, tglx, jason, marc.zyngier, jiang.liu,
	ralf, linux-mips

[-- Attachment #1: Type: text/plain, Size: 3503 bytes --]

Hi Qais,

[auto build test ERROR on tip/irq/core -- if it's inappropriate base, please suggest rules for selecting the more suitable base]

url:    https://github.com/0day-ci/linux/commits/Qais-Yousef/Implement-generic-IPI-support-mechanism/20151103-192028
config: mips-jz4740 (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=mips 

All errors (new ones prefixed by >>):

   kernel/irq/irqdomain.c: In function 'irq_reserve_ipi':
>> kernel/irq/irqdomain.c:890:9: error: implicit declaration of function '__irq_domain_alloc_irqs' [-Werror=implicit-function-declaration]
     virq = __irq_domain_alloc_irqs(domain, virq, nr_irqs, NUMA_NO_NODE,
            ^
   kernel/irq/irqdomain.c: In function 'irq_destroy_ipi':
>> kernel/irq/irqdomain.c:950:2: error: implicit declaration of function 'irq_domain_free_irqs' [-Werror=implicit-function-declaration]
     irq_domain_free_irqs(irq, nr_irqs);
     ^
   cc1: some warnings being treated as errors

vim +/__irq_domain_alloc_irqs +890 kernel/irq/irqdomain.c

   884		virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE);
   885		if (virq <= 0) {
   886			pr_warn("Can't reserve IPI, failed to alloc descs\n");
   887			return 0;
   888		}
   889	
 > 890		virq = __irq_domain_alloc_irqs(domain, virq, nr_irqs, NUMA_NO_NODE,
   891						(void *) dest, true);
   892		if (virq <= 0) {
   893			pr_warn("Can't reserve IPI, failed to alloc irqs\n");
   894			goto free_descs;
   895		}
   896	
   897		for (i = virq; i < virq + nr_irqs; i++) {
   898			data = irq_get_irq_data(i);
   899			data->common->ipi_mask = ipi_mask_alloc(dest->nbits);
   900			if (!data->common->ipi_mask)
   901				goto free_ipi_mask;
   902			ipi_mask_copy(data->common->ipi_mask, dest);
   903		}
   904	
   905		return virq;
   906	
   907	free_ipi_mask:
   908		for (i = virq; i < virq + nr_irqs; i++) {
   909			data = irq_get_irq_data(i);
   910			ipi_mask_free(data->common->ipi_mask);
   911		}
   912	free_descs:
   913		irq_free_descs(virq, nr_irqs);
   914		return 0;
   915	}
   916	
   917	/**
   918	 * irq_destroy_ipi() - unreserve an IPI that was previously allocated
   919	 * @irq: linux irq number to be destroyed
   920	 *
   921	 * Return the IPIs allocated with irq_reserve_ipi() to the system destroying all
   922	 * virqs associated with them.
   923	 */
   924	void irq_destroy_ipi(unsigned int irq)
   925	{
   926		struct irq_data *data = irq_get_irq_data(irq);
   927		struct irq_domain *domain;
   928		unsigned int nr_irqs, i;
   929	
   930		if (!irq || !data)
   931			return;
   932	
   933		domain = data->domain;
   934		if (WARN_ON(domain == NULL))
   935			return;
   936	
   937		if (!irq_domain_is_ipi(domain)) {
   938			pr_warn("Not an IPI domain!\n");
   939			return;
   940		}
   941	
   942		nr_irqs = ipi_mask_weight(data->common->ipi_mask);
   943		ipi_mask_free(data->common->ipi_mask);
   944	
   945		for (i = irq + 1; i < irq + nr_irqs; i++) {
   946			data = irq_get_irq_data(i);
   947			ipi_mask_free(data->common->ipi_mask);
   948		}
   949	
 > 950		irq_domain_free_irqs(irq, nr_irqs);
   951	}
   952	
   953	#ifdef	CONFIG_IRQ_DOMAIN_HIERARCHY

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 17582 bytes --]

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

* Re: [PATCH 09/14] genirq: Implement irq_send_ipi() to be used by drivers
@ 2015-11-03 12:09     ` kbuild test robot
  0 siblings, 0 replies; 64+ messages in thread
From: kbuild test robot @ 2015-11-03 12:09 UTC (permalink / raw)
  To: Qais Yousef
  Cc: kbuild-all, linux-kernel, tglx, jason, marc.zyngier, jiang.liu,
	ralf, linux-mips, Qais Yousef

[-- Attachment #1: Type: text/plain, Size: 2944 bytes --]

Hi Qais,

[auto build test WARNING on tip/irq/core -- if it's inappropriate base, please suggest rules for selecting the more suitable base]

url:    https://github.com/0day-ci/linux/commits/Qais-Yousef/Implement-generic-IPI-support-mechanism/20151103-192028
reproduce: make htmldocs

All warnings (new ones prefixed by >>):

   include/linux/irq.h:168: warning: No description found for parameter 'ipi_mask'
>> kernel/irq/manage.c:2103: warning: No description found for parameter 'desc'
>> kernel/irq/manage.c:2103: warning: Excess function parameter 'irq_desc' description in '__irq_desc_send_ipi'
   kernel/irq/manage.c:2146: warning: No description found for parameter 'virq'
   kernel/irq/manage.c:2146: warning: Excess function parameter 'irq' description in 'irq_send_ipi'
   kernel/irq/handle.c:1: warning: no structured comments found
--
   lib/crc32.c:148: warning: No description found for parameter 'tab)[256]'
   lib/crc32.c:148: warning: Excess function parameter 'tab' description in 'crc32_le_generic'
   lib/crc32.c:293: warning: No description found for parameter 'tab)[256]'
   lib/crc32.c:293: warning: Excess function parameter 'tab' description in 'crc32_be_generic'
   lib/crc32.c:1: warning: no structured comments found
>> kernel/irq/manage.c:2103: warning: No description found for parameter 'desc'
>> kernel/irq/manage.c:2103: warning: Excess function parameter 'irq_desc' description in '__irq_desc_send_ipi'
   kernel/irq/manage.c:2146: warning: No description found for parameter 'virq'
   kernel/irq/manage.c:2146: warning: Excess function parameter 'irq' description in 'irq_send_ipi'
   block/blk-core.c:1549: warning: No description found for parameter 'same_queue_rq'
   block/blk-core.c:1549: warning: No description found for parameter 'same_queue_rq'

vim +/desc +2103 kernel/irq/manage.c

  2087		return 0;
  2088	}
  2089	
  2090	/**
  2091	 *	__irq_desc_send_ipi - send an IPI to target CPU(s)
  2092	 *	@irq_desc: pointer to irq_desc of the IRQ
  2093	 *	@dest: dest CPU(s), must be the same or a subset of the mask passed to
  2094	 *	       irq_reserve_ipi()
  2095	 *
  2096	 *	Sends an IPI to all cpus in dest mask.
  2097	 *	This function is meant to be used from arch code to save the need to do
  2098	 *	desc lookup that happens in the generic irq_send_ipi().
  2099	 *
  2100	 *	Returns zero on success and negative error number on failure.
  2101	 */
  2102	int __irq_desc_send_ipi(struct irq_desc *desc, const struct ipi_mask *dest)
> 2103	{
  2104		struct irq_data *data = irq_desc_get_irq_data(desc);
  2105		struct irq_chip *chip = irq_data_get_irq_chip(data);
  2106	
  2107		if (!chip || !chip->irq_send_ipi)
  2108			return -EINVAL;
  2109	
  2110		if (dest->nbits > data->common->ipi_mask->nbits)
  2111			return -EINVAL;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 6062 bytes --]

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

* Re: [PATCH 09/14] genirq: Implement irq_send_ipi() to be used by drivers
@ 2015-11-03 12:09     ` kbuild test robot
  0 siblings, 0 replies; 64+ messages in thread
From: kbuild test robot @ 2015-11-03 12:09 UTC (permalink / raw)
  To: Qais Yousef
  Cc: kbuild-all, linux-kernel, tglx, jason, marc.zyngier, jiang.liu,
	ralf, linux-mips

[-- Attachment #1: Type: text/plain, Size: 2944 bytes --]

Hi Qais,

[auto build test WARNING on tip/irq/core -- if it's inappropriate base, please suggest rules for selecting the more suitable base]

url:    https://github.com/0day-ci/linux/commits/Qais-Yousef/Implement-generic-IPI-support-mechanism/20151103-192028
reproduce: make htmldocs

All warnings (new ones prefixed by >>):

   include/linux/irq.h:168: warning: No description found for parameter 'ipi_mask'
>> kernel/irq/manage.c:2103: warning: No description found for parameter 'desc'
>> kernel/irq/manage.c:2103: warning: Excess function parameter 'irq_desc' description in '__irq_desc_send_ipi'
   kernel/irq/manage.c:2146: warning: No description found for parameter 'virq'
   kernel/irq/manage.c:2146: warning: Excess function parameter 'irq' description in 'irq_send_ipi'
   kernel/irq/handle.c:1: warning: no structured comments found
--
   lib/crc32.c:148: warning: No description found for parameter 'tab)[256]'
   lib/crc32.c:148: warning: Excess function parameter 'tab' description in 'crc32_le_generic'
   lib/crc32.c:293: warning: No description found for parameter 'tab)[256]'
   lib/crc32.c:293: warning: Excess function parameter 'tab' description in 'crc32_be_generic'
   lib/crc32.c:1: warning: no structured comments found
>> kernel/irq/manage.c:2103: warning: No description found for parameter 'desc'
>> kernel/irq/manage.c:2103: warning: Excess function parameter 'irq_desc' description in '__irq_desc_send_ipi'
   kernel/irq/manage.c:2146: warning: No description found for parameter 'virq'
   kernel/irq/manage.c:2146: warning: Excess function parameter 'irq' description in 'irq_send_ipi'
   block/blk-core.c:1549: warning: No description found for parameter 'same_queue_rq'
   block/blk-core.c:1549: warning: No description found for parameter 'same_queue_rq'

vim +/desc +2103 kernel/irq/manage.c

  2087		return 0;
  2088	}
  2089	
  2090	/**
  2091	 *	__irq_desc_send_ipi - send an IPI to target CPU(s)
  2092	 *	@irq_desc: pointer to irq_desc of the IRQ
  2093	 *	@dest: dest CPU(s), must be the same or a subset of the mask passed to
  2094	 *	       irq_reserve_ipi()
  2095	 *
  2096	 *	Sends an IPI to all cpus in dest mask.
  2097	 *	This function is meant to be used from arch code to save the need to do
  2098	 *	desc lookup that happens in the generic irq_send_ipi().
  2099	 *
  2100	 *	Returns zero on success and negative error number on failure.
  2101	 */
  2102	int __irq_desc_send_ipi(struct irq_desc *desc, const struct ipi_mask *dest)
> 2103	{
  2104		struct irq_data *data = irq_desc_get_irq_data(desc);
  2105		struct irq_chip *chip = irq_data_get_irq_chip(data);
  2106	
  2107		if (!chip || !chip->irq_send_ipi)
  2108			return -EINVAL;
  2109	
  2110		if (dest->nbits > data->common->ipi_mask->nbits)
  2111			return -EINVAL;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 6062 bytes --]

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

* Re: [PATCH 04/14] genirq: Add new struct ipi_mask and helper functions
  2015-11-03 11:12   ` Qais Yousef
  (?)
@ 2015-11-07 12:05   ` Thomas Gleixner
  -1 siblings, 0 replies; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-07 12:05 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On Tue, 3 Nov 2015, Qais Yousef wrote:
>  /**
> + * struct ipi_mask - IPI mask information
> + * @nbits: number of bits in cpumask
> + * @global: whether the mask is SMP IPI ie: subset of cpu_possible_mask or not
> + * @cpumask: cpumask to be used when the ipi_mask is global
> + * @cpu_bitmap: the cpu bitmap to use when the ipi_mask is not global
> + *
> + * ipi_mask is similar to cpumask, but it provides nbits that's configurable
> + * rather than fixed to NR_CPUS.

Can you please add an explanation why we want that to the comment?

Thanks,

	tglx

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

* Re: [PATCH 06/14] genirq: Add struct ipi_mapping and its helper functions
  2015-11-03 11:12   ` Qais Yousef
  (?)
@ 2015-11-07 12:09   ` Thomas Gleixner
  2015-11-09 10:05       ` Qais Yousef
  -1 siblings, 1 reply; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-07 12:09 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On Tue, 3 Nov 2015, Qais Yousef wrote:

> struct ipi_mapping will provide a mechanism for irqchip code to fill out the
> mapping at reservation and to look it up when sending.

I'm fine with the code, but can you please move it to w new file,
i.e. kernel/irq/ipi.c and make the compilation depend on GENERIC_IPI?

Thanks,

	tglx

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

* Re: [PATCH 07/14] genirq: Add a new generic IPI reservation code to irq core
  2015-11-03 11:12   ` Qais Yousef
  (?)
  (?)
@ 2015-11-07 12:11   ` Thomas Gleixner
  -1 siblings, 0 replies; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-07 12:11 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On Tue, 3 Nov 2015, Qais Yousef wrote:

> Add a generic mechanism to dynamically allocate an IPI.
> 
> With this change the user can call irq_reserve_ipi() to dynamically allocate an
> IPI and use the associated virq to send one to 1 or more cpus.

Please move that to ipi.c as well.

Thanks,

	tglx

 

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

* Re: [PATCH 09/14] genirq: Implement irq_send_ipi() to be used by drivers
  2015-11-03 11:12   ` Qais Yousef
  (?)
  (?)
@ 2015-11-07 12:14   ` Thomas Gleixner
  -1 siblings, 0 replies; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-07 12:14 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On Tue, 3 Nov 2015, Qais Yousef wrote:
> --- a/kernel/irq/manage.c
> +++ b/kernel/irq/manage.c
> @@ -2013,7 +2013,6 @@ EXPORT_SYMBOL_GPL(irq_set_irqchip_state);
>  struct ipi_mapping *irq_alloc_ipi_mapping(unsigned int nr_cpus)
>  {
>  	struct ipi_mapping *map;
> -	int i;

That one wants to be folded back into the patch which adds it.

> +
> +/**
> + *	__irq_desc_send_ipi - send an IPI to target CPU(s)
> + *	@irq_desc: pointer to irq_desc of the IRQ
> + *	@dest: dest CPU(s), must be the same or a subset of the mask passed to
> + *	       irq_reserve_ipi()
> + *
> + *	Sends an IPI to all cpus in dest mask.
> + *	This function is meant to be used from arch code to save the need to do
> + *	desc lookup that happens in the generic irq_send_ipi().
> + *
> + *	Returns zero on success and negative error number on failure.
> + */
> +int __irq_desc_send_ipi(struct irq_desc *desc, const struct ipi_mask *dest)
> +{
> +	struct irq_data *data = irq_desc_get_irq_data(desc);
> +	struct irq_chip *chip = irq_data_get_irq_chip(data);
> +
> +	if (!chip || !chip->irq_send_ipi)
> +		return -EINVAL;
> +
> +	if (dest->nbits > data->common->ipi_mask->nbits)
> +		return -EINVAL;
> +
> +	/*
> +	 * Do not validate the mask for IPIs marked global. These are
> +	 * regular IPIs so we can avoid the operation as their target
> +	 * mask is the cpu_possible_mask.
> +	 */
> +	if (!data->common->ipi_mask->global) {
> +		if (dest->global)
> +			return -EINVAL;
> +
> +		if (!bitmap_subset(dest->cpu_bitmap,
> +				   data->common->ipi_mask->cpu_bitmap,
> +				   dest->nbits))
> +			return -EINVAL;
> +	} else {
> +		if (!dest->global)
> +			return -EINVAL;

We might want to add sanity checks here as well, but you can leave it
as is for now.

This can move to ipi.c as well.

Thanks,

	tglx


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

* Re: [PATCH 07/14] genirq: Add a new generic IPI reservation code to irq core
  2015-11-03 11:12   ` Qais Yousef
                     ` (2 preceding siblings ...)
  (?)
@ 2015-11-07 13:31   ` Thomas Gleixner
  2015-11-09 10:07       ` Qais Yousef
  -1 siblings, 1 reply; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-07 13:31 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On Tue, 3 Nov 2015, Qais Yousef wrote:
> +
> +	/* always allocate a virq per cpu */
> +	nr_irqs = ipi_mask_weight(dest);

That's not really a good assumption. Not all architectures need
seperate interrupt numbers / descriptors because they can allocate
from a per cpu interrupt space. We really want to handle that here as
well. So we need a flag in the IPI domain which tells us whether that
allocation needs to be weight(desc) or 1.

Thanks,

	tglx



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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
  2015-11-03 11:12   ` Qais Yousef
  (?)
@ 2015-11-07 14:51   ` Thomas Gleixner
  2015-11-09 11:10       ` Qais Yousef
  2015-11-12 15:12       ` Qais Yousef
  -1 siblings, 2 replies; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-07 14:51 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On Tue, 3 Nov 2015, Qais Yousef wrote:

> Add a new ipi domain on top of the normal domain.
> 
> MIPS GIC now supports dynamic allocation of an IPI.

I don't think you make use of the power of hierarchical irq
domains. You just whacked the current code into submission.

Let me explain it to you how that should look like and how that's
going to make the code way simpler.

The root domain is the GIC itself. It provides an allocation mechanism
for all GIC interrupts, global, ipi and per cpu plus the basic
management of them.

So the GIC domain looks at the complete hardware irq space. Now that
irq space is first partioned into local and shared interrupts.

   ------------- hwirq MAX

   Shared interrupts   

   ------------- hwirq 6

   Local interrupts

   ------------- hwirq 0

So that shared interrupt space is where your device interrupts and the
ipi interrupts come from. That local interrupt space seems to be
hardwired, so it'd be overkill to handle that in an extra domain.

I assume that that shared interrupt space is partitioned as well
because the potential device interrupts on the SoC are hardwired. So
the picture looks like this:

   ------------- hwirq MAX

   Shared assignable interrupts

   ------------- hwirq X

   Shared device interrupts   

   ------------- hwirq 6

   Local interrupts

   ------------- hwirq 0


So if we look at the resulting hierarchy it looks like this:

                 |----- [IPI domain]
  [ GIC domain] -
                 |----- [device domain]

The GIC domain manages a bitmap of the full irq space. The IPI domain
and the device domain request N interrupts from the GIC domain at
allocation time.

So when you allocate from the device domain, you tell the parent
domain, that this is actually a device interrupt, and from the IPI
domain you tell it it's an IPI.

So the allocator in the root domain can decide from which space of the
bitmap to allocate.

       if (device) {
       	      hwirq = translate_from_dt(arg);
	      if (test_and_set_bit(&allocated_irqs, hwirq))
	      	     return -EBUSY;
       } else {
       	      start = first_ipi_irq;
	      end = last_ipi_irq + 1;
	      hwirq = bitmap_find_next_zero_area(allocated_irqs, start, end,
       	       				  	 nrirqs, 0);
       }
       ....

So that gives you a consecutive hw irq space for your IPI.

That makes a lot of things simpler. You don't have to keep a mapping
of the hwirq to the target cpu. You just can use the base hwirq and
calculate the destination hwirq from there when sending an IPI
(general Linux ones). The coprocessor one will just be a natural
fallout.

So if you have the following in the generic ipi code:

void ipi_send_single(unsigned int irq, unsigned int cpu)
{
	struct irq_desc *desc = irq_to_desc(irq);
	struct irq_data *data = irq_desc_get_irq_data(desc);
	struct irq_chip *chip = irq_data_get_irq_chip(data);
	
	if (chip->ipi_send_single)
		chip->ipi_send_single(data, cpu);
	else
		chip->ipi_send_mask(data, cpumask_of(cpu));
}

void ipi_send_mask(unsigned int irq, const struct cpumask *dest)
{
	struct irq_desc *desc = irq_to_desc(irq);
	struct irq_data *data = irq_desc_get_irq_data(desc);
	struct irq_chip *chip = irq_data_get_irq_chip(data);
	int cpu;

	if (!chip->ipi_send_mask) {
		for_each_cpu(cpu, dest)
			chip->ipi_send_single(data, cpu);
	} else {
		chip->ipi_send_mask(data, dest);
	}
}

void ipi_send_coproc_mask(unsigned int irq, const struct ipi_mask *dest)
{
        Fill in the obvious code.
}

And your ipi_send_single() callback just boils down to:
{
    	target = data->hw_irq + cpu;

	tweak_chip_regs(target);
}

Sanity checks omitted for brevity.

And that whole thing works for your case and for the case where we
only have a single per cpu interrupt descriptor allocated. The irq
descriptor based variants are exactly the same thing.

So now for the irq chips of your device and IPI domains. You can
either set the proper GIC chip variant or in case you need some extra
magic for one of the domains, you implement your own special chip
which can have some of its callback implemented by the existing
irq_***_parent() variants.

That gets rid of all your extra mappings, bitmaps and whatever add ons
you have duct taped into the existing GIC code.

Thanks,

	tglx

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

* Re: [PATCH 06/14] genirq: Add struct ipi_mapping and its helper functions
@ 2015-11-09 10:05       ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-09 10:05 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/07/2015 12:09 PM, Thomas Gleixner wrote:
> On Tue, 3 Nov 2015, Qais Yousef wrote:
>
>> struct ipi_mapping will provide a mechanism for irqchip code to fill out the
>> mapping at reservation and to look it up when sending.
> I'm fine with the code, but can you please move it to w new file,
> i.e. kernel/irq/ipi.c and make the compilation depend on GENERIC_IPI?

I originally had ipi.c then removed it. I'll move all functionality there.

Thanks,
Qais

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

* Re: [PATCH 06/14] genirq: Add struct ipi_mapping and its helper functions
@ 2015-11-09 10:05       ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-09 10:05 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/07/2015 12:09 PM, Thomas Gleixner wrote:
> On Tue, 3 Nov 2015, Qais Yousef wrote:
>
>> struct ipi_mapping will provide a mechanism for irqchip code to fill out the
>> mapping at reservation and to look it up when sending.
> I'm fine with the code, but can you please move it to w new file,
> i.e. kernel/irq/ipi.c and make the compilation depend on GENERIC_IPI?

I originally had ipi.c then removed it. I'll move all functionality there.

Thanks,
Qais

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

* Re: [PATCH 07/14] genirq: Add a new generic IPI reservation code to irq core
@ 2015-11-09 10:07       ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-09 10:07 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/07/2015 01:31 PM, Thomas Gleixner wrote:
> On Tue, 3 Nov 2015, Qais Yousef wrote:
>> +
>> +	/* always allocate a virq per cpu */
>> +	nr_irqs = ipi_mask_weight(dest);
> That's not really a good assumption. Not all architectures need
> seperate interrupt numbers / descriptors because they can allocate
> from a per cpu interrupt space. We really want to handle that here as
> well. So we need a flag in the IPI domain which tells us whether that
> allocation needs to be weight(desc) or 1.

OK. But is it bad to always allocate the weight? I thought allocating 
virqs is cheap, or maybe not?

Thanks,
Qais

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

* Re: [PATCH 07/14] genirq: Add a new generic IPI reservation code to irq core
@ 2015-11-09 10:07       ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-09 10:07 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/07/2015 01:31 PM, Thomas Gleixner wrote:
> On Tue, 3 Nov 2015, Qais Yousef wrote:
>> +
>> +	/* always allocate a virq per cpu */
>> +	nr_irqs = ipi_mask_weight(dest);
> That's not really a good assumption. Not all architectures need
> seperate interrupt numbers / descriptors because they can allocate
> from a per cpu interrupt space. We really want to handle that here as
> well. So we need a flag in the IPI domain which tells us whether that
> allocation needs to be weight(desc) or 1.

OK. But is it bad to always allocate the weight? I thought allocating 
virqs is cheap, or maybe not?

Thanks,
Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-09 11:10       ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-09 11:10 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/07/2015 02:51 PM, Thomas Gleixner wrote:
> On Tue, 3 Nov 2015, Qais Yousef wrote:
>
>> Add a new ipi domain on top of the normal domain.
>>
>> MIPS GIC now supports dynamic allocation of an IPI.
> I don't think you make use of the power of hierarchical irq
> domains. You just whacked the current code into submission.
>
> Let me explain it to you how that should look like and how that's
> going to make the code way simpler.
>
> The root domain is the GIC itself. It provides an allocation mechanism
> for all GIC interrupts, global, ipi and per cpu plus the basic
> management of them.
>
> So the GIC domain looks at the complete hardware irq space. Now that
> irq space is first partioned into local and shared interrupts.
>
>     ------------- hwirq MAX
>
>     Shared interrupts
>
>     ------------- hwirq 6
>
>     Local interrupts
>
>     ------------- hwirq 0
>
> So that shared interrupt space is where your device interrupts and the
> ipi interrupts come from. That local interrupt space seems to be
> hardwired, so it'd be overkill to handle that in an extra domain.
>
> I assume that that shared interrupt space is partitioned as well
> because the potential device interrupts on the SoC are hardwired. So
> the picture looks like this:
>
>     ------------- hwirq MAX
>
>     Shared assignable interrupts
>
>     ------------- hwirq X
>
>     Shared device interrupts
>
>     ------------- hwirq 6
>
>     Local interrupts
>
>     ------------- hwirq 0
>
>
> So if we look at the resulting hierarchy it looks like this:
>
>                   |----- [IPI domain]
>    [ GIC domain] -
>                   |----- [device domain]
>
> The GIC domain manages a bitmap of the full irq space. The IPI domain
> and the device domain request N interrupts from the GIC domain at
> allocation time.
>
> So when you allocate from the device domain, you tell the parent
> domain, that this is actually a device interrupt, and from the IPI
> domain you tell it it's an IPI.
>
> So the allocator in the root domain can decide from which space of the
> bitmap to allocate.
>
>         if (device) {
>         	      hwirq = translate_from_dt(arg);
> 	      if (test_and_set_bit(&allocated_irqs, hwirq))
> 	      	     return -EBUSY;
>         } else {
>         	      start = first_ipi_irq;
> 	      end = last_ipi_irq + 1;
> 	      hwirq = bitmap_find_next_zero_area(allocated_irqs, start, end,
>         	       				  	 nrirqs, 0);
>         }
>         ....
>
> So that gives you a consecutive hw irq space for your IPI.


This is potentially dangerous. If a device allocation happens after an 
IPI allocation, and that device wants the hwirq at the region that IPI 
just allocated because it thought it's free, it'd fail.

Generally it's hard to know whether a real device is connected to a 
hwirq or not. I am saving a patch where we get a set of free hwirqs from 
DT as only the SoC designer knows what hwirq are actually free and safe 
to use for IPI. I'll send this patch with the DT IPI changes or the 
rproc driver that I will be send once these changes are merged.

The current code assumes that the last 2 * NR_CPUs hwirqs are always 
free to use for Linux SMP.

>
> That makes a lot of things simpler. You don't have to keep a mapping
> of the hwirq to the target cpu. You just can use the base hwirq and
> calculate the destination hwirq from there when sending an IPI
> (general Linux ones). The coprocessor one will just be a natural
> fallout.

Are you suggesting here to remove the whole new mapping API from the 
generic code or just that it's not necessary to use it in my case?

>
> So if you have the following in the generic ipi code:
>
> void ipi_send_single(unsigned int irq, unsigned int cpu)
> {
> 	struct irq_desc *desc = irq_to_desc(irq);
> 	struct irq_data *data = irq_desc_get_irq_data(desc);
> 	struct irq_chip *chip = irq_data_get_irq_chip(data);
> 	
> 	if (chip->ipi_send_single)
> 		chip->ipi_send_single(data, cpu);
> 	else
> 		chip->ipi_send_mask(data, cpumask_of(cpu));
> }
>
> void ipi_send_mask(unsigned int irq, const struct cpumask *dest)
> {
> 	struct irq_desc *desc = irq_to_desc(irq);
> 	struct irq_data *data = irq_desc_get_irq_data(desc);
> 	struct irq_chip *chip = irq_data_get_irq_chip(data);
> 	int cpu;
>
> 	if (!chip->ipi_send_mask) {
> 		for_each_cpu(cpu, dest)
> 			chip->ipi_send_single(data, cpu);
> 	} else {
> 		chip->ipi_send_mask(data, dest);
> 	}
> }
>
> void ipi_send_coproc_mask(unsigned int irq, const struct ipi_mask *dest)
> {
>          Fill in the obvious code.
> }
>
> And your ipi_send_single() callback just boils down to:
> {
>      	target = data->hw_irq + cpu;
>
> 	tweak_chip_regs(target);
> }
>
> Sanity checks omitted for brevity.

I'm confused here as well. Is this a complementary API or are you 
suggesting replacing the one this patch introduces?

>
> And that whole thing works for your case and for the case where we
> only have a single per cpu interrupt descriptor allocated. The irq
> descriptor based variants are exactly the same thing.
>
> So now for the irq chips of your device and IPI domains. You can
> either set the proper GIC chip variant or in case you need some extra
> magic for one of the domains, you implement your own special chip
> which can have some of its callback implemented by the existing
> irq_***_parent() variants.
>
> That gets rid of all your extra mappings, bitmaps and whatever add ons
> you have duct taped into the existing GIC code.

This is all new territory for me. I thought I did it the correct way and 
it seemed simple to me.

I'll follow your idea through and see what I come up with. I'm getting a 
bit confused about how the generic API should look like now though. I'll 
keep what I added and add any new needed stuff and hopefully once I 
start doing the work and when the next series is ready it'd be more 
obvious what's needed and what's not.

Thanks,
Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-09 11:10       ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-09 11:10 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/07/2015 02:51 PM, Thomas Gleixner wrote:
> On Tue, 3 Nov 2015, Qais Yousef wrote:
>
>> Add a new ipi domain on top of the normal domain.
>>
>> MIPS GIC now supports dynamic allocation of an IPI.
> I don't think you make use of the power of hierarchical irq
> domains. You just whacked the current code into submission.
>
> Let me explain it to you how that should look like and how that's
> going to make the code way simpler.
>
> The root domain is the GIC itself. It provides an allocation mechanism
> for all GIC interrupts, global, ipi and per cpu plus the basic
> management of them.
>
> So the GIC domain looks at the complete hardware irq space. Now that
> irq space is first partioned into local and shared interrupts.
>
>     ------------- hwirq MAX
>
>     Shared interrupts
>
>     ------------- hwirq 6
>
>     Local interrupts
>
>     ------------- hwirq 0
>
> So that shared interrupt space is where your device interrupts and the
> ipi interrupts come from. That local interrupt space seems to be
> hardwired, so it'd be overkill to handle that in an extra domain.
>
> I assume that that shared interrupt space is partitioned as well
> because the potential device interrupts on the SoC are hardwired. So
> the picture looks like this:
>
>     ------------- hwirq MAX
>
>     Shared assignable interrupts
>
>     ------------- hwirq X
>
>     Shared device interrupts
>
>     ------------- hwirq 6
>
>     Local interrupts
>
>     ------------- hwirq 0
>
>
> So if we look at the resulting hierarchy it looks like this:
>
>                   |----- [IPI domain]
>    [ GIC domain] -
>                   |----- [device domain]
>
> The GIC domain manages a bitmap of the full irq space. The IPI domain
> and the device domain request N interrupts from the GIC domain at
> allocation time.
>
> So when you allocate from the device domain, you tell the parent
> domain, that this is actually a device interrupt, and from the IPI
> domain you tell it it's an IPI.
>
> So the allocator in the root domain can decide from which space of the
> bitmap to allocate.
>
>         if (device) {
>         	      hwirq = translate_from_dt(arg);
> 	      if (test_and_set_bit(&allocated_irqs, hwirq))
> 	      	     return -EBUSY;
>         } else {
>         	      start = first_ipi_irq;
> 	      end = last_ipi_irq + 1;
> 	      hwirq = bitmap_find_next_zero_area(allocated_irqs, start, end,
>         	       				  	 nrirqs, 0);
>         }
>         ....
>
> So that gives you a consecutive hw irq space for your IPI.


This is potentially dangerous. If a device allocation happens after an 
IPI allocation, and that device wants the hwirq at the region that IPI 
just allocated because it thought it's free, it'd fail.

Generally it's hard to know whether a real device is connected to a 
hwirq or not. I am saving a patch where we get a set of free hwirqs from 
DT as only the SoC designer knows what hwirq are actually free and safe 
to use for IPI. I'll send this patch with the DT IPI changes or the 
rproc driver that I will be send once these changes are merged.

The current code assumes that the last 2 * NR_CPUs hwirqs are always 
free to use for Linux SMP.

>
> That makes a lot of things simpler. You don't have to keep a mapping
> of the hwirq to the target cpu. You just can use the base hwirq and
> calculate the destination hwirq from there when sending an IPI
> (general Linux ones). The coprocessor one will just be a natural
> fallout.

Are you suggesting here to remove the whole new mapping API from the 
generic code or just that it's not necessary to use it in my case?

>
> So if you have the following in the generic ipi code:
>
> void ipi_send_single(unsigned int irq, unsigned int cpu)
> {
> 	struct irq_desc *desc = irq_to_desc(irq);
> 	struct irq_data *data = irq_desc_get_irq_data(desc);
> 	struct irq_chip *chip = irq_data_get_irq_chip(data);
> 	
> 	if (chip->ipi_send_single)
> 		chip->ipi_send_single(data, cpu);
> 	else
> 		chip->ipi_send_mask(data, cpumask_of(cpu));
> }
>
> void ipi_send_mask(unsigned int irq, const struct cpumask *dest)
> {
> 	struct irq_desc *desc = irq_to_desc(irq);
> 	struct irq_data *data = irq_desc_get_irq_data(desc);
> 	struct irq_chip *chip = irq_data_get_irq_chip(data);
> 	int cpu;
>
> 	if (!chip->ipi_send_mask) {
> 		for_each_cpu(cpu, dest)
> 			chip->ipi_send_single(data, cpu);
> 	} else {
> 		chip->ipi_send_mask(data, dest);
> 	}
> }
>
> void ipi_send_coproc_mask(unsigned int irq, const struct ipi_mask *dest)
> {
>          Fill in the obvious code.
> }
>
> And your ipi_send_single() callback just boils down to:
> {
>      	target = data->hw_irq + cpu;
>
> 	tweak_chip_regs(target);
> }
>
> Sanity checks omitted for brevity.

I'm confused here as well. Is this a complementary API or are you 
suggesting replacing the one this patch introduces?

>
> And that whole thing works for your case and for the case where we
> only have a single per cpu interrupt descriptor allocated. The irq
> descriptor based variants are exactly the same thing.
>
> So now for the irq chips of your device and IPI domains. You can
> either set the proper GIC chip variant or in case you need some extra
> magic for one of the domains, you implement your own special chip
> which can have some of its callback implemented by the existing
> irq_***_parent() variants.
>
> That gets rid of all your extra mappings, bitmaps and whatever add ons
> you have duct taped into the existing GIC code.

This is all new territory for me. I thought I did it the correct way and 
it seemed simple to me.

I'll follow your idea through and see what I come up with. I'm getting a 
bit confused about how the generic API should look like now though. I'll 
keep what I added and add any new needed stuff and hopefully once I 
start doing the work and when the next series is ready it'd be more 
obvious what's needed and what's not.

Thanks,
Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-12 15:12       ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-12 15:12 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

Hi Thomas,

On 11/07/2015 02:51 PM, Thomas Gleixner wrote:
> On Tue, 3 Nov 2015, Qais Yousef wrote:
>
>> Add a new ipi domain on top of the normal domain.
>>
>> MIPS GIC now supports dynamic allocation of an IPI.
> I don't think you make use of the power of hierarchical irq
> domains. You just whacked the current code into submission.
>

This time I'm having problems digesting your suggestion. I can't see how 
it would make things simpler to be honest.

Issues I'm seeing:

     - Device domain would be identical to GIC domain and it would defer 
everything to the parent domain except for the extra level of 
indirection. No?

     - The race condition I mentioned in my earlier email where we must 
be told what hwirqs are available because we can't guarantee there's no 
real device connected to it which could interfere with the operation. We 
have always to work on a pre reserved set defined by the system. 
Currently GIC hard codes this set, but I'll be making it a DT property 
in the future.

     - If we remove the mapping, how can a coprocessor drivers find out 
the reverse mapping to pass the hwirq to the firmware so that it can 
send and listen on the correct hwirqs? I have to say my current patches 
missed dealing with this problem. Now I have something to test my rproc 
driver on I came to realise I haven't added the function to do the 
reverse mapping.

In summary. I can't see how adding the device domain would help in 
making things simpler and without having generic explicit cpu mapping I 
don't know how I can implement a generic reverse mapping function to get 
the hwirq to pass to the coprocessor firmware.

If I misunderstood your suggestion, mind rephrasing it please?

I can see though if I use irq_*_alloc_parent() I can probably get rid 
off the below since I'd be able to use gic_irq_domain all the time to do 
the revmap.

+		if (test_bit(intr, ipi_intrs)) {
+			virq = irq_linear_revmap(gic_ipi_domain,
+					GIC_SHARED_TO_HWIRQ(intr));
+		} else {
+			virq = irq_linear_revmap(gic_irq_domain,
+					GIC_SHARED_TO_HWIRQ(intr));
+		}
+



Thanks,
Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-12 15:12       ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-12 15:12 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

Hi Thomas,

On 11/07/2015 02:51 PM, Thomas Gleixner wrote:
> On Tue, 3 Nov 2015, Qais Yousef wrote:
>
>> Add a new ipi domain on top of the normal domain.
>>
>> MIPS GIC now supports dynamic allocation of an IPI.
> I don't think you make use of the power of hierarchical irq
> domains. You just whacked the current code into submission.
>

This time I'm having problems digesting your suggestion. I can't see how 
it would make things simpler to be honest.

Issues I'm seeing:

     - Device domain would be identical to GIC domain and it would defer 
everything to the parent domain except for the extra level of 
indirection. No?

     - The race condition I mentioned in my earlier email where we must 
be told what hwirqs are available because we can't guarantee there's no 
real device connected to it which could interfere with the operation. We 
have always to work on a pre reserved set defined by the system. 
Currently GIC hard codes this set, but I'll be making it a DT property 
in the future.

     - If we remove the mapping, how can a coprocessor drivers find out 
the reverse mapping to pass the hwirq to the firmware so that it can 
send and listen on the correct hwirqs? I have to say my current patches 
missed dealing with this problem. Now I have something to test my rproc 
driver on I came to realise I haven't added the function to do the 
reverse mapping.

In summary. I can't see how adding the device domain would help in 
making things simpler and without having generic explicit cpu mapping I 
don't know how I can implement a generic reverse mapping function to get 
the hwirq to pass to the coprocessor firmware.

If I misunderstood your suggestion, mind rephrasing it please?

I can see though if I use irq_*_alloc_parent() I can probably get rid 
off the below since I'd be able to use gic_irq_domain all the time to do 
the revmap.

+		if (test_bit(intr, ipi_intrs)) {
+			virq = irq_linear_revmap(gic_ipi_domain,
+					GIC_SHARED_TO_HWIRQ(intr));
+		} else {
+			virq = irq_linear_revmap(gic_irq_domain,
+					GIC_SHARED_TO_HWIRQ(intr));
+		}
+



Thanks,
Qais

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

* Re: [PATCH 07/14] genirq: Add a new generic IPI reservation code to irq core
  2015-11-09 10:07       ` Qais Yousef
  (?)
@ 2015-11-16 15:09       ` Thomas Gleixner
  -1 siblings, 0 replies; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-16 15:09 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On Mon, 9 Nov 2015, Qais Yousef wrote:
> On 11/07/2015 01:31 PM, Thomas Gleixner wrote:
> > On Tue, 3 Nov 2015, Qais Yousef wrote:
> > > +
> > > +	/* always allocate a virq per cpu */
> > > +	nr_irqs = ipi_mask_weight(dest);
> > That's not really a good assumption. Not all architectures need
> > seperate interrupt numbers / descriptors because they can allocate
> > from a per cpu interrupt space. We really want to handle that here as
> > well. So we need a flag in the IPI domain which tells us whether that
> > allocation needs to be weight(desc) or 1.
> 
> OK. But is it bad to always allocate the weight? I thought allocating virqs is
> cheap, or maybe not?

It's wrong to allocate the descriptors in the case of per cpu
interrupts. Aside of wasting memory its not representing what the
hardware does.

Thanks,

	tglx

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
  2015-11-09 11:10       ` Qais Yousef
  (?)
@ 2015-11-16 17:17       ` Thomas Gleixner
  2015-11-17 10:08           ` Qais Yousef
  2015-11-20 10:48           ` Qais Yousef
  -1 siblings, 2 replies; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-16 17:17 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On Mon, 9 Nov 2015, Qais Yousef wrote:
> On 11/07/2015 02:51 PM, Thomas Gleixner wrote:
> Generally it's hard to know whether a real device is connected to a hwirq or
> not. I am saving a patch where we get a set of free hwirqs from DT as only the
> SoC designer knows what hwirq are actually free and safe to use for IPI. I'll
> send this patch with the DT IPI changes or the rproc driver that I will be
> send once these changes are merged.
> 
> The current code assumes that the last 2 * NR_CPUs hwirqs are always free to
> use for Linux SMP.

So what you're saying is that you cannot rely on the last X hwirqs
being available for IPIs. That's insane and to my knowledge there is
no hardware out there which does not reserve a consecutive IPI space.

But nevertheless, lets look at the various (possible) requirements we
have:

1) IPI as per_cpu interrupts

   Single hwirq represented by a single irq descriptor

2) IPI with consecutive mapping space

   No extra mapping from virq base to target cpu required as its just
   linear. Everything can be handled via the base virq.

3) IPI with random mapping space

   Seperate mapping virq base to target cpu is required. The obvious
   place to store it are the irq descriptors. That needs a bit
   different machinery for ipi_send_mask(), but it's not rocket
   science.

> > That makes a lot of things simpler. You don't have to keep a mapping
> > of the hwirq to the target cpu. You just can use the base hwirq and
> > calculate the destination hwirq from there when sending an IPI
> > (general Linux ones). The coprocessor one will just be a natural
> > fallout.
> 
> Are you suggesting here to remove the whole new mapping API from the
> generic code or just that it's not necessary to use it in my case?

Err. I'm saying that you did not make use of hierarchical domains. You
just glued the IPI stuff sideways on the GIC.

We certainly want the generic code for managing the allocation etc.
 
> I'm confused here as well. Is this a complementary API or are you suggesting
> replacing the one this patch introduces?

Those are replacements. We just need to handle the random mapping case
if we really need it.
 
Thanks,

	tglx

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
  2015-11-12 15:12       ` Qais Yousef
  (?)
@ 2015-11-16 17:24       ` Thomas Gleixner
  2015-11-17 10:24           ` Qais Yousef
  -1 siblings, 1 reply; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-16 17:24 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On Thu, 12 Nov 2015, Qais Yousef wrote:
> Issues I'm seeing:
> 
>     - Device domain would be identical to GIC domain and it would defer
> everything to the parent domain except for the extra level of indirection. No?
 
It's not identical. It's a subset of the GIC domain and it has
different semantics than the IPI domain.

>     - The race condition I mentioned in my earlier email where we must be told
> what hwirqs are available because we can't guarantee there's no real device
> connected to it which could interfere with the operation. We have always to
> work on a pre reserved set defined by the system. Currently GIC hard codes
> this set, but I'll be making it a DT property in the future.

We do that better now as we really don't want to start over when it
turns out that the DT property imposes other issues on it.
 
>     - If we remove the mapping, how can a coprocessor drivers find out the
> reverse mapping to pass the hwirq to the firmware so that it can send and
> listen on the correct hwirqs? I have to say my current patches missed dealing
> with this problem. Now I have something to test my rproc driver on I came to
> realise I haven't added the function to do the reverse mapping.

int ipi_get_hw_irq(int irq)
{
	struct irq_data *d = irq_get_irq_data(irq);
	return d ? irqd_to_hwirq(d);
}
 
Hmm?

Thanks,

	tglx

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-17 10:08           ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-17 10:08 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/16/2015 05:17 PM, Thomas Gleixner wrote:
> On Mon, 9 Nov 2015, Qais Yousef wrote:
>> On 11/07/2015 02:51 PM, Thomas Gleixner wrote:
>> Generally it's hard to know whether a real device is connected to a hwirq or
>> not. I am saving a patch where we get a set of free hwirqs from DT as only the
>> SoC designer knows what hwirq are actually free and safe to use for IPI. I'll
>> send this patch with the DT IPI changes or the rproc driver that I will be
>> send once these changes are merged.
>>
>> The current code assumes that the last 2 * NR_CPUs hwirqs are always free to
>> use for Linux SMP.
> So what you're saying is that you cannot rely on the last X hwirqs
> being available for IPIs. That's insane and to my knowledge there is
> no hardware out there which does not reserve a consecutive IPI space.

If I read the code you were suggesting correctly, you were trying to fit 
the IPIs in any available non allocated area in the GIC space. What I am 
trying to say is that we can only work on a limited subset of this space 
that we are told explicitly it's safe to use for IPIs. Most likely it's 
consecutive, but I don't feel brave enough to make this assumption 
personally - maybe I'm over paranoid.. I'm more keen on anything that 
would simplify this patch series now though.

I'll do my best with the next series but maybe we'd need to iterate this 
more than once till I get it right.

Thanks,
Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-17 10:08           ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-17 10:08 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/16/2015 05:17 PM, Thomas Gleixner wrote:
> On Mon, 9 Nov 2015, Qais Yousef wrote:
>> On 11/07/2015 02:51 PM, Thomas Gleixner wrote:
>> Generally it's hard to know whether a real device is connected to a hwirq or
>> not. I am saving a patch where we get a set of free hwirqs from DT as only the
>> SoC designer knows what hwirq are actually free and safe to use for IPI. I'll
>> send this patch with the DT IPI changes or the rproc driver that I will be
>> send once these changes are merged.
>>
>> The current code assumes that the last 2 * NR_CPUs hwirqs are always free to
>> use for Linux SMP.
> So what you're saying is that you cannot rely on the last X hwirqs
> being available for IPIs. That's insane and to my knowledge there is
> no hardware out there which does not reserve a consecutive IPI space.

If I read the code you were suggesting correctly, you were trying to fit 
the IPIs in any available non allocated area in the GIC space. What I am 
trying to say is that we can only work on a limited subset of this space 
that we are told explicitly it's safe to use for IPIs. Most likely it's 
consecutive, but I don't feel brave enough to make this assumption 
personally - maybe I'm over paranoid.. I'm more keen on anything that 
would simplify this patch series now though.

I'll do my best with the next series but maybe we'd need to iterate this 
more than once till I get it right.

Thanks,
Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
  2015-11-17 10:08           ` Qais Yousef
  (?)
@ 2015-11-17 10:11           ` Thomas Gleixner
  2015-11-17 10:30               ` Qais Yousef
  -1 siblings, 1 reply; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-17 10:11 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On Tue, 17 Nov 2015, Qais Yousef wrote:
> On 11/16/2015 05:17 PM, Thomas Gleixner wrote:
> > On Mon, 9 Nov 2015, Qais Yousef wrote:
> > > On 11/07/2015 02:51 PM, Thomas Gleixner wrote:
> > > Generally it's hard to know whether a real device is connected to a hwirq
> > > or
> > > not. I am saving a patch where we get a set of free hwirqs from DT as only
> > > the
> > > SoC designer knows what hwirq are actually free and safe to use for IPI.
> > > I'll
> > > send this patch with the DT IPI changes or the rproc driver that I will be
> > > send once these changes are merged.
> > > 
> > > The current code assumes that the last 2 * NR_CPUs hwirqs are always free
> > > to
> > > use for Linux SMP.
> > So what you're saying is that you cannot rely on the last X hwirqs
> > being available for IPIs. That's insane and to my knowledge there is
> > no hardware out there which does not reserve a consecutive IPI space.
> 
> If I read the code you were suggesting correctly, you were trying to fit the
> IPIs in any available non allocated area in the GIC space. What I am trying to
> say is that we can only work on a limited subset of this space that we are
> told explicitly it's safe to use for IPIs. Most likely it's consecutive, but I
> don't feel brave enough to make this assumption personally - maybe I'm over
> paranoid.. I'm more keen on anything that would simplify this patch series now
> though.

Right, I was assuming a consecutive available space and your hardware
folks should really avoid to break that assumption.

Now you still need some DT support to describe the space which is
available for IPIs and that should be part of that series.

> I'll do my best with the next series but maybe we'd need to iterate
> this more than once till I get it right.

Thanks for being patient and persistant on that!

       tglx

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-17 10:24           ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-17 10:24 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/16/2015 05:24 PM, Thomas Gleixner wrote:
>
> int ipi_get_hw_irq(int irq)
> {
> 	struct irq_data *d = irq_get_irq_data(irq);
> 	return d ? irqd_to_hwirq(d);
> }
>   
> Hmm?
>

We need cpu as an argument too.

Taking your other comments into account and ignoring the random mapping 
space for now. I think I can expand that to do the right thing for when 
the IPI domain is per cpu or consecutive.

Thanks,
Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-17 10:24           ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-17 10:24 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/16/2015 05:24 PM, Thomas Gleixner wrote:
>
> int ipi_get_hw_irq(int irq)
> {
> 	struct irq_data *d = irq_get_irq_data(irq);
> 	return d ? irqd_to_hwirq(d);
> }
>   
> Hmm?
>

We need cpu as an argument too.

Taking your other comments into account and ignoring the random mapping 
space for now. I think I can expand that to do the right thing for when 
the IPI domain is per cpu or consecutive.

Thanks,
Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
  2015-11-17 10:24           ` Qais Yousef
  (?)
@ 2015-11-17 10:30           ` Thomas Gleixner
  -1 siblings, 0 replies; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-17 10:30 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On Tue, 17 Nov 2015, Qais Yousef wrote:
> On 11/16/2015 05:24 PM, Thomas Gleixner wrote:
> > 
> > int ipi_get_hw_irq(int irq)
> > {
> > 	struct irq_data *d = irq_get_irq_data(irq);
> > 	return d ? irqd_to_hwirq(d);
> > }
> >   Hmm?
> > 
> 
> We need cpu as an argument too.

Indeed.
 

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-17 10:30               ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-17 10:30 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/17/2015 10:11 AM, Thomas Gleixner wrote:
> Right, I was assuming a consecutive available space and your hardware
> folks should really avoid to break that assumption.
>
> Now you still need some DT support to describe the space which is
> available for IPIs and that should be part of that series.


It's a simple change that shouldn't be a problem adding it to this 
series. I just wanted to avoid having to take more acks from more 
maintainers for this series to go in. But if it's needed, then it is 
what it is.

Maybe I'm better off sending this change separately actually as it's 
independent from other changes and could be merged in first.

> Thanks for being patient and persistant on that!

Thanks a lot for your help and patience too!

Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-17 10:30               ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-17 10:30 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/17/2015 10:11 AM, Thomas Gleixner wrote:
> Right, I was assuming a consecutive available space and your hardware
> folks should really avoid to break that assumption.
>
> Now you still need some DT support to describe the space which is
> available for IPIs and that should be part of that series.


It's a simple change that shouldn't be a problem adding it to this 
series. I just wanted to avoid having to take more acks from more 
maintainers for this series to go in. But if it's needed, then it is 
what it is.

Maybe I'm better off sending this change separately actually as it's 
independent from other changes and could be merged in first.

> Thanks for being patient and persistant on that!

Thanks a lot for your help and patience too!

Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-20 10:48           ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-20 10:48 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

Hi Thomas,

On 11/16/2015 05:17 PM, Thomas Gleixner wrote:
> 1) IPI as per_cpu interrupts
>
>     Single hwirq represented by a single irq descriptor
>
> 2) IPI with consecutive mapping space
>
>     No extra mapping from virq base to target cpu required as its just
>     linear. Everything can be handled via the base virq.
>


I think I am seeing a major issue with this approach.

Take the case where we reserve an IPI with ipi_mask that has cpu 5 and 6 
set only. When allocating a per_cpu or consectuve mapping, we will 
require 2 consecutive virqs and hwirqs. But since the cpu location is 
not starting from 0, we can't use the cpu as an offset anymore.

So when a user wants to send an IPI to cpu 6 only, the code can't easily 
tell what's the correct offset from base virq or hwirq to use.

Same applies when doing the reverse mapping.

In other words, the ipi_mask won't always necessarily be linear to 
facilitate the 1:1 mapping that this approach assumes.

It is a solvable problem, but I think we're losing the elegance that 
promoted going into this direction and I think sticking to using struct 
ipi_mapping (with some enhancements to how it's exposed an integrated 
by/into generic code) is a better approach.

Thoughts?

I still don't have a working implementation otherwise I would have sent 
my patches, but I thought I'd raise this up before I spend more time on 
it unnecessarily.

Thanks,
Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain
@ 2015-11-20 10:48           ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-20 10:48 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

Hi Thomas,

On 11/16/2015 05:17 PM, Thomas Gleixner wrote:
> 1) IPI as per_cpu interrupts
>
>     Single hwirq represented by a single irq descriptor
>
> 2) IPI with consecutive mapping space
>
>     No extra mapping from virq base to target cpu required as its just
>     linear. Everything can be handled via the base virq.
>


I think I am seeing a major issue with this approach.

Take the case where we reserve an IPI with ipi_mask that has cpu 5 and 6 
set only. When allocating a per_cpu or consectuve mapping, we will 
require 2 consecutive virqs and hwirqs. But since the cpu location is 
not starting from 0, we can't use the cpu as an offset anymore.

So when a user wants to send an IPI to cpu 6 only, the code can't easily 
tell what's the correct offset from base virq or hwirq to use.

Same applies when doing the reverse mapping.

In other words, the ipi_mask won't always necessarily be linear to 
facilitate the 1:1 mapping that this approach assumes.

It is a solvable problem, but I think we're losing the elegance that 
promoted going into this direction and I think sticking to using struct 
ipi_mapping (with some enhancements to how it's exposed an integrated 
by/into generic code) is a better approach.

Thoughts?

I still don't have a working implementation otherwise I would have sent 
my patches, but I thought I'd raise this up before I spend more time on 
it unnecessarily.

Thanks,
Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domaind
  2015-11-20 10:48           ` Qais Yousef
  (?)
@ 2015-11-20 20:39           ` Thomas Gleixner
  2015-11-23 16:55               ` Qais Yousef
  -1 siblings, 1 reply; 64+ messages in thread
From: Thomas Gleixner @ 2015-11-20 20:39 UTC (permalink / raw)
  To: Qais Yousef
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

Qais,

On Fri, 20 Nov 2015, Qais Yousef wrote:
> On 11/16/2015 05:17 PM, Thomas Gleixner wrote:
> > 1) IPI as per_cpu interrupts
> > 
> >     Single hwirq represented by a single irq descriptor
> > 
> > 2) IPI with consecutive mapping space
> > 
> >     No extra mapping from virq base to target cpu required as its just
> >     linear. Everything can be handled via the base virq.
> > 
> 
> 
> I think I am seeing a major issue with this approach.
> 
> Take the case where we reserve an IPI with ipi_mask that has cpu 5 and 6 set
> only. When allocating a per_cpu or consectuve mapping, we will require 2
> consecutive virqs and hwirqs. But since the cpu location is not starting from
> 0, we can't use the cpu as an offset anymore.
> 
> So when a user wants to send an IPI to cpu 6 only, the code can't easily tell
> what's the correct offset from base virq or hwirq to use.

Well, you can store the start offset easily and subtract it. It's 0
for most of the cases.

> Same applies when doing the reverse mapping.
> 
> In other words, the ipi_mask won't always necessarily be linear to facilitate
> the 1:1 mapping that this approach assumes.
> 
> It is a solvable problem, but I think we're losing the elegance that promoted
> going into this direction and I think sticking to using struct ipi_mapping
> (with some enhancements to how it's exposed an integrated by/into generic
> code) is a better approach.

The only reason to use the ipi_mapping thing is if we need non
consecutive masks, i.e. cpu 5 and 9.

I really don't want to have it mandatory as it does not make any sense
for systems where the IPI is a single per_cpu interrupt. For the
linear consecutive space it is just adding memory and cache footprint
for no benefit. Think about machines with 4k and more cpus ....

If you make ipi_mapping in a way that it can express the per_cpu,
linear and scattered mappings, then we should be fine. The extra
conditional you need in send_ipi() is not a problem.

Thanks,

	tglx



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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domaind
@ 2015-11-23 16:55               ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-23 16:55 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/20/2015 08:39 PM, Thomas Gleixner wrote:
>> Same applies when doing the reverse mapping.
>>
>> In other words, the ipi_mask won't always necessarily be linear to facilitate
>> the 1:1 mapping that this approach assumes.
>>
>> It is a solvable problem, but I think we're losing the elegance that promoted
>> going into this direction and I think sticking to using struct ipi_mapping
>> (with some enhancements to how it's exposed an integrated by/into generic
>> code) is a better approach.
> The only reason to use the ipi_mapping thing is if we need non
> consecutive masks, i.e. cpu 5 and 9.

That's the case I had in mind.

>
> I really don't want to have it mandatory as it does not make any sense
> for systems where the IPI is a single per_cpu interrupt. For the
> linear consecutive space it is just adding memory and cache footprint
> for no benefit. Think about machines with 4k and more cpus ....

OK. Although so far I think the ovehead is higher without the 
ipi_mapping because of all the extra checkings we have to do when 
sending an IPI. I'll leave this to code review when I have something 
ready though.

I'm debugging more problems and hopefully I'll send something this week.

Thanks,
Qais

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

* Re: [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domaind
@ 2015-11-23 16:55               ` Qais Yousef
  0 siblings, 0 replies; 64+ messages in thread
From: Qais Yousef @ 2015-11-23 16:55 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: linux-kernel, jason, marc.zyngier, jiang.liu, ralf, linux-mips

On 11/20/2015 08:39 PM, Thomas Gleixner wrote:
>> Same applies when doing the reverse mapping.
>>
>> In other words, the ipi_mask won't always necessarily be linear to facilitate
>> the 1:1 mapping that this approach assumes.
>>
>> It is a solvable problem, but I think we're losing the elegance that promoted
>> going into this direction and I think sticking to using struct ipi_mapping
>> (with some enhancements to how it's exposed an integrated by/into generic
>> code) is a better approach.
> The only reason to use the ipi_mapping thing is if we need non
> consecutive masks, i.e. cpu 5 and 9.

That's the case I had in mind.

>
> I really don't want to have it mandatory as it does not make any sense
> for systems where the IPI is a single per_cpu interrupt. For the
> linear consecutive space it is just adding memory and cache footprint
> for no benefit. Think about machines with 4k and more cpus ....

OK. Although so far I think the ovehead is higher without the 
ipi_mapping because of all the extra checkings we have to do when 
sending an IPI. I'll leave this to code review when I have something 
ready though.

I'm debugging more problems and hopefully I'll send something this week.

Thanks,
Qais

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

end of thread, other threads:[~2015-11-23 16:55 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-03 11:12 [PATCH 00/14] Implement generic IPI support mechanism Qais Yousef
2015-11-03 11:12 ` Qais Yousef
2015-11-03 11:12 ` [PATCH 01/14] genirq: Add new IRQ_DOMAIN_FLAGS_IPI Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-03 11:12 ` [PATCH 02/14] genirq: Add DOMAIN_BUS_IPI Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-03 11:12 ` [PATCH 03/14] genirq: Add GENERIC_IRQ_IPI Kconfig symbol Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-03 11:12 ` [PATCH 04/14] genirq: Add new struct ipi_mask and helper functions Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-07 12:05   ` Thomas Gleixner
2015-11-03 11:12 ` [PATCH 05/14] genirq: Add struct ipi_mask to irq_data Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-03 11:12 ` [PATCH 06/14] genirq: Add struct ipi_mapping and its helper functions Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-07 12:09   ` Thomas Gleixner
2015-11-09 10:05     ` Qais Yousef
2015-11-09 10:05       ` Qais Yousef
2015-11-03 11:12 ` [PATCH 07/14] genirq: Add a new generic IPI reservation code to irq core Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-03 12:06   ` kbuild test robot
2015-11-03 12:06     ` kbuild test robot
2015-11-07 12:11   ` Thomas Gleixner
2015-11-07 13:31   ` Thomas Gleixner
2015-11-09 10:07     ` Qais Yousef
2015-11-09 10:07       ` Qais Yousef
2015-11-16 15:09       ` Thomas Gleixner
2015-11-03 11:12 ` [PATCH 08/14] genirq: Add a new irq_send_ipi() to irq_chip Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-03 11:12 ` [PATCH 09/14] genirq: Implement irq_send_ipi() to be used by drivers Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-03 12:09   ` kbuild test robot
2015-11-03 12:09     ` kbuild test robot
2015-11-07 12:14   ` Thomas Gleixner
2015-11-03 11:12 ` [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-07 14:51   ` Thomas Gleixner
2015-11-09 11:10     ` Qais Yousef
2015-11-09 11:10       ` Qais Yousef
2015-11-16 17:17       ` Thomas Gleixner
2015-11-17 10:08         ` Qais Yousef
2015-11-17 10:08           ` Qais Yousef
2015-11-17 10:11           ` Thomas Gleixner
2015-11-17 10:30             ` Qais Yousef
2015-11-17 10:30               ` Qais Yousef
2015-11-20 10:48         ` Qais Yousef
2015-11-20 10:48           ` Qais Yousef
2015-11-20 20:39           ` [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domaind Thomas Gleixner
2015-11-23 16:55             ` Qais Yousef
2015-11-23 16:55               ` Qais Yousef
2015-11-12 15:12     ` [PATCH 10/14] irqchip/mips-gic: Add a IPI hierarchy domain Qais Yousef
2015-11-12 15:12       ` Qais Yousef
2015-11-16 17:24       ` Thomas Gleixner
2015-11-17 10:24         ` Qais Yousef
2015-11-17 10:24           ` Qais Yousef
2015-11-17 10:30           ` Thomas Gleixner
2015-11-03 11:12 ` [PATCH 11/14] MIPS: Add generic SMP IPI support Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-03 11:12 ` [PATCH 12/14] MIPS: Make smp CMP, CPS and MT use the new generic IPI functions Qais Yousef
2015-11-03 11:12   ` Qais Yousef
2015-11-03 11:13 ` [PATCH 13/14] MIPS: Delete smp-gic.c Qais Yousef
2015-11-03 11:13   ` Qais Yousef
2015-11-03 11:13 ` [PATCH 14/14] Docs: IRQ: Add new IRQ-ipi.txt Qais Yousef
2015-11-03 11:13   ` Qais Yousef

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.