LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 0/7] Level-triggered MSI support
@ 2018-04-23 10:34 Marc Zyngier
2018-04-23 10:34 ` [PATCH 1/7] genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers Marc Zyngier
` (9 more replies)
0 siblings, 10 replies; 17+ messages in thread
From: Marc Zyngier @ 2018-04-23 10:34 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper
Cc: Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, linux-kernel
This series is a first shot at teaching the kernel about the oxymoron
expressed in $SUBJECT. Over the past couple of years, we've seen some
SoCs coming up with ways of signalling level interrupts using a new
flavor of MSIs, where the MSI controller uses two distinct messages:
one that raises a virtual line, and one that lowers it. The target MSI
controller is in charge of maintaining the state of the line.
This allows for a much simplified HW signal routing (no need to have
hundreds of discrete lines to signal level interrupts if you already
have a memory bus), but results in a departure from the current idea
the kernel has of MSIs.
This series takes a minimal approach to the problem, which is to allow
MSI controllers to use not only one, but up to two messages at a
time. This is controlled by a flag exposed at MSI irq domain creation,
and is only supported with platform MSI.
The rest of the series repaints the Marvell ICU/GICP drivers which
already make use of this feature with a side-channel, and adds support
for the same feature in GICv3. A side effect of the last GICv3 patch
is that you can also use SPIs to signal PCI MSIs. This is a last
resort measure for SoCs where the ITS is unusable for unspeakable
reasons.
Marc Zyngier (7):
genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers
genirq/msi: Limit level-triggered MSI to platform devices
irqchip/mvebu-gicp: Use level-triggered MSIs between ICU and GICP
dma-iommu: Fix compilation when !CONFIG_IOMMU_DMA
irqchip/gic-v3: Add support for Message Based Interrupts as an MSI
controller
irqchip/gic-v3: Add PCI/MSI support to the GICv3 MBI sub-driver
dt-bindings/gic-v3: Add documentation for MBI support
.../bindings/interrupt-controller/arm,gic-v3.txt | 17 +
drivers/base/platform-msi.c | 3 +
drivers/irqchip/Makefile | 2 +-
drivers/irqchip/irq-gic-v3-mbi.c | 343 +++++++++++++++++++++
drivers/irqchip/irq-gic-v3.c | 6 +
drivers/irqchip/irq-mvebu-gicp.c | 37 +--
drivers/irqchip/irq-mvebu-gicp.h | 12 -
drivers/irqchip/irq-mvebu-icu.c | 33 +-
drivers/pci/msi.c | 3 +
include/linux/dma-iommu.h | 1 +
include/linux/irqchip/arm-gic-v3.h | 1 +
include/linux/msi.h | 2 +
kernel/irq/msi.c | 32 +-
13 files changed, 427 insertions(+), 65 deletions(-)
create mode 100644 drivers/irqchip/irq-gic-v3-mbi.c
delete mode 100644 drivers/irqchip/irq-mvebu-gicp.h
--
2.14.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 1/7] genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers
2018-04-23 10:34 [PATCH 0/7] Level-triggered MSI support Marc Zyngier
@ 2018-04-23 10:34 ` Marc Zyngier
2018-04-23 10:34 ` [PATCH 2/7] genirq/msi: Limit level-triggered MSI to platform devices Marc Zyngier
` (8 subsequent siblings)
9 siblings, 0 replies; 17+ messages in thread
From: Marc Zyngier @ 2018-04-23 10:34 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper
Cc: Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, linux-kernel
So far, MSIs have been used to signal edge-triggered interrupts, as
a write is a good model for an edge (you can't "unwrite" something).
On the other hand, routing zillions of wires in an SoC because you
need level interrupts is a bit extreme.
People have come up with a variety of schemes to support this, which
involves sending two messages: one to signal the interrupt, and one
to clear it. Since the kernel cannot represent this, we've ended up
with side-band mechanisms that are pretty awful.
Instead, let's acknoledge the requirement, and ensure that, under the
right circumstances, the irq_compose_msg and irq_write_msg can take
as a parameter an array of two messages instead of a pointer to a
single one. We also add some checking that the compose method only
clobbers the second message if the MSI domain has been created with
the MSI_FLAG_LEVEL_CAPABLE flags.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/linux/msi.h | 2 ++
kernel/irq/msi.c | 32 +++++++++++++++++++++++---------
2 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 1f1bbb5b4679..5839d8062dfc 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -289,6 +289,8 @@ enum {
* MSI_FLAG_ACTIVATE_EARLY has been set.
*/
MSI_FLAG_MUST_REACTIVATE = (1 << 5),
+ /* Is level-triggered capable, using two messages */
+ MSI_FLAG_LEVEL_CAPABLE = (1 << 6),
};
int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c
index 2a8571f72b17..a6fbf6008dcb 100644
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -76,6 +76,18 @@ static inline void irq_chip_write_msi_msg(struct irq_data *data,
data->chip->irq_write_msi_msg(data, msg);
}
+static void msi_check_level(struct irq_domain *domain, struct msi_msg *msg)
+{
+ struct msi_domain_info *info = domain->host_data;
+
+ /*
+ * If the MSI provider has messed with the second message and
+ * not advertized that it is level-capable, signal the breakage.
+ */
+ WARN_ON(!(info->flags & MSI_FLAG_LEVEL_CAPABLE) &&
+ (msg[1].address_lo || msg[1].address_hi || msg[1].data));
+}
+
/**
* msi_domain_set_affinity - Generic affinity setter function for MSI domains
* @irq_data: The irq data associated to the interrupt
@@ -89,13 +101,14 @@ int msi_domain_set_affinity(struct irq_data *irq_data,
const struct cpumask *mask, bool force)
{
struct irq_data *parent = irq_data->parent_data;
- struct msi_msg msg;
+ struct msi_msg msg[2] = { [1] = { }, };
int ret;
ret = parent->chip->irq_set_affinity(parent, mask, force);
if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) {
- BUG_ON(irq_chip_compose_msi_msg(irq_data, &msg));
- irq_chip_write_msi_msg(irq_data, &msg);
+ BUG_ON(irq_chip_compose_msi_msg(irq_data, msg));
+ msi_check_level(irq_data->domain, msg);
+ irq_chip_write_msi_msg(irq_data, msg);
}
return ret;
@@ -104,20 +117,21 @@ int msi_domain_set_affinity(struct irq_data *irq_data,
static int msi_domain_activate(struct irq_domain *domain,
struct irq_data *irq_data, bool early)
{
- struct msi_msg msg;
+ struct msi_msg msg[2] = { [1] = { }, };
- BUG_ON(irq_chip_compose_msi_msg(irq_data, &msg));
- irq_chip_write_msi_msg(irq_data, &msg);
+ BUG_ON(irq_chip_compose_msi_msg(irq_data, msg));
+ msi_check_level(irq_data->domain, msg);
+ irq_chip_write_msi_msg(irq_data, msg);
return 0;
}
static void msi_domain_deactivate(struct irq_domain *domain,
struct irq_data *irq_data)
{
- struct msi_msg msg;
+ struct msi_msg msg[2];
- memset(&msg, 0, sizeof(msg));
- irq_chip_write_msi_msg(irq_data, &msg);
+ memset(msg, 0, sizeof(msg));
+ irq_chip_write_msi_msg(irq_data, msg);
}
static int msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
--
2.14.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2/7] genirq/msi: Limit level-triggered MSI to platform devices
2018-04-23 10:34 [PATCH 0/7] Level-triggered MSI support Marc Zyngier
2018-04-23 10:34 ` [PATCH 1/7] genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers Marc Zyngier
@ 2018-04-23 10:34 ` Marc Zyngier
2018-04-26 19:50 ` Thomas Gleixner
2018-04-23 10:34 ` [PATCH 3/7] irqchip/mvebu-gicp: Use level-triggered MSIs between ICU and GICP Marc Zyngier
` (7 subsequent siblings)
9 siblings, 1 reply; 17+ messages in thread
From: Marc Zyngier @ 2018-04-23 10:34 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper
Cc: Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, linux-kernel
Nobody would be insane enough to try and use level triggered
MSIs on PCI, but let's make sure it doesn't happen. Also,
let's mandate that the irqchip backing the platform MSI domain
is providing an irq_set_type method (or the whole thing would
be a bit useless).
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/base/platform-msi.c | 3 +++
drivers/pci/msi.c | 3 +++
2 files changed, 6 insertions(+)
diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 8e22073aeeed..3b9694a6beaa 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -101,6 +101,9 @@ static void platform_msi_update_chip_ops(struct msi_domain_info *info)
chip->irq_set_affinity = msi_domain_set_affinity;
if (!chip->irq_write_msi_msg)
chip->irq_write_msi_msg = platform_msi_write_msg;
+ if (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE) &&
+ !chip->irq_set_type))
+ info->flags &= ~MSI_FLAG_LEVEL_CAPABLE;
}
static void platform_msi_free_descs(struct device *dev, int base, int nvec)
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 30250631efe7..f45b74fcc059 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1434,6 +1434,9 @@ struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
{
struct irq_domain *domain;
+ if (WARN_ON(info->flags & MSI_FLAG_LEVEL_CAPABLE))
+ info->flags &= ~MSI_FLAG_LEVEL_CAPABLE;
+
if (info->flags & MSI_FLAG_USE_DEF_DOM_OPS)
pci_msi_domain_update_dom_ops(info);
if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
--
2.14.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 3/7] irqchip/mvebu-gicp: Use level-triggered MSIs between ICU and GICP
2018-04-23 10:34 [PATCH 0/7] Level-triggered MSI support Marc Zyngier
2018-04-23 10:34 ` [PATCH 1/7] genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers Marc Zyngier
2018-04-23 10:34 ` [PATCH 2/7] genirq/msi: Limit level-triggered MSI to platform devices Marc Zyngier
@ 2018-04-23 10:34 ` Marc Zyngier
2018-04-23 10:34 ` [PATCH 4/7] dma-iommu: Fix compilation when !CONFIG_IOMMU_DMA Marc Zyngier
` (6 subsequent siblings)
9 siblings, 0 replies; 17+ messages in thread
From: Marc Zyngier @ 2018-04-23 10:34 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper
Cc: Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, linux-kernel
The ICU and GICP drivers are using an ugly side-band mechanism to
find out about the "clear" doorbell when using level interrupts.
Let's convert it to level-triggered MSIs, which result in a nice
cleanup.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/irqchip/irq-mvebu-gicp.c | 37 ++++++++++---------------------------
drivers/irqchip/irq-mvebu-gicp.h | 12 ------------
drivers/irqchip/irq-mvebu-icu.c | 33 +++++++++++++++++----------------
3 files changed, 27 insertions(+), 55 deletions(-)
delete mode 100644 drivers/irqchip/irq-mvebu-gicp.h
diff --git a/drivers/irqchip/irq-mvebu-gicp.c b/drivers/irqchip/irq-mvebu-gicp.c
index 17a4a7b6cdbb..b5a3cc8bf370 100644
--- a/drivers/irqchip/irq-mvebu-gicp.c
+++ b/drivers/irqchip/irq-mvebu-gicp.c
@@ -19,8 +19,6 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include "irq-mvebu-gicp.h"
-
#define GICP_SETSPI_NSR_OFFSET 0x0
#define GICP_CLRSPI_NSR_OFFSET 0x8
@@ -55,34 +53,18 @@ static int gicp_idx_to_spi(struct mvebu_gicp *gicp, int idx)
return -EINVAL;
}
-int mvebu_gicp_get_doorbells(struct device_node *dn, phys_addr_t *setspi,
- phys_addr_t *clrspi)
-{
- struct platform_device *pdev;
- struct mvebu_gicp *gicp;
-
- pdev = of_find_device_by_node(dn);
- if (!pdev)
- return -ENODEV;
-
- gicp = platform_get_drvdata(pdev);
- if (!gicp)
- return -ENODEV;
-
- *setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET;
- *clrspi = gicp->res->start + GICP_CLRSPI_NSR_OFFSET;
-
- return 0;
-}
-
static void gicp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
{
struct mvebu_gicp *gicp = data->chip_data;
phys_addr_t setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET;
-
- msg->data = data->hwirq;
- msg->address_lo = lower_32_bits(setspi);
- msg->address_hi = upper_32_bits(setspi);
+ phys_addr_t clrspi = gicp->res->start + GICP_CLRSPI_NSR_OFFSET;
+
+ msg[0].data = data->hwirq;
+ msg[0].address_lo = lower_32_bits(setspi);
+ msg[0].address_hi = upper_32_bits(setspi);
+ msg[1].data = data->hwirq;
+ msg[1].address_lo = lower_32_bits(clrspi);
+ msg[1].address_hi = upper_32_bits(clrspi);
}
static struct irq_chip gicp_irq_chip = {
@@ -176,7 +158,8 @@ static struct msi_domain_ops gicp_msi_ops = {
};
static struct msi_domain_info gicp_msi_domain_info = {
- .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS),
+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+ MSI_FLAG_LEVEL_CAPABLE),
.ops = &gicp_msi_ops,
.chip = &gicp_msi_irq_chip,
};
diff --git a/drivers/irqchip/irq-mvebu-gicp.h b/drivers/irqchip/irq-mvebu-gicp.h
deleted file mode 100644
index eaa12fb72102..000000000000
--- a/drivers/irqchip/irq-mvebu-gicp.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __MVEBU_GICP_H__
-#define __MVEBU_GICP_H__
-
-#include <linux/types.h>
-
-struct device_node;
-
-int mvebu_gicp_get_doorbells(struct device_node *dn, phys_addr_t *setspi,
- phys_addr_t *clrspi);
-
-#endif /* __MVEBU_GICP_H__ */
diff --git a/drivers/irqchip/irq-mvebu-icu.c b/drivers/irqchip/irq-mvebu-icu.c
index e18c48d3a92e..13063339b416 100644
--- a/drivers/irqchip/irq-mvebu-icu.c
+++ b/drivers/irqchip/irq-mvebu-icu.c
@@ -21,8 +21,6 @@
#include <dt-bindings/interrupt-controller/mvebu-icu.h>
-#include "irq-mvebu-gicp.h"
-
/* ICU registers */
#define ICU_SETSPI_NSR_AL 0x10
#define ICU_SETSPI_NSR_AH 0x14
@@ -43,6 +41,7 @@ struct mvebu_icu {
void __iomem *base;
struct irq_domain *domain;
struct device *dev;
+ atomic_t initialized;
};
struct mvebu_icu_irq_data {
@@ -51,6 +50,18 @@ struct mvebu_icu_irq_data {
unsigned int type;
};
+static void mvebu_icu_init(struct mvebu_icu *icu, struct msi_msg *msg)
+{
+ if (atomic_cmpxchg(&icu->initialized, false, true))
+ return;
+
+ /* Set Clear/Set ICU SPI message address in AP */
+ writel_relaxed(msg[0].address_hi, icu->base + ICU_SETSPI_NSR_AH);
+ writel_relaxed(msg[0].address_lo, icu->base + ICU_SETSPI_NSR_AL);
+ writel_relaxed(msg[1].address_hi, icu->base + ICU_CLRSPI_NSR_AH);
+ writel_relaxed(msg[1].address_lo, icu->base + ICU_CLRSPI_NSR_AL);
+}
+
static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg)
{
struct irq_data *d = irq_get_irq_data(desc->irq);
@@ -59,6 +70,8 @@ static void mvebu_icu_write_msg(struct msi_desc *desc, struct msi_msg *msg)
unsigned int icu_int;
if (msg->address_lo || msg->address_hi) {
+ /* One off initialization */
+ mvebu_icu_init(icu, msg);
/* Configure the ICU with irq number & type */
icu_int = msg->data | ICU_INT_ENABLE;
if (icu_irqd->type & IRQ_TYPE_EDGE_RISING)
@@ -197,9 +210,7 @@ static int mvebu_icu_probe(struct platform_device *pdev)
struct device_node *node = pdev->dev.of_node;
struct device_node *gicp_dn;
struct resource *res;
- phys_addr_t setspi, clrspi;
- u32 i, icu_int;
- int ret;
+ int i;
icu = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_icu),
GFP_KERNEL);
@@ -242,22 +253,12 @@ static int mvebu_icu_probe(struct platform_device *pdev)
if (!gicp_dn)
return -ENODEV;
- ret = mvebu_gicp_get_doorbells(gicp_dn, &setspi, &clrspi);
- if (ret)
- return ret;
-
- /* Set Clear/Set ICU SPI message address in AP */
- writel_relaxed(upper_32_bits(setspi), icu->base + ICU_SETSPI_NSR_AH);
- writel_relaxed(lower_32_bits(setspi), icu->base + ICU_SETSPI_NSR_AL);
- writel_relaxed(upper_32_bits(clrspi), icu->base + ICU_CLRSPI_NSR_AH);
- writel_relaxed(lower_32_bits(clrspi), icu->base + ICU_CLRSPI_NSR_AL);
-
/*
* Clean all ICU interrupts with type SPI_NSR, required to
* avoid unpredictable SPI assignments done by firmware.
*/
for (i = 0 ; i < ICU_MAX_IRQS ; i++) {
- icu_int = readl(icu->base + ICU_INT_CFG(i));
+ u32 icu_int = readl_relaxed(icu->base + ICU_INT_CFG(i));
if ((icu_int >> ICU_GROUP_SHIFT) == ICU_GRP_NSR)
writel_relaxed(0x0, icu->base + ICU_INT_CFG(i));
}
--
2.14.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 4/7] dma-iommu: Fix compilation when !CONFIG_IOMMU_DMA
2018-04-23 10:34 [PATCH 0/7] Level-triggered MSI support Marc Zyngier
` (2 preceding siblings ...)
2018-04-23 10:34 ` [PATCH 3/7] irqchip/mvebu-gicp: Use level-triggered MSIs between ICU and GICP Marc Zyngier
@ 2018-04-23 10:34 ` Marc Zyngier
2018-04-23 10:34 ` [PATCH 5/7] irqchip/gic-v3: Add support for Message Based Interrupts as an MSI controller Marc Zyngier
` (5 subsequent siblings)
9 siblings, 0 replies; 17+ messages in thread
From: Marc Zyngier @ 2018-04-23 10:34 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper
Cc: Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, linux-kernel
Inclusion of include/dma-iommu.h when CONFIG_IOMMU_DMA is not selected
results in the following splat:
In file included from drivers/irqchip/irq-gic-v3-mbi.c:20:0:
./include/linux/dma-iommu.h:95:69: error: unknown type name ‘dma_addr_t’
static inline int iommu_get_msi_cookie(struct iommu_domain *domain, dma_addr_t base)
^~~~~~~~~~
./include/linux/dma-iommu.h:108:74: warning: ‘struct list_head’ declared inside parameter list will not be visible outside of this definition or declaration
static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
^~~~~~~~~
scripts/Makefile.build:312: recipe for target 'drivers/irqchip/irq-gic-v3-mbi.o' failed
Fix it by including linux/types.h.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
include/linux/dma-iommu.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 92f20832fd28..e8ca5e654277 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -17,6 +17,7 @@
#define __DMA_IOMMU_H
#ifdef __KERNEL__
+#include <linux/types.h>
#include <asm/errno.h>
#ifdef CONFIG_IOMMU_DMA
--
2.14.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 5/7] irqchip/gic-v3: Add support for Message Based Interrupts as an MSI controller
2018-04-23 10:34 [PATCH 0/7] Level-triggered MSI support Marc Zyngier
` (3 preceding siblings ...)
2018-04-23 10:34 ` [PATCH 4/7] dma-iommu: Fix compilation when !CONFIG_IOMMU_DMA Marc Zyngier
@ 2018-04-23 10:34 ` Marc Zyngier
2018-04-26 20:53 ` Thomas Gleixner
2018-04-23 10:34 ` [PATCH 6/7] irqchip/gic-v3: Add PCI/MSI support to the GICv3 MBI sub-driver Marc Zyngier
` (4 subsequent siblings)
9 siblings, 1 reply; 17+ messages in thread
From: Marc Zyngier @ 2018-04-23 10:34 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper
Cc: Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, linux-kernel
GICv3 offers the possibility to signal SPIs using a pair of doorbells
(SETPI, CLRSPI) under the name of Message Based Interrupts (MBI).
They can be used as either traditional (edge) MSIs, or the more exotic
level-triggered flavour.
Let's implement support for platform MSI, which is the original intent
for this feature.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/irqchip/Makefile | 2 +-
drivers/irqchip/irq-gic-v3-mbi.c | 287 +++++++++++++++++++++++++++++++++++++
drivers/irqchip/irq-gic-v3.c | 6 +
include/linux/irqchip/arm-gic-v3.h | 1 +
4 files changed, 295 insertions(+), 1 deletion(-)
create mode 100644 drivers/irqchip/irq-gic-v3-mbi.c
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 5ed465ab1c76..15f268f646bf 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -27,7 +27,7 @@ obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o
obj-$(CONFIG_ARM_GIC_PM) += irq-gic-pm.o
obj-$(CONFIG_ARCH_REALVIEW) += irq-gic-realview.o
obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o
-obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o
+obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-v3-mbi.o irq-gic-common.o
obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o
obj-$(CONFIG_ARM_GIC_V3_ITS_PCI) += irq-gic-v3-its-pci-msi.o
obj-$(CONFIG_ARM_GIC_V3_ITS_FSL_MC) += irq-gic-v3-its-fsl-mc-msi.o
diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c
new file mode 100644
index 000000000000..20303f54e8c0
--- /dev/null
+++ b/drivers/irqchip/irq-gic-v3-mbi.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2018 ARM Limited, All Rights Reserved.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) "GICv3: " fmt
+
+#include <linux/dma-iommu.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/msi.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <linux/irqchip/arm-gic-v3.h>
+
+struct mbi_range {
+ u32 spi_start;
+ u32 nr_spis;
+ unsigned long *bm;
+};
+
+static spinlock_t mbi_lock;
+static phys_addr_t mbi_phys_base;
+static struct mbi_range *mbi_ranges;
+static unsigned int mbi_range_nr;
+
+static struct irq_chip mbi_irq_chip = {
+ .name = "MBI",
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_set_type = irq_chip_set_type_parent,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+};
+
+static int mbi_irq_gic_domain_alloc(struct irq_domain *domain,
+ unsigned int virq,
+ irq_hw_number_t hwirq)
+{
+ struct irq_fwspec fwspec;
+ struct irq_data *d;
+ int err;
+
+ /*
+ * Using ACPI? There is no MBI support in the spec, you
+ * shouldn't even be here.
+ */
+ if (!is_of_node(domain->parent->fwnode))
+ return -EINVAL;
+
+ /*
+ * Let's default to edge. This is consistent with traditional
+ * MSIs, and systems requiring level signaling will just
+ * enforce the trigger on their own.
+ */
+ fwspec.fwnode = domain->parent->fwnode;
+ fwspec.param_count = 3;
+ fwspec.param[0] = 0;
+ fwspec.param[1] = hwirq - 32;
+ fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+
+ err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
+ if (err)
+ return err;
+
+ d = irq_domain_get_irq_data(domain->parent, virq);
+ d->chip->irq_set_type(d, IRQ_TYPE_EDGE_RISING);
+
+ return 0;
+}
+
+static void mbi_free_msi(struct mbi_range *mbi, unsigned int hwirq,
+ int nr_irqs)
+{
+ spin_lock(&mbi_lock);
+ bitmap_release_region(mbi->bm, hwirq - mbi->spi_start,
+ get_count_order(nr_irqs));
+ spin_unlock(&mbi_lock);
+}
+
+static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *args)
+{
+ struct mbi_range *mbi = NULL;
+ int hwirq, offset, i, err = 0;
+
+ spin_lock(&mbi_lock);
+ for (i = 0; i < mbi_range_nr; i++) {
+ offset = bitmap_find_free_region(mbi_ranges[i].bm,
+ mbi_ranges[i].nr_spis,
+ get_count_order(nr_irqs));
+ if (offset >= 0) {
+ mbi = &mbi_ranges[i];
+ break;
+ }
+ }
+ spin_unlock(&mbi_lock);
+
+ if (!mbi)
+ return -ENOSPC;
+
+ hwirq = mbi->spi_start + offset;
+
+ for (i = 0; i < nr_irqs; i++) {
+ err = mbi_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
+ if (err)
+ goto fail;
+
+ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+ &mbi_irq_chip, mbi);
+ }
+
+ return 0;
+
+fail:
+ irq_domain_free_irqs_parent(domain, virq, nr_irqs);
+ mbi_free_msi(mbi, hwirq, nr_irqs);
+ return err;
+}
+
+static void mbi_irq_domain_free(struct irq_domain *domain,
+ unsigned int virq, unsigned int nr_irqs)
+{
+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
+ struct mbi_range *mbi = irq_data_get_irq_chip_data(d);
+
+ mbi_free_msi(mbi, d->hwirq, nr_irqs);
+ irq_domain_free_irqs_parent(domain, virq, nr_irqs);
+}
+
+static const struct irq_domain_ops mbi_domain_ops = {
+ .alloc = mbi_irq_domain_alloc,
+ .free = mbi_irq_domain_free,
+};
+
+static void mbi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ msg[0].address_hi = upper_32_bits(mbi_phys_base + GICD_SETSPI_NSR);
+ msg[0].address_lo = lower_32_bits(mbi_phys_base + GICD_SETSPI_NSR);
+ msg[0].data = data->parent_data->hwirq;
+
+ iommu_dma_map_msi_msg(data->irq, msg);
+}
+
+static void mbi_compose_mbi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ mbi_compose_msi_msg(data, msg);
+
+ msg[1].address_hi = upper_32_bits(mbi_phys_base + GICD_CLRSPI_NSR);
+ msg[1].address_lo = lower_32_bits(mbi_phys_base + GICD_CLRSPI_NSR);
+ msg[1].data = data->parent_data->hwirq;
+
+ iommu_dma_map_msi_msg(data->irq, &msg[1]);
+}
+
+/* Platform-MSI specific irqchip */
+static struct irq_chip mbi_pmsi_irq_chip = {
+ .name = "pMSI",
+ .irq_set_type = irq_chip_set_type_parent,
+ .irq_compose_msi_msg = mbi_compose_mbi_msg,
+};
+
+static struct msi_domain_ops mbi_pmsi_ops = {
+};
+
+static struct msi_domain_info mbi_pmsi_domain_info = {
+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+ MSI_FLAG_LEVEL_CAPABLE),
+ .ops = &mbi_pmsi_ops,
+ .chip = &mbi_pmsi_irq_chip,
+};
+
+static int mbi_allocate_domains(struct irq_domain *parent)
+{
+ struct irq_domain *nexus_domain, *plat_domain;
+
+ nexus_domain = irq_domain_create_tree(parent->fwnode,
+ &mbi_domain_ops, NULL);
+ if (!nexus_domain)
+ return -ENOMEM;
+
+ irq_domain_update_bus_token(nexus_domain, DOMAIN_BUS_NEXUS);
+ nexus_domain->parent = parent;
+
+ plat_domain = platform_msi_create_irq_domain(parent->fwnode,
+ &mbi_pmsi_domain_info,
+ nexus_domain);
+
+ if (!plat_domain) {
+ irq_domain_remove(plat_domain);
+ irq_domain_remove(nexus_domain);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+int __init mbi_init(struct fwnode_handle *fwnode, struct irq_domain *parent)
+{
+ struct device_node *np;
+ const __be32 *reg;
+ int ret, n;
+
+ np = to_of_node(fwnode);
+
+ if (!of_property_read_bool(np, "msi-controller"))
+ return 0;
+
+ n = of_property_count_elems_of_size(np, "mbi-ranges", sizeof(u32));
+ if (n <= 0 || n % 2)
+ return -EINVAL;
+
+ mbi_range_nr = n / 2;
+ mbi_ranges = kcalloc(mbi_range_nr, sizeof(*mbi_ranges), GFP_KERNEL);
+ if (!mbi_ranges)
+ return -ENOMEM;
+
+ for (n = 0; n < mbi_range_nr; n++) {
+ ret = of_property_read_u32_index(np, "mbi-ranges", n * 2,
+ &mbi_ranges[n].spi_start);
+ if (ret)
+ goto err_free_mbi;
+ ret = of_property_read_u32_index(np, "mbi-ranges", n * 2 + 1,
+ &mbi_ranges[n].nr_spis);
+ if (ret)
+ goto err_free_mbi;
+
+ mbi_ranges[n].bm = kcalloc(BITS_TO_LONGS(mbi_ranges[n].nr_spis),
+ sizeof(long), GFP_KERNEL);
+ if (!mbi_ranges[n].bm) {
+ ret = -ENOMEM;
+ goto err_free_mbi;
+ }
+ pr_info("MBI range [%d:%d]\n", mbi_ranges[n].spi_start,
+ mbi_ranges[n].spi_start + mbi_ranges[n].nr_spis - 1);
+ }
+
+ reg = of_get_property(np, "mbi-alias", NULL);
+ if (reg) {
+ mbi_phys_base = of_translate_address(np, reg);
+ if (mbi_phys_base == OF_BAD_ADDR) {
+ ret = -ENXIO;
+ goto err_free_mbi;
+ }
+ } else {
+ struct resource res;
+
+ if (of_address_to_resource(np, 0, &res)) {
+ ret = -ENXIO;
+ goto err_free_mbi;
+ }
+
+ mbi_phys_base = res.start;
+ }
+
+ pr_info("Using MBI frame %pa\n", &mbi_phys_base);
+
+ ret = mbi_allocate_domains(parent);
+ if (ret)
+ goto err_free_mbi;
+
+ return 0;
+
+err_free_mbi:
+ if (mbi_ranges) {
+ for (n = 0; n < mbi_range_nr; n++)
+ kfree(mbi_ranges[n].bm);
+ kfree(mbi_ranges);
+ }
+
+ return ret;
+}
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index e5d101418390..1c6d039f22a3 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1112,6 +1112,12 @@ static int __init gic_init_bases(void __iomem *dist_base,
pr_info("Distributor has %sRange Selector support\n",
gic_data.has_rss ? "" : "no ");
+ if (typer & GICD_TYPER_MBIS) {
+ err = mbi_init(handle, gic_data.domain);
+ if (err)
+ pr_err("Failed to initialize MBIs\n");
+ }
+
set_handle_irq(gic_handle_irq);
gic_update_vlpi_properties();
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index f5af3b594e6e..cbb872c1b607 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -587,6 +587,7 @@ struct fwnode_handle;
int its_cpu_init(void);
int its_init(struct fwnode_handle *handle, struct rdists *rdists,
struct irq_domain *domain);
+int mbi_init(struct fwnode_handle *fwnode, struct irq_domain *parent);
static inline bool gic_enable_sre(void)
{
--
2.14.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 6/7] irqchip/gic-v3: Add PCI/MSI support to the GICv3 MBI sub-driver
2018-04-23 10:34 [PATCH 0/7] Level-triggered MSI support Marc Zyngier
` (4 preceding siblings ...)
2018-04-23 10:34 ` [PATCH 5/7] irqchip/gic-v3: Add support for Message Based Interrupts as an MSI controller Marc Zyngier
@ 2018-04-23 10:34 ` Marc Zyngier
2018-04-23 10:34 ` [PATCH 7/7] dt-bindings/gic-v3: Add documentation for MBI support Marc Zyngier
` (3 subsequent siblings)
9 siblings, 0 replies; 17+ messages in thread
From: Marc Zyngier @ 2018-04-23 10:34 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper
Cc: Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, linux-kernel
You would hope that if you have a GICv3 in your system, you'd use the ITS,
as it provides a large interrupt ID space and device isolation. Sadly,
some SoC integrations are less than perfect, and the ITS is not usesable on
those.
The only solution for these systems is to use the MBI interface, and
rely on a very small number of possible vectors.
This patch thus adds minimal support for PCI/MSI on top of the GICv3
MBI driver. Please don't use it if you can avoid it.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/irqchip/irq-gic-v3-mbi.c | 62 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 59 insertions(+), 3 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-mbi.c b/drivers/irqchip/irq-gic-v3-mbi.c
index 20303f54e8c0..acbeb236f157 100644
--- a/drivers/irqchip/irq-gic-v3-mbi.c
+++ b/drivers/irqchip/irq-gic-v3-mbi.c
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/msi.h>
#include <linux/of_address.h>
+#include <linux/of_pci.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@@ -157,6 +158,55 @@ static void mbi_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
iommu_dma_map_msi_msg(data->irq, msg);
}
+#ifdef CONFIG_PCI_MSI
+/* PCI-specific irqchip */
+static void mbi_mask_msi_irq(struct irq_data *d)
+{
+ pci_msi_mask_irq(d);
+ irq_chip_mask_parent(d);
+}
+
+static void mbi_unmask_msi_irq(struct irq_data *d)
+{
+ pci_msi_unmask_irq(d);
+ irq_chip_unmask_parent(d);
+}
+
+static struct irq_chip mbi_msi_irq_chip = {
+ .name = "MSI",
+ .irq_mask = mbi_mask_msi_irq,
+ .irq_unmask = mbi_unmask_msi_irq,
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_compose_msi_msg = mbi_compose_msi_msg,
+ .irq_write_msi_msg = pci_msi_domain_write_msg,
+};
+
+static struct msi_domain_info mbi_msi_domain_info = {
+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+ MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI),
+ .chip = &mbi_msi_irq_chip,
+};
+
+static int mbi_allocate_pci_domain(struct irq_domain *nexus_domain,
+ struct irq_domain **pci_domain)
+{
+ *pci_domain = pci_msi_create_irq_domain(nexus_domain->parent->fwnode,
+ &mbi_msi_domain_info,
+ nexus_domain);
+ if (!*pci_domain)
+ return -ENOMEM;
+
+ return 0;
+}
+#else
+static int mbi_allocate_pci_domain(struct irq_domain *nexus_domain,
+ struct irq_domain **pci_domain)
+{
+ *pci_domain = NULL;
+ return 0;
+}
+#endif
+
static void mbi_compose_mbi_msg(struct irq_data *data, struct msi_msg *msg)
{
mbi_compose_msi_msg(data, msg);
@@ -187,7 +237,8 @@ static struct msi_domain_info mbi_pmsi_domain_info = {
static int mbi_allocate_domains(struct irq_domain *parent)
{
- struct irq_domain *nexus_domain, *plat_domain;
+ struct irq_domain *nexus_domain, *pci_domain, *plat_domain;
+ int err;
nexus_domain = irq_domain_create_tree(parent->fwnode,
&mbi_domain_ops, NULL);
@@ -197,12 +248,17 @@ static int mbi_allocate_domains(struct irq_domain *parent)
irq_domain_update_bus_token(nexus_domain, DOMAIN_BUS_NEXUS);
nexus_domain->parent = parent;
+ err = mbi_allocate_pci_domain(nexus_domain, &pci_domain);
+
plat_domain = platform_msi_create_irq_domain(parent->fwnode,
&mbi_pmsi_domain_info,
nexus_domain);
- if (!plat_domain) {
- irq_domain_remove(plat_domain);
+ if (err || !plat_domain) {
+ if (plat_domain)
+ irq_domain_remove(plat_domain);
+ if (pci_domain)
+ irq_domain_remove(pci_domain);
irq_domain_remove(nexus_domain);
return -ENOMEM;
}
--
2.14.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 7/7] dt-bindings/gic-v3: Add documentation for MBI support
2018-04-23 10:34 [PATCH 0/7] Level-triggered MSI support Marc Zyngier
` (5 preceding siblings ...)
2018-04-23 10:34 ` [PATCH 6/7] irqchip/gic-v3: Add PCI/MSI support to the GICv3 MBI sub-driver Marc Zyngier
@ 2018-04-23 10:34 ` Marc Zyngier
2018-04-23 11:51 ` [PATCH 0/7] Level-triggered MSI support Ard Biesheuvel
` (2 subsequent siblings)
9 siblings, 0 replies; 17+ messages in thread
From: Marc Zyngier @ 2018-04-23 10:34 UTC (permalink / raw)
To: Thomas Gleixner, Jason Cooper
Cc: Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, linux-kernel
Add the required properties to support the MBI feature on GICv3.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
.../bindings/interrupt-controller/arm,gic-v3.txt | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
index 0a57f2f4167d..3ea78c4ef887 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
@@ -57,6 +57,20 @@ Optional
occupied by the redistributors. Required if more than one such
region is present.
+- msi-controller: Boolean property. Identifies the node as an MSI
+ controller. Only present if the Message Based Interrupt
+ functionnality is being exposed by the HW, and the mbi-ranges
+ property present.
+
+- mbi-ranges: A list of pairs <intid span>, where "intid" is the first
+ SPI of a range that can be used an MBI, and "span" the size of that
+ range. Multiple ranges can be provided. Requires "msi-controller" to
+ be set.
+
+- mbi-alias: Address property. Base address of an alias of the GICD
+ region containing only the {SET,CLR}SPI registers to be used if
+ isolation is required, and if supported by the HW.
+
Sub-nodes:
PPI affinity can be expressed as a single "ppi-partitions" node,
@@ -99,6 +113,9 @@ Examples:
<0x0 0x2c020000 0 0x2000>; // GICV
interrupts = <1 9 4>;
+ msi-controller;
+ mbi-ranges = <256 128>;
+
gic-its@2c200000 {
compatible = "arm,gic-v3-its";
msi-controller;
--
2.14.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/7] Level-triggered MSI support
2018-04-23 10:34 [PATCH 0/7] Level-triggered MSI support Marc Zyngier
` (6 preceding siblings ...)
2018-04-23 10:34 ` [PATCH 7/7] dt-bindings/gic-v3: Add documentation for MBI support Marc Zyngier
@ 2018-04-23 11:51 ` Ard Biesheuvel
2018-04-23 12:31 ` Marc Zyngier
2018-04-23 15:53 ` Marc Zyngier
2018-04-23 12:43 ` Srinivas Kandagatla
2018-04-23 15:32 ` Miquel Raynal
9 siblings, 2 replies; 17+ messages in thread
From: Ard Biesheuvel @ 2018-04-23 11:51 UTC (permalink / raw)
To: Marc Zyngier
Cc: Thomas Gleixner, Jason Cooper, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, Linux Kernel Mailing List
On 23 April 2018 at 12:34, Marc Zyngier <marc.zyngier@arm.com> wrote:
> This series is a first shot at teaching the kernel about the oxymoron
> expressed in $SUBJECT. Over the past couple of years, we've seen some
> SoCs coming up with ways of signalling level interrupts using a new
> flavor of MSIs, where the MSI controller uses two distinct messages:
> one that raises a virtual line, and one that lowers it. The target MSI
> controller is in charge of maintaining the state of the line.
>
> This allows for a much simplified HW signal routing (no need to have
> hundreds of discrete lines to signal level interrupts if you already
> have a memory bus), but results in a departure from the current idea
> the kernel has of MSIs.
>
> This series takes a minimal approach to the problem, which is to allow
> MSI controllers to use not only one, but up to two messages at a
> time. This is controlled by a flag exposed at MSI irq domain creation,
> and is only supported with platform MSI.
>
> The rest of the series repaints the Marvell ICU/GICP drivers which
> already make use of this feature with a side-channel, and adds support
> for the same feature in GICv3. A side effect of the last GICv3 patch
> is that you can also use SPIs to signal PCI MSIs. This is a last
> resort measure for SoCs where the ITS is unusable for unspeakable
> reasons.
>
Hi Marc,
I am hitting the splat below when trying this series on SynQuacer,
with mbi range <64 32> (which is reserved in the h/w manual but note
that I haven't confirmed with Socionext whether these are expected to
work or not. However, I don't think that makes any difference
regarding the issue below.)
Unable to handle kernel read from unreadable memory at virtual address 00000018
Mem abort info:
ESR = 0x96000004
Exception class = DABT (current EL), IL = 32 bits
SET = 0, FnV = 0
EA = 0, S1PTW = 0
Data abort info:
ISV = 0, ISS = 0x00000004
CM = 0, WnR = 0
user pgtable: 4k pages, 48-bit VAs, pgdp = (ptrval)
[0000000000000018] pgd=0000000000000000
Internal error: Oops: 96000004 [#1] PREEMPT SMP
Modules linked in: gpio_keys(+) efivarfs ip_tables x_tables autofs4
ext4 crc16 mbcache jbd2 fscrypto sr_mod cdrom sd_mod ahci xhci_pci
libahci xhci_hcd libata usbcore scsi_mod realtek netsec of_mdio
fixed_phy libphy i2c_synquacer gpio_mb86s7x
CPU: 19 PID: 398 Comm: systemd-udevd Tainted: G W
4.17.0-rc2+ #54
Hardware name: Socionext SynQuacer E-series DeveloperBox, BIOS build
#101 Apr 2 2018
pstate: a0400085 (NzCv daIf +PAN -UAO)
pc : iommu_dma_map_msi_msg+0x40/0x1e8
lr : iommu_dma_map_msi_msg+0x34/0x1e8
sp : ffff00000b8db690
x29: ffff00000b8db690 x28: ffffeca6f07442a0
x27: 0000000000000000 x26: ffffeca6f07442d4
x25: ffffeca6f0744398 x24: 0000000000000000
x23: 0000000000000016 x22: 0000000000000000
x21: ffffeca6f755ed00 x20: ffff00000b8db770
x19: 0000000000000016 x18: ffffffffffffffff
x17: ffff446c203fd000 x16: ffff446c1f3b5108
x15: ffffeca6f0a095b0 x14: ffffeca6f0a3a587
x13: ffffeca6f0a3a586 x12: 0000000000000040
x11: 0000000000000004 x10: 0000000000000016
x9 : ffffeca6f70009d8 x8 : 0000000000000000
x7 : ffffeca6f0744200 x6 : ffffeca6f0744200
x5 : ffffeca6f7000900 x4 : ffffeca6f0744200
x3 : 0000000000000000 x2 : 0000000000000000
x1 : ffffeca6f0744258 x0 : 0000000000000000
Process systemd-udevd (pid: 398, stack limit = 0x (ptrval))
Call trace:
iommu_dma_map_msi_msg+0x40/0x1e8
mbi_compose_msi_msg+0x54/0x60
mbi_compose_mbi_msg+0x28/0x68
irq_chip_compose_msi_msg+0x5c/0x78
msi_domain_activate+0x40/0x90
__irq_domain_activate_irq+0x74/0xb8
__irq_domain_activate_irq+0x3c/0xb8
irq_domain_activate_irq+0x4c/0x60
irq_activate+0x40/0x50
__setup_irq+0x4bc/0x7e0
request_threaded_irq+0xf0/0x198
request_any_context_irq+0x6c/0xc0
devm_request_any_context_irq+0x78/0xf0
gpio_keys_probe+0x324/0x9a0 [gpio_keys]
platform_drv_probe+0x60/0xc8
driver_probe_device+0x2c4/0x490
__driver_attach+0x10c/0x128
bus_for_each_dev+0x78/0xe0
driver_attach+0x30/0x40
bus_add_driver+0x1d0/0x298
driver_register+0x68/0x100
__platform_driver_register+0x54/0x60
gpio_keys_init+0x24/0x1000 [gpio_keys]
do_one_initcall+0x68/0x258
do_init_module+0x64/0x1e0
load_module+0x1e20/0x21a8
sys_finit_module+0x108/0x140
EFI Variables Facility v0.08 2004-May-17
__sys_trace_return+0x0/0x4
Code: 97ec1444 b4000ca0 f9400800 f9400800 (f9400c18)
---[ end trace f7956dc89d9f3be7 ]---
00000000000014a0 <iommu_dma_map_msi_msg>:
14a0: a9ba7bfd stp x29, x30, [sp, #-96]!
14a4: 910003fd mov x29, sp
14a8: a90153f3 stp x19, x20, [sp, #16]
14ac: a9025bf5 stp x21, x22, [sp, #32]
14b0: a90363f7 stp x23, x24, [sp, #48]
14b4: a9046bf9 stp x25, x26, [sp, #64]
14b8: a90573fb stp x27, x28, [sp, #80]
14bc: 2a0003f3 mov w19, w0
14c0: aa1e03e0 mov x0, x30
14c4: aa0103f4 mov x20, x1
14c8: 94000000 bl 0 <_mcount>
14cc: 2a1303e0 mov w0, w19
14d0: 94000000 bl 0 <irq_get_irq_data>
14d4: b4000ca0 cbz x0, 1668 <iommu_dma_map_msi_msg+0x1c8>
14d8: f9400800 ldr x0, [x0, #16]
14dc: f9400800 ldr x0, [x0, #16]
14e0: f9400c18 ldr x24, [x0, #24]
14e4: aa1803e0 mov x0, x24
14e8: 94000000 bl 0 <iommu_get_domain_for_dev>
14ec: aa0003f3 mov x19, x0
14f0: b40008a0 cbz x0, 1604 <iommu_dma_map_msi_msg+0x164>
14f4: f9402015 ldr x21, [x0, #64]
14f8: b4000875 cbz x21, 1604 <iommu_dma_map_msi_msg+0x164>
14fc: 911d82b6 add x22, x21, #0x760
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/7] Level-triggered MSI support
2018-04-23 11:51 ` [PATCH 0/7] Level-triggered MSI support Ard Biesheuvel
@ 2018-04-23 12:31 ` Marc Zyngier
2018-04-23 15:53 ` Marc Zyngier
1 sibling, 0 replies; 17+ messages in thread
From: Marc Zyngier @ 2018-04-23 12:31 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Thomas Gleixner, Jason Cooper, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, Linux Kernel Mailing List
HI Ard,
On 23/04/18 12:51, Ard Biesheuvel wrote:
> On 23 April 2018 at 12:34, Marc Zyngier <marc.zyngier@arm.com> wrote:
>> This series is a first shot at teaching the kernel about the oxymoron
>> expressed in $SUBJECT. Over the past couple of years, we've seen some
>> SoCs coming up with ways of signalling level interrupts using a new
>> flavor of MSIs, where the MSI controller uses two distinct messages:
>> one that raises a virtual line, and one that lowers it. The target MSI
>> controller is in charge of maintaining the state of the line.
>>
>> This allows for a much simplified HW signal routing (no need to have
>> hundreds of discrete lines to signal level interrupts if you already
>> have a memory bus), but results in a departure from the current idea
>> the kernel has of MSIs.
>>
>> This series takes a minimal approach to the problem, which is to allow
>> MSI controllers to use not only one, but up to two messages at a
>> time. This is controlled by a flag exposed at MSI irq domain creation,
>> and is only supported with platform MSI.
>>
>> The rest of the series repaints the Marvell ICU/GICP drivers which
>> already make use of this feature with a side-channel, and adds support
>> for the same feature in GICv3. A side effect of the last GICv3 patch
>> is that you can also use SPIs to signal PCI MSIs. This is a last
>> resort measure for SoCs where the ITS is unusable for unspeakable
>> reasons.
>>
>
> Hi Marc,
>
> I am hitting the splat below when trying this series on SynQuacer,
> with mbi range <64 32> (which is reserved in the h/w manual but note
> that I haven't confirmed with Socionext whether these are expected to
> work or not. However, I don't think that makes any difference
> regarding the issue below.)
Thanks for giving it a go. Something looks odd below:
>
> Unable to handle kernel read from unreadable memory at virtual address 00000018
> Mem abort info:
> ESR = 0x96000004
> Exception class = DABT (current EL), IL = 32 bits
> SET = 0, FnV = 0
> EA = 0, S1PTW = 0
> Data abort info:
> ISV = 0, ISS = 0x00000004
> CM = 0, WnR = 0
> user pgtable: 4k pages, 48-bit VAs, pgdp = (ptrval)
> [0000000000000018] pgd=0000000000000000
> Internal error: Oops: 96000004 [#1] PREEMPT SMP
> Modules linked in: gpio_keys(+) efivarfs ip_tables x_tables autofs4
> ext4 crc16 mbcache jbd2 fscrypto sr_mod cdrom sd_mod ahci xhci_pci
> libahci xhci_hcd libata usbcore scsi_mod realtek netsec of_mdio
> fixed_phy libphy i2c_synquacer gpio_mb86s7x
> CPU: 19 PID: 398 Comm: systemd-udevd Tainted: G W
> 4.17.0-rc2+ #54
> Hardware name: Socionext SynQuacer E-series DeveloperBox, BIOS build
> #101 Apr 2 2018
> pstate: a0400085 (NzCv daIf +PAN -UAO)
> pc : iommu_dma_map_msi_msg+0x40/0x1e8
> lr : iommu_dma_map_msi_msg+0x34/0x1e8
> sp : ffff00000b8db690
> x29: ffff00000b8db690 x28: ffffeca6f07442a0
> x27: 0000000000000000 x26: ffffeca6f07442d4
> x25: ffffeca6f0744398 x24: 0000000000000000
> x23: 0000000000000016 x22: 0000000000000000
> x21: ffffeca6f755ed00 x20: ffff00000b8db770
> x19: 0000000000000016 x18: ffffffffffffffff
> x17: ffff446c203fd000 x16: ffff446c1f3b5108
> x15: ffffeca6f0a095b0 x14: ffffeca6f0a3a587
> x13: ffffeca6f0a3a586 x12: 0000000000000040
> x11: 0000000000000004 x10: 0000000000000016
> x9 : ffffeca6f70009d8 x8 : 0000000000000000
> x7 : ffffeca6f0744200 x6 : ffffeca6f0744200
> x5 : ffffeca6f7000900 x4 : ffffeca6f0744200
> x3 : 0000000000000000 x2 : 0000000000000000
> x1 : ffffeca6f0744258 x0 : 0000000000000000
> Process systemd-udevd (pid: 398, stack limit = 0x (ptrval))
> Call trace:
> iommu_dma_map_msi_msg+0x40/0x1e8
We die here because irq_get_msi_desc() has returned a NULL pointer.
That's not really expected.
> mbi_compose_msi_msg+0x54/0x60
> mbi_compose_mbi_msg+0x28/0x68
We're requesting a platform MSI...
> irq_chip_compose_msi_msg+0x5c/0x78
> msi_domain_activate+0x40/0x90
> __irq_domain_activate_irq+0x74/0xb8
> __irq_domain_activate_irq+0x3c/0xb8
> irq_domain_activate_irq+0x4c/0x60
> irq_activate+0x40/0x50
> __setup_irq+0x4bc/0x7e0
> request_threaded_irq+0xf0/0x198
> request_any_context_irq+0x6c/0xc0
> devm_request_any_context_irq+0x78/0xf0
> gpio_keys_probe+0x324/0x9a0 [gpio_keys]
from the gpio_keys driver, which shouldn't be doing platform MSI at all.
It looks like we've looked-up the wrong irq domain, and really bad
things happen after that.
Could you point me to the device-tree of this machine? I need to
understand how we can end-up in such a situation.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/7] Level-triggered MSI support
2018-04-23 10:34 [PATCH 0/7] Level-triggered MSI support Marc Zyngier
` (7 preceding siblings ...)
2018-04-23 11:51 ` [PATCH 0/7] Level-triggered MSI support Ard Biesheuvel
@ 2018-04-23 12:43 ` Srinivas Kandagatla
2018-04-23 15:32 ` Miquel Raynal
9 siblings, 0 replies; 17+ messages in thread
From: Srinivas Kandagatla @ 2018-04-23 12:43 UTC (permalink / raw)
To: Marc Zyngier, Thomas Gleixner, Jason Cooper
Cc: Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal, linux-kernel
On 23/04/18 11:34, Marc Zyngier wrote:
> This series is a first shot at teaching the kernel about the oxymoron
> expressed in $SUBJECT. Over the past couple of years, we've seen some
> SoCs coming up with ways of signalling level interrupts using a new
> flavor of MSIs, where the MSI controller uses two distinct messages:
> one that raises a virtual line, and one that lowers it. The target MSI
> controller is in charge of maintaining the state of the line.
>
> This allows for a much simplified HW signal routing (no need to have
> hundreds of discrete lines to signal level interrupts if you already
> have a memory bus), but results in a departure from the current idea
> the kernel has of MSIs.
>
> This series takes a minimal approach to the problem, which is to allow
> MSI controllers to use not only one, but up to two messages at a
> time. This is controlled by a flag exposed at MSI irq domain creation,
> and is only supported with platform MSI.
>
> The rest of the series repaints the Marvell ICU/GICP drivers which
> already make use of this feature with a side-channel, and adds support
> for the same feature in GICv3. A side effect of the last GICv3 patch
> is that you can also use SPIs to signal PCI MSIs. This is a last
> resort measure for SoCs where the ITS is unusable for unspeakable
> reasons.
>
> Marc Zyngier (7):
> genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers
> genirq/msi: Limit level-triggered MSI to platform devices
> irqchip/mvebu-gicp: Use level-triggered MSIs between ICU and GICP
> dma-iommu: Fix compilation when !CONFIG_IOMMU_DMA
> irqchip/gic-v3: Add support for Message Based Interrupts as an MSI
> controller
> irqchip/gic-v3: Add PCI/MSI support to the GICv3 MBI sub-driver
> dt-bindings/gic-v3: Add documentation for MBI support
>
Thanks for the patches,
Am able to get PCIe MSI interrupts on Qualcomm DragonBoard DB820c with
this patchset.
root@linaro-alip:~# cat /proc/interrupts | grep -i MSI
44: 0 0 0 0 GICv3 437 Edge
qcom-pcie-msi
45: 0 0 0 0 GICv3 445 Edge
qcom-pcie-msi
46: 0 0 0 0 GICv3 453 Edge
qcom-pcie-msi
80: 0 0 0 0 MSI 134217728
Edge PCIe PME, aerdrv
114: 0 0 0 0 MSI 268435456
Edge PCIe PME, aerdrv
115: 0 0 0 0 MSI 134742016
Edge ahci[0001:01:00.0]
197: 0 0 0 0 MSI 0 Edge
PCIe PME, aerdrv
199: 2108 0 0 0 MSI 524288 Edge
ath10k_pci
202: 295 0 0 0 MSI 268959744
Edge eth0
Tested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
--srini
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/7] Level-triggered MSI support
2018-04-23 10:34 [PATCH 0/7] Level-triggered MSI support Marc Zyngier
` (8 preceding siblings ...)
2018-04-23 12:43 ` Srinivas Kandagatla
@ 2018-04-23 15:32 ` Miquel Raynal
9 siblings, 0 replies; 17+ messages in thread
From: Miquel Raynal @ 2018-04-23 15:32 UTC (permalink / raw)
To: Marc Zyngier
Cc: Thomas Gleixner, Jason Cooper, Ard Biesheuvel, Thomas Petazzoni,
Srinivas Kandagatla, linux-kernel
Hi Marc,
On Mon, 23 Apr 2018 11:34:33 +0100, Marc Zyngier <marc.zyngier@arm.com>
wrote:
> This series is a first shot at teaching the kernel about the oxymoron
> expressed in $SUBJECT. Over the past couple of years, we've seen some
> SoCs coming up with ways of signalling level interrupts using a new
> flavor of MSIs, where the MSI controller uses two distinct messages:
> one that raises a virtual line, and one that lowers it. The target MSI
> controller is in charge of maintaining the state of the line.
>
> This allows for a much simplified HW signal routing (no need to have
> hundreds of discrete lines to signal level interrupts if you already
> have a memory bus), but results in a departure from the current idea
> the kernel has of MSIs.
>
> This series takes a minimal approach to the problem, which is to allow
> MSI controllers to use not only one, but up to two messages at a
> time. This is controlled by a flag exposed at MSI irq domain creation,
> and is only supported with platform MSI.
>
> The rest of the series repaints the Marvell ICU/GICP drivers which
> already make use of this feature with a side-channel, and adds support
> for the same feature in GICv3. A side effect of the last GICv3 patch
> is that you can also use SPIs to signal PCI MSIs. This is a last
> resort measure for SoCs where the ITS is unusable for unspeakable
> reasons.
>
> Marc Zyngier (7):
> genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers
> genirq/msi: Limit level-triggered MSI to platform devices
> irqchip/mvebu-gicp: Use level-triggered MSIs between ICU and GICP
> dma-iommu: Fix compilation when !CONFIG_IOMMU_DMA
> irqchip/gic-v3: Add support for Message Based Interrupts as an MSI
> controller
> irqchip/gic-v3: Add PCI/MSI support to the GICv3 MBI sub-driver
> dt-bindings/gic-v3: Add documentation for MBI support
>
> .../bindings/interrupt-controller/arm,gic-v3.txt | 17 +
> drivers/base/platform-msi.c | 3 +
> drivers/irqchip/Makefile | 2 +-
> drivers/irqchip/irq-gic-v3-mbi.c | 343 +++++++++++++++++++++
> drivers/irqchip/irq-gic-v3.c | 6 +
> drivers/irqchip/irq-mvebu-gicp.c | 37 +--
> drivers/irqchip/irq-mvebu-gicp.h | 12 -
> drivers/irqchip/irq-mvebu-icu.c | 33 +-
> drivers/pci/msi.c | 3 +
> include/linux/dma-iommu.h | 1 +
> include/linux/irqchip/arm-gic-v3.h | 1 +
> include/linux/msi.h | 2 +
> kernel/irq/msi.c | 32 +-
> 13 files changed, 427 insertions(+), 65 deletions(-)
> create mode 100644 drivers/irqchip/irq-gic-v3-mbi.c
> delete mode 100644 drivers/irqchip/irq-mvebu-gicp.h
>
Thanks for the series, I gave it a try on Armada-8040-DB:
# cat /proc/interrupts | grep ICU
28: 0 0 0 0 ICU.f21e0000 107 Level ahci[f2540000.sata]
29: 0 0 0 0 ICU.f41e0000 107 Level ahci[f4540000.sata]
35: 2 0 0 0 ICU.f21e0000 129 Level
36: 3 0 0 0 ICU.f21e0000 41 Level eth1
37: 0 0 0 0 ICU.f21e0000 45 Level eth1
38: 0 0 4 0 ICU.f21e0000 49 Level eth1
39: 0 0 0 2 ICU.f21e0000 53 Level eth1
40: 128 0 0 0 ICU.f21e0000 57 Level eth1
47: 2 0 0 0 ICU.f41e0000 129 Level
54: 82 0 0 0 ICU.f21e0000 106 Level xhci-hcd:usb3
55: 82 0 0 0 ICU.f21e0000 105 Level xhci-hcd:usb5
56: 4 0 0 0 ICU.f41e0000 106 Level xhci-hcd:usb7
57: 0 0 0 0 ICU.f41e0000 105 Level xhci-hcd:usb1
58: 0 0 0 0 ICU.f41e0000 77 Level f4284000.rtc
59: 224 0 0 0 ICU.f21e0000 120 Level mv64xxx_i2c
60: 0 0 0 0 ICU.f41e0000 120 Level mv64xxx_i2c
61: 52 0 0 0 ICU.f21e0000 27 Level mmc1
63: 0 0 0 0 ICU.f21e0000 22 Level armada8k-pcie, PCIe PME, aerdrv
64: 0 0 0 0 ICU.f21e0000 23 Level armada8k-pcie, PCIe PME, aerdrv
65: 0 0 0 0 ICU.f41e0000 22 Level armada8k-pcie, PCIe PME, aerdrv
66: 0 0 0 0 ICU.f41e0000 24 Level armada8k-pcie, PCIe PME, aerdrv
67: 0 0 0 0 ICU.f41e0000 23 Level armada8k-pcie, PCIe PME, aerdrv
All these interrupts are NSRs and go through the GICP. I was able to
use the network (CP0), an I2C bus (CP0) and the USB host ports (on each
CP).
Tested-by: Miquel Raynal <miquel.raynal@bootlin.com>
Thanks,
Miquèl
--
Miquel Raynal, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/7] Level-triggered MSI support
2018-04-23 11:51 ` [PATCH 0/7] Level-triggered MSI support Ard Biesheuvel
2018-04-23 12:31 ` Marc Zyngier
@ 2018-04-23 15:53 ` Marc Zyngier
2018-04-23 16:48 ` Ard Biesheuvel
1 sibling, 1 reply; 17+ messages in thread
From: Marc Zyngier @ 2018-04-23 15:53 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Thomas Gleixner, Jason Cooper, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, Linux Kernel Mailing List
On 23/04/18 12:51, Ard Biesheuvel wrote:
> On 23 April 2018 at 12:34, Marc Zyngier <marc.zyngier@arm.com> wrote:
>> This series is a first shot at teaching the kernel about the oxymoron
>> expressed in $SUBJECT. Over the past couple of years, we've seen some
>> SoCs coming up with ways of signalling level interrupts using a new
>> flavor of MSIs, where the MSI controller uses two distinct messages:
>> one that raises a virtual line, and one that lowers it. The target MSI
>> controller is in charge of maintaining the state of the line.
>>
>> This allows for a much simplified HW signal routing (no need to have
>> hundreds of discrete lines to signal level interrupts if you already
>> have a memory bus), but results in a departure from the current idea
>> the kernel has of MSIs.
>>
>> This series takes a minimal approach to the problem, which is to allow
>> MSI controllers to use not only one, but up to two messages at a
>> time. This is controlled by a flag exposed at MSI irq domain creation,
>> and is only supported with platform MSI.
>>
>> The rest of the series repaints the Marvell ICU/GICP drivers which
>> already make use of this feature with a side-channel, and adds support
>> for the same feature in GICv3. A side effect of the last GICv3 patch
>> is that you can also use SPIs to signal PCI MSIs. This is a last
>> resort measure for SoCs where the ITS is unusable for unspeakable
>> reasons.
>>
>
> Hi Marc,
>
> I am hitting the splat below when trying this series on SynQuacer,
> with mbi range <64 32> (which is reserved in the h/w manual but note
> that I haven't confirmed with Socionext whether these are expected to
> work or not. However, I don't think that makes any difference
> regarding the issue below.)
[...]
For the record: After some IRC debugging with Ard, this turns out to be
due to two issues:
- GICv3 is now advertising several domains, all using the same device nodes
- irq_find_host() is picking the first one, which is the wrong one.
A good way to avoid this mess is to:
- Let GICv3 advertise its core domain with DOMAIN_BUS_WIRED (consistent
with what the armada-370-xp driver is already doing)
- Let irq_find_host return DOMAIN_BUS_WIRED before trying DOMAIN_BUS_ANY
(consistent with the way irq_create_fwspec_mapping works).
I've stashed the whole series at [1] with these two fixes.
M.
[1] git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git
irq/level-msi
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/7] Level-triggered MSI support
2018-04-23 15:53 ` Marc Zyngier
@ 2018-04-23 16:48 ` Ard Biesheuvel
0 siblings, 0 replies; 17+ messages in thread
From: Ard Biesheuvel @ 2018-04-23 16:48 UTC (permalink / raw)
To: Marc Zyngier
Cc: Thomas Gleixner, Jason Cooper, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, Linux Kernel Mailing List
On 23 April 2018 at 17:53, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On 23/04/18 12:51, Ard Biesheuvel wrote:
>> On 23 April 2018 at 12:34, Marc Zyngier <marc.zyngier@arm.com> wrote:
>>> This series is a first shot at teaching the kernel about the oxymoron
>>> expressed in $SUBJECT. Over the past couple of years, we've seen some
>>> SoCs coming up with ways of signalling level interrupts using a new
>>> flavor of MSIs, where the MSI controller uses two distinct messages:
>>> one that raises a virtual line, and one that lowers it. The target MSI
>>> controller is in charge of maintaining the state of the line.
>>>
>>> This allows for a much simplified HW signal routing (no need to have
>>> hundreds of discrete lines to signal level interrupts if you already
>>> have a memory bus), but results in a departure from the current idea
>>> the kernel has of MSIs.
>>>
>>> This series takes a minimal approach to the problem, which is to allow
>>> MSI controllers to use not only one, but up to two messages at a
>>> time. This is controlled by a flag exposed at MSI irq domain creation,
>>> and is only supported with platform MSI.
>>>
>>> The rest of the series repaints the Marvell ICU/GICP drivers which
>>> already make use of this feature with a side-channel, and adds support
>>> for the same feature in GICv3. A side effect of the last GICv3 patch
>>> is that you can also use SPIs to signal PCI MSIs. This is a last
>>> resort measure for SoCs where the ITS is unusable for unspeakable
>>> reasons.
>>>
>>
>> Hi Marc,
>>
>> I am hitting the splat below when trying this series on SynQuacer,
>> with mbi range <64 32> (which is reserved in the h/w manual but note
>> that I haven't confirmed with Socionext whether these are expected to
>> work or not. However, I don't think that makes any difference
>> regarding the issue below.)
>
> [...]
>
> For the record: After some IRC debugging with Ard, this turns out to be
> due to two issues:
> - GICv3 is now advertising several domains, all using the same device nodes
> - irq_find_host() is picking the first one, which is the wrong one.
>
> A good way to avoid this mess is to:
> - Let GICv3 advertise its core domain with DOMAIN_BUS_WIRED (consistent
> with what the armada-370-xp driver is already doing)
> - Let irq_find_host return DOMAIN_BUS_WIRED before trying DOMAIN_BUS_ANY
> (consistent with the way irq_create_fwspec_mapping works).
>
> I've stashed the whole series at [1] with these two fixes.
>
For the fixed version (1c1eff8a4d6b14aae9a709570e692f5fcd837670)
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> # SynQuacer
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/7] genirq/msi: Limit level-triggered MSI to platform devices
2018-04-23 10:34 ` [PATCH 2/7] genirq/msi: Limit level-triggered MSI to platform devices Marc Zyngier
@ 2018-04-26 19:50 ` Thomas Gleixner
2018-05-01 10:15 ` Marc Zyngier
0 siblings, 1 reply; 17+ messages in thread
From: Thomas Gleixner @ 2018-04-26 19:50 UTC (permalink / raw)
To: Marc Zyngier
Cc: Jason Cooper, Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, linux-kernel
On Mon, 23 Apr 2018, Marc Zyngier wrote:
> Nobody would be insane enough to try and use level triggered
> MSIs on PCI, but let's make sure it doesn't happen. Also,
> let's mandate that the irqchip backing the platform MSI domain
> is providing an irq_set_type method (or the whole thing would
> be a bit useless).
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> drivers/base/platform-msi.c | 3 +++
> drivers/pci/msi.c | 3 +++
> 2 files changed, 6 insertions(+)
>
> diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
> index 8e22073aeeed..3b9694a6beaa 100644
> --- a/drivers/base/platform-msi.c
> +++ b/drivers/base/platform-msi.c
> @@ -101,6 +101,9 @@ static void platform_msi_update_chip_ops(struct msi_domain_info *info)
> chip->irq_set_affinity = msi_domain_set_affinity;
> if (!chip->irq_write_msi_msg)
> chip->irq_write_msi_msg = platform_msi_write_msg;
> + if (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE) &&
> + !chip->irq_set_type))
Shouldn't we just require something like IRQCHIP_SUPPORTS_MSI_LEVEL or such
in chip->flags being set instead?
Thanks,
tglx
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 5/7] irqchip/gic-v3: Add support for Message Based Interrupts as an MSI controller
2018-04-23 10:34 ` [PATCH 5/7] irqchip/gic-v3: Add support for Message Based Interrupts as an MSI controller Marc Zyngier
@ 2018-04-26 20:53 ` Thomas Gleixner
0 siblings, 0 replies; 17+ messages in thread
From: Thomas Gleixner @ 2018-04-26 20:53 UTC (permalink / raw)
To: Marc Zyngier
Cc: Jason Cooper, Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, linux-kernel
On Mon, 23 Apr 2018, Marc Zyngier wrote:
> --- /dev/null
> +++ b/drivers/irqchip/irq-gic-v3-mbi.c
> @@ -0,0 +1,287 @@
> +/*
> + * Copyright (C) 2018 ARM Limited, All Rights Reserved.
> + * Author: Marc Zyngier <marc.zyngier@arm.com>
Can you please:
1) Add the proper SPDX-License-Identifier
// SPDX-License-Identifier: GPL-2.0
at the first line of the file and
2) Remove the boiler plate? Please talk to Jilayne.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +struct mbi_range {
> + u32 spi_start;
> + u32 nr_spis;
> + unsigned long *bm;
> +};
> +
> +static spinlock_t mbi_lock;
DEFINE_SPINLOCK() please
> +static phys_addr_t mbi_phys_base;
> +static struct mbi_range *mbi_ranges;
> +static unsigned int mbi_range_nr;
> +
> +static struct irq_chip mbi_irq_chip = {
> + .name = "MBI",
> + .irq_mask = irq_chip_mask_parent,
> + .irq_unmask = irq_chip_unmask_parent,
> + .irq_eoi = irq_chip_eoi_parent,
> + .irq_set_type = irq_chip_set_type_parent,
> + .irq_set_affinity = irq_chip_set_affinity_parent,
> +};
> +
> +static int mbi_irq_gic_domain_alloc(struct irq_domain *domain,
> + unsigned int virq,
> + irq_hw_number_t hwirq)
> +{
> + struct irq_fwspec fwspec;
> + struct irq_data *d;
> + int err;
> +
> + /*
> + * Using ACPI? There is no MBI support in the spec, you
> + * shouldn't even be here.
> + */
> + if (!is_of_node(domain->parent->fwnode))
> + return -EINVAL;
> +
> + /*
> + * Let's default to edge. This is consistent with traditional
> + * MSIs, and systems requiring level signaling will just
> + * enforce the trigger on their own.
> + */
> + fwspec.fwnode = domain->parent->fwnode;
> + fwspec.param_count = 3;
> + fwspec.param[0] = 0;
> + fwspec.param[1] = hwirq - 32;
> + fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
> +
> + err = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
> + if (err)
> + return err;
> +
> + d = irq_domain_get_irq_data(domain->parent, virq);
> + d->chip->irq_set_type(d, IRQ_TYPE_EDGE_RISING);
irq_chip_set_type_parent(d, ....) ?
> +
> + return 0;
> +}
> +
> +static void mbi_free_msi(struct mbi_range *mbi, unsigned int hwirq,
> + int nr_irqs)
> +{
> + spin_lock(&mbi_lock);
> + bitmap_release_region(mbi->bm, hwirq - mbi->spi_start,
> + get_count_order(nr_irqs));
> + spin_unlock(&mbi_lock);
> +}
> +
> +static int mbi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
> + unsigned int nr_irqs, void *args)
> +{
> + struct mbi_range *mbi = NULL;
> + int hwirq, offset, i, err = 0;
> +
> + spin_lock(&mbi_lock);
There is no real reason that this must be a spinlock, right? Make it a
mutex please.
> + for (i = 0; i < mbi_range_nr; i++) {
> + offset = bitmap_find_free_region(mbi_ranges[i].bm,
> + mbi_ranges[i].nr_spis,
> + get_count_order(nr_irqs));
> + if (offset >= 0) {
> + mbi = &mbi_ranges[i];
> + break;
> + }
> + }
> + spin_unlock(&mbi_lock);
> +/* Platform-MSI specific irqchip */
> +static struct irq_chip mbi_pmsi_irq_chip = {
> + .name = "pMSI",
> + .irq_set_type = irq_chip_set_type_parent,
> + .irq_compose_msi_msg = mbi_compose_mbi_msg,
Fun. I did not expect this to work w/o any of the other callbacks. Magic!
Other than the above nits, this looks pretty good.
Thanks,
tglx
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/7] genirq/msi: Limit level-triggered MSI to platform devices
2018-04-26 19:50 ` Thomas Gleixner
@ 2018-05-01 10:15 ` Marc Zyngier
0 siblings, 0 replies; 17+ messages in thread
From: Marc Zyngier @ 2018-05-01 10:15 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Jason Cooper, Ard Biesheuvel, Thomas Petazzoni, Miquel Raynal,
Srinivas Kandagatla, linux-kernel
On 26/04/18 20:50, Thomas Gleixner wrote:
> On Mon, 23 Apr 2018, Marc Zyngier wrote:
>
>> Nobody would be insane enough to try and use level triggered
>> MSIs on PCI, but let's make sure it doesn't happen. Also,
>> let's mandate that the irqchip backing the platform MSI domain
>> is providing an irq_set_type method (or the whole thing would
>> be a bit useless).
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>> drivers/base/platform-msi.c | 3 +++
>> drivers/pci/msi.c | 3 +++
>> 2 files changed, 6 insertions(+)
>>
>> diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
>> index 8e22073aeeed..3b9694a6beaa 100644
>> --- a/drivers/base/platform-msi.c
>> +++ b/drivers/base/platform-msi.c
>> @@ -101,6 +101,9 @@ static void platform_msi_update_chip_ops(struct msi_domain_info *info)
>> chip->irq_set_affinity = msi_domain_set_affinity;
>> if (!chip->irq_write_msi_msg)
>> chip->irq_write_msi_msg = platform_msi_write_msg;
>> + if (WARN_ON((info->flags & MSI_FLAG_LEVEL_CAPABLE) &&
>> + !chip->irq_set_type))
>
> Shouldn't we just require something like IRQCHIP_SUPPORTS_MSI_LEVEL or such
> in chip->flags being set instead?
That definitely makes sense. Thanks for the suggestion.
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2018-05-01 10:15 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-23 10:34 [PATCH 0/7] Level-triggered MSI support Marc Zyngier
2018-04-23 10:34 ` [PATCH 1/7] genirq/msi: Allow level-triggered MSIs to be exposed by MSI providers Marc Zyngier
2018-04-23 10:34 ` [PATCH 2/7] genirq/msi: Limit level-triggered MSI to platform devices Marc Zyngier
2018-04-26 19:50 ` Thomas Gleixner
2018-05-01 10:15 ` Marc Zyngier
2018-04-23 10:34 ` [PATCH 3/7] irqchip/mvebu-gicp: Use level-triggered MSIs between ICU and GICP Marc Zyngier
2018-04-23 10:34 ` [PATCH 4/7] dma-iommu: Fix compilation when !CONFIG_IOMMU_DMA Marc Zyngier
2018-04-23 10:34 ` [PATCH 5/7] irqchip/gic-v3: Add support for Message Based Interrupts as an MSI controller Marc Zyngier
2018-04-26 20:53 ` Thomas Gleixner
2018-04-23 10:34 ` [PATCH 6/7] irqchip/gic-v3: Add PCI/MSI support to the GICv3 MBI sub-driver Marc Zyngier
2018-04-23 10:34 ` [PATCH 7/7] dt-bindings/gic-v3: Add documentation for MBI support Marc Zyngier
2018-04-23 11:51 ` [PATCH 0/7] Level-triggered MSI support Ard Biesheuvel
2018-04-23 12:31 ` Marc Zyngier
2018-04-23 15:53 ` Marc Zyngier
2018-04-23 16:48 ` Ard Biesheuvel
2018-04-23 12:43 ` Srinivas Kandagatla
2018-04-23 15:32 ` Miquel Raynal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).