aboutsummaryrefslogtreecommitdiffstats
path: root/meta-seattle/recipes-kernel/linux/files/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-seattle/recipes-kernel/linux/files/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch')
-rw-r--r--meta-seattle/recipes-kernel/linux/files/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch422
1 files changed, 422 insertions, 0 deletions
diff --git a/meta-seattle/recipes-kernel/linux/files/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch b/meta-seattle/recipes-kernel/linux/files/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch
new file mode 100644
index 00000000..7e3514e8
--- /dev/null
+++ b/meta-seattle/recipes-kernel/linux/files/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch
@@ -0,0 +1,422 @@
+From 6082a087207706d5951768d2d48aaa2d21fc2c0d Mon Sep 17 00:00:00 2001
+From: Adrian Calianu <adrian.calianu@enea.com>
+Date: Tue, 11 Aug 2015 15:09:19 +0200
+Subject: [PATCH] DO NOT UPSTREAM YET: Introducing ACPI support for GICv2m
+
+From: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
+Date: Tue, 20 Jan 2015 23:21:20 -0600
+
+Upstream-Status: Pending
+
+Ported from 3.19 kernel, patch provided by AMD.
+
+Signed-off-by: Adrian Calianu <adrian.calianu@enea.com>
+---
+ drivers/irqchip/irq-gic-v2m.c | 193 ++++++++++++++++++++++++++---------
+ drivers/pci/pci-acpi.c | 55 ++++++----
+ include/linux/irqchip/arm-gic-acpi.h | 1 +
+ include/linux/pci-acpi.h | 3 +
+ 4 files changed, 185 insertions(+), 67 deletions(-)
+
+diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
+index fdf7065..c32eb55 100644
+--- a/drivers/irqchip/irq-gic-v2m.c
++++ b/drivers/irqchip/irq-gic-v2m.c
+@@ -15,6 +15,7 @@
+
+ #define pr_fmt(fmt) "GICv2m: " fmt
+
++#include <linux/acpi.h>
+ #include <linux/irq.h>
+ #include <linux/irqdomain.h>
+ #include <linux/kernel.h>
+@@ -22,6 +23,7 @@
+ #include <linux/of_pci.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
++#include <linux/irqchip/arm-gic.h>
+
+ /*
+ * MSI_TYPER:
+@@ -45,7 +47,6 @@
+
+ struct v2m_data {
+ spinlock_t msi_cnt_lock;
+- struct msi_controller mchip;
+ struct resource res; /* GICv2m resource */
+ void __iomem *base; /* GICv2m virt address */
+ u32 spi_start; /* The SPI number that MSIs start */
+@@ -115,17 +116,17 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
+ unsigned int virq,
+ irq_hw_number_t hwirq)
+ {
+- struct of_phandle_args args;
++ struct gic_irq_alloc_info info;
+ struct irq_data *d;
+ int err;
+
+- args.np = domain->parent->of_node;
+- args.args_count = 3;
+- args.args[0] = 0;
+- args.args[1] = hwirq - 32;
+- args.args[2] = IRQ_TYPE_EDGE_RISING;
++ err = gic_init_irq_alloc_info(GIC_INT_TYPE_NONE, hwirq,
++ IRQ_TYPE_EDGE_RISING,
++ domain->parent->of_node, &info);
++ if (err)
++ return err;
+
+- err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
++ err = irq_domain_alloc_irqs_parent(domain, virq, 1, &info);
+ if (err)
+ return err;
+
+@@ -192,7 +193,7 @@ static void gicv2m_irq_domain_free(struct irq_domain *domain,
+ irq_domain_free_irqs_parent(domain, virq, nr_irqs);
+ }
+
+-static const struct irq_domain_ops gicv2m_domain_ops = {
++static struct irq_domain_ops gicv2m_domain_ops = {
+ .alloc = gicv2m_irq_domain_alloc,
+ .free = gicv2m_irq_domain_free,
+ };
+@@ -213,11 +214,18 @@ static bool is_msi_spi_valid(u32 base, u32 num)
+ return true;
+ }
+
+-static int __init gicv2m_init_one(struct device_node *node,
+- struct irq_domain *parent)
++char gicv2m_msi_domain_name[] = "V2M-MSI";
++char gicv2m_domain_name[] = "GICV2M";
++
++static int __init gicv2m_init_one(struct irq_domain *parent,
++ u32 *spi_start, u32 *nr_spis,
++ struct resource *res,
++ enum irq_domain_ref_type type,
++ void *ref)
+ {
+ int ret;
+ struct v2m_data *v2m;
++ struct irq_domain *inner_domain;
+
+ v2m = kzalloc(sizeof(struct v2m_data), GFP_KERNEL);
+ if (!v2m) {
+@@ -225,23 +233,17 @@ static int __init gicv2m_init_one(struct device_node *node,
+ return -ENOMEM;
+ }
+
+- ret = of_address_to_resource(node, 0, &v2m->res);
+- if (ret) {
+- pr_err("Failed to allocate v2m resource.\n");
+- goto err_free_v2m;
+- }
+-
+- v2m->base = ioremap(v2m->res.start, resource_size(&v2m->res));
++ v2m->base = ioremap(res->start, resource_size(res));
+ if (!v2m->base) {
+ pr_err("Failed to map GICv2m resource\n");
+ ret = -ENOMEM;
+ goto err_free_v2m;
+ }
++ memcpy(&v2m->res,res, sizeof(struct resource));
+
+- if (!of_property_read_u32(node, "arm,msi-base-spi", &v2m->spi_start) &&
+- !of_property_read_u32(node, "arm,msi-num-spis", &v2m->nr_spis)) {
+- pr_info("Overriding V2M MSI_TYPER (base:%u, num:%u)\n",
+- v2m->spi_start, v2m->nr_spis);
++ if (*spi_start && *nr_spis) {
++ v2m->spi_start = *spi_start;
++ v2m->nr_spis = *nr_spis;
+ } else {
+ u32 typer = readl_relaxed(v2m->base + V2M_MSI_TYPER);
+
+@@ -261,43 +263,50 @@ static int __init gicv2m_init_one(struct device_node *node,
+ goto err_iounmap;
+ }
+
+- v2m->domain = irq_domain_add_tree(NULL, &gicv2m_domain_ops, v2m);
+- if (!v2m->domain) {
++ inner_domain = irq_domain_add_tree(node, &gicv2m_domain_ops, v2m);
++ if (!inner_domain) {
+ pr_err("Failed to create GICv2m domain\n");
+ ret = -ENOMEM;
+ goto err_free_bm;
+ }
+
+- v2m->domain->parent = parent;
+- v2m->mchip.of_node = node;
+- v2m->mchip.domain = pci_msi_create_irq_domain(node,
+- &gicv2m_msi_domain_info,
+- v2m->domain);
+- if (!v2m->mchip.domain) {
+- pr_err("Failed to create MSI domain\n");
+- ret = -ENOMEM;
+- goto err_free_domains;
+- }
+-
+- spin_lock_init(&v2m->msi_cnt_lock);
+-
+- ret = of_pci_msi_chip_add(&v2m->mchip);
+- if (ret) {
+- pr_err("Failed to add msi_chip.\n");
+- goto err_free_domains;
+- }
+-
+- pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", node->name,
+- (unsigned long)v2m->res.start, (unsigned long)v2m->res.end,
+- v2m->spi_start, (v2m->spi_start + v2m->nr_spis));
++ inner_domain->bus_token = DOMAIN_BUS_PLATFORM_MSI;
++ inner_domain->name = gicv2m_domain_name;
++
++ ret = -ENOMEM;
++ if (type == IRQ_DOMAIN_REF_OF_DEV_NODE) {
++ v2m->domain = pci_msi_create_irq_domain(
++ (struct device_node *)ref,
++ &gicv2m_msi_domain_info,
++ inner_domain);
++ if (!v2m->domain) {
++ pr_err("Failed to create MSI domain\n");
++ goto err_free_domains;
++ }
++ } else {
++ v2m->domain = pci_msi_create_irq_domain( NULL,
++ &gicv2m_msi_domain_info,
++ inner_domain);
++ if (!v2m->domain) {
++ pr_err("Failed to create MSI domain\n");
++ goto err_free_domains;
++ }
++
++ v2m->domain->type = type;
++ v2m->domain->acpi_ref = ref;
++ }
++
++ v2m->domain->name = gicv2m_msi_domain_name;
++
++ spin_lock_init(&v2m->msi_cnt_lock);
+
+ return 0;
+
+ err_free_domains:
+- if (v2m->mchip.domain)
+- irq_domain_remove(v2m->mchip.domain);
+ if (v2m->domain)
+ irq_domain_remove(v2m->domain);
++ if (inner_domain)
++ irq_domain_remove(inner_domain);
+ err_free_bm:
+ kfree(v2m->bm);
+ err_iounmap:
+@@ -319,15 +328,101 @@ int __init gicv2m_of_init(struct device_node *node, struct irq_domain *parent)
+
+ for (child = of_find_matching_node(node, gicv2m_device_id); child;
+ child = of_find_matching_node(child, gicv2m_device_id)) {
++ u32 spi_start = 0, nr_spis = 0;
++ struct resource res;
++
+ if (!of_find_property(child, "msi-controller", NULL))
+ continue;
+
+- ret = gicv2m_init_one(child, parent);
++ ret = of_address_to_resource(child, 0, &res);
++ if (ret) {
++ pr_err("Failed to allocate v2m resource.\n");
++ break;
++ }
++
++ if (!of_property_read_u32(child, "arm,msi-base-spi", &spi_start) &&
++ !of_property_read_u32(child, "arm,msi-num-spis", &nr_spis))
++ pr_info("Overriding V2M MSI_TYPER (base:%u, num:%u)\n",
++ spi_start, nr_spis);
++
++ ret = gicv2m_init_one(parent, &spi_start, &nr_spis, &res,
++ IRQ_DOMAIN_REF_OF_DEV_NODE, child);
++
+ if (ret) {
+ of_node_put(node);
+ break;
+ }
++ pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", child->name,
++ (unsigned long)res.start, (unsigned long)res.end,
++ spi_start, (spi_start + nr_spis));
+ }
+
+ return ret;
+ }
++
++#ifdef CONFIG_ACPI
++static struct acpi_madt_generic_msi_frame *msi_frame;
++
++static int __init
++gicv2m_acpi_parse_madt_msi(struct acpi_subtable_header *header,
++ const unsigned long end)
++{
++ struct acpi_madt_generic_msi_frame *frame;
++
++ frame = (struct acpi_madt_generic_msi_frame *)header;
++ if (BAD_MADT_ENTRY(frame, end))
++ return -EINVAL;
++
++ if (msi_frame)
++ pr_warn("Only one GIC MSI FRAME supported.\n");
++ else
++ msi_frame = frame;
++
++ return 0;
++}
++
++int __init gicv2m_acpi_init(struct acpi_table_header *table,
++ struct irq_domain *parent)
++{
++ int ret = 0;
++ int count, i;
++ struct acpi_madt_generic_msi_frame *cur;
++
++ count = acpi_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt),
++ gicv2m_acpi_parse_madt_msi, table,
++ ACPI_MADT_TYPE_GENERIC_MSI_FRAME, 0);
++
++ if ((count <= 0) || !msi_frame) {
++ pr_debug("No valid ACPI GIC MSI FRAME exist\n");
++ return 0;
++ }
++
++ for (i = 0, cur = msi_frame; i < count; i++, cur++) {
++ struct resource res;
++ u32 spi_start = 0, nr_spis = 0;
++
++ res.start = cur->base_address;
++ res.end = cur->base_address + 0x1000;
++
++ if (cur->flags & ACPI_MADT_OVERRIDE_SPI_VALUES) {
++ spi_start = cur->spi_base;
++ nr_spis = cur->spi_count;
++
++ pr_info("ACPI overriding V2M MSI_TYPER (base:%u, num:%u)\n",
++ spi_start, nr_spis);
++ }
++
++ ret = gicv2m_init_one(parent, &spi_start, &nr_spis, &res,
++ IRQ_DOMAIN_REF_ACPI_MSI_FRAME, msi_frame);
++ if (ret)
++ break;
++
++ pr_info("MSI frame ID %u: range[%#lx:%#lx], SPI[%d:%d]\n",
++ cur->msi_frame_id,
++ (unsigned long)res.start, (unsigned long)res.end,
++ spi_start, (spi_start + nr_spis));
++ }
++ return ret;
++}
++
++#endif /* CONFIG_ACPI */
+diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
+index fe42097..fa0d8ec 100644
+--- a/drivers/pci/pci-acpi.c
++++ b/drivers/pci/pci-acpi.c
+@@ -9,6 +9,7 @@
+
+ #include <linux/delay.h>
+ #include <linux/init.h>
++#include <linux/irqdomain.h>
+ #include <linux/pci.h>
+ #include <linux/pci_hotplug.h>
+ #include <linux/module.h>
+@@ -717,25 +718,43 @@ static int __init acpi_pci_init(void)
+ arch_initcall(acpi_pci_init);
+
+ #ifdef CONFIG_PCI_MSI
+-void pci_acpi_set_phb_msi_domain(struct pci_bus *bus) {
++static struct acpi_madt_generic_msi_frame *msi_frame;
++static int
++pci_acpi_parse_madt_msi(struct acpi_subtable_header *header,
++ const unsigned long end)
++{
++ struct acpi_madt_generic_msi_frame *frame;
++ frame = (struct acpi_madt_generic_msi_frame *)header;
++ if (BAD_MADT_ENTRY(frame, end))
++ return -EINVAL;
++
++ /* We currently support one MSI frame only */
++ if (!msi_frame)
++ msi_frame = frame;
++
++ return 0;
++}
++
++void pci_acpi_set_phb_msi_domain(struct pci_bus *bus)
++{
++ int count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_MSI_FRAME,
++ pci_acpi_parse_madt_msi, 0);
++ if (count > 0) {
+ #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+- u32 msi_frame_id = 0;
+- int num;
+-
+- if (acpi_disabled)
+- return;
+-
+- /**
+- * Since ACPI 5.1 currently does not define
+- * a way to associate MSI frame ID to a device,
+- * we can only support single MSI frame at the moment.
+- * Therefore, the id 0 is used as a default.
+- */
+- num = msi_get_num_irq_domain();
+- if (num <= 0 || num > 1)
+- return;
+-
+- dev_set_msi_domain(&bus->dev, irq_find_acpi_msi_domain(msi_frame_id));
++ struct irq_domain *domain;
++ /**
++ * Since ACPI 5.1 currently does not define
++ * a way to associate MSI frame ID to a device,
++ * we can only support single MSI frame at the moment.
++ */
++ domain = irq_find_domain(IRQ_DOMAIN_REF_ACPI_MSI_FRAME, msi_frame);
++ if (!domain) {
++ pr_debug("Fail to find domain for MSI\n");
++ return;
++ }
++
++ dev_set_msi_domain(&bus->dev, domain);
+ #endif
++ }
+ }
+ #endif /* CONFIG_PCI_MSI */
+diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
+index fa8033b..b02f065 100644
+--- a/include/linux/irqchip/arm-gic-acpi.h
++++ b/include/linux/irqchip/arm-gic-acpi.h
+@@ -26,6 +26,7 @@ struct acpi_table_header;
+
+ void acpi_irq_init(void);
+ int gic_v2_acpi_init(struct acpi_table_header *table, struct irq_domain **domain);
++int gicv2m_acpi_init(struct acpi_table_header *table, struct irq_domain *parent);
+ #else
+ static inline void acpi_gic_init(void) { }
+ #endif
+diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
+index a965efa..759916d 100644
+--- a/include/linux/pci-acpi.h
++++ b/include/linux/pci-acpi.h
+@@ -77,6 +77,8 @@ static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
+ static inline void acpiphp_check_host_bridge(struct acpi_device *adev) { }
+ #endif
+
++void pci_acpi_set_phb_msi_domain(struct pci_bus *bus);
++
+ extern const u8 pci_acpi_dsm_uuid[];
+ #define DEVICE_LABEL_DSM 0x07
+ #define RESET_DELAY_DSM 0x08
+@@ -85,6 +87,7 @@ extern const u8 pci_acpi_dsm_uuid[];
+ #else /* CONFIG_ACPI */
+ static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
+ static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
++static inline void pci_acpi_set_phb_msi_domain(struct pci_bus *bus) { };
+ #endif /* CONFIG_ACPI */
+
+ #ifdef CONFIG_ACPI_APEI
+--
+1.9.1
+