mirror of https://github.com/hak5/openwrt.git
183 lines
5.8 KiB
Diff
183 lines
5.8 KiB
Diff
From dab02a7cc54494740e849cd51b554d100eb5541d Mon Sep 17 00:00:00 2001
|
|
From: Yangbo Lu <yangbo.lu@nxp.com>
|
|
Date: Thu, 5 Jul 2018 17:36:09 +0800
|
|
Subject: [PATCH 23/32] irqchip: support layerscape
|
|
|
|
This is an integrated patch for layerscape gic support.
|
|
|
|
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com>
|
|
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
|
|
---
|
|
drivers/irqchip/Makefile | 1 +
|
|
drivers/irqchip/irq-gic-v3-its.c | 1 +
|
|
include/linux/irqchip/arm-gic-v3.h | 3 +++
|
|
include/linux/irqdomain.h | 36 +++++++++++++++++++++++++++
|
|
kernel/irq/irqdomain.c | 39 ++++++++++++++++++++++++++++++
|
|
kernel/irq/msi.c | 4 +--
|
|
6 files changed, 82 insertions(+), 2 deletions(-)
|
|
|
|
--- a/drivers/irqchip/Makefile
|
|
+++ b/drivers/irqchip/Makefile
|
|
@@ -75,3 +75,4 @@ obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scf
|
|
obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
|
|
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o
|
|
obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
|
|
+obj-$(CONFIG_QUICC_ENGINE) += irq-qeic.o
|
|
--- a/drivers/irqchip/irq-gic-v3-its.c
|
|
+++ b/drivers/irqchip/irq-gic-v3-its.c
|
|
@@ -1658,6 +1658,7 @@ static int its_init_domain(struct fwnode
|
|
|
|
inner_domain->parent = its_parent;
|
|
inner_domain->bus_token = DOMAIN_BUS_NEXUS;
|
|
+ inner_domain->flags |= IRQ_DOMAIN_FLAG_MSI_REMAP;
|
|
info->ops = &its_msi_domain_ops;
|
|
info->data = its;
|
|
inner_domain->host_data = info;
|
|
--- a/include/linux/irqchip/arm-gic-v3.h
|
|
+++ b/include/linux/irqchip/arm-gic-v3.h
|
|
@@ -133,6 +133,9 @@
|
|
#define GIC_BASER_SHAREABILITY(reg, type) \
|
|
(GIC_BASER_##type << reg##_SHAREABILITY_SHIFT)
|
|
|
|
+/* encode a size field of width @w containing @n - 1 units */
|
|
+#define GIC_ENCODE_SZ(n, w) (((unsigned long)(n) - 1) & GENMASK_ULL(((w) - 1), 0))
|
|
+
|
|
#define GICR_PROPBASER_SHAREABILITY_SHIFT (10)
|
|
#define GICR_PROPBASER_INNER_CACHEABILITY_SHIFT (7)
|
|
#define GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT (56)
|
|
--- a/include/linux/irqdomain.h
|
|
+++ b/include/linux/irqdomain.h
|
|
@@ -187,6 +187,12 @@ enum {
|
|
/* Irq domain is an IPI domain with single virq */
|
|
IRQ_DOMAIN_FLAG_IPI_SINGLE = (1 << 3),
|
|
|
|
+ /* Irq domain implements MSIs */
|
|
+ IRQ_DOMAIN_FLAG_MSI = (1 << 4),
|
|
+
|
|
+ /* Irq domain implements MSI remapping */
|
|
+ IRQ_DOMAIN_FLAG_MSI_REMAP = (1 << 5),
|
|
+
|
|
/*
|
|
* Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
|
|
* for implementation specific purposes and ignored by the
|
|
@@ -220,6 +226,7 @@ struct irq_domain *irq_domain_add_legacy
|
|
void *host_data);
|
|
extern struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec,
|
|
enum irq_domain_bus_token bus_token);
|
|
+extern bool irq_domain_check_msi_remap(void);
|
|
extern void irq_set_default_host(struct irq_domain *host);
|
|
extern int irq_domain_alloc_descs(int virq, unsigned int nr_irqs,
|
|
irq_hw_number_t hwirq, int node,
|
|
@@ -453,6 +460,19 @@ static inline bool irq_domain_is_ipi_sin
|
|
{
|
|
return domain->flags & IRQ_DOMAIN_FLAG_IPI_SINGLE;
|
|
}
|
|
+
|
|
+static inline bool irq_domain_is_msi(struct irq_domain *domain)
|
|
+{
|
|
+ return domain->flags & IRQ_DOMAIN_FLAG_MSI;
|
|
+}
|
|
+
|
|
+static inline bool irq_domain_is_msi_remap(struct irq_domain *domain)
|
|
+{
|
|
+ return domain->flags & IRQ_DOMAIN_FLAG_MSI_REMAP;
|
|
+}
|
|
+
|
|
+extern bool irq_domain_hierarchical_is_msi_remap(struct irq_domain *domain);
|
|
+
|
|
#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) { }
|
|
@@ -484,6 +504,22 @@ static inline bool irq_domain_is_ipi_sin
|
|
{
|
|
return false;
|
|
}
|
|
+
|
|
+static inline bool irq_domain_is_msi(struct irq_domain *domain)
|
|
+{
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static inline bool irq_domain_is_msi_remap(struct irq_domain *domain)
|
|
+{
|
|
+ return false;
|
|
+}
|
|
+
|
|
+static inline bool
|
|
+irq_domain_hierarchical_is_msi_remap(struct irq_domain *domain)
|
|
+{
|
|
+ return false;
|
|
+}
|
|
#endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */
|
|
|
|
#else /* CONFIG_IRQ_DOMAIN */
|
|
--- a/kernel/irq/irqdomain.c
|
|
+++ b/kernel/irq/irqdomain.c
|
|
@@ -319,6 +319,31 @@ struct irq_domain *irq_find_matching_fws
|
|
EXPORT_SYMBOL_GPL(irq_find_matching_fwspec);
|
|
|
|
/**
|
|
+ * irq_domain_check_msi_remap - Check whether all MSI irq domains implement
|
|
+ * IRQ remapping
|
|
+ *
|
|
+ * Return: false if any MSI irq domain does not support IRQ remapping,
|
|
+ * true otherwise (including if there is no MSI irq domain)
|
|
+ */
|
|
+bool irq_domain_check_msi_remap(void)
|
|
+{
|
|
+ struct irq_domain *h;
|
|
+ bool ret = true;
|
|
+
|
|
+ mutex_lock(&irq_domain_mutex);
|
|
+ list_for_each_entry(h, &irq_domain_list, link) {
|
|
+ if (irq_domain_is_msi(h) &&
|
|
+ !irq_domain_hierarchical_is_msi_remap(h)) {
|
|
+ ret = false;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ mutex_unlock(&irq_domain_mutex);
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(irq_domain_check_msi_remap);
|
|
+
|
|
+/**
|
|
* irq_set_default_host() - Set a "default" irq domain
|
|
* @domain: default domain pointer
|
|
*
|
|
@@ -1420,6 +1445,20 @@ static void irq_domain_check_hierarchy(s
|
|
if (domain->ops->alloc)
|
|
domain->flags |= IRQ_DOMAIN_FLAG_HIERARCHY;
|
|
}
|
|
+
|
|
+/**
|
|
+ * irq_domain_hierarchical_is_msi_remap - Check if the domain or any
|
|
+ * parent has MSI remapping support
|
|
+ * @domain: domain pointer
|
|
+ */
|
|
+bool irq_domain_hierarchical_is_msi_remap(struct irq_domain *domain)
|
|
+{
|
|
+ for (; domain; domain = domain->parent) {
|
|
+ if (irq_domain_is_msi_remap(domain))
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
#else /* CONFIG_IRQ_DOMAIN_HIERARCHY */
|
|
/**
|
|
* irq_domain_get_irq_data - Get irq_data associated with @virq and @domain
|
|
--- a/kernel/irq/msi.c
|
|
+++ b/kernel/irq/msi.c
|
|
@@ -272,8 +272,8 @@ struct irq_domain *msi_create_irq_domain
|
|
if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
|
|
msi_domain_update_chip_ops(info);
|
|
|
|
- return irq_domain_create_hierarchy(parent, 0, 0, fwnode,
|
|
- &msi_domain_ops, info);
|
|
+ return irq_domain_create_hierarchy(parent, IRQ_DOMAIN_FLAG_MSI, 0,
|
|
+ fwnode, &msi_domain_ops, info);
|
|
}
|
|
|
|
int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,
|