summaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-hierofalcon/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-kernel/linux/linux-hierofalcon/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch')
-rw-r--r--recipes-kernel/linux/linux-hierofalcon/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch418
1 files changed, 418 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-hierofalcon/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch b/recipes-kernel/linux/linux-hierofalcon/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch
new file mode 100644
index 0000000..16c2dbd
--- /dev/null
+++ b/recipes-kernel/linux/linux-hierofalcon/412-7-styx-linux-tracking.git-f9a9d954f23b967cd26338afda9a0a96afe62c25.patch
@@ -0,0 +1,418 @@
1From 6082a087207706d5951768d2d48aaa2d21fc2c0d Mon Sep 17 00:00:00 2001
2From: Adrian Calianu <adrian.calianu@enea.com>
3Date: Tue, 11 Aug 2015 15:09:19 +0200
4Subject: [PATCH] DO NOT UPSTREAM YET: Introducing ACPI support for GICv2m
5
6From: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
7Date: Tue, 20 Jan 2015 23:21:20 -0600
8
9Signed-off-by: Adrian Calianu <adrian.calianu@enea.com>
10---
11 drivers/irqchip/irq-gic-v2m.c | 193 ++++++++++++++++++++++++++---------
12 drivers/pci/pci-acpi.c | 55 ++++++----
13 include/linux/irqchip/arm-gic-acpi.h | 1 +
14 include/linux/pci-acpi.h | 3 +
15 4 files changed, 185 insertions(+), 67 deletions(-)
16
17diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
18index fdf7065..c32eb55 100644
19--- a/drivers/irqchip/irq-gic-v2m.c
20+++ b/drivers/irqchip/irq-gic-v2m.c
21@@ -15,6 +15,7 @@
22
23 #define pr_fmt(fmt) "GICv2m: " fmt
24
25+#include <linux/acpi.h>
26 #include <linux/irq.h>
27 #include <linux/irqdomain.h>
28 #include <linux/kernel.h>
29@@ -22,6 +23,7 @@
30 #include <linux/of_pci.h>
31 #include <linux/slab.h>
32 #include <linux/spinlock.h>
33+#include <linux/irqchip/arm-gic.h>
34
35 /*
36 * MSI_TYPER:
37@@ -45,7 +47,6 @@
38
39 struct v2m_data {
40 spinlock_t msi_cnt_lock;
41- struct msi_controller mchip;
42 struct resource res; /* GICv2m resource */
43 void __iomem *base; /* GICv2m virt address */
44 u32 spi_start; /* The SPI number that MSIs start */
45@@ -115,17 +116,17 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
46 unsigned int virq,
47 irq_hw_number_t hwirq)
48 {
49- struct of_phandle_args args;
50+ struct gic_irq_alloc_info info;
51 struct irq_data *d;
52 int err;
53
54- args.np = domain->parent->of_node;
55- args.args_count = 3;
56- args.args[0] = 0;
57- args.args[1] = hwirq - 32;
58- args.args[2] = IRQ_TYPE_EDGE_RISING;
59+ err = gic_init_irq_alloc_info(GIC_INT_TYPE_NONE, hwirq,
60+ IRQ_TYPE_EDGE_RISING,
61+ domain->parent->of_node, &info);
62+ if (err)
63+ return err;
64
65- err = irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
66+ err = irq_domain_alloc_irqs_parent(domain, virq, 1, &info);
67 if (err)
68 return err;
69
70@@ -192,7 +193,7 @@ static void gicv2m_irq_domain_free(struct irq_domain *domain,
71 irq_domain_free_irqs_parent(domain, virq, nr_irqs);
72 }
73
74-static const struct irq_domain_ops gicv2m_domain_ops = {
75+static struct irq_domain_ops gicv2m_domain_ops = {
76 .alloc = gicv2m_irq_domain_alloc,
77 .free = gicv2m_irq_domain_free,
78 };
79@@ -213,11 +214,18 @@ static bool is_msi_spi_valid(u32 base, u32 num)
80 return true;
81 }
82
83-static int __init gicv2m_init_one(struct device_node *node,
84- struct irq_domain *parent)
85+char gicv2m_msi_domain_name[] = "V2M-MSI";
86+char gicv2m_domain_name[] = "GICV2M";
87+
88+static int __init gicv2m_init_one(struct irq_domain *parent,
89+ u32 *spi_start, u32 *nr_spis,
90+ struct resource *res,
91+ enum irq_domain_ref_type type,
92+ void *ref)
93 {
94 int ret;
95 struct v2m_data *v2m;
96+ struct irq_domain *inner_domain;
97
98 v2m = kzalloc(sizeof(struct v2m_data), GFP_KERNEL);
99 if (!v2m) {
100@@ -225,23 +233,17 @@ static int __init gicv2m_init_one(struct device_node *node,
101 return -ENOMEM;
102 }
103
104- ret = of_address_to_resource(node, 0, &v2m->res);
105- if (ret) {
106- pr_err("Failed to allocate v2m resource.\n");
107- goto err_free_v2m;
108- }
109-
110- v2m->base = ioremap(v2m->res.start, resource_size(&v2m->res));
111+ v2m->base = ioremap(res->start, resource_size(res));
112 if (!v2m->base) {
113 pr_err("Failed to map GICv2m resource\n");
114 ret = -ENOMEM;
115 goto err_free_v2m;
116 }
117+ memcpy(&v2m->res,res, sizeof(struct resource));
118
119- if (!of_property_read_u32(node, "arm,msi-base-spi", &v2m->spi_start) &&
120- !of_property_read_u32(node, "arm,msi-num-spis", &v2m->nr_spis)) {
121- pr_info("Overriding V2M MSI_TYPER (base:%u, num:%u)\n",
122- v2m->spi_start, v2m->nr_spis);
123+ if (*spi_start && *nr_spis) {
124+ v2m->spi_start = *spi_start;
125+ v2m->nr_spis = *nr_spis;
126 } else {
127 u32 typer = readl_relaxed(v2m->base + V2M_MSI_TYPER);
128
129@@ -261,43 +263,50 @@ static int __init gicv2m_init_one(struct device_node *node,
130 goto err_iounmap;
131 }
132
133- v2m->domain = irq_domain_add_tree(NULL, &gicv2m_domain_ops, v2m);
134- if (!v2m->domain) {
135+ inner_domain = irq_domain_add_tree(node, &gicv2m_domain_ops, v2m);
136+ if (!inner_domain) {
137 pr_err("Failed to create GICv2m domain\n");
138 ret = -ENOMEM;
139 goto err_free_bm;
140 }
141
142- v2m->domain->parent = parent;
143- v2m->mchip.of_node = node;
144- v2m->mchip.domain = pci_msi_create_irq_domain(node,
145- &gicv2m_msi_domain_info,
146- v2m->domain);
147- if (!v2m->mchip.domain) {
148- pr_err("Failed to create MSI domain\n");
149- ret = -ENOMEM;
150- goto err_free_domains;
151- }
152-
153- spin_lock_init(&v2m->msi_cnt_lock);
154-
155- ret = of_pci_msi_chip_add(&v2m->mchip);
156- if (ret) {
157- pr_err("Failed to add msi_chip.\n");
158- goto err_free_domains;
159- }
160-
161- pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", node->name,
162- (unsigned long)v2m->res.start, (unsigned long)v2m->res.end,
163- v2m->spi_start, (v2m->spi_start + v2m->nr_spis));
164+ inner_domain->bus_token = DOMAIN_BUS_PLATFORM_MSI;
165+ inner_domain->name = gicv2m_domain_name;
166+
167+ ret = -ENOMEM;
168+ if (type == IRQ_DOMAIN_REF_OF_DEV_NODE) {
169+ v2m->domain = pci_msi_create_irq_domain(
170+ (struct device_node *)ref,
171+ &gicv2m_msi_domain_info,
172+ inner_domain);
173+ if (!v2m->domain) {
174+ pr_err("Failed to create MSI domain\n");
175+ goto err_free_domains;
176+ }
177+ } else {
178+ v2m->domain = pci_msi_create_irq_domain( NULL,
179+ &gicv2m_msi_domain_info,
180+ inner_domain);
181+ if (!v2m->domain) {
182+ pr_err("Failed to create MSI domain\n");
183+ goto err_free_domains;
184+ }
185+
186+ v2m->domain->type = type;
187+ v2m->domain->acpi_ref = ref;
188+ }
189+
190+ v2m->domain->name = gicv2m_msi_domain_name;
191+
192+ spin_lock_init(&v2m->msi_cnt_lock);
193
194 return 0;
195
196 err_free_domains:
197- if (v2m->mchip.domain)
198- irq_domain_remove(v2m->mchip.domain);
199 if (v2m->domain)
200 irq_domain_remove(v2m->domain);
201+ if (inner_domain)
202+ irq_domain_remove(inner_domain);
203 err_free_bm:
204 kfree(v2m->bm);
205 err_iounmap:
206@@ -319,15 +328,101 @@ int __init gicv2m_of_init(struct device_node *node, struct irq_domain *parent)
207
208 for (child = of_find_matching_node(node, gicv2m_device_id); child;
209 child = of_find_matching_node(child, gicv2m_device_id)) {
210+ u32 spi_start = 0, nr_spis = 0;
211+ struct resource res;
212+
213 if (!of_find_property(child, "msi-controller", NULL))
214 continue;
215
216- ret = gicv2m_init_one(child, parent);
217+ ret = of_address_to_resource(child, 0, &res);
218+ if (ret) {
219+ pr_err("Failed to allocate v2m resource.\n");
220+ break;
221+ }
222+
223+ if (!of_property_read_u32(child, "arm,msi-base-spi", &spi_start) &&
224+ !of_property_read_u32(child, "arm,msi-num-spis", &nr_spis))
225+ pr_info("Overriding V2M MSI_TYPER (base:%u, num:%u)\n",
226+ spi_start, nr_spis);
227+
228+ ret = gicv2m_init_one(parent, &spi_start, &nr_spis, &res,
229+ IRQ_DOMAIN_REF_OF_DEV_NODE, child);
230+
231 if (ret) {
232 of_node_put(node);
233 break;
234 }
235+ pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", child->name,
236+ (unsigned long)res.start, (unsigned long)res.end,
237+ spi_start, (spi_start + nr_spis));
238 }
239
240 return ret;
241 }
242+
243+#ifdef CONFIG_ACPI
244+static struct acpi_madt_generic_msi_frame *msi_frame;
245+
246+static int __init
247+gicv2m_acpi_parse_madt_msi(struct acpi_subtable_header *header,
248+ const unsigned long end)
249+{
250+ struct acpi_madt_generic_msi_frame *frame;
251+
252+ frame = (struct acpi_madt_generic_msi_frame *)header;
253+ if (BAD_MADT_ENTRY(frame, end))
254+ return -EINVAL;
255+
256+ if (msi_frame)
257+ pr_warn("Only one GIC MSI FRAME supported.\n");
258+ else
259+ msi_frame = frame;
260+
261+ return 0;
262+}
263+
264+int __init gicv2m_acpi_init(struct acpi_table_header *table,
265+ struct irq_domain *parent)
266+{
267+ int ret = 0;
268+ int count, i;
269+ struct acpi_madt_generic_msi_frame *cur;
270+
271+ count = acpi_parse_entries(ACPI_SIG_MADT, sizeof(struct acpi_table_madt),
272+ gicv2m_acpi_parse_madt_msi, table,
273+ ACPI_MADT_TYPE_GENERIC_MSI_FRAME, 0);
274+
275+ if ((count <= 0) || !msi_frame) {
276+ pr_debug("No valid ACPI GIC MSI FRAME exist\n");
277+ return 0;
278+ }
279+
280+ for (i = 0, cur = msi_frame; i < count; i++, cur++) {
281+ struct resource res;
282+ u32 spi_start = 0, nr_spis = 0;
283+
284+ res.start = cur->base_address;
285+ res.end = cur->base_address + 0x1000;
286+
287+ if (cur->flags & ACPI_MADT_OVERRIDE_SPI_VALUES) {
288+ spi_start = cur->spi_base;
289+ nr_spis = cur->spi_count;
290+
291+ pr_info("ACPI overriding V2M MSI_TYPER (base:%u, num:%u)\n",
292+ spi_start, nr_spis);
293+ }
294+
295+ ret = gicv2m_init_one(parent, &spi_start, &nr_spis, &res,
296+ IRQ_DOMAIN_REF_ACPI_MSI_FRAME, msi_frame);
297+ if (ret)
298+ break;
299+
300+ pr_info("MSI frame ID %u: range[%#lx:%#lx], SPI[%d:%d]\n",
301+ cur->msi_frame_id,
302+ (unsigned long)res.start, (unsigned long)res.end,
303+ spi_start, (spi_start + nr_spis));
304+ }
305+ return ret;
306+}
307+
308+#endif /* CONFIG_ACPI */
309diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
310index fe42097..fa0d8ec 100644
311--- a/drivers/pci/pci-acpi.c
312+++ b/drivers/pci/pci-acpi.c
313@@ -9,6 +9,7 @@
314
315 #include <linux/delay.h>
316 #include <linux/init.h>
317+#include <linux/irqdomain.h>
318 #include <linux/pci.h>
319 #include <linux/pci_hotplug.h>
320 #include <linux/module.h>
321@@ -717,25 +718,43 @@ static int __init acpi_pci_init(void)
322 arch_initcall(acpi_pci_init);
323
324 #ifdef CONFIG_PCI_MSI
325-void pci_acpi_set_phb_msi_domain(struct pci_bus *bus) {
326+static struct acpi_madt_generic_msi_frame *msi_frame;
327+static int
328+pci_acpi_parse_madt_msi(struct acpi_subtable_header *header,
329+ const unsigned long end)
330+{
331+ struct acpi_madt_generic_msi_frame *frame;
332+ frame = (struct acpi_madt_generic_msi_frame *)header;
333+ if (BAD_MADT_ENTRY(frame, end))
334+ return -EINVAL;
335+
336+ /* We currently support one MSI frame only */
337+ if (!msi_frame)
338+ msi_frame = frame;
339+
340+ return 0;
341+}
342+
343+void pci_acpi_set_phb_msi_domain(struct pci_bus *bus)
344+{
345+ int count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_MSI_FRAME,
346+ pci_acpi_parse_madt_msi, 0);
347+ if (count > 0) {
348 #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
349- u32 msi_frame_id = 0;
350- int num;
351-
352- if (acpi_disabled)
353- return;
354-
355- /**
356- * Since ACPI 5.1 currently does not define
357- * a way to associate MSI frame ID to a device,
358- * we can only support single MSI frame at the moment.
359- * Therefore, the id 0 is used as a default.
360- */
361- num = msi_get_num_irq_domain();
362- if (num <= 0 || num > 1)
363- return;
364-
365- dev_set_msi_domain(&bus->dev, irq_find_acpi_msi_domain(msi_frame_id));
366+ struct irq_domain *domain;
367+ /**
368+ * Since ACPI 5.1 currently does not define
369+ * a way to associate MSI frame ID to a device,
370+ * we can only support single MSI frame at the moment.
371+ */
372+ domain = irq_find_domain(IRQ_DOMAIN_REF_ACPI_MSI_FRAME, msi_frame);
373+ if (!domain) {
374+ pr_debug("Fail to find domain for MSI\n");
375+ return;
376+ }
377+
378+ dev_set_msi_domain(&bus->dev, domain);
379 #endif
380+ }
381 }
382 #endif /* CONFIG_PCI_MSI */
383diff --git a/include/linux/irqchip/arm-gic-acpi.h b/include/linux/irqchip/arm-gic-acpi.h
384index fa8033b..b02f065 100644
385--- a/include/linux/irqchip/arm-gic-acpi.h
386+++ b/include/linux/irqchip/arm-gic-acpi.h
387@@ -26,6 +26,7 @@ struct acpi_table_header;
388
389 void acpi_irq_init(void);
390 int gic_v2_acpi_init(struct acpi_table_header *table, struct irq_domain **domain);
391+int gicv2m_acpi_init(struct acpi_table_header *table, struct irq_domain *parent);
392 #else
393 static inline void acpi_gic_init(void) { }
394 #endif
395diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
396index a965efa..759916d 100644
397--- a/include/linux/pci-acpi.h
398+++ b/include/linux/pci-acpi.h
399@@ -77,6 +77,8 @@ static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
400 static inline void acpiphp_check_host_bridge(struct acpi_device *adev) { }
401 #endif
402
403+void pci_acpi_set_phb_msi_domain(struct pci_bus *bus);
404+
405 extern const u8 pci_acpi_dsm_uuid[];
406 #define DEVICE_LABEL_DSM 0x07
407 #define RESET_DELAY_DSM 0x08
408@@ -85,6 +87,7 @@ extern const u8 pci_acpi_dsm_uuid[];
409 #else /* CONFIG_ACPI */
410 static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
411 static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
412+static inline void pci_acpi_set_phb_msi_domain(struct pci_bus *bus) { };
413 #endif /* CONFIG_ACPI */
414
415 #ifdef CONFIG_ACPI_APEI
416--
4171.9.1
418