diff options
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.patch | 422 |
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 + |